در آموزش‌های پیشین مجله فرادرس، با پیاده‌سازی شبکه عصبی RBF در پایتون آشنا شدیم. در این آموزش، روش پیاده سازی شبکه عصبی SOM در پایتون را شرح می‌دهیم.

شبکه عصبی SOM

شبکه‌های عصبی SOM یا Self-Organizing Map که با نام شبکه کوهونن (Kohonen Network) نیز شناخته می‌شوند، یک روش غیرنظارت‌شده (Unsupervised Learning) برای استخراج ویژگی و کاهش ابعاد است که با وجود سادگی، توانایی زیادی از خود نشان داده است.

آموزش شبکه عصبی SOM

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

الگوریتم آموزش SOM به‌صورت زیر است:

۱. همه داده‌ها تک تک وارد شبکه می‌شوند.

۲. فاصله همه نورون‌ها از بردار ورودی محاسبه می‌شود.

۳. نزدیک‌ترین نورون به بردار ورودی تعیین و به‌عنوان نورون برنده انتخاب می‌شود.

۴. موقعیت نورون برنده با استفاده از رابطه زیر به‌روزرسانی می‌شود:

$$ \large W _ J ^ { t + 1 } = W _ J ^ t + \eta \cdot ( x – W _ J ^ t ) $$

5. موقعیت نورون‌های موجود در همسایگی نورون برنده با استفاده از رابطه زیر به‌روزرسانی می‌شود:

$$ \large W _ N ^ { t + 1 } = W _ N ^ t + \theta \cdot \eta \cdot ( x – W _ N ^ t ) $$

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

توجه داشته باشید که در مراحل 3 و 4 فاز رقابت (Competition) و در مرحله 5 فاز همکاری (Cooperation) وجود دارد و وجود این دو عامل، SOM را خاص‌تر می‌کند.

برای یادگیری برنامه‌نویسی با زبان پایتون، پیشنهاد می‌کنیم به مجموعه آموزش‌های مقدماتی تا پیشرفته پایتون فرادرس مراجعه کنید که لینک آن در ادامه آورده شده است.

  • برای مشاهده مجموعه آموزش‌های برنامه نویسی پایتون (Python) — مقدماتی تا پیشرفته + اینجا کلیک کنید.

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

حال برای پیاده‌سازی SOM وارد محیط برنامه‌نویسی شده و کتابخانه‌های مورد نیاز را فراخوانی می‌کنیم:

import numpy as np
import matplotlib.pyplot as plt

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

حال Random Seed و Plot Style را تنظیم می‌کنیم:

np.random.seed(0)
plt.style.use('ggplot')

برای پیاده‌سازی و آموزش مدل، به یک مجموعه داده ساده نیاز داریم. می‌توانیم یک مجموعه داده دوبعدی به شکل دایره توخالی (دونات) ایجاد کنیم.

تعداد داده‌ها، شعاع داخلی و شعاع خارجی دایره را تعیین می‌کنیم:

nD = 1000 # Data Size
r1 = 1 # Inner Radius
r2 = 2 # Outer Radius

حال یک آرایه برای ذخیره داده‌ها ایجاد می‌کنیم:

nX = 2
X = np.zeros((nD, nX)) # Placeholder for Data

عدد nX نشان‌دهنده تعداد ویژگی‌های هر داده است که به‌دلیل محدودیت در نمایش آن‌ها، از داده‌های دوبُعدی استفاده می‌کنیم.

حال یک حلقه While ایجاد می‌کنیم و تا زمانی که تعداد داده‌های مورد نیاز تأمین نشده باشد، عملیات را ادامه می‌دهیم:

i = 0
while i<nD:

حال باید یک داده به‌صورت تصادفی درون مربع اول انتخاب کنیم:

i = 0
while i<nD:
    x = np.random.uniform(-r2, +r2, nX)

حال باید شعاع داده از مرکز مختصات را حساب کنیم و در صورتی که داده دارای شعاعی بین $$r_1$$ و $$r_2$$ بود، آن را به‌عنوان داده جدید به مجموعه داده اضافه کنیم:

i = 0
while i<nD:
    x = np.random.uniform(-r2, +r2, nX)
    r = np.linalg.norm(x)
    if r1 <= r <= r2:
        X[i] = x
        i += 1

به این ترتیب، داده‌های مورد نیاز ایجاد می‌شود.

حال برای مصورسازی می‌توانیم به‌شکل زیر عمل کنیم:

plt.scatter(X[:, 0], X[:, 1], s=12, label='Data')
plt.title('Created Dataset')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend()
plt.show()

نتیجه این مصورسازی در نمودار زیر نشان داده شده است.

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

به این صورت، مجموعه داده مورد نیاز تولید می‌شود.

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

nK = 20 # Kohonen Neurons Count
W = np.random.uniform(-r2, +r2, (nK, nX)) # Kohonen Neurons Position

توجه داشته باشید که می‌توان موقعیت‌های اولیه را به صورت منظم نیز انتخاب کرد.

برای رسم نورون‌ها روی مجموعه داده خواهیم داشت:

plt.scatter(X[:, 0], X[:, 1], s=12, label='Data')
plt.plot(W[:, 0], W[:, 1], lw=1, c='b', marker='o', ms=4, label='Neurons')
plt.title('Created Dataset + Neurons Initial Position')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend()
plt.show()

در نهایت نمودار زیر حاصل می‌شود.

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

به این ترتیب، موقعیت نورون‌ها نیز مقداردهی اولیه می‌شود.

توجه داشته باشید که خطوط بین هر نورون، نشان‌دهنده همسایگی بین آن‌ها است.

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

nEpochs = 50 # Model Learning Epochs Count
LR = 0.5 # Learning Rate
dLR = -0.01 # Learning Rate Linear Decay
Theta = 1/4 # Cooperation Coefficient

حال می‌توانیم حلقه اصلی آموزش مدل را ایجاد کنیم:

for i in range(nEpochs):

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

for i in range(nEpochs):
    for x in X:

حال باید فاصله داده از هر نورون را محاسبه کنیم:

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)

حال با استفاده از Argmin می‌توانیم نورون برنده را تعیین کنیم:

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)
        J = np.argmin(D)

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

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)
        J = np.argmin(D)
        W[J] += LR * (x - W[J])

حال باید فاز همکاری را نیز وارد کد کنیم. با توجه به اینکه یک Lattice یک‌بُعدی استفاده می‌شود، برای نورون برنده J دو نورون J+1 و J-1 همسایه انتخاب و به‌روزرسانی می‌شوند:

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)
        J = np.argmin(D)
        W[J] += LR * (x - W[J])
        W[J+1] += Theta * LR * (x - W[J+1])
        W[J-1] += Theta * LR * (x - W[J-1])

این کد برای نورون‌ها موجود در اواسط Lattice درست کار می‌کند، اما برای نورون‌های موجود در مرز‌های Lattice دچار خطا می‌شود، بنابراین، باید شرط‌هایی به‌صورت زیر اضافه کنیم:

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)
        J = np.argmin(D)
        W[J] += LR * (x - W[J])
        if J == 0:
            W[J+1] += Theta * LR * (x - W[J+1])
        elif J == nK-1:
            W[J-1] += Theta * LR * (x - W[J-1])
        else:
            W[J+1] += Theta * LR * (x - W[J+1])
            W[J-1] += Theta * LR * (x - W[J-1])

به این ترتیب، همه مراحل پیاده‌سازی شدند.

حال در انتهای Epoch نرخ یادگیری را به‌روز‌رسانی می‌کنیم و پیام اتمام مرحله را می‌نویسیم:

for i in range(nEpochs):
    for x in X:
        D = np.linalg.norm(W - x, axis=1)
        J = np.argmin(D)
        W[J] += LR * (x - W[J])
        if J == 0:
            W[J+1] += Theta * LR * (x - W[J+1])
        elif J == nK-1:
            W[J-1] += Theta * LR * (x - W[J-1])
        else:
            W[J+1] += Theta * LR * (x - W[J+1])
            W[J-1] += Theta * LR * (x - W[J-1])
    LR += dLR
    print(f'Epoch {i+1} Ended.')

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

plt.scatter(X[:, 0], X[:, 1], s=12, label='Data')
plt.plot(W[:, 0], W[:, 1], lw=1, c='b', marker='o', ms=4, label='Neurons')
plt.title('Created Dataset + Neurons Final Position')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend()
plt.show()

که نمودار نهایی زیر حاصل می‌شود.

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

به این ترتیب، مشاهده می‌کنیم که نورون‌ها وضعیت مناسبی به خود می‌گیرند. حال اگر تعداد نورون‌ها را از 20 به 100 عدد برسانیم، نمودار زیر حاصل خواهد شد.

به این ترتیب مشاهده می‌کنیم که نورون‌ها وضعیت مناسبی به خود می‌گیرند. حال اگر تعداد نورون‌ها را از 20 به 100 عدد برسانیم، نمودار زیر حاصل خواهد شد:

مشاهده می‌کنیم که شبکه همه داده‌ها را به‌خوبی پوشش داده شده است، اما به‌دلیل زیاد بودن تعداد نورون‌ها نسبت به پیچیدگی مسئله، مشکلاتی در آموزش آن رخ داده است. اگر تعداد مناسبی از نورون‌ها انتخاب کنیم، حالتی میان این دو نمودار خواهیم داشت. شکل زیر این موضوع را به‌خوبی نشان می‌دهد.

شبکه عصبی SOM در پایتون

مشاهده می‌کنیم که نورون‌ها به‌صورت همگن پخش شده‌اند و همه نورون‌ها در موقعیت مناسبی درون داده‌ها قرار دارند.

اگر ضریب $$\theta$$ را از $$\frac 14$$ به $$\frac 1{10}$$ کاهش دهیم، نتایج نهایی به‌شکل زیر خواهد بود.

شبکه عصبی SOM در پایتون

مشاهده می‌کنیم که نظم موجود در حالت قبلی در این نتایج وجود ندارد که نشان‌دهنده اهمیت مقدار $$\theta $$ است.

معرفی فیلم آموزش یادگیری ماشین Machine Learning با پایتون Python

آموزش یادگیری ماشین Machine Learning با پایتون Python

فیلم آموزش یادگیری ماشین Machine Learning با پایتون Python در ۱۰ ساعت و در قالب ۹ درس ارائه شده است. عناوین درس‌های این آموزش، عبارت‌اند از:‌ مقدمه‌ای در رابطه با یادگیری ماشین، آشنایی با بسته NumPy، آشنایی با بسته Pandas، ترسیم داده‌ها، آشنایی مقدماتی با مباحث آماری، پیش‌پردازش داده‌ها، یادگیری نظارت‌شده، یادگیری غیرنظارت‌شده و کاهش ابعاد.

جمع‌بندی

در این مطلب به پیاده سازی شبکه عصبی SOM در پایتون پرداختیم. برای بررسی‌ها بیشتر، می‌توان موارد زیر را بررسی کرد:

  • مقداردهی اولیه به موقعیت نورون‌ها به‌صورت Lattice منظم
  • بررسی مقدار اینرسی در طول آموزش شبکه
  • بررسی روند آموزش مدل در شرایطی که نرخ یادگیری ثابت است

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

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

«سید علی کلامی هریس»، دانشجوی سال چهارم داروسازی دانشگاه علوم پزشکی تهران است. او در سال 1397 از دبیرستان «پروفسور حسابی» تبریز فارغ‌التحصیل شد و هم اکنون در کنار تحصیل در حوزه دارو‌سازی، به فعالیت در زمینه برنامه‌نویسی، یادگیری ماشین و تحلیل بازارهای مالی با استفاده از الگوریتم‌های هوشمند می‌پردازد.

نظر شما چیست؟

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

مشاهده بیشتر