برنامه نویسی و طراحی سایت

متعادل کردن داده در پایتون — بخش اول: وزن دهی دسته ها

متعادل کردن داده در پایتون — بخش اول: وزن دهی دسته ها

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

فهرست مطالب این نوشته
دلایل عدم تعادل داده‌ها

متعادل کردن داده در پایتون: روش وزن دهی دسته ها

جمع‌بندی

faradars mobile

دلایل عدم تعادل داده‌ها

در مسائل طبقه‌بندی، تعداد داده‌های موجود در هر دسته حائز اهمیت است و به هم خوردن این تعادل، باعث مشکلاتی در مدل‌سازی می‌شود. دو دلیل عمده برای این اتفاق وجود دارد:

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

کلیک کنید

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

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

برای مثال، فرض کنید یک مسئله طبقه‌بندی با 4 دسته وجود دارد که سهم هر دسته از کل مجموعه داده به شرح زیر است:

سهم از کل دسته
9% 1
12% 2
71% 3
8% 4

اگر یک مدل Dummy (مدلی که بدون توجه با داده ورودی، تنها Label مربوط به دسته غالب را در خروجی می‌دهد) روی این مجموعه داده آموزش دهیم، خیلی ساده به دقت %71 می‌رسیم که در ظاهر عدد بسیار مناسبی است. اما با بررسی Recall و F1 Score مربوط به سایر دسته‌ها، متوجه اشکال مدل می‌شویم.

آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم
فیلم آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم در تم آف

کلیک کنید

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

  1. وزن‌دهی به هر دسته با توجه به تعداد داده‌های آن
  2. تغییر مجموعه داده:
    1. حذف بخشی از داده‌های دسته‌های موجود در اکثریت
    2. افزایش داده‌های دسته‌های موجود در اقلیت

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

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

متعادل کردن داده در پایتون: روش وزن دهی دسته ها

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

آموزش کتابخانه scikit-learn در پایتون – الگوریتم های یادگیری ماشین
فیلم آموزش کتابخانه scikit-learn در پایتون – الگوریتم های یادگیری ماشین در تم آف

کلیک کنید

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

import numpy as np
import sklearn.metrics as met
import sklearn.datasets as dt
import sklearn.linear_model as li
import sklearn.model_selection as ms

هر فراخوانی به ترتیب برای موارد زیر مورد استفاده قرار خواهد گرفت:

  1. کار و عملیات روی آرایه‌ها
  2. محاسبه معیارهای سنجش مدل‌ها
  3. فراخوانی داده
  4. استفاده از مدل‌های خطی
  5. تقسیم داده

حال Random State را تنظیم می‌کنیم:

np.random.seed(0)

برای شروع، ابتدا باید یک مجموعه داده انتخاب و آن را فراخوانی کنیم. به این منظور از مجموعه داده IRIS استفاده خواهیم کرد:

IRIS = dt.load_iris()
X = IRIS.data
Y = IRIS.target
TN = IRIS.target_names

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

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

کلیک کنید

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

N = {tn: Y[Y == i].size for i, tn in enumerate(TN)}

به این ترتیب، تعداد داده‌های هر دسته با کلید مربوط به اسم مروبوطه در دیکشنری N ذخیره می‌شود. با خروجی گرفتن از N خواهیم داشت:

{'setosa': 50, 'versicolor': 50, 'virginica': 50}

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

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

trX, teX, trY, teY = ms.train_test_split(X, Y,
                                         train_size=0.7,
                                         random_state=0)

یک مدل «رگرسیون لجستیک» (Logistic Regression) روی مجموعه داده آموزش می‌دهیم:

Model = li.LogisticRegression(random_state=0)
Model.fit(trX, trY)

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

trAc = 100 * Model.score(trX, trY)
teAc = 100 * Model.score(teX, teY)

print(f'Train Accuracy: {round(trAc, 2)} %')
print(f'Test  Accuracy: {round(teAc, 2)} %')

که خواهیم داشت:

trAc = 98.09 %
teAc = 97.77 %

به این ترتیب مشاهده می‌کنیم که دقت بسیار مناسب است.

آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم
فیلم آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم در تم آف

کلیک کنید

حال Classification Report را محاسبه و نشان می‌دهیم:

tePr = Model.predict(teX)

teCR = met.classification_report(teY, tePr, target_names=TN)

print(f'Test Classification Report:n{teCR}')

که در این بخش نیز خروجی زیر حاصل می‌شود:

Test Classification Report:

               precision    recall  f1-score   support

      setosa       1.00      1.00      1.00        16
  versicolor       1.00      0.94      0.97        18
   virginica       0.92      1.00      0.96        11

    accuracy                           0.98        45
   macro avg       0.97      0.98      0.98        45
weighted avg       0.98      0.98      0.98        45

و به این ترتیب مشاهده می‌کنیم که مقدار Recall و F1 Score برای تمامی دسته‌ها مناسب است و بنابراین در این حالت مشکلی وجود ندارد.

حال مقداری عدم تعادل در اندازه دسته‌ها ایجاد می‌کنیم. برای این منظور، 50 داده از دسته اول، 10 داده از دسته دوم و 15 داده از دسته سوم انتخاب می‌کنیم.

آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم
فیلم آموزش یادگیری ماشین و پیاده سازی در پایتون Python – بخش یکم در تم آف

کلیک کنید

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

ind = list(range(0, 50)) + list(range(50, 60)) + list(range(100, 115))

حال ویژگی‌های ورودی و خروجی را نیز براساس ind دوباره تعریف می‌کنیم:

X = IRIS.data[ind]
Y = IRIS.target[ind]

حال اگر دیکشنری N را نمایش دهیم، به اعداد زیر می‌رسیم:

{'setosa': 50, 'versicolor': 10, 'virginica': 15}

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

حال اگر مدل را آموزش دهیم به دقت‌های زیر می‌رسیم:

Train Accuracy: 100.0 %
Test  Accuracy: 78.26 %

که به نظر می‌رسد مدل از شرایط نسبتاً مناسبی برخوردار است. حال اگر teCR را نمایش دهیم:

Test Classification Report:

               precision    recall  f1-score   support


      setosa       0.92      1.00      0.96        12
  versicolor       0.67      0.33      0.44         6
   virginica       0.57      0.80      0.67         5

    accuracy                           0.78        23
   macro avg       0.72      0.71      0.69        23
weighted avg       0.78      0.78      0.76        23

متوجه می‌شویم که Recall و F1 Score برای دسته‌های Versicolor و Virginica مناسب نیست.

آموزش انتخاب مدل های یادگیری ماشین در پایتون Python
فیلم آموزش انتخاب مدل های یادگیری ماشین در پایتون Python در تم آف

کلیک کنید

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

رفع مشکل

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

$$w_{1} n_{1}=w_{2} n_{2}$$

از طرفی مجموع این مقادیر نیز برابر 1  خواهد بود:

$$w_{1} n_{1}+w_{2} n_{2}=1$$

از حل این دستگاه دومعادله و دو مجهول به جواب‌های زیر می‌رسیم:

$$begin{aligned}
&w_{1}=frac{1}{2 times n_{1}} \
&w_{2}=frac{1}{2 times n_{2}}
end{aligned}$$

که اگر این روابط را تعمیم دهیم، خواهیم داشت:

$$w_{x}=frac{1}{C times n_{i}}$$

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

nTotal = Y.size

W = {i: (nTotal - N[TN[i]]) / (2 * nTotal) for i in range(3)}

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

{0: 0.16, 1: 0.43, 2: 0.40}

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

آموزش تجزیه و تحلیل و آماده سازی داده ها با پایتون Python
فیلم آموزش تجزیه و تحلیل و آماده سازی داده ها با پایتون Python در تم آف

کلیک کنید

اکنون مدل ایجاد شده را تغییر داده و وزن دسته‌ها را به آن می‌دهیم:

Model = li.LogisticRegression(random_state=0, class_weight=W)

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

Train Accuracy: 94.23 %
Test Accuracy: 78.26 %

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

همچنین Classification Report به شکل زیر درخواهد آمد:

Test Classification Report:

               precision    recall  f1-score   support

       setosa       0.92      1.00      0.96        12
  versicolor       1.00      0.17      0.29         6
   virginica       0.56      1.00      0.71         5

     accuracy                           0.78        23
   macro avg       0.83      0.72      0.65        23
weighted avg       0.86      0.78      0.73        23

که مشاهده می‌کنیم مقدار Recall و F1 Score برای دسته virginica بهبود یافته است.

توجه داشته باشید که کاهش معیار‌های گفته شده برای دسته Versicolor را نیز داریم، اما در کل avg برای معیار‌های مختلف افزایش یافته است که نشانه خوبی از اثر وزن‌دهی است.

مجموعه آموزش داده کاوی و یادگیری ماشین
فیلم مجموعه آموزش داده کاوی و یادگیری ماشین در تم آف

کلیک کنید

به این ترتیب، توانستیم یک مدل رگرسیون لجستیک (Logistic Regression) را روی مجموعه داده‌ تغییر یافته IRIS آموزش دهیم و با وجود نامتعادل بودن دسته‌ها، نتایج مناسب‌تری بگیریم.

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

جمع‌بندی

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

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

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.