वहाँ एक समारोह के रूप में नुकसान के अपने भूखंडों में एक संकेत है । इन भूखंडों के पास पास एक "किंक" है : ऐसा इसलिए है क्योंकि 0 के बाईं ओर, हानि की ढाल 0 पर गायब हो रही है (हालाँकि, एक उप-अपनाने वाला समाधान है क्योंकि नुकसान वहां से अधिक है जो )। इसके अलावा, इस साजिश से पता चलता है कि नुकसान फ़ंक्शन गैर-उत्तल है (आप एक रेखा खींच सकते हैं जो 3 या अधिक स्थानों में हानि वक्र को पार करता है), ताकि यह संकेत मिले कि हमें स्थानीय ऑप्टिमाइज़र जैसे कि डब्ल्यूडब्ल्यूडी का उपयोग करते समय सतर्क रहना चाहिए। वास्तव में, निम्नलिखित विश्लेषण से पता चलता है कि जब को नकारात्मक होने के लिए आरंभीकृत किया जाता है, तो एक उप-अपनाने वाले समाधान में परिवर्तित करना संभव है।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
जब आप शुरू करते हैं , तो आपको सही उत्तर के करीब आने के लिए के दूसरी ओर जाना होगा, जो । यह करना कठिन है, क्योंकि जब आपके पासबहुत, बहुत छोटा, ढाल वैसे ही गायब हो जाएगा छोटा है। इसके अलावा, आप बाईं ओर से 0 के करीब हो जाएंगे, आपकी प्रगति धीमी हो जाएगी!w<00w=1|w|
यही कारण है कि आपके प्लॉट्स में इनिशियलाइज़ेशन के लिए नेगेटिव , आपके ट्रैजेटरी सभी पास स्टाल करते हैं । यह वही है जो आपका दूसरा एनीमेशन दिखा रहा है।w(0)<0w(i)=0
यह मरने वाली रिले घटना से संबंधित है; कुछ चर्चा के लिए, मेरा ReLU नेटवर्क लॉन्च करने में विफल रहता है
एक दृष्टिकोण जो अधिक सफल हो सकता है, वह लीक रिल्यू के रूप में एक अलग नॉनलाइनियरिटी का उपयोग करना होगा, जिसमें तथाकथित "लुप्त होने वाली ढाल" मुद्दा नहीं है। टपका हुआ रिले समारोह है
g(x)={x,cx,if x>0otherwise
जहां एक स्थिरांक है तोछोटा और सकारात्मक है। इसका कारण यह है कि व्युत्पन्न कार्य 0 है "बाईं ओर।"c|c|
g′(x)={1,c,if x>0if x<0
सेट करना साधारण रिले है। ज्यादातर लोग का चयन कुछ ऐसे करते हैं जैसे या । मैंने उपयोग नहीं देखा है, हालांकि मैं इस बात का अध्ययन करना चाहूंगा कि इस तरह के नेटवर्क पर क्या प्रभाव पड़ता है, यदि कोई हो। (ध्यान दें कि यह पहचान फ़ंक्शन को कम कर देता है, के लिए; , ऐसी कई परतों की रचनाएं विस्फोटकों का कारण बन सकती हैं क्योंकि क्रमिक क्रमिक परतों में बड़े हो जाते हैं।)c=0c0.10.3c<0c=1,|c|>1
ओपी कोड को थोड़ा संशोधित करना एक प्रदर्शन प्रदान करता है कि समस्या सक्रियण फ़ंक्शन की पसंद के साथ है। यह कोड को ऋणात्मक बनाता है और साधारण के स्थान पर उपयोग करता है । नुकसान जल्दी से एक छोटे से मूल्य तक कम हो जाता है, और वजन सही ढंग से , जो कि इष्टतम है।wLeakyReLU
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)
मैंने इस कोड के साथ कुछ के आसपास खेला है और मैंने पाया है कि पर इनिशियलाइज़ेशन छोड़ रहा है और ऑप्टिमाइज़र को SGD से एडम, एडम + AMSGrad या SGD + गति में बदलने से मदद के लिए कुछ नहीं करता है। इसके अलावा, इस समस्या पर लुप्त होती प्रवणता को दूर करने में मदद नहीं करने के अलावा, एसडब्लूए से एडम को बदलने से वास्तव में प्रगति धीमी हो जाती है।w(0)=−10
दूसरी ओर, आप के लिए प्रारंभ बदलते हैं और एडम (कदम आकार 0.01) के लिए अनुकूलक बदलने के लिए, तो आप वास्तव में गायब हो जाने ढाल दूर कर सकते हैं। यह तब भी काम करता है जब आप और SGD को गति (चरण आकार 0.01) के साथ उपयोग करते हैं। यहां तक कि अगर आप वेनिला SGD (चरण आकार 0.01) और उपयोग करते हैं तो भी यह काम करता है ।w(0)=−1 w(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)