هوش مصنوعی ۶۲۷۹ بازدید

بنابر «قضیه عمومی تقریب» (Universal Approximation Theorem)، در صورتی که تعداد مناسبی از لایه‌ها (لایه‌های نهان) در «شبکه های عصبی مصنوعی» (Artificial Neural Networks) طراحی شود و «حاشیه خطای» (Error Margin) مطلوبی برای این دسته از الگوریتم‌های حوزه «هوش مصنوعی» (Artificial Intelligence) و «یادگیری ماشین» (Machine Learning) تعریف شود، این مدل‌ها قادر هستند تا هر نوع «تابعی» (Function) را تقریب بزنند، یاد بگیرند و نمایش دهند.

شبکه های عصبی مصنوعی چند لایه، معمولا با استفاده از مدل‌سازی یک نمایش‌‌ پیچیده روی نمایش‌های ساده‌تر از داده‌ها، رفتار توابع و مدلسازی یک «تابع واقعی» (True Function) مبتنی بر داده را یاد می‌گیرند. منظور از تابع واقعی، مدل تابعی است که می‌تواند داده‌های مسئله را به بهترین شکل ممکن دسته‌بندی کند.

در هر کدام از «لایه‌های نهان» (Hidden Layers) تعبیه شده در مدل‌های شبکه عصبی، ابتدا با استفاده از یک «تبدیل خطی» (Linear Transformation) از داده‌های ورودی داده شده و در مرحله بعد، اعمال کردن یک «تابع غیرخطی» (Non-Linear Function)، شبکه عصبی قادر به یادگیری «فضای ویژگی» (Feature Space) جدید خواهد بود. حاصل این عملیات (خروجی این مراحل)، ورودی لایه بعدی را تشکیل خواهد داد. این فرایند تا زمانی که خروجی‌ها به لایه آخر یا «لایه خروجی» (Output Layer) برسند، ادامه پیدا می‌کند.

شبکه های عصبی مصنوعی (Artificial Neural Networks)

بنابراین، یک شبکه عصبی را می‌توان در قالب جریان اطلاعاتی از لایه ورودی به لایه‌های نهان و پس از آن به لایه خروجی تعریف کرد. برای یک «شبکه عصبی سه لایه» (Three-Layers Neural Network)، تابع واقعی که قرار است توسط شبکه یادگیری شود، به شکل زیر نمایش داده خواهد شد:

$$f ( x ) = f _ { 3 } ( f _ { 2 } ( f _ { 1 } ( x ) ) )$$

در این تابع، هر کدام از توابع تو در توی داخلی وظیفه خاصی بر عهده دارند:

  • تابع $$ f _ { 1 } ( x )$$: تابعی که در لایه نهان اول شبکه های عصبی مصنوعی یاد گرفته خواهد شد.
  • تابع $$ f _ { 2 } ( x )$$: تابعی که در لایه نهان دوم شبکه های عصبی مصنوعی یاد گرفته خواهد شد.
  • تابع $$ f _ { 3 } ( x )$$: تابعی که در لایه خروجی شبکه های عصبی مصنوعی یاد گرفته خواهد شد.

به عبارت دیگر، در هر کدام از لایه‌های شبکه های عصبی مصنوعی چند لایه، مدل‌های نمایشی متفاوتی یاد گرفته می‌شود. البته نکته مهم در مورد یادگیری توابع بالا این است که هر چه قدر به سمت لایه‌های نهان انتهایی حرکت می‌کنیم، مدل نمایشی یادگیری شده در شبکه های عصبی مصنوعی، پیچیده‌تر و پیشرفته‌تر می‌شود. شکل زیر، نمونه‌ای از یک شبکه عصبی سه لایه را نمایش می‌دهد (معمولا لایه اول، در محاسبه تعداد لایه‌های شبکه های عصبی مصنوعی لحاظ نمی‌شود).

شبکه های عصبی مصنوعی (Artificial Neural Networks)
معماری یک شبکه عصبی مصنوعی چند لایه

به عنوان نمونه، کامپیوترها درکی از تصاویر دیجیتالی ندارند و به طور مستقیم، قادر به استنتاج در مورد مؤلفه‌های سازنده یک تصویر نیستند. از سوی دیگر، یک سیستم کامپیوتری بدون وجود یک مدل نرم‌افزاری (هوشمند)، قادر به انجام عملیات جهت استخراج اطلاعات بامعنی از تصاویر نیست. با این حال، شبکه های عصبی مصنوعی به راحتی قادر خواهند بود با استفاده از مدل‌سازی یک نمایش ساده از تصویر در لایه‌های نهان ابتدایی، «لبه‌های» (Edges) موجود در تصویر را شناسایی کنند.

شبکه های عصبی مصنوعی چند لایه، با داشتن خروجی متناظر با اولین لایه نهان، به راحتی می‌توانند «گوشه‌ها» (Corners) و «کانتورهای» (Contours) موجود در تصویر را تشخیص دهند. همچنین، این شبکه‌های عصبی، با داشتن خروجی متناظر با لایه نهان دوم، بخش‌های خاصی از یک تصویر نظیر بینی یک انسان را شناسایی می‌کنند. در نهایت، و با در کنار هم قرار دادن تمامی مدل‌های نمایشی تولید شده در لایه‌های نهان و تولید یک مدل نمایشی پیچیده، شبکه های عصبی مصنوعی قادر خواهند بود تا نوع اشیاء موجود در تصویر را نیز شناسایی کنند.

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

یکی از بخش‌های مهم طراحی یک مدل یادگیری ماشین، «مهندسی ویژگی‌ها» (Feature Engineering) یا مشخص کردن بهترین ویژگی‌های ممکن برای تولید یک مدل نمایشی بهینه است. ویژگی مهم شبکه های عصبی مصنوعی این است که به «مهندسان هوش مصنوعی» (AI Engineers) و «دانشمندان داده» (Data Scientists) این امکان را می‌دهند که بدون صرف کردن وقت و هزینه زیاد روی بخش مهندسی ویژگی‌ها، یک مدل نمایشی خوب از داده‌ها تولید و در کاربردهای مختلف مورد استفاده قرار دهند.

مطلب پیش رو از دو بخش اصلی تشکیل شده است:

  1. کدنویسی شبکه های عصبی مصنوعی چند لایه: در این بخش، نحوه تعریف توابع کمکی لازم برای پیاده‌سازی شبکه های عصبی مصنوعی چند لایه تشریح و کدهای پیاده‌سازی آن‌ها در «زبان برنامه‌نویسی پایتون» (Python Programming Language) نمایش داده خواهد شد. همچنین، بنیان نظری بخش‌های مختلف پیاده‌سازی شبکه های عصبی مصنوعی نیز شرح داده خواهد شد.
  2. کاربرد: در این بخش، از کدهای پیاده‌سازی شده در بخش قبل، برای توسعه یک سیستم «بازشناسی تصویر» (Image Recognition) استفاده می‌شود. از سیستم بازشناسی تصویر، برای سنجش عملکرد شبکه عصبی مصنوعی در تشخیص «گربه» (Cat) یا «غیر گربه» (No Cat) در تصاویر ورودی استفاده می‌شود.
 Import packages
import os as os

import h5py
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

کدنویسی شبکه های عصبی مصنوعی چند لایه

در این بخش، با بخش‌های مختلف الگوریتم یادگیری در یک شبکه عصبی مصنوعی چند لایه آشنا خواهید شد.

شبکه های عصبی مصنوعی (Artificial Neural Networks)

انتشار رو به جلو (Forward Propagation)

ورودی $$X$$، اطلاعات ابتدایی لازم را در مورد دامنه مسئله‌ای که قرار است توسط شبکه های عصبی مصنوعی حل شود، در اختیار سیستم قرار می‌دهد. در مراحل بعد، ورودی‌ها به واحدها یا «نودهای» (Nodes) موجود در هر کدام از لایه‌ها انتشار پیدا می‌کنند و در نهایت، یک خروجی $$\widehat { Y }$$ تولید می‌شود. برای مشخص کردن معماری شبکه های عصبی مصنوعی، لازم است تا «عمق» (Depth)، «پهنا» (Width) و «تابع فعال‌سازی» (Activation Function) که در هر لایه مورد استفاده قرار می‌گیرد، مشخص شوند.

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

برای پیاده‌سازی شبکه های عصبی مصنوعی، توابع فعال‌سازی گوناگونی نظیر «واحد خطی اصلاح شده» (Rectified Linear Unit)، «تابع سیگموئید» (Sigmoid Function)، «تابع تانژانت هذلولوی یا هیپربولیک» (Hyperbolic Tangent) و سایر موارد معرفی شده‌اند. تحقیقات انجام شده در مورد پیاده‌سازی شبکه های عصبی مصنوعی نشان داده است که شبکه‌های عمیق‌تر (شبکه‌های حاوی لایه‌های نهان بیشتر)، عملکرد به مراتب بهتری نسبت به شبکه‌های حاوی نودهای نهان بیشتر دارند.بنابراین، آموزش یک شبکه عصبی مصنوعی عمیق‌تر توصیه می‌شود.

ابتدا لازم است تا برخی از نمادهایی که در طول این مطلب با آن‌ها برخورد می‌شود، تعریف شوند:

  • ماتریس $$W ^ { l }$$: ماتریس وزن لایه $$l$$اُم.
  • بردار $$b ^ { l }$$: بردار بایاس لایه $$l$$اُم.
  • تابع $$Z ^ { l }$$: تابع تبدیل خطی ورودی‌های داده شده برای لایه $$l$$اُم.
  • تابع $$g ^ { l }$$: تابع فعال‌سازی که روی لایه $$l$$اُم شبکه عصبی مصنوعی اعمال می‌شود.
  • مقدار $$A ^ { l }$$: خروجی حاصل پس از اعمال تابع فعال‌سازی روی لایه $$l$$اُم شبکه عصبی مصنوعی.
  • مقدار $$d W ^ { l }$$: مشتق «تابع هزینه» (Cost Function) نسبت به $$W ^ { l }$$ ($$\frac { \partial J } { \partial (W ^ l ) }$$).
  • مقدار $$d b ^ { l }$$: مشتق «تابع هزینه» (Cost Function) نسبت به $$b ^ { l }$$ ($$\frac { \partial J } { \partial (b ^ l ) }$$).
  • مقدار $$d Z ^ { l }$$: مشتق «تابع هزینه» (Cost Function) نسبت به $$Z ^ { l }$$ ($$\frac { \partial J } { \partial (Z ^ l ) }$$).
  • مقدار $$d A ^ { l }$$: مشتق «تابع هزینه» (Cost Function) نسبت به $$A ^ { l }$$ ($$\frac { \partial J } { \partial (A ^ l ) }$$).
  • مقدار $$n ^ { l }$$: تعداد واحدها یا نودهای لایه $$l$$اُم.
  • مقدار $$m$$: تعداد نمونه‌ها.
  • مقدار $$L$$: تعداد لایه‌های موجود در شبکه عصبی مصنوعی طراحی شده (بدون در نظر گرفتن لایه ورودی).

در مرحله بعد، «ابعاد» (Dimensions) یک شبکه عصبی چند لایه به «شکل عمومی» (General Form) نمایش داده خواهد شد تا عملیات ضرب ماتریسی در شبکه تسهیل شود. یکی از مهم‌ترین چالش‌های موجود در پیاده‌سازی شبکه های عصبی مصنوعی، محاسبه درست ابعاد آن‌ها است.

  • مقادیر ($$W ^ { l } \; , d W ^ { l }$$): تعداد نودهای موجود در لایه $$l$$اُم شبکه x تعداد نودهای موجود در لایه $$(l-1)$$اُم.
  • مقادیر ($$b ^ { l } \; , d b ^ { l }$$): تعداد نودهای موجود در لایه $$l$$اُم شبکه x عدد (1).
  • مقادیر ($$Z ^ { l } \; , d Z ^ { l }$$): تعداد نودهای موجود در لایه $$l$$اُم شبکه x تعداد نمونه‌ها.
  • مقادیر ($$A ^ { l } \; , d A ^ { l }$$): تعداد نودهای موجود در لایه $$l$$اُم شبکه x تعداد نمونه‌ها.

دو معادله‌ای که از طریق آن‌ها قادر به پیاده‌سازی مرحله انتشار رو به جلو خواهیم بود عبارتند از:

$$Z ^ { l } = W ^ { l } \; A ^ { l – 1 } + b ^ { l }$$

$$A ^ { l }= g ^ { l } ( Z ^ { l } ) =g ^ { l } ( w ^ { l } A ^ { l – 1 } + b ^ { l } )$$

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

مقداردهی اولیه پارامترها

در ابتدای کار، ماتریس‌های وزن و بردارهای بایاس متناظر با هر کدام از لایه‌ها، مقداردهی اولیه خواهند شد. شایان ذکر است که مقادیر پارامترهای مسئله نباید توسط مقادیر صفر مقداردهی اولیه شوند؛ زیرا، با انجام چنین کاری، «گرادیان‌ها» (Gradients) محاسبه شده برای تمامی حالات برابر خواهد شد و در هر تکرار، خروجی یکسان خواهد شد. در نتیجه، الگوریتم شبکه عصبی مصنوعی، عملا چیزی یاد نخواهد گرفت. بنابراین، بسیار حیاتی است که پارامترهای شبکه های عصبی مصنوعی به وسیله مقادیر تصادفی بین 0 و 1 مقداردهی اولیه شوند.

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

# Initialize parameters
def initialize_parameters(layers_dims):
    """
    Initialize parameters dictionary.
    
    Weight matrices will be initialized to random values from uniform normal
    distribution.
    bias vectors will be initialized to zeros.

    Arguments
    ---------
    layers_dims : list or array-like
        dimensions of each layer in the network.

    Returns
    -------
    parameters : dict
        weight matrix and the bias vector for each layer.
    """
    np.random.seed(1)               
    parameters = {}
    L = len(layers_dims)            

    for l in range(1, L):           
        parameters["W" + str(l)] = np.random.randn(
            layers_dims[l], layers_dims[l - 1]) * 0.01
        parameters["b" + str(l)] = np.zeros((layers_dims[l], 1))

        assert parameters["W" + str(l)].shape == (
            layers_dims[l], layers_dims[l - 1])
        assert parameters["b" + str(l)].shape == (layers_dims[l], 1)

    return parameters

توابع فعال‌سازی در شبکه های عصبی مصنوعی چند لایه

یکی از چالش‌هایی که توسعه دهندگان در هنگام پیاده‌سازی شبکه های عصبی مصنوعی با آن دست و پنجه نرم می‌کنند، انتخاب تابع فعال‌سازی مناسب برای لایه‌های مختلف موجود در شبکه عصبی است. در این زمینه، راهکاری قطعی برای انتخاب بهترین تابع فعال‌سازی برای یک مسأله خاص وجود ندارد. انتخاب تابع فعال‌سازی مناسب، یک فرایند «آزمون و خطا» (Trial and Error) است که در آن، توسعه دهنده، مجموعه‌ای از توابع متفاوت را امتحان و بهترین تابع را برای مسأله مورد نظر انتخاب می‌کند.

شبکه های عصبی مصنوعی (Artificial Neural Networks)
مهم‌ترین توابع فعال‌سازی شبکه‌های عصبی مصنوعی

در این بخش، چهار تابع فعال‌سازی مهم و پر کاربرد در پیاده‌سازی شبکه های عصبی مصنوعی مورد بررسی قرار می‌گیرند:

  • تابع سیگموئید: از آنجایی که برد مقادیر خروجی این تابع بین صفر و یک است، به شدت توصیه می‌ود که از این تابع فعال‌سازی در لایه خروجی استفاده شود تا به راحتی بتوان خروجی‌ها را در قالب مقادیر «احتمالی» (Probability) تفسیر کرد. یکی از معایب استفاده از تابع سیگموئیدی، به عنوان تابع فعال‌سازی در لایه‌های نهان، این است که مقادیر گرادیان‌ها در بخش بزرگی از دامنه مسأله، بسیار نزدیک به صفر خواهند بود؛ در نتیجه، الگوریتم یادگیری بسیار کند و کار آن برای مدل‌سازی داده‌ها بسیار سخت خواهد شد.

$$g ( Z ) = \frac { 1 } { 1 + e^ { -z } }$$

  • تابع تانژانت هذلولوی یا هیپربولیک: از آنجایی که «میانگین» (Mean) خروجی این تابع بسیار نزدیک به صفر است، نسبت به تابع سیگموئیدی برتری دارد. زیرا، مرکزیت خروجی واحدهای فعال‌سازی در اطراف صفر قرار می‌گیرد و این سبب می‌شود که برد مقادیر خروجی، بسیار کوچک و فرایند یادگیری، سریع‌تر انجام شود. یکی از معایب استفاده از تابع تانژانت هذلولوی یا هیپربولیک، به عنوان تابع فعال‌سازی در لایه‌های نهان (که با تابع سیگموئیدی در اشتراک است)، این است که مقادیر گرادیان‌ها در بخش بزرگی از دامنه، بسیار نزدیک به صفر خواهند بود.

$$g ( Z ) = \frac { e ^ { z } + e ^ { -z } } { e ^ { z } + e ^ { -z } }$$

  • تابع «واحد خطی اصلاح شده» (ReLU): مدل‌های نزدیک به مدل خطی بسیار ساده هستند و بهینه‌سازی آن‌ها نیز بسیار آسان است. از آنجایی که تابع ReLU، بسیاری از مشخصه‌های توابع خطی را به اشتراک می‌گذارد، در بسیاری از مسائل کارایی خوبی از خود نشان می‌دهد. تنها مشکل این توابع این است که مشتق آن‌ها در $$Z=0$$ تعریف نمی‌شود. راه حل این مشکل این است که در $$Z=0$$، مشتق برابر صفر در نظر گرفته شود. با این حال، این بدین معنی است که برای تمامی مقادیر $$Z \leq 0$$، گرادیان برابر صفر خواهد شد و الگوریتم قادر به یادگیری نخواهد بود.

$$g ( Z ) = max \left \{ 0, Z \right \}$$

  • تابع «واحد خطی اصلاح شده نشتی» (Leaky ReLU): این تابع، از طریق اختصاص مقدار $$\alpha$$ (مقداری کوچک) به تمامی مقادیر $$Z \leq 0$$، بر مشکل «گرادیان صفر» (Zero Gradient) فائق آمده است.

$$g ( Z ) = max \left \{ \alpha \star Z , \; Z \right \}$$

در صورتی که مطمئن نیستید کدام تابع فعال‌سازی برای مسأله شما مناسب است، کار آموزش شبکه عصبی مصنوعی را تابع فعال‌سازی ReLU شروع کنید. در ادامه، هر کدام از توابع بالا در پایتون پیاده‌سازی و گراف متناظر با آن‌ها رسم خواهد شد (از این طریق، دامنه و برد هر تابع به خوبی مشخص می‌شود).

# Define activation functions that will be used in forward propagation
def sigmoid(Z):
    """
    Computes the sigmoid of Z element-wise.

    Arguments
    ---------
    Z : array
        output of affine transformation.

    Returns
    -------
    A : array
        post activation output.
    Z : array
        output of affine transformation.
    """
    A = 1 / (1 + np.exp(-Z))

    return A, Z


def tanh(Z):
    """
    Computes the Hyperbolic Tagent of Z elemnet-wise.

    Arguments
    ---------
    Z : array
        output of affine transformation.

    Returns
    -------
    A : array
        post activation output.
    Z : array
        output of affine transformation.
    """
    A = np.tanh(Z)

    return A, Z


def relu(Z):
    """
    Computes the Rectified Linear Unit (ReLU) element-wise.

    Arguments
    ---------
    Z : array
        output of affine transformation.

    Returns
    -------
    A : array
        post activation output.
    Z : array
        output of affine transformation.
    """
    A = np.maximum(0, Z)

    return A, Z


def leaky_relu(Z):
    """
    Computes Leaky Rectified Linear Unit element-wise.

    Arguments
    ---------
    Z : array
        output of affine transformation.

    Returns
    -------
    A : array
        post activation output.
    Z : array
        output of affine transformation.
    """
    A = np.maximum(0.1 * Z, Z)

    return A, Z

نمایش گرافی توابع فعال‌سازی:

# Plot the 4 activation functions
z = np.linspace(-10, 10, 100)

# Computes post-activation outputs
A_sigmoid, z = sigmoid(z)
A_tanh, z = tanh(z)
A_relu, z = relu(z)
A_leaky_relu, z = leaky_relu(z)

# Plot sigmoid
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.plot(z, A_sigmoid, label = "Function")
plt.plot(z, A_sigmoid * (1 - A_sigmoid), label = "Derivative")
plt.legend(loc = "upper left")
plt.xlabel("z")
plt.ylabel(r"$\frac{1}{1 + e^{-z}}$")
plt.title("Sigmoid Function", fontsize = 16)
# Plot tanh
plt.subplot(2, 2, 2)
plt.plot(z, A_tanh, 'b', label = "Function")
plt.plot(z, 1 - np.square(A_tanh), 'r',label = "Derivative")
plt.legend(loc = "upper left")
plt.xlabel("z")
plt.ylabel(r"$\frac{e^z - e^{-z}}{e^z + e^{-z}}$")
plt.title("Hyperbolic Tangent Function", fontsize = 16)
# plot relu
plt.subplot(2, 2, 3)
plt.plot(z, A_relu, 'g')
plt.xlabel("z")
plt.ylabel(r"$max\{0, z\}$")
plt.title("ReLU Function", fontsize = 16)
# plot leaky relu
plt.subplot(2, 2, 4)
plt.plot(z, A_leaky_relu, 'y')
plt.xlabel("z")
plt.ylabel(r"$max\{0.1z, z\}$")
plt.title("Leaky ReLU Function", fontsize = 16)
plt.tight_layout();
شبکه های عصبی مصنوعی (Artificial Neural Networks)
نمایش گرافی توابع فعال‌سازی

فرایند پیشخور (Feedforward) در شبکه های عصبی مصنوعی‎

هر واحد یا نود موجود در لایه‌های شبکه عصبی مصنوعی (به جز نودهای لایه ورودی)، با داشتن ورودی‌ها از لایه قبلی (خروجی لایه قبلی، ورودی لایه بعدی خواهد بود)، تبدیل خطی $$Z = W ^ { T } x + b$$ ورودی‌ها را محاسبه و تابع فعال‌سازی $$g ( z )$$ نظیر ReLU را، به صورت «عنصر به عنصر» (Element-Wise) بر روی عناصر آن اعمال می‌کند. در طی این فرایند، تمامی متغیرهای محاسبه شده ذخیره می‌شوند تا در مرحله «پس انتشار» (BackPropagation) خطا مورد استفاده قرار بگیرند. شایان توجه است که ممکن است هر کدام از لایه‌های شبکه عصبی مصنوعی، توابع فعال‌سازی متفاوتی داشته باشند.

# Define helper functions that will be used in L-model forward prop
def linear_forward(A_prev, W, b):
    """
    Computes affine transformation of the input.

    Arguments
    ---------
    A_prev : 2d-array
        activations output from previous layer.
    W : 2d-array
        weight matrix, shape: size of current layer x size of previuos layer.
    b : 2d-array
        bias vector, shape: size of current layer x 1.

    Returns
    -------
    Z : 2d-array
        affine transformation output.
    cache : tuple
        stores A_prev, W, b to be used in backpropagation.
    """
    Z = np.dot(W, A_prev) + b
    cache = (A_prev, W, b)

    return Z, cache


def linear_activation_forward(A_prev, W, b, activation_fn):
    """
    Computes post-activation output using non-linear activation function.

    Arguments
    ---------
    A_prev : 2d-array
        activations output from previous layer.
    W : 2d-array
        weight matrix, shape: size of current layer x size of previuos layer.
    b : 2d-array
        bias vector, shape: size of current layer x 1.
    activation_fn : str
        non-linear activation function to be used: "sigmoid", "tanh", "relu".

    Returns
    -------
    A : 2d-array
        output of the activation function.
    cache : tuple
        stores linear_cache and activation_cache. ((A_prev, W, b), Z) to be used in backpropagation.
    """
    assert activation_fn == "sigmoid" or activation_fn == "tanh" or \
        activation_fn == "relu"

    if activation_fn == "sigmoid":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = sigmoid(Z)

    elif activation_fn == "tanh":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = tanh(Z)

    elif activation_fn == "relu":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = relu(Z)

    assert A.shape == (W.shape[0], A_prev.shape[1])

    cache = (linear_cache, activation_cache)

    return A, cache


def L_model_forward(X, parameters, hidden_layers_activation_fn="relu"):
    """
    Computes the output layer through looping over all units in topological
    order.

    Arguments
    ---------
    X : 2d-array
        input matrix of shape input_size x training_examples.
    parameters : dict
        contains all the weight matrices and bias vectors for all layers.
    hidden_layers_activation_fn : str
        activation function to be used on hidden layers: "tanh", "relu".

    Returns
    -------
    AL : 2d-array
        probability vector of shape 1 x training_examples.
    caches : list
        that contains L tuples where each layer has: A_prev, W, b, Z.
    """
    A = X                           
    caches = []                     
    L = len(parameters) // 2        

    for l in range(1, L):
        A_prev = A
        A, cache = linear_activation_forward(
            A_prev, parameters["W" + str(l)], parameters["b" + str(l)],
            activation_fn=hidden_layers_activation_fn)
        caches.append(cache)

    AL, cache = linear_activation_forward(
        A, parameters["W" + str(L)], parameters["b" + str(L)],
        activation_fn="sigmoid")
    caches.append(cache)

    assert AL.shape == (1, X.shape[1])

    return AL, caches

تابع هزینه (Cost) در شبکه های عصبی مصنوعی

در این مطلب، از تابع هزینه باینری «آنتروپی متقابل» (Cross-Entropy) استفاده می‌شود. این روش، از «درست‌نمایی بر حسب لگاریتم» (Log-Likelihood) برای محاسبه خطا استفاده می‌کند. تابع هزینه به شکل زیر تعریف می‌شود:

$$J ( W , b) = – \frac { 1 } { m } \Large {\sum} _ { i = 1 } ^ m ( y ^ { i } log ( \widehat { y ^ { i } } ) + ( 1 – y ^ { i } ) log ( 1 -\widehat { y ^ { i } } ) )$$

تابع هزینه بالا، یک تابع محدب است؛ با این حال، شبکه عصبی معمولا در دام «کمینه محلی» (Local Minimum) قرار می‌گیرد و تضمینی برای رسیدن به پارامترهای «بهینه سراسری» (GLobal Optimum) وجود ندارد. در این مطلب، الگوریتم یادگیری شبکه عصبی، از روش «گرادیان کاهشی» (Gradient Descent) استفاده می‌کند.

# Compute cross-entropy cost
def compute_cost(AL, y):
    """
    Computes the binary Cross-Entropy cost.

    Arguments
    ---------
    AL : 2d-array
        probability vector of shape 1 x training_examples.
    y : 2d-array
        true "label" vector.

    Returns
    -------
    cost : float
        binary cross-entropy cost.
    """
    m = y.shape[1]              
    cost = - (1 / m) * np.sum(
        np.multiply(y, np.log(AL)) + np.multiply(1 - y, np.log(1 - AL)))

    return cost

الگوریتم یادگیری پس انتشار (BackPropagation) در شبکه های عصبی مصنوعی چند لایه

الگوریتم پس انتشار در شبکه عصبی مصنوعی به اطلاعات اجازه می‌دهد تا از تابع هزینه لایه خروجی به سمت لایه‌های پیشین شبکه عصبی انتشار پیدا کنند (پس انتشار اطلاعات) و از این طریق، گرادیان‌ها محاسبه شوند. بنابراین، در الگوریتم پس انتشار، از نود پایانی در جهت معکوس «ترتیب توپولوژیکی» (Topological Order) شبکه عصبی، پیمایش انجام می‌شود تا مشتق مقدار خروجی نود پایانی، نسبت به هرکدام از نودهای لایه پیشین (و مشتق مقدار خروجی نود آخرین لایه نهان، نسبت به هرکدام از نودهای لایه‌های نهان پیشین و همینطور الی آخر) محاسبه شود.

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

$$d A ^ { L } = \frac { A ^ { L } – Y } { A ^ { L } ( 1 – A ^ { L } ) }$$

$$d Z ^ { L } ={ A ^ { L } – Y } $$

$$d W ^ { l }= \frac { 1 } { m }d Z^{ l } A ^ { l – 1 ^ { T } }$$

$$d b ^ { l }= \frac { 1 } { m } \Large { \sum } _ i ( d Z ^ { l } )$$

$$d A ^ { l-1 }= W^{i^{T}} d Z ^ { l } $$

$$d Z ^ { l }= d A ^ { l } \star g ^ { ‘ l } ( Z ^ { l } )$$

از آنجایی که $$b^{l}$$ همیشه یک بردار است، جمع ماتریسی در راستای سطرهای ماتریس انجام می‌شود (زیرا، هر ستون یک نمونه را نمایش می‌دهد).

# Define derivative of activation functions w.r.t z that will be used in back-propagation
def sigmoid_gradient(dA, Z):
    """
    Computes the gradient of sigmoid output w.r.t input Z.

    Arguments
    ---------
    dA : 2d-array
        post-activation gradient, of any shape.
    Z : 2d-array
        input used for the activation fn on this layer.

    Returns
    -------
    dZ : 2d-array
        gradient of the cost with respect to Z.
    """
    A, Z = sigmoid(Z)
    dZ = dA * A * (1 - A)

    return dZ


def tanh_gradient(dA, Z):
    """
    Computes the gradient of hyperbolic tangent output w.r.t input Z.

    Arguments
    ---------
    dA : 2d-array
        post-activation gradient, of any shape.
    Z : 2d-array
        input used for the activation fn on this layer.

    Returns
    -------
    dZ : 2d-array
        gradient of the cost with respect to Z.
    """
    A, Z = tanh(Z)
    dZ = dA * (1 - np.square(A))

    return dZ


def relu_gradient(dA, Z):
    """
    Computes the gradient of ReLU output w.r.t input Z.

    Arguments
    ---------
    dA : 2d-array
        post-activation gradient, of any shape.
    Z : 2d-array
        input used for the activation fn on this layer.

    Returns
    -------
    dZ : 2d-array
        gradient of the cost with respect to Z.
    """
    A, Z = relu(Z)
    dZ = np.multiply(dA, np.int64(A > 0))

    return dZ


# define helper functions that will be used in L-model back-prop
def linear_backword(dZ, cache):
    """
    Computes the gradient of the output w.r.t weight, bias, and post-activation
    output of (l - 1) layers at layer l.

    Arguments
    ---------
    dZ : 2d-array
        gradient of the cost w.r.t. the linear output (of current layer l).
    cache : tuple
        values of (A_prev, W, b) coming from the forward propagation in the current layer.

    Returns
    -------
    dA_prev : 2d-array
        gradient of the cost w.r.t. the activation (of the previous layer l-1).
    dW : 2d-array
        gradient of the cost w.r.t. W (current layer l).
    db : 2d-array
        gradient of the cost w.r.t. b (current layer l).
    """
    A_prev, W, b = cache
    m = A_prev.shape[1]

    dW = (1 / m) * np.dot(dZ, A_prev.T)
    db = (1 / m) * np.sum(dZ, axis=1, keepdims=True)
    dA_prev = np.dot(W.T, dZ)

    assert dA_prev.shape == A_prev.shape
    assert dW.shape == W.shape
    assert db.shape == b.shape

    return dA_prev, dW, db


def linear_activation_backward(dA, cache, activation_fn):
    """
    Arguments
    ---------
    dA : 2d-array
        post-activation gradient for current layer l.
    cache : tuple
        values of (linear_cache, activation_cache).
    activation : str
        activation used in this layer: "sigmoid", "tanh", or "relu".

    Returns
    -------
    dA_prev : 2d-array
        gradient of the cost w.r.t. the activation (of the previous layer l-1), same shape as A_prev.
    dW : 2d-array
        gradient of the cost w.r.t. W (current layer l), same shape as W.
    db : 2d-array
        gradient of the cost w.r.t. b (current layer l), same shape as b.
    """
    linear_cache, activation_cache = cache

    if activation_fn == "sigmoid":
        dZ = sigmoid_gradient(dA, activation_cache)
        dA_prev, dW, db = linear_backword(dZ, linear_cache)

    elif activation_fn == "tanh":
        dZ = tanh_gradient(dA, activation_cache)
        dA_prev, dW, db = linear_backword(dZ, linear_cache)

    elif activation_fn == "relu":
        dZ = relu_gradient(dA, activation_cache)
        dA_prev, dW, db = linear_backword(dZ, linear_cache)

    return dA_prev, dW, db


def L_model_backward(AL, y, caches, hidden_layers_activation_fn="relu"):
    """
    Computes the gradient of output layer w.r.t weights, biases, etc. starting
    on the output layer in reverse topological order.

    Arguments
    ---------
    AL : 2d-array
        probability vector, output of the forward propagation (L_model_forward()).
    y : 2d-array
        true "label" vector (containing 0 if non-cat, 1 if cat).
    caches : list
        list of caches for all layers.
    hidden_layers_activation_fn :
        activation function used on hidden layers: "tanh", "relu".

    Returns
    -------
    grads : dict
        with the gradients.
    """
    y = y.reshape(AL.shape)
    L = len(caches)
    grads = {}

    dAL = np.divide(AL - y, np.multiply(AL, 1 - AL))

    grads["dA" + str(L - 1)], grads["dW" + str(L)], grads[
        "db" + str(L)] = linear_activation_backward(
            dAL, caches[L - 1], "sigmoid")

    for l in range(L - 1, 0, -1):
        current_cache = caches[l - 1]
        grads["dA" + str(l - 1)], grads["dW" + str(l)], grads[
            "db" + str(l)] = linear_activation_backward(
                grads["dA" + str(l)], current_cache,
                hidden_layers_activation_fn)

    return grads


# define the function to update both weight matrices and bias vectors
def update_parameters(parameters, grads, learning_rate):
    """
    Update the parameters' values using gradient descent rule.

    Arguments
    ---------
    parameters : dict
        contains all the weight matrices and bias vectors for all layers.
    grads : dict
        stores all gradients (output of L_model_backward).

    Returns
    -------
    parameters : dict
        updated parameters.
    """
    L = len(parameters) // 2

    for l in range(1, L + 1):
        parameters["W" + str(l)] = parameters[
            "W" + str(l)] - learning_rate * grads["dW" + str(l)]
        parameters["b" + str(l)] = parameters[
            "b" + str(l)] - learning_rate * grads["db" + str(l)]

    return parameters

کاربرد شبکه های عصبی مصنوعی در بازشناسی تصویر

مجموعه داده‌ای که برای این کاربرد مورد استفاده قرار گرفته است از 209 تصویر تشکیل شده است. دقت پیکسلی هر تصویر 64×64 است و در فضای رنگی RGB قرار دارد. هدف این کاربرد، پیاده‌سازی شبکه عصبی مصنوعی برای دسته‌بندی دسته‌بندی تصاویر در دو کلاس گربه و غیر گربه است. بنابراین، $$y ^ { i } \in \left \{ 0 , 1 \right\}$$.

  • در ابتدا، تصاویر در سیستم بارگیری می‌شوند.
  • سپس، ماتریس ورودی به گونه‌ای تغییر شکل داده می‌شود که هر ستون، یک نمونه را نشان دهد. از آنجایی که ابعاد هر تصویر برابر با 64x64x3 است، بنابراین هر کدام از تصاویر، 12288 ویژگی خواهند داشت. بنابراین، اندازه ماتریس ورودی برابر با 12288×209 خواهد بود.
  • داده‌ها «استانداردسازی» (Standardize) می‌شوند تا مقادیر گرادیان‌های محاسبه شده از کنترل خارج نشوند. چنین کاری، سبب یکسان شدن «برد» (Range) مقادیر نودهای لایه نهان می‌شود. در این مطلب، برای استاندارد‌سازی تصاویر، مقادیر تمامی پیکسل‌ها بر عدد 255 تقسیم می‌شوند. با این حال، توصیه می‌شود که داده‌ها به گونه‌ای استاندارد‌سازی شوند که «میانگین» (Mean) آماری آن‌ها برابر با صفر و «انحراف معیار» (Standard Deviation) آن‌ها برابر با 1 باشد.

برای دانلود داده‌های آموزشی و تست این کاربرد، به لینک [+] زیر مراجعه شود.

# Import training dataset
train_dataset = h5py.File("../data/train_catvnoncat.h5")
X_train = np.array(train_dataset["train_set_x"])
y_train = np.array(train_dataset["train_set_y"])

test_dataset = h5py.File("../data/test_catvnoncat.h5")
X_test = np.array(test_dataset["test_set_x"])
y_test = np.array(test_dataset["test_set_y"])

# print the shape of input data and label vector
print(f"""Original dimensions:\n{20 * '-'}\nTraining: {X_train.shape}, {y_train.shape}
Test: {X_test.shape}, {y_test.shape}""")

# plot cat image
plt.figure(figsize=(6, 6))
plt.imshow(X_train[50])
plt.axis("off");

# Transform input data and label vector
X_train = X_train.reshape(209, -1).T
y_train = y_train.reshape(-1, 209)

X_test = X_test.reshape(50, -1).T
y_test = y_test.reshape(-1, 50)

# standarize the data
X_train = X_train / 255
X_test = X_test / 255

print(f"""\nNew dimensions:\n{15 * '-'}\nTraining: {X_train.shape}, {y_train.shape}
Test: {X_test.shape}, {y_test.shape}""")

خروجی:

Original dimensions:
--------------------
Training: (209, 64, 64, 3), (209,)
Test: (50, 64, 64, 3), (50,)

New dimensions:
---------------
Training: (12288, 209), (1, 209)
Test: (12288, 50), (1, 50)

شبکه های عصبی مصنوعی (Artificial Neural Networks)

پس از این مرحله، مجموعه داده لازم برای «آموزش» (Training) و «تست» (Test) شبکه عصبی آماده خواهد شد. در ابتدا، تابع تولید «مدل چند لایه» (Multi-Layer Model) برای پیاده‌سازی الگوریتم یادگیری مبتنی بر روش گرادیان نمایش داده می‌شود. برای تولید این تابع، از تعداد تکرار (3000) و نرخ یادگیری (0٫۰۱) مشخص استفاده می‌شود.

# Define the multi-layer model using all the helper functions we wrote before


def L_layer_model(
        X, y, layers_dims, learning_rate=0.01, num_iterations=3000,
        print_cost=True, hidden_layers_activation_fn="relu"):
    """
    Implements multilayer neural network using gradient descent as the
    learning algorithm.

    Arguments
    ---------
    X : 2d-array
        data, shape: number of examples x num_px * num_px * 3.
    y : 2d-array
        true "label" vector, shape: 1 x number of examples.
    layers_dims : list
        input size and size of each layer, length: number of layers + 1.
    learning_rate : float
        learning rate of the gradient descent update rule.
    num_iterations : int
        number of iterations of the optimization loop.
    print_cost : bool
        if True, it prints the cost every 100 steps.
    hidden_layers_activation_fn : str
        activation function to be used on hidden layers: "tanh", "relu".

    Returns
    -------
    parameters : dict
        parameters learnt by the model. They can then be used to predict test examples.
    """
    np.random.seed(1)

    # initialize parameters
    parameters = initialize_parameters(layers_dims)

    # intialize cost list
    cost_list = []

    # iterate over num_iterations
    for i in range(num_iterations):
        # iterate over L-layers to get the final output and the cache
        AL, caches = L_model_forward(
            X, parameters, hidden_layers_activation_fn)

        # compute cost to plot it
        cost = compute_cost(AL, y)

        # iterate over L-layers backward to get gradients
        grads = L_model_backward(AL, y, caches, hidden_layers_activation_fn)

        # update parameters
        parameters = update_parameters(parameters, grads, learning_rate)

        # append each 100th cost to the cost list
        if (i + 1) % 100 == 0 and print_cost:
            print(f"The cost after {i + 1} iterations is: {cost:.4f}")

        if i % 100 == 0:
            cost_list.append(cost)

    # plot the cost curve
    plt.figure(figsize=(10, 6))
    plt.plot(cost_list)
    plt.xlabel("Iterations (per hundreds)")
    plt.ylabel("Loss")
    plt.title(f"Loss curve for the learning rate = {learning_rate}")

    return parameters


def accuracy(X, parameters, y, activation_fn="relu"):
    """
    Computes the average accuracy rate.

    Arguments
    ---------
    X : 2d-array
        data, shape: number of examples x num_px * num_px * 3.
    parameters : dict
        learnt parameters.
    y : 2d-array
        true "label" vector, shape: 1 x number of examples.
    activation_fn : str
        activation function to be used on hidden layers: "tanh", "relu".

    Returns
    -------
    accuracy : float
        accuracy rate after applying parameters on the input data
    """
    probs, caches = L_model_forward(X, parameters, activation_fn)
    labels = (probs >= 0.5) * 1
    accuracy = np.mean(labels == y) * 100

    return f"The accuracy rate is: {accuracy:.2f}%."

در مرحله بعد، دو نسخه از شبکه عصبی پیاده‌سازی شده آموزش داده می‌شود؛ در نسخه اول، از تابع ReLU و در نسخه دوم، از تابع تانژانت هذلولوی یا هیپربولیک، به عنوان تابع فعال‌سازی لایه‌های نهان استفاده شده است. سپس، از دو مدل شبکه عصبی آموزش دیده، برای دسته‌بندی تصاویر تست و محاسبه نرخ دقت در مرحله تست استفاده می‌شود. با استفاده از نتایج دقت دو مدل آموزش دیده، بهترین تابع فعال‌سازی برای آموزش شبکه عصبی مشخص می‌شود.

# Setting layers dims
layers_dims = [X_train.shape[0], 5, 5, 1]

# NN with tanh activation fn
parameters_tanh = L_layer_model(
    X_train, y_train, layers_dims, learning_rate=0.03, num_iterations=3000,
    hidden_layers_activation_fn="tanh")

# Print the accuracy
accuracy(X_test, parameters_tanh, y_test, activation_fn="tanh")
The cost after 100 iterations is: 0.6556
The cost after 500 iterations is: 0.6440
The cost after 1000 iterations is: 0.6439
The cost after 1500 iterations is: 0.6437
The cost after 2000 iterations is: 0.6124
The cost after 2500 iterations is: 0.3387
The cost after 3000 iterations is: 0.1040

'The accuracy rate is: 68.00%.'

شبکه های عصبی مصنوعی (Artificial Neural Networks)

# NN with relu activation fn
parameters_relu = L_layer_model(
    X_train, y_train, layers_dims, learning_rate=0.03, num_iterations=3000,
    hidden_layers_activation_fn="relu")

# Print the accuracy
accuracy(X_test, parameters_relu, y_test, activation_fn="relu")
The cost after 100 iterations is: 0.6556
The cost after 500 iterations is: 0.6440
The cost after 1000 iterations is: 0.6440
The cost after 1500 iterations is: 0.6439
The cost after 2000 iterations is: 0.6432
The cost after 2500 iterations is: 0.5262
The cost after 3000 iterations is: 0.3641

'The accuracy rate is: 42.00%.'

شبکه های عصبی مصنوعی (Artificial Neural Networks)

جمع‌بندی

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

  1. حتی اگر شبکه های عصبی مصنوعی قادر به مدل‌سازی و نمایش هر نوع تابعی باشند، به دو دلیل مهم، ممکن است قادر به یادگیری بهینه آن نباشند:
    • ممکن است الگوریتم بهینه‌سازی قادر به پیدا کردن بهترین مقادیر برای پارامترهای تابع نباشد؛ یعنی، در کمینه محلی قرار بگیرد.
    • به دلیل «بیش‌برازش» (Overfitting)، الگوریتم یادگیری ممکن است شکل تابعی متفاوت از شکل تابعی مورد نظر را پیدا کند.
  2. اگرچه شبکه‌های عصبی به ندرت به جواب بهینه سراسری همگرا می‌شوند و معمولا در کمینه سراسری قرار می‌گیرند، با این حال، هزینه‌ها (محاسباتی) را به شدت کاهش می‌دهند و مدل‌های بسیار پیچیده و با دقت بالا برای حل مسائل ارائه می‌دهند.
  3. شبکه عصبی استفاده شده در این مطلب، شبکه عصبی استاندارد «کاملا مصل» (Fully Connected) است. دو نوع شبکه عصبی متداول دیگر عبارتند از:
    • «شبکه‌های عصبی پیچشی» (Convolutional Neural Network): در این نوع شبکه عصبی، نودهای شبکه کاملا به هم متصل نیستند و بیشتر برای کاربردهایی نظیر بازشناسی تصویر مورد استفاده قرار می‌گیرند.
    • «شبکه‌های عصبی بازگشتی» (Recurrent Neural Network): در این نوع شبکه عصبی، وجود «ارتباطات بازخوردی» (Feedback Connection) در سیستم سبب می‌شود تا خروجی مدل، دوباره وارد همان مدل شود. از این دسته از روش‌ها، بیشتر برای «مدل‌سازی ترتیبی» (Sequential Modelling) استفاده می‌شود.
  4. شبکه‌های عصبی استاندارد کاملا متصل، حافظه‌ای از اتفاقات رخ داده در مراحل قبل ندارند. همچنین، هیچ‌گونه اطلاعاتی در رابطه با خروجی ندارند.
  5. تعدادی از «اَبَرپارامترهای» شبکه عصبی را می‌توان با استفاده از «اعتبارسنجی متقابل» (Cross-Validation) بهینه‌سازی کرد تا بهترین عملکرد ممکن توسط شبکه عصبی حاصل شود:
    • نرخ یادگیری: اندازه گام‌های به روز رسانی پارامترهای شبکه عصبی را مشخص می‌کند. مقدار کم برای نرخ یادگیری، سبب همگرایی آهسته و افزایش بار محاسباتی سیستم می‌شود. مقدار زیاد برای نرخ یادگیری، ممکن است سبب عدم همگرایی مدل به جواب (یا تقریب مناسبی از جواب) بهینه شود.
    • تعداد لایه‌های نهان (عمق): تعداد بیشتر لایه‌های نهان، سبب عملکرد بهینه سیستم یادگیری می‌شود ولی هزینه محاسباتی را افزایش می‌دهد.
    • تعداد نودهای در هر لایه (پهنا): تحقیقات نشان داده است که تعداد زیاد نودهای در لایه‌های مختلف، منجر به بهبود عملکرد سیستم نخواهد شد.
    • تابع فعال‌سازی: انتخاب تابع فعال‌سازی مناسب برای یک کاربرد خاص، یک فرایند آزمون و خطا است و بستگی زیادی به نوع کاربرد دارد.
    • تعداد تکرارهای الگوریتم یادگیری برای رسید به جواب.
  6. استانداردسازی داده‌ها: به توابع فعال‌سازی کمک می‌کند تا خروجی‌های مشابهی (از لحاظ برد مقادیر) داشته باشند. همچنین، به سیستم در کنترل مقادیر گرادیان‌های محاسبه شده کمک می‌کند.

شبکه های عصبی مصنوعی (Artificial Neural Networks)

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۱۰ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

«مرتضی جادریان»، دانشجوی مقطع دکتری مهندسی کامپیوتر گرایش هوش مصنوعی است. او در زمینه سیستم‌های هوشمند، به ویژه سیستم‌های هوشمند اطلاعاتی، روش‌های یادگیری ماشین، سیستم‌های دانش محور و محاسبات تکاملی فعالیت دارد.

2 نظر در “کدنویسی شبکه های عصبی مصنوعی چند لایه در پایتون — راهنمای کامل

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد.

برچسب‌ها

مشاهده بیشتر