শেখার হার গভীর শিক্ষার নেটওয়ার্কে একটি গুরুত্বপূর্ণ হাইপারপ্যারামিটার - এবং এটি সরাসরি নির্দেশ করে ডিগ্রী যার জন্য ওজনের আপডেটগুলি সঞ্চালিত হয়, যা কিছু প্রদত্ত ক্ষতি ফাংশন কমিয়ে আনতে অনুমান করা হয়। এসজিডিতে:
$$
weight_{t+1} = weight_t – lr * frac{derror}{dweight_t}
$$
একটি শেখার হার সঙ্গে 0
, আপডেট করা ওজন ঠিক নিজের কাছে ফিরে এসেছে - ওজনt. শেখার হার কার্যকরীভাবে একটি ঠোঁট যা আমরা শেখার সক্ষম বা অক্ষম করতে পারি, এবং ওজন আপডেটের মাত্রা সরাসরি নিয়ন্ত্রণ করে কতটা শেখা হচ্ছে তার উপর এটির বড় প্রভাব রয়েছে।
বিভিন্ন অপ্টিমাইজাররা শেখার হার ভিন্নভাবে ব্যবহার করে – কিন্তু অন্তর্নিহিত ধারণা একই থাকে। বলা বাহুল্য, শেখার হার অনেক অধ্যয়ন, কাগজপত্র এবং অনুশীলনকারীর বেঞ্চমার্কের বস্তু হয়েছে।
সাধারণভাবে বলতে গেলে, মোটামুটি সবাই একমত যে একটি স্ট্যাটিক শেখার হার এটিকে কাটবে না, এবং বেশিরভাগ কৌশলগুলিতে কিছু ধরণের শেখার হার হ্রাস ঘটে যা প্রশিক্ষণের সময় শেখার হারকে সুর করে – এটি একটি একঘেয়ে, কোসাইন, ত্রিভুজাকার বা অন্যান্য ধরণের হ্রাস
একটি কৌশল যা সাম্প্রতিক বছরগুলিতে পা রাখা হয়েছে শেখার হার ওয়ার্মআপ, যা কার্যত অন্য কোন হ্রাস কৌশলের সাথে যুক্ত করা যেতে পারে।
শেখার হার ওয়ার্মআপ
শেখার হার গরম করার পিছনে ধারণা সহজ. প্রশিক্ষণের প্রাথমিক পর্যায়ে - ওজন তাদের আদর্শ অবস্থা থেকে অনেক দূরে। এর অর্থ হল পুরো বোর্ড জুড়ে বড় আপডেটগুলি, যা প্রতিটি ওজনের জন্য "অতিসংশোধন" হিসাবে দেখা যেতে পারে - যেখানে অন্যটির কঠোর আপডেট অন্য কিছু ওজনের আপডেটকে অস্বীকার করতে পারে, প্রশিক্ষণের প্রাথমিক স্তরগুলিকে আরও অস্থির করে তোলে।
এই পরিবর্তনগুলি লোহা আউট, কিন্তু শুরু করার জন্য একটি ছোট শেখার হার, একটি আরও স্থিতিশীল সাবঅপ্টিমাল অবস্থায় পৌঁছানোর এবং তারপর একটি বৃহত্তর শেখার হার প্রয়োগ করে এড়ানো যেতে পারে। আপনি আপডেটে নেটওয়ার্ক সহজ করতে পারেন, বরং তাদের সাথে এটি আঘাত.
এটা শেখার হার ওয়ার্মআপ! একটি কম (বা 0) শেখার হার দিয়ে শুরু করা এবং একটি প্রাথমিক শেখার হারে বৃদ্ধি করা (যাই হোক আপনি যা দিয়ে শুরু করবেন)। এই বৃদ্ধি সত্যিই যে কোনো ফাংশন অনুসরণ করতে পারে, কিন্তু সাধারণত রৈখিক।
প্রাথমিক হারে পৌঁছানোর পর, অন্যান্য সময়সূচী যেমন কোসাইন ক্ষয়, রৈখিক হ্রাস, ইত্যাদি প্রয়োগ করা যেতে পারে প্রশিক্ষণের শেষ না হওয়া পর্যন্ত ধীরে ধীরে হার কমাতে। লার্নিং রেট ওয়ার্মআপ সাধারণত একটি দুই-শিডিউলের সময়সূচীর অংশ, যেখানে LR ওয়ার্মআপ প্রথম হয়, যখন হার একটি সূচনা বিন্দুতে পৌঁছানোর পরে আরেকটি সময়সূচী গ্রহণ করে।
এই নির্দেশিকায়, আমরা কেরাস/টেনসরফ্লো-এ একটি লার্নিং রেট ওয়ার্মআপ প্রয়োগ করব keras.optimizers.schedules.LearningRateSchedule
উপশ্রেণী এবং keras.callbacks.Callback
কলব্যাক থেকে শেখার হার বাড়ানো হবে 0
থেকে target_lr
এবং কোসাইন ক্ষয় প্রয়োগ করুন, কারণ এটি একটি খুব সাধারণ মাধ্যমিক সময়সূচী। যথারীতি, কেরাস বিভিন্ন উপায়ে নমনীয় সমাধানগুলি বাস্তবায়ন করা এবং সেগুলিকে আপনার নেটওয়ার্কের সাথে প্রেরণ করা সহজ করে তোলে।
বিঃদ্রঃ: বাস্তবায়ন জেনেরিক এবং দ্বারা অনুপ্রাণিত হয় টনির কেরাস বাস্তবায়ন কৌশলগুলির মধ্যে "কনভোল্যুশনাল নিউরাল নেটওয়ার্কের সাথে ইমেজ ক্লাসিফিকেশনের জন্য ব্যাগ অফ ট্রিক্স”.
কেরাস কলব্যাকের সাথে শেখার হার
যেকোনো শেখার হারের সময়সূচী বাস্তবায়নের সবচেয়ে সহজ উপায় হল একটি ফাংশন তৈরি করা যা lr
প্যারামিটার (float32
), কিছু রূপান্তরের মধ্য দিয়ে এটি পাস করে এবং এটি ফেরত দেয়। এই ফাংশন তারপর পাস করা হয় LearningRateScheduler
কলব্যাক, যা শেখার হারে ফাংশন প্রয়োগ করে।
এখন tf.keras.callbacks.LearningRateScheduler()
এটি শেখার হার গণনা করার জন্য যে ফাংশনটি ব্যবহার করে তাতে যুগের সংখ্যা পাস করে, যা বেশ মোটা। প্রতিটিতে এলআর ওয়ার্মআপ করা উচিত ধাপ (ব্যাচ), epoch নয়, তাই আমাদের একটি বের করতে হবে global_step
(সমস্ত যুগ জুড়ে) পরিবর্তে শেখার হার গণনা করতে, এবং সাবক্লাস করুন Callback
শুধুমাত্র ফাংশন পাস করার পরিবর্তে একটি কাস্টম কলব্যাক তৈরি করার জন্য ক্লাস, যেহেতু আমাদের প্রতিটি কলে আর্গুমেন্ট পাস করতে হবে, যা শুধুমাত্র ফাংশন পাস করার সময় অসম্ভব:
def func():
return ...
keras.callbacks.LearningRateScheduler(func)
এই পদ্ধতিটি অনুকূল হয় যখন আপনি উচ্চ-স্তরের কাস্টমাইজেশন চান না এবং আপনি কেরাস যেভাবে আচরণ করে তাতে হস্তক্ষেপ করতে চান না lr
, এবং বিশেষ করে যদি আপনি কলব্যাক ব্যবহার করতে চান ReduceLROnPlateau()
যেহেতু এটি শুধুমাত্র একটি ফ্লোট-ভিত্তিক সাথে কাজ করতে পারে lr
. আসুন একটি সুবিধার ফাংশন দিয়ে শুরু করে কেরাস কলব্যাক ব্যবহার করে একটি শেখার হার ওয়ার্মআপ প্রয়োগ করি:
def lr_warmup_cosine_decay(global_step,
warmup_steps,
hold = 0,
total_steps=0,
start_lr=0.0,
target_lr=1e-3):
learning_rate = 0.5 * target_lr * (1 + np.cos(np.pi * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))
warmup_lr = target_lr * (global_step / warmup_steps)
if hold > 0:
learning_rate = np.where(global_step > warmup_steps + hold,
learning_rate, target_lr)
learning_rate = np.where(global_step < warmup_steps, warmup_lr, learning_rate)
return learning_rate
প্রতিটি ধাপে, আমরা শেখার হার এবং ওয়ার্মআপ শেখার হার (সূচির উভয় উপাদান) গণনা করি, start_lr
এবং target_lr
. start_lr
সাধারণত শুরু হবে 0.0
যখন target_lr
আপনার নেটওয়ার্ক এবং অপ্টিমাইজারের উপর নির্ভর করে - 1e-3
একটি ভাল ডিফল্ট নাও হতে পারে, তাই পদ্ধতিতে কল করার সময় আপনার লক্ষ্য শুরু LR সেট করতে ভুলবেন না।
যদি global_step
প্রশিক্ষণে এর চেয়ে বেশি warmup_steps
আমরা সেট করেছি - আমরা কোসাইন ক্ষয় শিডিউল এলআর ব্যবহার করি। যদি না হয়, তাহলে এর মানে হল যে আমরা এখনও ওয়ার্ম আপ করছি, তাই ওয়ার্মআপ এলআর ব্যবহার করা হয়। যদি hold
যুক্তি সেট করা হয়েছে, আমরা ধরে রাখব target_lr
ওয়ার্মআপের পরে এবং কোসাইন ক্ষয়ের আগে এই সংখ্যক পদক্ষেপের জন্য। np.where()
এই জন্য একটি মহান সিনট্যাক্স প্রদান করে:
np.where(condition, value_if_true, value_if_false)
আপনি এর সাথে ফাংশনটি কল্পনা করতে পারেন:
steps = np.arange(0, 1000, 1)
lrs = []
for step in steps:
lrs.append(lr_warmup_cosine_decay(step, total_steps=len(steps), warmup_steps=100, hold=10))
plt.plot(lrs)
এখন, আমরা কলব্যাকের একটি অংশ হিসাবে এই ফাংশনটি ব্যবহার করতে চাই এবং অপ্টিমাইজার ধাপটি পাস করতে চাই global_step
একটি নির্বিচারে অ্যারের একটি উপাদানের পরিবর্তে – অথবা আপনি ক্লাসের মধ্যে গণনা করতে পারেন। এর সাবক্লস করা যাক Callback
শ্রেণী:
from keras import backend as K
class WarmupCosineDecay(keras.callbacks.Callback):
def __init__(self, total_steps=0, warmup_steps=0, start_lr=0.0, target_lr=1e-3, hold=0):
super(WarmupCosineDecay, self).__init__()
self.start_lr = start_lr
self.hold = hold
self.total_steps = total_steps
self.global_step = 0
self.target_lr = target_lr
self.warmup_steps = warmup_steps
self.lrs = []
def on_batch_end(self, batch, logs=None):
self.global_step = self.global_step + 1
lr = model.optimizer.lr.numpy()
self.lrs.append(lr)
def on_batch_begin(self, batch, logs=None):
lr = lr_warmup_cosine_decay(global_step=self.global_step,
total_steps=self.total_steps,
warmup_steps=self.warmup_steps,
start_lr=self.start_lr,
target_lr=self.target_lr,
hold=self.hold)
K.set_value(self.model.optimizer.lr, lr)
সেরা-অভ্যাস, শিল্প-স্বীকৃত মান এবং অন্তর্ভুক্ত চিট শীট সহ গিট শেখার জন্য আমাদের হ্যান্ডস-অন, ব্যবহারিক গাইড দেখুন। গুগলিং গিট কমান্ড এবং আসলে বন্ধ করুন শেখা এটা!
প্রথমত, আমরা ক্লাসের জন্য কনস্ট্রাক্টরকে সংজ্ঞায়িত করি এবং এর ক্ষেত্রগুলির উপর নজর রাখি। শেষ হওয়া প্রতিটি ব্যাচে, আমরা বিশ্বব্যাপী পদক্ষেপ বাড়াব, বর্তমান LR নোট করব এবং এটিকে এখন পর্যন্ত LR-এর তালিকায় যুক্ত করব। প্রতিটি ব্যাচের শুরুতে - আমরা ব্যবহার করে এলআর গণনা করব lr_warmup_cosine_decay()
ফাংশন এবং সেই LR কে অপ্টিমাইজারের বর্তমান LR হিসাবে সেট করুন। এই ব্যাকএন্ড এর সঙ্গে সম্পন্ন করা হয় set_value()
.
এটি হয়ে গেলে - কেবলমাত্র মোট ধাপগুলি গণনা করুন (দৈর্ঘ্য/ব্যাচ_সাইজ* যুগ) এবং আপনার জন্য সেই সংখ্যার একটি অংশ নিন warmup_steps
:
total_steps = len(train_set)*config['EPOCHS']
warmup_steps = int(0.05*total_steps)
callback = WarmupCosineDecay(total_steps=total_steps,
warmup_steps=warmup_steps,
hold=int(warmup_steps/2),
start_lr=0.0,
target_lr=1e-3)
অবশেষে, আপনার মডেল তৈরি করুন এবং কলব্যাক প্রদান করুন fit()
কল:
model = keras.applications.EfficientNetV2B0(weights=None,
classes=n_classes,
input_shape=[224, 224, 3])
model.compile(loss="sparse_categorical_crossentropy",
optimizer='adam',
jit_compile=True,
metrics=['accuracy'])
প্রশিক্ষণ শেষে, আপনি এর মাধ্যমে পরিবর্তিত এলআরগুলি পেতে এবং কল্পনা করতে পারেন:
lrs = callback.lrs
plt.plot(lrs)
আপনি যদি LR ওয়ার্মআপ সহ এবং ছাড়া প্রশিক্ষিত একটি মডেলের ইতিহাস প্লট করেন - আপনি প্রশিক্ষণের স্থায়িত্বের মধ্যে একটি স্বতন্ত্র পার্থক্য দেখতে পাবেন:
LearningRateSchedule সাবক্লাস সহ শেখার হার
একটি কলব্যাক তৈরি করার একটি বিকল্প হল একটি তৈরি করা LearningRateSchedule
সাবক্লাস, যা LR কে ম্যানিপুলেট করে না - এটি প্রতিস্থাপন করে। এই পদ্ধতির সাহায্যে আপনি কেরাস/টেনসরফ্লো-এর ব্যাকএন্ডে আরও কিছুটা এগিয়ে যেতে পারবেন, কিন্তু যখন ব্যবহার করা হবে, তখন অন্য এলআর-সম্পর্কিত কলব্যাকের সাথে একত্রিত করা যাবে না, যেমন ReduceLROnPlateau()
, যা ফ্লোটিং পয়েন্ট সংখ্যা হিসাবে LR-এর সাথে ডিল করে।
অতিরিক্তভাবে, সাবক্লাস ব্যবহার করার জন্য আপনাকে এটিকে সিরিয়ালাইজেবল করতে হবে (ওভারলোড get_config()
) এটি মডেলের একটি অংশ হয়ে ওঠে, যদি আপনি মডেলের ওজন সংরক্ষণ করতে চান। আরেকটি বিষয় লক্ষণীয় যে ক্লাসটি একচেটিয়াভাবে কাজ করার আশা করবে tf.Tensor
s সৌভাগ্যক্রমে, আমরা যেভাবে কাজ করি তার মধ্যে একমাত্র পার্থক্য কল করা হবে tf.func()
পরিবর্তে np.func()
যেহেতু TensorFlow এবং NumPy APIগুলি আশ্চর্যজনকভাবে একই রকম এবং সামঞ্জস্যপূর্ণ।
এর সুবিধার আউট পুনর্লিখন করা যাক lr_warmup_cosine_decay()
পরিবর্তে TensorFlow অপারেশন ব্যবহার করার জন্য ফাংশন:
def lr_warmup_cosine_decay(global_step,
warmup_steps,
hold = 0,
total_steps=0,
start_lr=0.0,
target_lr=1e-3):
learning_rate = 0.5 * target_lr * (1 + tf.cos(tf.constant(np.pi) * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))
warmup_lr = target_lr * (global_step / warmup_steps)
if hold > 0:
learning_rate = tf.where(global_step > warmup_steps + hold,
learning_rate, target_lr)
learning_rate = tf.where(global_step < warmup_steps, warmup_lr, learning_rate)
return learning_rate
কনভিনিয়েন্স ফাংশনের সাহায্যে আমরা সাবক্লাস করতে পারি LearningRateSchedule
ক্লাস প্রতিটি __call__()
(ব্যাচ), আমরা ফাংশন ব্যবহার করে LR গণনা করব এবং এটি ফেরত দেব। আপনি স্বাভাবিকভাবেই সাবক্লাসড ক্লাসের মধ্যে গণনা প্যাকেজ করতে পারেন।
সিনট্যাক্স এর চেয়ে পরিষ্কার Callback
sublcass, প্রাথমিকভাবে কারণ আমরা অ্যাক্সেস পেতে step
ক্ষেত্র, আমাদের নিজের থেকে এটির ট্র্যাক রাখার পরিবর্তে, কিন্তু এটিকে শ্রেণি বৈশিষ্ট্যগুলির সাথে কাজ করা কিছুটা কঠিন করে তোলে - বিশেষত, এটি বের করা কঠিন করে তোলে lr
একটি থেকে tf.Tensor()
একটি তালিকায় ট্র্যাক রাখতে অন্য কোনো ধরনের মধ্যে. এটি আগ্রহী মোডে চালানোর মাধ্যমে প্রযুক্তিগতভাবে ঠেকানো যেতে পারে, তবে ডিবাগিংয়ের উদ্দেশ্যে এলআর ট্র্যাক রাখার জন্য একটি বিরক্তি উপস্থাপন করে এবং এড়ানো যায়:
class WarmUpCosineDecay(keras.optimizers.schedules.LearningRateSchedule):
def __init__(self, start_lr, target_lr, warmup_steps, total_steps, hold):
super().__init__()
self.start_lr = start_lr
self.target_lr = target_lr
self.warmup_steps = warmup_steps
self.total_steps = total_steps
self.hold = hold
def __call__(self, step):
lr = lr_warmup_cosine_decay(global_step=step,
total_steps=self.total_steps,
warmup_steps=self.warmup_steps,
start_lr=self.start_lr,
target_lr=self.target_lr,
hold=self.hold)
return tf.where(
step > self.total_steps, 0.0, lr, name="learning_rate"
)
পরামিতিগুলি একই, এবং আগের মতো একইভাবে গণনা করা যেতে পারে:
total_steps = len(train_set)*config['EPOCHS']
warmup_steps = int(0.05*total_steps)
schedule = WarmUpCosineDecay(start_lr=0.0, target_lr=1e-3, warmup_steps=warmup_steps, total_steps=total_steps, hold=warmup_steps)
এবং প্রশিক্ষণ পাইপলাইন শুধুমাত্র পার্থক্য যে আমরা অপ্টিমাইজারের LR সেট schedule
:
model = keras.applications.EfficientNetV2B0(weights=None,
classes=n_classes,
input_shape=[224, 224, 3])
model.compile(loss="sparse_categorical_crossentropy",
optimizer=tf.keras.optimizers.Adam(learning_rate=schedule),
jit_compile=True,
metrics=['accuracy'])
history3 = model.fit(train_set,
epochs = config['EPOCHS'],
validation_data=valid_set)
আপনি মডেল সংরক্ষণ করতে চান, WarmupCosineDecay
সময়সূচী ওভাররাইড করতে হবে get_config()
পদ্ধতি:
def get_config(self):
config = {
'start_lr': self.start_lr,
'target_lr': self.target_lr,
'warmup_steps': self.warmup_steps,
'total_steps': self.total_steps,
'hold': self.hold
}
return config
অবশেষে, মডেল লোড করার সময়, আপনাকে একটি পাস করতে হবে WarmupCosineDecay
একটি কাস্টম বস্তু হিসাবে:
model = keras.models.load_model('weights.h5',
custom_objects={'WarmupCosineDecay', WarmupCosineDecay})
উপসংহার
এই নির্দেশিকায়, আমরা লার্নিং রেট ওয়ার্মআপের পিছনের অন্তর্দৃষ্টির দিকে নজর দিয়েছি – নিউরাল নেটওয়ার্কগুলিকে প্রশিক্ষণের সময় শেখার হারকে ম্যানিপুলেট করার একটি সাধারণ কৌশল।
আমরা কোসাইন ক্ষয় সহ লার্নিং রেট ওয়ার্মআপ প্রয়োগ করেছি, ওয়ার্মআপের সাথে যুক্ত সবচেয়ে সাধারণ ধরনের LR হ্রাস। আপনি কমানোর জন্য অন্য কোনো ফাংশন বাস্তবায়ন করতে পারেন, বা শেখার হার একেবারেই কমাতে পারবেন না – এটিকে অন্যান্য কলব্যাকগুলিতে ছেড়ে দেওয়া যেমন ReduceLROnPlateau()
. আমরা কেরাস কলব্যাক, সেইসাথে কেরাস অপ্টিমাইজার সময়সূচী হিসাবে শেখার হার ওয়ার্মআপ প্রয়োগ করেছি এবং যুগের মাধ্যমে শেখার হার প্লট করেছি।