توی قسمت اول این آموزش اومدیم یه مثال ساده تعریف کردیم برای خودمون برای تمرین رگرسیون با دیتاست NYCTaxiFares و یه سری پیش پردازشهای اولیه روی دیتا انجام دادیم. توی این قسمت میخوایم یه ذره حرفه ای تر کار کنیم و توی کار با دیتامون عمیقتر بشیم.
یه مفهوم اولیه ای که در مورد داده ها وجود داره تعریف انواع اونهاست.مثلا داده های اسمی، عددی گسسته، عددی پیوسته، boolean ، categorical و غیره. اگه میتونین اینجا رو بخونین.
مثلا اسم رنگها میتونه یه متغیر اسمی باشه، نمره آدما توی هر درسی میتونه عددی پیوسته باشه. اینکه مبتلا به یه بیماری هستن یا نه داده بولین هست. یه نوع داده ی خیلی پرکاربرد داده های دسته بندی یا categorical هستن. که خب خیلی پراستفاده ان .
وقتی مقادیر یه فیچر جوریه که میشه دیتا رو برحسب اون دسته بندی کرد بهش میگیم categorical . حالا جنسش میتونه هر چی باشه. string باشه، تاریخ باشه، یا حتی عدد باشه. منتها فرق این عدد با نوع داده عددی چیه؟ دیگه نمیشه کارای آماری روش انجام داد. مثلا رتبه بندی. مثلا نمیتونی میانگین رتبه آدما رو بگیری. بیمعنی میشه.
یه چیز خوبی که این متغیرهای categorical دارن اینه که میشه روشون groupby زد با پانداس. و پلات کشید و خلاصه که چیزای خوبین :)
حالا بیاید دیتای categorical رو از دیتای عددی جدا کنیم که برای مرحله بعد بهش احتیاج داریم.
تا اینجای کار ستونهایی که داریم چیا هستن:
df.columns
تاریخ و ساعت سوار کردن مسافر، مقدار کرایه، دسته بندی کرایه، مختصات سوار کردن و پیاده کردن مسافر، تعداد مسافرها، مسافت طی شده، ساعت به وقت نیویورک، ساعت، صبح و بعدازظهر بودن و روز هفته.
الان متغیرهای categorical ما کدومان؟ ببینین . 'fare_amount', 'fare_class'
که بیشتر لیبل هستن و بعدا باهاشون کار داریم. 'dist_km'
هم که یه متغیر عددیه. چون مثلا میتونیم روش min و max بگیریم. یا مثلا 'passenger_count'
حالا ولی متغیرهایی مثل 'AMorPM'
و 'Weekday'
بیشتر به categorical میخورن چون میشه طبق اونها یه دسته بندی ای انجام داد. حالا پس بیاید یه متغیر جدید تعریف کنیم و اسم ستونهای categorical رو توش ذخیره کنیم. لیبلها رو جدا و متغیرهای عددی رو هم جدا سیو کنیم.
cat_cols = ['Hour', 'AMorPM', 'Weekday'] cont_cols = ['pickup_latitude', 'pickup_longitude', 'dropoff_latitude', 'dropoff_longitude', passenger_count', 'dist_km'] y_col = ['fare_amount']
یه چیزی که جادی خیلی توی اموزشهای ماشین لرنینگش میگفت data experts بود. ینی کسانی که با دیتا آشنایی دقیقتر و بهتری دارن. ینی تشخیص داده ی عددی از categorical به این آسونیا نیست . گاهی توی یه پروژه یه دیتایی بهتون میدن که شما تا حالا به گوشتون هم نخورده و این متخصصهای داده هستن که بهتون میگن مثلا این فیچر عددیه یا چی.
اگه از من میشنوین سعی کنین خودتون توی پروژه ها سریع آشنایی پیدا کنین با فضای کار و مسئله و خیلی سیس پیور دیولوپر ( pure developer ) برندارین چون برچسب خنگی روتون میمونه :)
حالا چرا اینکار رو کردیم ؟ تا بتونیم با این مقادیر categorical کار کنیم. و برای اینکار باید تبدیلشون کنیم به عدد. ینی اینکه به am یا pm توی ستون AMorPM عدد تخصیص بدیم. کلا باید همه داده ها با هر نوعی رو به عدد تبدیل کنیم. این یکی از مراحل اولیه پیش پردازش دیتاس.
حالا بیاید یه بار دیگه به انواع داده هامون یه نگاه بندازیم :
df.dtypes
میبین که ستونهای categorical مون از نوع string هستند (object) و عددی ها float اند. پانداس یه نوع داده داره به اسم category . میایم تایپ اون سه تا ستون رو میذاریم category تا بتون از متدهای به دردبخور پانداس استفاده کنیم:
for cat in cat_cols: df[cat] = df[cat].astype('category')
با استفاده از متد astype نوع فیچرهایی که توی متغیر cat_cols ذخیره کرده بودیم رو گذاشتیم category . حالا نوع داده های دیتافریممون رو میبینیم که تغییر کرده :
حالا بیاید ببینیم با تغییر نوع فیچرها از string به category مقادیرشون چی شد:
df['AMorPM'].head()
خب میبینید که مقادیر موجود در این category فقط دو تا هست : am و pm .دو تا فیچر باقیمونده هم همینه. خودتون تست کنین.
حالا مثلا یه چیزی که با تبدیل نوع داده به category اولین کار اینه که به ازای مقادیر یونیک ایندکس داریم. ینی الان برای am و pm مقدار 0 و 1 ست شده :
df['AMorPM'].head().cat.codes
حالا بیاید از این مسخره بازیا رد بشیم و یه ذره موآپ کنیم. بیاید با استفاده از دیتای کتگوریکال ( از تغییر زبان کیبردم خسته شدم ) یه تنسور بسازیم. بعدا از این تنسور به عنوان امبدینگ دیتای ورودی به شبکه استفاده میکنیم.
hr = df['Hour'].cat.codes.values ampm = df['AMorPM'].cat.codes.values wkdy = df['Weekday'].cat.codes.values cats = np.stack([hr, ampm, wkdy], 1) cats[:5]
اون 1 مقدار متغیر axis هست. توی متد stack مشخص میکنه ارایه ها سطری با هم ترکیب بشن یا ستونی . حالا برای تبدیل این ماتریس 3 در 120000 به تنسور خیلی ساده مینویسیم :
conts = torch.tensor(cats, dtype=torch.float)
این استک کردن آرایه های مقادیر رو میتونیم توی خط هم انجام بدیم. بنابراین برای مقادیر عددی پیوسته ساده تر مینویسیم :
conts = np.stack([df[col].values for col in cont_cols], 1) conts = torch.tensor(conts, dtype=torch.float) conts[:5]
آرایه cont_cols رو بالا تعریف کردیم و لیست فیچرهای عددی مون بود. ورودی متد stack رو ببینیند یه حلقه یه خطی نوشتیم برای فیچرهای عددی داخل لیست و valueهای داخلش رو گرفتیم. استک کردیم به صورت ستونی. در نهایت هم که ازش که تنسور ساختیم
حالا بیاید لیبل ها رو تنسور کنیم :
y = torch.tensor(df[y_col].values, dtype=torch.float).reshape(-1,1) y[:5]
این قسمت reshape(-1,1) برای اینه که مطمئن بشیم تنسور به صورت ستونی ذخیره شده و نه یک آرایه فلت ساده. ینی هر سطرش یه مقدار داره و 120000 تا سطر داره.
خب این هم از این. تا اینجای کار فقط پیش پردازش دیتا انجام دادیم. از قسمت بعدی میریم سراغ طراحی شبکه که اون هم خیلی ساده است.