۴- پردازش داده‌ها برای ماشین‌لرنینگ با sklearn و pandas

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

  • مقادیر گمشده-missing values: داده‌های که ممکنه در مجموعه داده‌های ما وجود نداشته باشند مثلا در زمان آمارگیری یا در زمان ورود به کامپیوتر وارد نشده باشن یا حتی ممکنه نمونه مورد نظر اون ویژگی رو نداشته باشه.
  • داده‌های کیفی(قطعی) یا categorical داده‌هایی هستند که معمولا با عدد بیان نمی‌شن این داده‌ها دو دسته‌ هستند:

> ترتیبی-ordinal که در اون‌ها ترتیب اهمیت داره مثل سایز لباس

> اسمی یا nominal که در اون‌ها ترتیب اهمیت نداره مثلا رنگ

پردازش داده‌ها
پردازش داده‌ها


بدون معطلی بریم سراغ راه‌حل‌ها.



مقادیر گمشده -missing values

اگر با دیتاست‌های مختلف کار کرده باشید حتما مقادیر گمشده را داخل آن‌ها مشاهده کردید جایی که به جای یک عدد یا عبارت مقدار nan یا Null رو مشاهده می‌کنید. متاسفانه ابزارهای محاسباتی امکان مدیریت این اتفاق‌ها را ندارند و برای همین قبل از ورود اون‌ها به این ابزار‌ها - مثل الگوریتم‌های یادگیری ماشین- لازم هست که اون‌ها رو کنترل کنیم.

یکی از راه‌حل‌های موجود برای کنترل این مسئله حذف نمونه‌ها با مقادیر گمشده است و مطابق بیشتر اوقات برای مدیریت داده‌های جدولی بهترین ابزار در پایتون کتاباخانه pandas است که برای این منظور متد dropna را برای استفاده در اختیار ما قرار می‌ده:

csv_data = '''A,B,C,D
1.0,2.0,3.0,4.0
5.0,,,8.0
10.0,11.0,12.0,'''
df = pd.read_csv(StringIO(csv_data))
df.dropna(axis=1)  # remove columns that contain missing values
df.dropna(thresh=3) # drop rows that have fewer than ۲ real values 
df.dropna(subset=['C'])# only drop rows where NaN appear in specific columns (here: 'C')

همونطور که در کد بالا مشاهده می‌کنید ۳ راه برای حذف این داده‌های پیشنهاد شد:

  • حذف تمامی سطر‌هایی که مقادیر گمشده دارند: dropna(axis=1) I
  • حذف تمامی سطر‌ها که حداقل دو داده حقیقی دارند: dropna(thresh=3) I
  • حذف سطر‌هایی که فقط از یک زیر مجموعه دارای مقادیر گمشده هستند.df.dropna(subset=['C']I
برای درک بهتر، مشاهده خروجی‌ها و بازی کردن با کدها حتما به صفحه گیتهاب این درس برید و با کلیک بر روی دکمه binder کد‌ها رو به صورت تعاملی اجرا کنید و خروجی رو مشاهده کنید.

کد گیتهاب

جایگزینی مقادیر گمشده

همیشه حذف مقادیر گمشده بهترین راه حل نیست و ممکنه که باعث بشه شما حجم زیادی از داده خودتون رو از دست بدید در این مواقع انتصاب یک مقدار به مقادیر گمشده می‌تونه راه حل بهتری باشه.

برای اینکار کتابخانه sklearn یک ابزار برای انتصاب مقادیر گمشده به شماه ارائه می‌دهد. SimpleImputer یک کلاس از پردازشگر‌های داده‌هااست که از طریق زیر در دسترس است:

from sklearn.impute import SimpleImputer

این کلاس به شما این امکان را می‌دهد که داده‌های گمشده را با ۴ استراتژی مختلف پر کنید:

  • میانگین سایر داده‌ها
  • میانه‌ سایر داده‌ها
  • بیشترین تکرار
  • و یا یک عدد ثابت

در این مثال داده‌ها با میانگین سایر داده‌ها جایگزین شده اند:

imr = SimpleImputer(missing_values=np.nan, strategy='mean')
imr = imr.fit(df.values)
imputed_data = imr.transform(df.values)

در این کد ابتدا یک انتصاب‌گر با قوانین مشخص خودمون می‌سازیم. انتصابگری که داده‌های nan را با میانگین سایر داده‌ها جایگزین می‌کنه و بعد از شناسایی میانگین‌ها - fit- داده‌ها را با مکانیزم انتصابی خودش تبدیل می کند.

انتصابگر-SimpleImputer ساده تنها انتصابگر sklearn نیست و خوبه که برای تمرین نگاهی به سایر انتصاب‌گرها KNNImputer مثل داشته باشد.



داده‌های کیفی- categorical


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

داده‌های ترتیبی

داده‌هایی که ترتیب آن‌ها اهمیت داشته باشه باید با احتیاط و توجه به ماهیتشون به مقادیر عددی تبدیل بشن. به عنوان اندازه لباس ممکنه به صورت کوچک، متوسط و یا بزرگ در داده‌ها وجود داشته باشند و این مورد احتمالا در الگوریتم یادگیری ماشین ما تاثیر گذار خواهد بود. رمز‌گذاری encoding برای تبدیل این‌داده‌ها معمولا به صورت دستی و با استفاده از تابع map در کتابخانه pandas صورت می‌گیره:

size_mapping = {'XL': 3,
                'L': 2,
                'M': 1}
df['size'] = df['size'].map(size_mapping)

در بخش اول یک تناظر mapping بین سایز لباس و اعداد معرفی کردم و بعد از آن با استفاده از متد map سایز‌ها را به فرمت جدید تبدیل کردیم. اگر نیاز داشته باشیم که از داده‌های جدید رمزشکافی -decoding- کنیم می‌توانیم با استفاده از dict comperhension تناظر معکوس رو برقرار کنیم.

inv_size_mapping = {v: k for k, v in size_mapping.items()}
df['size'].map(inv_size_mapping)

داده‌های اسمی

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

برای تبدیل برچسب‌ها دو راه حل وجود دارد:

‍۱- استفاده از یک تناظر که با استفاده از dict comperhension ساخته می‌شه

۲- استفاده از کلاس LabelEncoder از کتابخانه sklear

class_mapping = {label: idx for idx, label in enumerate(np.unique(df['classlabel']))}
df['classlabel'] = df['classlabel'].map(class_mapping)
inv_class_mapping = {v: k for k, v in class_mapping.items()}df['classlabel'] = df['classlabel'].map(inv_class_mapping)
#### LabelEncoder
from sklearn.preprocessing import LabelEncoder
class_le = LabelEncoder()
y = class_le.fit_transform(df['classlabel'].values)
class_le.inverse_transform(y) ## same as inv_class_mapping

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

روش پیشنهادی در ادبیات یادگیری ماشین لرنینگ به one-hot encoding مشهور است و در ادبیات اقتصادسنجی به متغیر دامی یا متغیر ساختگی شناخته می‌شه. در این روش به ازای هر برچسب (مثلا به ازای هر رنگ) یک ستون جدید به داده‌ها اضافه میکند که برای نمونه‌هایی که منطبق بر اون ویژگی هستند(مثلا قرمز رنگ) ۱ و برای سایر نمونه‌‌ها صفر است با این روش هیچ گونه ترتیب رو برای داده‌ها در نظر نمی‌گیرد. برای پیاده‌سازی این روش هم دو راه حل وجود داره:

۱- استفاده از OneHotEncoder از کتابخانه sklearn

۲- استفاده از تابع get_dummies از کتابخانه pandas

from sklearn.preprocessing import OneHotEncoder
X = df[['color', 'size', 'price']].values
color_ohe = OneHotEncoder()
color_ohe.fit_transform(X[:, 0].reshape(-1, 1)).toarray()

در این روش اول داده‌های ورودی را در یک متغیر مجزا X نگهداری می‌کنیم بعد از اون یک رمزنگار onehot برای رمزنگاری رنگ‌ها انتخاب می‌کنیم و بعد با متد fit_transform رمزنگار را آماده تبدیل کردن میکنیم و به صورت همزمان داده‌ها رو به حالت onehot رمزنگاری می‌کنیم. توجه داشته باشید که reshape(-1,1) l برای تبدیل داده‌های رنگ به حالت ستونی و جلوگیری از تغییر داده‌های دو ستون دیگه است. برای تمرین سعی کنید که کد بالا را بدون استفاده از reshape اجرا کنید.

روش دوم با استفاده از پانداس است، در این روش شما تنها با استفاده از داده‌های ورودی در تابع pd.get_dummies یک دیتافریم جدید با داده‌های جدید خواهید داشت. اگر به تابع پارامتر drop_first را فعال کنید، اولین متغیر به عنوان متغیر مرجع در نظر گرفته شده و حذف می‌شود.

pd.get_dummies(df[['price', 'color', 'size']])
pd.get_dummies(df[['price', 'color', 'size']], drop_first=True)



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

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

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

https://virgool.io/@ghodsizadeh/%D9%82%D8%B3%D9%85%D8%AA-%D8%B5%D9%81%D8%B1%D8%AF%D9%88%D8%B1%D9%87-%DB%8C%D8%A7%D8%AF%DA%AF%DB%8C%D8%B1%DB%8C-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%B1%D9%88%D8%B2%D9%87%D8%A7%DB%8C-%D9%82%D8%B1%D9%86%D8%B7%DB%8C%D9%86%D9%87-ooa5tkefxkjw


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

https://bit.ly/39gnJ6H

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

https://bit.ly/2UgZhOp