কেন একটি সিএলইউ একটি আরএলইউ শিখতে পারে না?


15

আমার নিউরাল নেটওয়ার্কের ফলোআপ হিসাবে ইউক্লিডিয়ান দূরত্বটি শিখতেও পারছে না আমি আরও বেশি সরল করেছি এবং একক রিলুতে (এলোমেলো ওজন সহ) একক আরএলইউতে প্রশিক্ষণের চেষ্টা করেছি। এটি সেখানে রয়েছে সহজতম নেটওয়ার্ক এবং তবুও এটি রূপান্তর করতে ব্যর্থ অর্ধেক সময়।

প্রাথমিক অনুমান যদি লক্ষ্য হিসাবে একই রকমের দিকে থাকে তবে তা দ্রুত শিখে এবং 1 এর সঠিক ওজনে রূপান্তরিত করে:

রিলু শেখার রিয়েলুজের অ্যানিমেশন

কনভার্জেন্স পয়েন্ট দেখাচ্ছে ক্ষতি বক্ররেখা

প্রাথমিক অনুমানটি যদি "পিছনের দিকে" হয় তবে এটি শূন্যের ওজনে আটকে যায় এবং এটি কখনই নিম্ন ক্ষতির অঞ্চলে যায় না:

ReLU অ্যানিমেশন রিলু শিখতে ব্যর্থ

ReLU শিখতে ব্যর্থ হয়েছে RLU এর ক্ষতির বক্ররেখা

ক্ষতি বক্ররেখার বন্ধ 0

আমি বুঝতে পারছি না কেন। গ্রেডিয়েন্ট বংশোদ্ভূতগুলি কী সহজেই বিশ্বব্যাপী মিনিমাতে লোকসানের বক্ররেখা অনুসরণ করে না?

উদাহরণ কোড:

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(ReLU())
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('ReLU 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()

এখানে চিত্র বর্ণনা লিখুন

অনুরূপ জিনিসগুলি যদি আমি পক্ষপাত যুক্ত করি তবে ঘটে থাকে: 2 ডি ক্ষতির ক্রিয়াটি মসৃণ এবং সহজ, তবে যদি রিলুটি উল্টে শুরু হয় তবে এটি চারদিকে বৃত্তাকার হয়ে যায় এবং আটকে যায় (লাল প্রারম্ভিক বিন্দু), এবং নূন্যতমের নিচে গ্রেডিয়েন্টটি অনুসরণ করে না (এটি পছন্দ করে) নীল শুরুর পয়েন্টগুলির জন্য):

এখানে চিত্র বর্ণনা লিখুন

যদি আমি আউটপুট ওজন এবং পক্ষপাতও যুক্ত করি তবে অনুরূপ জিনিসগুলি ঘটে। (এটি বাম থেকে ডানদিকে বা ডাউন-টু-আপ ফ্লিপ করবে তবে উভয়ই নয় not)


3
@ সাইকোরাক্স না এটি কোনও সদৃশ নয়, এটি একটি নির্দিষ্ট সমস্যা সম্পর্কে জিজ্ঞাসা করে, সাধারণ পরামর্শ নয়। আমি এটিকে একটি ন্যূনতম, সম্পূর্ণ এবং যাচাইযোগ্য উদাহরণে হ্রাস করতে উল্লেখযোগ্য পরিমাণ সময় ব্যয় করেছি। এটি কেবল মুছে ফেলবেন না কারণ এটি অন্য কিছু ওভার-ব্রড প্রশ্নের মতো অস্পষ্ট similar এই প্রশ্নের স্বীকৃত উত্তরের একটি পদক্ষেপ হ'ল "প্রথমে, একটি গোপন স্তর সহ একটি ছোট নেটওয়ার্ক তৈরি করুন এবং এটি সঠিকভাবে কাজ করে যাচাই করুন Then ঠিক এটিই আমি করছি এবং এটি কাজ করছে না।
এন্ডোলিথ

2
আমি এনএন-তে এই "সিরিজ "টি সত্যিই উপভোগ করছি সাধারণ ফাংশনগুলিতে প্রয়োগ: eats_popcorn_gif:
ক্যাম.ড্যাভিডসন.পিলন

রিলু একটি আদর্শ সংশোধক যেমন ডায়োডের মতো কাজ করে। এটি একমুখী আপনি যদি দিকটি সংশোধন করতে চান তবে সফটপ্লাস ব্যবহারের বিষয়ে বিবেচনা করুন, তারপরে প্রশিক্ষণটি ইতিবাচক হলে রিলিউতে স্যুইচ করুন, বা ELU এর মতো অন্য কোনও রূপ ব্যবহার করুন।
কার্ল

এটি অন্য উপায়ে বলতে গেলে, একটি রিলিউইউ জন্য অকেজো বলে আশা করা হচ্ছে , জন্য শেখার দিকে তাকান ; এটি সমতল, এটি শিখছে না। x < 0x<0x<0
কার্ল

1
গ্রেডিয়েন্ট শূন্যের নীচে জন্য শূন্যের দিকে ঝোঁক; এটা স্টল। x
কার্ল

উত্তর:


14

ww=0w=0w=1w নেতিবাচক হতে শুরু করা হয়, একটি suboptimal সমাধান রূপান্তর করা সম্ভব।

minw,bf(x)y22f(x)=max(0,wx+b)

এবং আপনি এটি করতে ফার্স্ট-অর্ডার অপ্টিমাইজেশন ব্যবহার করছেন। এই পদ্ধতির সাথে একটি সমস্যা হ'ল এর গ্রেডিয়েন্ট রয়েছেf

f(x)={w,if x>00,if x<0

আপনি যখন দিয়ে শুরু করবেন তখন সঠিক উত্তরটির নিকটে আসতে আপনাকে এর অন্য দিকে যেতে হবে, যা । এটি করা শক্ত, কারণ যখন আপনারখুব, খুব ছোট, গ্রেডিয়েন্টটি তেমনি ছোট হয়ে যাবে। তদুপরি, আপনি বাম দিক থেকে 0 এর কাছাকাছি যাবেন, আপনার অগ্রগতি ধীর হবে!w<00w=1|w|

এই কারণেই আপনার আরম্ভের জন্য প্লটগুলিতে negative , আপনার ট্রাজেক্টরিগুলি নিকটে রয়েছে । এটি আপনার দ্বিতীয় অ্যানিমেশনটিও প্রদর্শিত হচ্ছে।w(0)<0w(i)=0

এটি ডাইং রিলু ঘটনাটির সাথে সম্পর্কিত; কিছু আলোচনার জন্য, দেখুন আমার আরএলইউ নেটওয়ার্ক চালু করতে ব্যর্থ

আরও সফল হতে পারে এমন একটি দৃষ্টিভঙ্গি হ'ল আলগা রেলুর মতো ভিন্ন ভিন্ন লাইন ব্যবহার করা, এতে তথাকথিত "বিলুপ্ত গ্রেডিয়েন্ট" সমস্যা নেই। ফুটো রিলু ফাংশন হয়

g(x)={x,if x>0cx,otherwise
যেখানে একটি ধ্রুবক যাতেছোট এবং ধনাত্মক। যে কারণে এটি কাজ করে তা ডেরাইভেটিভ 0 "বাম দিকে" নয়।c|c|

g(x)={1,if x>0c,if x<0

নির্ধারণ করা সাধারণ রিলু। বেশিরভাগ লোক বা বা মতো কিছু হতে পছন্দ করে । আমি ব্যবহৃত দেখিনি , যদিও আমি এই জাতীয় নেটওয়ার্কগুলিতে এর প্রভাব কী, যদি তা হয় তবে তার গবেষণা সম্পর্কে আগ্রহী হতে চাই। (দ্রষ্টব্য যে জন্য এটি সনাক্তকরণের ক্রিয়াকে হ্রাস করে;; , এই জাতীয় অনেক স্তরগুলির সংমিশ্রণগুলি বিস্ফোরিত গ্রেডিয়েন্টের কারণ হতে পারে কারণ গ্রেডিয়েন্টগুলি ধারাবাহিক স্তরগুলিতে বৃহত্তর হয়))c=0c0.10.3c<0c=1,|c|>1

ওপির কোডটি সামান্যভাবে সংশোধন করা একটি বিক্ষোভ সরবরাহ করে যে বিষয়টি সক্রিয়করণ ফাংশনটির নির্বাচনের সাথে সম্পর্কিত। এই কোডটি ডাব্লুকে নেতিবাচক হতে শুরু করে এবং জায়গায় ব্যবহার করে । ক্ষয়টি দ্রুত একটি অল্প মূল্যে হ্রাস পায় এবং ওজন সঠিকভাবে চলে যায় , যা সর্বোত্তম।wLeakyReLUReLUw=1

LeakyReLU সমস্যার সমাধান করে

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()

জটিলতার আরও একটি স্তর এই উত্থাপিত হয়েছিল যে আমরা অনাদিকালীনভাবে চলছি না, বরং চূড়ান্তভাবে অনেকগুলি "লাফিয়ে", এবং এই জাম্পগুলি আমাদের এক পুনরাবৃত্তি থেকে পরের দিকে নিয়ে যায়। কিছু পরিস্থিতিতে আছে এই উপায়ে যেখানে নেতিবাচক প্রাথমিক vales করা হবে না আটকে যান; এই কেসগুলি particular এবং গ্রেডিয়েন্ট বংশোদ্ভূত পদক্ষেপের মাপগুলি বিন্যাসযোগ্য গ্রেডিয়েন্টের উপর "জাম্প" করার জন্য যথেষ্ট বড় আকারের সংমিশ্রণের জন্য উত্থিত হয় ।w w(0)

আমি এই কোডটির সাথে কিছুটা খেলেছি এবং আমি দেখতে পেয়েছি যে ডাব্লু এ আরম্ভকরণটি ছেড়ে যাওয়া এবং এসজিডি থেকে অ্যাডাম, অ্যাডাম + এএমএসগ্র্যাড বা এসজিডি + গতিবেগকে অপ্টিমাইজার পরিবর্তন করা সাহায্য করার পক্ষে কিছুই করে না। তদ্ব্যতীত, এসজিডি থেকে অ্যাডামে পরিবর্তন আসলে এই সমস্যাটির অদৃশ্য গ্রেডিয়েন্টকে অতিক্রম করতে সহায়তা না করার পাশাপাশি অগ্রগতিটি ধীর করে দেয়w(0)=10

অন্যদিকে, আপনাকে আরম্ভের পরিবর্তন এবং আদম (ধাপ আকার 0.01) এর অপটিমাইজার পরিবর্তন করেন, তারপর আপনি আসলে অন্তর্ধান গ্রেডিয়েন্ট পরাস্ত করতে পারেন। যদি আপনি এবং এসজিডি গতিবেগ (পদক্ষেপের আকার 0.01) ব্যবহার করেন তবে এটিও কাজ করে । এমনকি আপনি ভ্যানিলা এসজিডি (পদক্ষেপের আকার 0.01) এবং ব্যবহার করলেও এটি কাজ করে ।w(0)=1 ডাব্লু ( 0 ) = - 1 ডাব্লু ( 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)

আমি যখন আউটপুট ওজন এবং পক্ষপাতিত্ব করেছি তখন আমি LeakyReLU, ELU, SELU- তে একই সমস্যা দেখেছি, তবে আমি নিশ্চিত না যে আমি আউটপুট ছাড়াই চেষ্টা করেছি কিনা। আমি চেক করব
এন্ডোলিথ

1
(হ্যাঁ, আপনি ঠিক বলেছেন যে এই উদাহরণটির জন্য LeakyReLU এবং ELU খুব ভাল কাজ করেছে)
এন্ডোলিথ

2
ওহ আমি এটা বুঝতে পেরেছি. এটা তোলে হয় ক্ষয় ফাংশনের গ্রেডিয়েন্ট বংশদ্ভুত করছেন, এটা ঠিক যে ক্ষতি ফাংশন তাই গ্রেডিয়েন্ট বংশদ্ভুত সেখানে আটকে পায় ফ্ল্যাট (0 গ্রেডিয়েন্ট) 0 এ হয়ে যখন নেতিবাচক পার্শ্ব থেকে এসে পড়েছে, না। এখন এটা সুস্পষ্ট বলে মনে হচ্ছে। : ডি
এন্ডোলিথ

2
যথাযথভাবে। আপনার ক্ষতির বনাম ডাব্লু কীভাবে 0 এর কাছাকাছি একটি "কিঙ্ক" রয়েছে তা লক্ষ্য করুন: এটি কারণ 0 এর বাম দিকে, ক্ষতির গ্রেডিয়েন্ট 0টি অদৃশ্য হয়ে যাচ্ছে (তবে, এটি একটি সাবঅপটিমাল সমাধান কারণ ক্ষতির চেয়ে সেখানে ক্ষতি আরও বেশি জন্য )। তদুপরি, এই প্লটটি দেখায় যে ক্ষতির ফাংশনটি নন-উত্তল (আপনি একটি লাইন আঁকতে পারেন যা ক্ষতি বা বক্ররেখা 3 বা ততোধিক স্থানে অতিক্রম করে), যাতে সিগন্যাল দেয় যে এসজিডি-র মতো স্থানীয় অপ্টিমাইজার ব্যবহার করার সময় আমাদের সতর্ক হওয়া উচিত। ডাব্লু = 0ww=0
সাইকোরাক্স 21

2
Relu অ্যাক্টিভেশন ব্যবহারের সময়, এমনকি SGD ছাড়া ভরবেগ ঠোঁটের উপর যেতে পারে, যদি ধাপ আকারের যাই হোক না কেন সুনির্দিষ্ট মানের জন্য বড় যথেষ্ট । w(i)
সাইকোরাক্স মনিকাকে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.