اسلاید قبلی
اسلاید بعدی

فصل ششم-معرفی بهینه سازی

معرفی بهینه سازی

اکنون که شبکه عصبی ساخته شده است، می تواند داده ها را از آن عبور دهد و قادر به محاسبه ضرر باشد، گام بعدی تعیین نحوه تنظیم وزن ها و بایاس ها برای کاهش تلفات است. یافتن روشی هوشمندانه برای تنظیم وزن و سوگیری ورودی نورون ها برای به حداقل رساندن ضرر، مشکل اصلی شبکه های عصبی است.

اولین گزینه ای که ممکن است به آن فکر کنید این است که به طور تصادفی وزن ها را تغییر دهید، ضرر را بررسی کنید و این کار را تکرار کنید تا زمانی که با کمترین ضرر یافت شده خوشحال شوید. برای دیدن این در عمل، ما از یک مجموعه داده ساده تر از آنچه تاکنون با آن کار کرده ایم استفاده خواهیم کرد:

import matplotlib.pyplot as plt

import nnfs

from nnfs.datasets import vertical_data

nnfs.init()

X, y = vertical_data(samples=100, classes=3)

plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=’brg’)

plt.show()

که به نظر می رسد:

شکل 6.01: “داده های عمودی” نمودار شده است.

با استفاده از کد ایجاد شده قبلی تا این مرحله، می توانیم از این مجموعه داده جدید با یک شبکه عصبی ساده استفاده کنیم:

# Create dataset

X, y = vertical_data(samples=100, classes=3)

# Create model

dense1 = Layer_Dense(2, 3)  # first dense layer, 2 inputs

activation1 = Activation_ReLU()

dense2 = Layer_Dense(3, 3)  # second dense layer, 3 inputs, 3 outputs

activation2 = Activation_Softmax()

# Create loss function

loss_function = Loss_CategoricalCrossentropy()

سپس چند متغیر برای ردیابی بهترین ضرر و وزن ها و سوگیری های مرتبط ایجاد کنید:

# Helper variables

lowest_loss = 9999999  # some initial value

best_dense1_weights = dense1.weights.copy()

best_dense1_biases = dense1.biases.copy()

best_dense2_weights = dense2.weights.copy()

best_dense2_biases = dense2.biases.copy()

ما ضرر را به مقدار زیادی مقداردهی اولیه کردیم و زمانی که ضرر جدید و پایین تر یافت شود، آن را کاهش خواهیم داد. ما همچنین وزن ها و تعصبات را کپی می کنیم ( copy()به جای ارجاع به شیء، یک کپی کامل را تضمین می کند). اکنون هر چند بار که می خواهیم تکرار می کنیم، مقادیر تصادفی را برای وزن ها و تعصبات انتخاب می کنیم و وزن ها و سوگیری ها را در صورت ایجاد کمترین ضرر ذخیره می کنیم:

for iteration in range(10000):

    # مجموعه جدیدی از وزن ها را برای تکرار ایجاد کنید

    dense1.weights = 0.05 * np.random.randn(2, 3)

    dense1.biases = 0.05 * np.random.randn(1, 3)

    dense2.weights = 0.05 * np.random.randn(3, 3)

    dense2.biases = 0.05 * np.random.randn(1, 3)

    # یک پاس رو به جلو از داده های آموزشی را از طریق این لایه انجام دهید

    dense1.forward(X)

    activation1.forward(dense1.output)

    dense2.forward(activation1.output)

    activation2.forward(dense2.output)

    # عملکرد فعال سازی را از طریق عبور رو به جلو انجام دهید

    # خروجی لایه متراکم دوم را در اینجا می گیرد و ضرر را برمی گرداند

    loss = loss_function.calculate(activation2.output, y)

    # محاسبه دقت از خروجی فعال سازی2 و اهداف

    # مقادیر را در امتداد محور اول محاسبه کنید

    predictions = np.argmax(activation2.output, axis=1)

    accuracy = np.mean(predictions==y)

    # اگر ضرر کمتر است – وزن ها و تعصبات را چاپ کرده و کنار بگذارید

    if loss < lowest_loss:

        print(‘New set of weights found, iteration:’, iteration,

              ‘loss:’, loss, ‘acc:’, accuracy)

        best_dense1_weights = dense1.weights.copy()

        best_dense1_biases = dense1.biases.copy()

        best_dense2_weights = dense2.weights.copy()

        best_dense2_biases = dense2.biases.copy()

        lowest_loss = loss

>>> 

New set of weights found, iteration: 0 loss: 1.0986564 acc: 0.3333333333333333

New set of weights found, iteration: 3 loss: 1.098138 acc: 0.3333333333333333

New set of weights found, iteration: 117 loss: 1.0980115 acc: 0.3333333333333333

New set of weights found, iteration: 124 loss: 1.0977516 acc: 0.6

New set of weights found, iteration: 165 loss: 1.097571 acc: 0.3333333333333333

New set of weights found, iteration: 552 loss: 1.0974693 acc: 0.34

New set of weights found, iteration: 778 loss: 1.0968257 acc: 0.3333333333333333

New set of weights found, iteration: 4307 loss: 1.0965533 acc: 0.3333333333333333

New set of weights found, iteration: 4615 loss: 1.0964499 acc: 0.3333333333333333

New set of weights found, iteration: 9450 loss: 1.0964295 acc: 0.3333333333333333

ضرر مطمئنا کاهش می یابد، اگرچه نه چندان. دقت بهبود نیافت، به جز یک وضعیت منحصر به فرد که در آن مدل به طور تصادفی مجموعه ای از وزن ها را با دقت بهتر پیدا کرد. با این حال، با ضرر نسبتا بزرگ، این وضعیت پایدار نیست. اجرای 90,000 تکرار اضافی برای 100,000 در مجموع:

New set of weights found, iteration: 13361 loss: 1.0963014 acc: 0.3333333333333333

New set of weights found, iteration: 14001 loss: 1.0959858 acc: 0.3333333333333333

New set of weights found, iteration: 24598 loss: 1.0947444 acc: 0.3333333333333333

ضرر همچنان کاهش یافت، اما دقت تغییر نکرد. به نظر نمی رسد این روش قابل اعتمادی برای به حداقل رساندن ضرر باشد. پس از اجرای 1 میلیارد تکرار، نتیجه زیر بهترین (کمترین ضرر) بود:

New set of weights found, iteration: 229865000 loss: 1.0911305 acc: 0.3333333333333333

حتی با این مجموعه داده اولیه، می بینیم که جستجوی تصادفی برای ترکیب وزن و سوگیری بسیار طولانی تر از آن است که یک روش قابل قبول باشد. ایده دیگر ممکن است این باشد که به جای تنظیم پارامترها با مقادیر تصادفی انتخاب شده در هر تکرار، کسری از این مقادیر را روی پارامترها اعمال کنید. با این کار، وزن ها از آنچه در حال حاضر کمترین ضرر را برای ما به همراه دارد به جای تصادفی بی هدف، به روز می شوند. اگر تنظیم ضرر را کاهش دهد، آن را به نقطه جدیدی برای تنظیم تبدیل می کنیم. اگر در عوض ضرر به دلیل تعدیل افزایش یابد، به نقطه قبلی باز می گردیم. با استفاده از کدهای مشابه قبلی، ابتدا از انتخاب تصادفی وزن ها و سوگیری ها به تنظیم تصادفی آنها تغییر می دهیم  :

    # وزن ها را با چند مقدار تصادفی کوچک به روز کنید

    dense1.weights += 0.05 * np.random.randn(2, 3)

    dense1.biases += 0.05 * np.random.randn(1, 3)

    dense2.weights += 0.05 * np.random.randn(3, 3)

    dense2.biases += 0.05 * np.random.randn(1, 3)

سپس پایانه خود را تغییر می دهیم اگر عبارت به صورت زیر است:

    # اگر ضرر کمتر است – وزن ها و تعصبات را چاپ کرده و کنار بگذارید

    if loss < lowest_loss:

        print(‘New set of weights found, iteration:’, iteration,

              ‘loss:’, loss, ‘acc:’, accuracy)

        best_dense1_weights = dense1.weights.copy()

        best_dense1_biases = dense1.biases.copy()

        best_dense2_weights = dense2.weights.copy()

        best_dense2_biases = dense2.biases.copy()

        lowest_loss = loss

    # وزن ها و سوگیری ها را برگردانید

    else:

        dense1.weights = best_dense1_weights.copy()

        dense1.biases = best_dense1_biases.copy()

        dense2.weights = best_dense2_weights.copy()

        dense2.biases = best_dense2_biases.copy()

 

کد کامل تا این مرحله:

# مجموعه داده ایجاد کنید

X, y = vertical_data(samples=100, classes=3)

# ایجاد مدل

dense1 = Layer_Dense(2, 3)  # اولین لایه متراکم، 2 ورودی

activation1 = Activation_ReLU()

dense2 = Layer_Dense(3, 3)  # لایه متراکم دوم، 3 ورودی، 3 خروجی

activation2 = Activation_Softmax()

# ایجاد عملکرد از دست دادن

loss_function = Loss_CategoricalCrossentropy()

# متغیرهای کمکی

lowest_loss = 9999999  # مقداری ارزش اولیه

best_dense1_weights = dense1.weights.copy()

best_dense1_biases = dense1.biases.copy()

best_dense2_weights = dense2.weights.copy()

best_dense2_biases = dense2.biases.copy()

for iteration in range(10000):

    # وزن ها را با چند مقدار تصادفی کوچک به روز کنید

    dense1.weights += 0.05 * np.random.randn(2, 3)

    dense1.biases += 0.05 * np.random.randn(1, 3)

    dense2.weights += 0.05 * np.random.randn(3, 3)

    dense2.biases += 0.05 * np.random.randn(1, 3)

    # یک پاس رو به جلو از داده های آموزشی خود را از طریق این لایه انجام دهید

    dense1.forward(X)

    activation1.forward(dense1.output)

    dense2.forward(activation1.output)

    activation2.forward(dense2.output)

    # عملکرد فعال سازی را از طریق عبور رو به جلو انجام دهید

    # خروجی لایه متراکم دوم را در اینجا می گیرد و ضرر را برمی گرداند

    loss = loss_function.calculate(activation2.output, y)

    # محاسبه دقت از خروجی فعال سازی2 و اهداف

    # مقادیر را در امتداد محور اول محاسبه کنید

    predictions = np.argmax(activation2.output, axis=1)

    accuracy = np.mean(predictions==y)

    # اگر ضرر کمتر است – وزن ها و تعصبات را چاپ کرده و کنار بگذارید

    if loss < lowest_loss:

        print(‘New set of weights found, iteration:’, iteration,

              ‘loss:’, loss, ‘acc:’, accuracy)

        best_dense1_weights = dense1.weights.copy()

        best_dense1_biases = dense1.biases.copy()

        best_dense2_weights = dense2.weights.copy()

        best_dense2_biases = dense2.biases.copy()

        lowest_loss = loss

    # وزن ها و سوگیری ها را برگردانید

    else:

        dense1.weights = best_dense1_weights.copy()

        dense1.biases = best_dense1_biases.copy()

        dense2.weights = best_dense2_weights.copy()

        dense2.biases = best_dense2_biases.copy()

>>> 

New set of weights found, iteration: 0 loss: 1.0987684 acc: 0.3333333333333333 …

New set of weights found, iteration: 29 loss: 1.0725244 acc: 0.5266666666666666

New set of weights found, iteration: 30 loss: 1.0724432 acc: 0.3466666666666667 …

New set of weights found, iteration: 48 loss: 1.0303522 acc: 0.6666666666666666

New set of weights found, iteration: 49 loss: 1.0292586 acc: 0.6666666666666666 …

New set of weights found, iteration: 97 loss: 0.9277446 acc: 0.7333333333333333 …

New set of weights found, iteration: 152 loss: 0.73390484 acc: 0.8433333333333334

New set of weights found, iteration: 156 loss: 0.7235515 acc: 0.87

New set of weights found, iteration: 160 loss: 0.7049076 acc: 0.9066666666666666 …

New set of weights found, iteration: 7446 loss: 0.17280102 acc:

0.9333333333333333

New set of weights found, iteration: 9397 loss: 0.17279711 acc: 0.93

این بار ضرر به میزان مناسبی کاهش یافت و دقت به میزان قابل توجهی افزایش یافت. استفاده از کسری از مقادیر تصادفی در واقع منجر به نتیجه ای می شود که تقریبا می توانیم آن را راه حل بنامیم. اگر 100000 تکرار را امتحان کنید، پیشرفت بیشتری نخواهید کرد:

>>> …

New set of weights found, iteration: 14206 loss: 0.1727932 acc:

0.9333333333333333

New set of weights found, iteration: 63704 loss: 0.17278232 acc:

0.9333333333333333

بیایید به جای آن این را با مجموعه داده مارپیچی که قبلا دیده شده بود امتحان کنیم:

# مجموعه داده ایجاد کنید

X, y = spiral_data(samples=100, classes=3)

>>> 

New set of weights found, iteration: 0 loss: 1.1008677 acc: 0.3333333333333333 …

New set of weights found, iteration: 31 loss: 1.0982264 acc: 0.37333333333333335 …

New set of weights found, iteration: 65 loss: 1.0954362 acc:

0.38333333333333336

New set of weights found, iteration: 67 loss: 1.093989 acc: 0.4166666666666667 …

New set of weights found, iteration: 129 loss: 1.0874122 acc: 0.42333333333333334 …

New set of weights found, iteration: 5415 loss: 1.0790575 acc: 0.39

این جلسه آموزشی تقریبا بدون هیچ پیشرفتی به پایان رسید. تلفات کمی کاهش یافت و دقت به سختی بالاتر از مقدار اولیه است. بعدا خواهیم فهمید که محتمل ترین دلیل این امر حداقل ضرر محلی نامیده می شود. پیچیدگی داده ها نیز در اینجا بی ربط نیست. به نظر می رسد که مشکلات سخت به دلایلی سخت هستند و ما باید هوشمندانه تر به این مشکل نزدیک شویم.

مواد تکمیلی: https://nnfs.io/ch6

کد فصل، منابع بیشتر و اشتباهات این فصل.

فصل 7 – مشتقات

فصل دهم-Optimizers

Optimizers هنگامی که شیب را محاسبه کردیم، می توانیم از این اطلاعات برای تنظیم وزن ها و بایاس ها برای کاهش اندازه گیری ضرر استفاده کنیم. در یک مثال اسباب بازی قبلی، ما نشان دادیم که چگونه می توانیم با موفقیت خروجی تابع فعال سازی نورون (ReLU) را به این روش کاهش دهیم. به یاد بیاورید که ما کسری از گرادیان را برای هر پارامتر وزن و بایاس کم کردیم. در حالی که بسیار ابتدایی است، اما هنوز هم یک بهینه ساز رایج به نام Stochastic Gradient Descent (SGD) است. همانطور که به زودی متوجه خواهید شد، اکثر بهینه سازها

فصل نهم-پس انتشار

پس انتشار اکنون که ایده ای در مورد نحوه اندازه گیری تأثیر متغیرها بر خروجی یک تابع داریم، می توانیم شروع به نوشتن کد برای محاسبه این مشتقات جزئی کنیم تا نقش آنها را در به حداقل رساندن تلفات مدل ببینیم. قبل از اعمال این در یک شبکه عصبی کامل، بیایید با یک پاس رو به جلو ساده شده تنها با یک نورون شروع کنیم. به جای پس انتشار از تابع از دست دادن برای یک شبکه عصبی کامل، بیایید تابع ReLU را برای یک نورون واحد پس انتشار کنیم و طوری عمل کنیم که گویی قصد داریم خروجی این

فصل هشتم-گرادیان ها، مشتقات جزئی و قانون زنجیره ای

گرادیان ها، مشتقات جزئی و قانون زنجیره ای دو تا از آخرین قطعات پازل، قبل از ادامه کدنویسی شبکه عصبی، مفاهیم مرتبط گرادیان ها و مشتقات جزئی هستند. مشتقاتی که تاکنون حل کرده ایم مواردی بوده اند که فقط یک متغیر مستقل در تابع وجود دارد – یعنی نتیجه فقط به x بستگی  دارد. با این حال ، شبکه عصبی ما به عنوان مثال از نورون ها تشکیل شده است که دارای ورودی های متعدد هستند. هر ورودی در وزن مربوطه ضرب می شود (تابعی از 2 پارامتر) ، و آنها با بایاس جمع می شوند (تابعی از پارامترهای به

فصل هفتم-مشتقات

مشتقات تغییر تصادفی و جستجوی وزن ها و سوگیری های بهینه به یک دلیل اصلی مثمر ثمر نبود: تعداد ترکیبات احتمالی وزن ها و سوگیری ها بی نهایت است و برای دستیابی به هر موفقیتی به چیزی هوشمندانه تر از شانس خالص نیاز داریم. هر وزن و سوگیری نیز ممکن است درجات مختلفی از تأثیر بر کاهش داشته باشد – این تأثیر به خود پارامترها و همچنین به نمونه فعلی بستگی دارد که ورودی لایه اول است. سپس این مقادیر ورودی در وزن ها ضرب می شوند، بنابراین داده های ورودی بر خروجی نورون تأثیر می گذارند و بر تأثیری

فصل پنجم-محاسبه خطای شبکه با ضرر

محاسبه خطای شبکه با ضرر با یک مدل که به طور تصادفی مقداردهی اولیه شده است، یا حتی مدلی که با رویکردهای پیچیده تر مقداردهی اولیه شده است، هدف ما آموزش یا آموزش یک مدل در طول زمان است. برای آموزش یک مدل، وزن ها و سوگیری ها را تغییر می دهیم تا دقت و اطمینان مدل را بهبود بخشیم. برای این کار محاسبه می کنیم که مدل چقدر خطا دارد. تابع ضرر که به آن تابع هزینه نیز گفته می شود، الگوریتمی است که میزان اشتباه بودن یک مدل را تعیین می کند. ضرر معیار این معیار است. از

فصل چهارم-توابع فعال سازی

توابع فعال سازی در این فصل، به چند مورد از توابع فعال سازی می پردازیم و نقش آنها را مورد بحث قرار می دهیم. ما از توابع فعال سازی متفاوتی برای موارد مختلف استفاده می کنیم و درک نحوه عملکرد آنها می تواند به شما کمک کند تا کدام یک از آنها را به درستی برای کارتان انتخاب کنید. عملکرد فعال سازی به خروجی یک نورون (یا لایه ای از نورون ها) اعمال می شود که خروجی ها را تغییر می دهد. ما از توابع فعال سازی استفاده می کنیم زیرا اگر تابع فعال سازی خود غیرخطی باشد، به شبکه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *