اولین مرحله برای توسعه یک شبکه عصبی تولید خروجی از دادههای ورودی است. این کار با ساخت یک مجموع وزندار از متغیرها انجام میشود. برای شروع باید با استفاده از کتابخانه NumPy در پایتون دادهها را نمایش دهید.
نمایش دادههای شبکه عصبی با NumPy
شما باید از NumPy برای نمایش بردارهای ورودی به عنوان آرایه استفاده کنید. اما قبل از این کار بهتر است کمی با بردارها در پایتون کار کنید تا درک بهتری از فرایند داشته باشید.
در این مثال شما یک بردار ورودی و دو بردار وزن دارید. هدف پیدا کردن برداری است که از نظر جهت و اندازه بیشترین شباهت را با بردار ورودی دارد. بردارها به شکل زیر هستند:
میبینید که weights_2 به بردار ورودی ما شباهت بیشتری دارد. حالا این چطور باید این موضوع را در پایتون بفهمیم؟
اول از همه باید هر سه بردار را تعریف کنید. بعد از آن باید میزان شباهت هر کدام از بردارهای وزن را با بردار ورودی بسنجید. برای این کار از ضرب داخلی استفاده میکنیم. از آنجایی که همه بردارها دو بعدی هستند، باید این مراحل را طی کنیم:
- اولین عدد input_vector را در اولین عدد weights_1 ضرب میکنیم.
- دومین عدد input_vector را در دومین عدد weights_2 ضرب میکنیم.
- نتیجه هر دو ضرب را جمع میکنیم.
برای انجام این مراحل در پایتون ابتدا باید یک محیط مجازی درست کنیم. پایتون ۳.۳ به بعد با venv. ارائه میشوند و کافی است در شل دستورات زیر را اجرا کنید:
۱ ۲ |
$ python -m venv ~/.my-env $ source ~/.my-env/bin/activate |
حالا باید کنسول IPython را با کمک pip نصب کنیم. از آنجایی که به NumPy و Matplotlib نیز نیاز داریم، آنها را هم نصب میکنیم.
۱ ۲ |
(my-env) $ python -m pip install ipython numpy matplotlib (my-env) $ ipython |
حال از کد زیر در پایتون برای محاسبه ضرب داخلی input_vector و weights_1 استفاده میکنیم:
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ ۱۱ |
In &#۰۹۱;۱]: input_vector = [1.72, 1.23] In &#۰۹۱;۲]: weights_1 = [1.26, 0] In &#۰۹۱;۳]: weights_2 = [2.17, 0.32] In &#۰۹۱;۴]: # Computing the dot product of input_vector and weights_1 In &#۰۹۱;۵]: first_indexes_mult = input_vector[0] * weights_1[0] In &#۰۹۱;۶]: second_indexes_mult = input_vector[1] * weights_1[1] In &#۰۹۱;۷]: dot_product_1 = first_indexes_mult + second_indexes_mult In &#۰۹۱;۸]: print(f"The dot product is: {dot_product_1}") Out&#۰۹۱;۸]: The dot product is: 2.1672 |
ضریب داخلی برابر با ۲/۱۶۷۲ است. ما میتوانیم از کلاس ()np.dot در NumPy برای محاسبه ضرب داخلی استفاده کنیم:
۱ ۲ ۳ ۴ ۵ ۶ |
In &#۰۹۱;۹]: import numpy as np In &#۰۹۱;۱۰]: dot_product_1 = np.dot(input_vector, weights_1) In &#۰۹۱;۱۱]: print(f"The dot product is: {dot_product_1}") Out&#۰۹۱;۱۱]: The dot product is: 2.1672 |
در گام بعد باید ضرب داخلی input_vector و weights_2 را محاسبه کنیم:
۱ ۲ ۳ ۴ |
In &#۰۹۱;۱۰]: dot_product_2 = np.dot(input_vector, weights_2) In &#۰۹۱;۱۱]: print(f"The dot product is: {dot_product_2}") Out&#۰۹۱;۱۱]: The dot product is: 4.1259 |
این بار به عدد ۴/۱۲۵۹ میرسیم. از آنجایی که این عدد بزرگتر از ضرب داخلی قبلی است، پس نتیجه میگیریم input_vector و weights_2 بیشتر به یکدیگر شبیه هستند.
در ادامه با هم مدلی میسازیم که فقط دو خروجی دارد. نتیجه یا ۰ است یا ۱. این مسئله دستهبندی که یکی از زیرمجموعههای یادگیری با ناظر است که در آن شما یک مجموعه داده با وروردیها و اهداف مشخص دارید. جدول زیر ورودیها و خروجیهای دیتاست را نشان میدهد:
بردار ورودی | هدف |
[۱/۵۶، ۱/۶۶] | ۱ |
[۱/۵، ۲] | ۰ |
هدف در واقع متغیری است که میخواهید آن را پیشبینی کنید. دیتاست در این مثال تنها شامل اعداد است، اما در کاربردهای واقعی دیتاستها گاهی به صورت فایل شامل عکس و متن ارائه میشوند.
اولین پیشبینی
برای این تمرین ما یک شبکه عصبی با دو لایه میسازیم. تا به اینجا از دو عملیات ضرب داخلی و جمع استفاده کردهایم که هر دو عملیاتهای خطی هستند. اگر شما لایه های بیشتری اضافه کنید اما تنها از عملیاتهای خطی بهره ببرید، خروجی تغییری نخواهد داشت، چرا که هر لایه با لایه قبلی همبستگی دارد. از این رو به ازای هر شبکه عصبی با چندین لایه، یک شبکه عصبی با لایههای کمتر وجود دارد که همان کار را انجام میدهد.
کاری که شما باید انجام دهید این است که یک عملیات پیدا کنید که گاهی باعث همبستگی لایههای میانی با ورودیها شود و گاهی نیز این همبستگی را نشان ندهد. این امر با استفاده از توابع غیرخطی ممکن میشود. به این توابع غیر خطی، توابع فعالسازی میگوییم.
شبکه عصبی که ما در حال ساخت آن هستیم از تابع سیگموید استفاده میکند. این تابع خروجی را به طیفی بین ۰ تا ۱ محدود میکند. فرمول تابع سیگموید را در زیر میبینید:
ثابت e در این تابع عدد اویلر نام دارد و شما می توانید از کلاس (np.exp(x برای محاسبه eˣ استفاده کنید. از آنجایی که این تابع خروجی را به عددی بین ۰ تا ۱ محدود میکند، از آن برای پیشبینی احتمالات استفاده میکنیم. اگر عدد بالاتر از ۰/۵ بود، آن را ۱ و اگر پایینتر بود آن را ۰ در نظر میگیریم.
شکل زیر محاسبات داخلی شبکهای که در حال ساخت آن هستید را نشان می دهد.
حالا باید این اطلاعات را به کد تبدیل کنیم. کد زیر توابع نشاندادهشده در بالا را نشان میدهد:
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ ۱۱ ۱۲ ۱۳ ۱۴ ۱۵ ۱۶ ۱۷ |
In &#۰۹۱;۱۲]: # Wrapping the vectors in NumPy arrays In &#۰۹۱;۱۳]: input_vector = np.array([1.66, 1.56]) In &#۰۹۱;۱۴]: weights_1 = np.array([1.45, -0.66]) In &#۰۹۱;۱۵]: bias = np.array([0.0]) In &#۰۹۱;۱۶]: def sigmoid(x): ...: return ۱ / (۱ + np.exp(-x)) In &#۰۹۱;۱۷]: def make_prediction(input_vector, weights, bias): ...: layer_1 = np.dot(input_vector, weights) + bias ...: layer_2 = sigmoid(layer_1) ...: return layer_2 In &#۰۹۱;۱۸]: prediction = make_prediction(input_vector, weights_1, bias) In &#۰۹۱;۱۹]: print(f"The prediction result is: {prediction}") Out&#۰۹۱;۱۹]: The prediction result is: [0.7985731] |
نتیجه عدد ۰/۷۹ است به این ترتیب خروجی ۱ میشود. شبکه ما پیشبینی درست را انجام داده است. حالا بردار دوم را امتحان میکنیم. خروجی درست برای این بردار ۰ است.
۱ ۲ ۳ ۴ ۵ ۶ ۷ |
In &#۰۹۱;۲۰]: # Changing the value of input_vector In &#۰۹۱;۲۱]: input_vector = np.array([2, 1.5]) In &#۰۹۱;۲۲]: prediction = make_prediction(input_vector, weights_1, bias) In &#۰۹۱;۲۳]: print(f"The prediction result is: {prediction}") Out&#۰۹۱;۲۳]: The prediction result is: [0.87101915] |
میبینیم که این بار مدل خروجی را اشتباه پیشبینی کرده است. اما این پیشبینی چقدر اشتباه بوده؟ در پست بعدی راهی برای اندازهگیری میزان اشتباه و آموزش مدل پیدا میکنیم.