มีคำแนะนำในแปลงของคุณของการสูญเสียเป็นหน้าที่ของเป็นWแปลงเหล่านี้มี "kink" ใกล้ : นั่นเป็นเพราะด้านซ้ายของ 0 การไล่ระดับสีของการสูญเสียจะหายไปเป็น 0 (อย่างไรก็ตามเป็นทางออกที่ไม่ดีเพราะการสูญเสียสูงกว่าสำหรับ ) นอกจากนี้พล็อตนี้แสดงให้เห็นว่าฟังก์ชั่นการสูญเสียไม่ใช่แบบนูน (คุณสามารถวาดเส้นที่ข้ามเส้นโค้งการสูญเสียใน 3 ตำแหน่งหรือมากกว่า) เพื่อให้สัญญาณว่าเราควรระมัดระวังเมื่อใช้เครื่องมือเพิ่มประสิทธิภาพท้องถิ่นเช่น SGD การวิเคราะห์ต่อไปนี้แสดงให้เห็นว่าเมื่อถูกกำหนดค่าเริ่มต้นให้เป็นค่าลบก็เป็นไปได้ที่จะมาบรรจบกันเป็นวิธีแก้ปัญหาที่ไม่ดีww=0w = 0 w = 1 ww=0w=1w
ปัญหาการเหมาะสมคือ
minw,bf(x)∥f(x)−y∥22=max(0,wx+b)
และคุณกำลังใช้การปรับให้เหมาะสมอันดับแรกเพื่อทำเช่นนั้น ปัญหาของวิธีนี้คือมีการไล่ระดับสีf
f′(x)={w,0,if x>0if x<0
เมื่อคุณเริ่มต้นด้วยคุณจะต้องย้ายไปที่ด้านอื่น ๆ ของจะมาใกล้ชิดกับคำตอบที่ถูกต้องซึ่งเป็น 1 สิ่งนี้ทำยากเพราะเมื่อคุณมีมากน้อยมากการไล่ระดับสีก็จะกลายเป็นขนาดเล็กเช่นกัน ยิ่งคุณเข้าใกล้มากถึง 0 จากด้านซ้ายความคืบหน้าของคุณก็จะช้าลงเท่านั้น!w<00w=1|w|
นี่คือเหตุผลที่ในแปลงของคุณสำหรับ initializations ที่เป็นลบ , ไบร์ทของคุณทุกแผงอยู่ใกล้กับ 0 นี่เป็นสิ่งที่แอนิเมชั่นที่สองของคุณแสดงw(0)<0w(i)=0
เรื่องนี้เกี่ยวข้องกับปรากฏการณ์ relu ที่กำลังจะตาย สำหรับการสนทนาดูที่เครือข่าย ReLU ของฉันไม่สามารถเปิดได้
วิธีที่อาจประสบความสำเร็จมากกว่านั้นก็คือการใช้ความไม่เชิงเส้นที่แตกต่างกันเช่น relu ที่รั่วซึ่งไม่มีปัญหาที่เรียกว่า "การไล่ระดับสีที่หายไป" ฟังก์ชั่น relu ที่รั่วไหลคือ
g(x)={x,cx,if x>0otherwise
โดยที่เป็นค่าคงที่ดังนั้นมีขนาดเล็กและเป็นบวก เหตุผลที่ใช้งานได้คืออนุพันธ์ไม่ใช่ 0 "ทางซ้าย"c|c|
g′(x)={1,c,if x>0if x<0
การตั้งค่าเป็น relu สามัญ คนส่วนใหญ่เลือกจะเป็นสิ่งที่ชอบหรือ0.3ฉันไม่ได้เห็นการใช้ถึงแม้ว่าฉันสนใจที่จะดูการศึกษาว่ามีผลกระทบอย่างไรหากมีในเครือข่ายดังกล่าว (โปรดทราบว่าสำหรับสิ่งนี้จะลดไปที่ฟังก์ชันเอกลักษณ์สำหรับองค์ประกอบของเลเยอร์จำนวนมากอาจทำให้เกิดการไล่ระดับสีแบบระเบิดเนื่องจากการไล่ระดับสีมีขนาดใหญ่ขึ้นในชั้นที่ต่อเนื่องกัน)c=0c0.10.3c<0c=1,|c|>1
การแก้ไขโค้ด OP เล็กน้อยให้การสาธิตว่าปัญหาอยู่ที่ตัวเลือกของฟังก์ชั่นการเปิดใช้งาน รหัสนี้เริ่มต้นจะเป็นเชิงลบและใช้ในสถานที่ของธรรมดา การสูญเสียลดลงอย่างรวดเร็วเป็นค่าน้อยและน้ำหนักถูกต้องย้ายไปที่ซึ่งเป็นสิ่งที่ดีที่สุดww = 1LeakyReLU
ReLU
w=1
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, ReLU
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
batch = 1000
def tests():
while True:
test = np.random.randn(batch)
# Generate ReLU test case
X = test
Y = test.copy()
Y[Y < 0] = 0
yield X, Y
model = Sequential(
[Dense(1,
input_dim=1,
activation=None,
use_bias=False)
])
model.add(keras.layers.LeakyReLU(alpha=0.3))
model.set_weights([[[-10]]])
model.compile(loss='mean_squared_error', optimizer='sgd')
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.losses = []
self.weights = []
self.n = 0
self.n += 1
def on_epoch_end(self, batch, logs={}):
self.losses.append(logs.get('loss'))
w = model.get_weights()
self.weights.append([x.flatten()[0] for x in w])
self.n += 1
history = LossHistory()
model.fit_generator(tests(), steps_per_epoch=100, epochs=20,
callbacks=[history])
fig, (ax1, ax2) = plt.subplots(2, 1, True, num='Learning')
ax1.set_title('LeakyReLU learning ReLU')
ax1.semilogy(history.losses)
ax1.set_ylabel('Loss')
ax1.grid(True, which="both")
ax1.margins(0, 0.05)
ax2.plot(history.weights)
ax2.set_ylabel('Weight')
ax2.set_xlabel('Epoch')
ax2.grid(True, which="both")
ax2.margins(0, 0.05)
plt.tight_layout()
plt.show()
ความซับซ้อนอีกชั้นเกิดขึ้นจากความจริงที่ว่าเราไม่ได้เคลื่อนไหวอย่างไร้ขอบเขต แต่ใน "การกระโดด" และการกระโดดเหล่านี้จะนำเราจากการทำซ้ำครั้งต่อไป ซึ่งหมายความว่ามีบางสถานการณ์ที่ค่าลบเริ่มต้นของจะไม่ติด; กรณีเหล่านี้เกิดขึ้นสำหรับการรวมกันโดยเฉพาะอย่างยิ่งของและขนาดการไล่ระดับสีที่ลาดลงขนาดใหญ่พอที่จะ "กระโดด" เหนือการไล่ระดับสีที่หายไปw w ( 0 )w(0)
ฉันได้เล่นกับโค้ดนี้บ้างแล้วและฉันพบว่าการปล่อยให้ค่าเริ่มต้นที่และการเปลี่ยนออพติไมเซอร์จาก SGD เป็น Adam, Adam + AMSGrad หรือ SGD + ไม่ช่วยอะไรเลย ยิ่งกว่านั้นการเปลี่ยนจาก SGD เป็น Adam ทำให้ความคืบหน้าช้าลงและไม่ช่วยในการแก้ไขปัญหานี้w(0)=−10
ในทางกลับกันถ้าคุณเปลี่ยนค่าเริ่มต้นเป็นและเปลี่ยนเครื่องมือเพิ่มประสิทธิภาพเป็น Adam (ขนาดขั้นตอน 0.01) คุณสามารถเอาชนะการไล่ระดับสีที่หายไปได้จริง นอกจากนี้ยังใช้งานได้หากคุณใช้และ SGD พร้อมโมเมนตัม (ขนาดขั้นตอน 0.01) มันยังทำงานถ้าคุณใช้วานิลลา SGD (ขั้นตอนขนาด 0.01) และ 1w(0)=−1 w ( 0 ) = - 1 w ( 0 ) = - 1w(0)=−1w(0)=−1
รหัสที่เกี่ยวข้องอยู่ด้านล่าง ใช้หรือopt_sgd
opt_adam
opt_sgd = keras.optimizers.SGD(lr=1e-2, momentum=0.9)
opt_adam = keras.optimizers.Adam(lr=1e-2, amsgrad=True)
model.compile(loss='mean_squared_error', optimizer=opt_sgd)