چون قرار است تبدیلهای مختلفی را روی مجموعهٔ آموزشی کامل امتحان کنید، بهتر است نسخهای از دادهٔ اصلی بسازید تا بعداً بتوانید به آن برگردید:
housing = strat_train_set.copy()
مصورسازی دادههای جغرافیایی
از آنجا که مجموعهداده شامل اطلاعات جغرافیایی - عرض و طول جغرافیایی - است، بهتر است برای دیدن ساختار داده نمودار پراکندگی همهٔ ناحیهها را رسم کنید:
housing.plot(kind="scatter", x="longitude", y="latitude", grid=True)
plt.show()
شکل ۲-۱۱. نمودار پراکندگی جغرافیایی دادهها
شکل کلی واقعاً شبیه کالیفرنیاست، اما جز آن دیدن الگوی مشخصی دشوار است. با تنظیم گزینهٔ alpha روی ۰٫۲، محلهایی که چگالی نقاط داده بالاست بسیار واضحتر میشوند:
housing.plot(kind="scatter", x="longitude", y="latitude", grid=True, alpha=0.2)
plt.show()
شکل ۲-۱۲. مصورسازی بهتر که ناحیههای پرتراکم را برجسته میکند
حالا تصویر بسیار گویاتر است: ناحیههای با چگالی زیاد بهوضوح دیده میشوند؛ منطقهٔ خلیج، اطراف Los Angeles و San Diego، و خطی بلند از ناحیههای نسبتاً پرتراکم در Central Valley، بهویژه اطراف Sacramento و Fresno. مغز ما در دیدن الگوها در تصویر بسیار توانمند است، اما گاهی باید با پارامترهای مصورسازی بازی کنید تا الگوها برجسته شوند.
اکنون قیمت مسکن را نیز وارد مصورسازی میکنید. شعاع هر دایره جمعیت ناحیه را نشان میدهد - گزینهٔ s - و رنگ، قیمت را - گزینهٔ c. در اینجا از نقشهرنگ ازپیشتعریفشدهٔ jet استفاده میشود که از آبی برای مقادیر پایین تا قرمز برای قیمتهای بالا امتداد دارد:۸
housing.plot(kind="scatter", x="longitude", y="latitude", grid=True,
s=housing["population"] / 100, label="population",
c="median_house_value", cmap="jet", colorbar=True,
legend=True, sharex=False, figsize=(10, 7))
plt.show()
شکل ۲-۱۳. قیمت مسکن کالیفرنیا: قرمز گران و آبی ارزان است و دایرههای بزرگتر ناحیههای پرجمعیتتر را نشان میدهند
این تصویر نشان میدهد قیمت مسکن ارتباط زیادی با موقعیت - برای مثال نزدیکی به اقیانوس - و همچنین با تراکم جمعیت دارد؛ چیزی که احتمالاً از قبل انتظار داشتید. یک الگوریتم خوشهبندی میتواند برای یافتن خوشههای اصلی و افزودن ویژگیهای تازهای که نزدیکی به مرکز خوشهها را میسنجند مفید باشد. ویژگی ocean_proximity نیز احتمالاً سودمند است، هرچند در شمال کالیفرنیا قیمت مسکن در ناحیههای ساحلی چندان بالا نیست، بنابراین رابطه به یک قاعدهٔ ساده محدود نمیشود.
جستوجوی همبستگیها
چون مجموعهداده خیلی بزرگ نیست، میتوانید ضریب همبستگی استاندارد - که «r پیرسون» نیز نامیده میشود - را میان هر جفت ویژگی بهآسانی با متد corr() محاسبه کنید:
corr_matrix = housing.corr()
اکنون میتوانید ببینید هر ویژگی چه میزان با قیمت میانهٔ خانه همبسته است:
>>> corr_matrix["median_house_value"].sort_values(ascending=False)
median_house_value 1.000000
median_income 0.688380
total_rooms 0.137455
housing_median_age 0.102175
households 0.071426
total_bedrooms 0.054635
population -0.020153
longitude -0.050859
latitude -0.139584
Name: median_house_value, dtype: float64
ضریب همبستگی از ۱- تا ۱ تغییر میکند. وقتی به ۱ نزدیک باشد یعنی همبستگی مثبت قوی وجود دارد؛ برای نمونه، با افزایش درآمد میانه قیمت میانهٔ خانه نیز تمایل به افزایش دارد. وقتی ضریب به ۱- نزدیک باشد یعنی همبستگی منفی قوی وجود دارد؛ در دادهٔ ما میان عرض جغرافیایی و قیمت میانهٔ خانه یک همبستگی منفی ضعیف دیده میشود، یعنی هرچه به شمال میروید قیمتها اندکی میل به کاهش دارند. ضرایب نزدیک صفر نشان میدهند همبستگی خطی وجود ندارد.
روش دیگر برای بررسی همبستگی میان ویژگیها استفاده از تابع scatter_matrix() در Pandas است. این تابع هر ویژگی عددی را در برابر همهٔ ویژگیهای عددی دیگر رسم میکند. اکنون ۱۱ ویژگی عددی داریم، پس در صورت رسم همهٔ آنها 11² = 121 نمودار ساخته میشود که در یک صفحه جا نمیگیرد. بنابراین روی چند ویژگی امیدوارکننده که ظاهراً بیشترین همبستگی را با قیمت میانهٔ خانه دارند تمرکز میکنیم:
from pandas.plotting import scatter_matrix
attributes = ["median_house_value", "median_income", "total_rooms",
"housing_median_age"]
scatter_matrix(housing[attributes], figsize=(12, 8))
plt.show()
شکل ۲-۱۴. ماتریس پراکندگی هر ویژگی عددی منتخب را در برابر ویژگیهای دیگر رسم میکند و روی قطر اصلی، از بالا-چپ تا پایین-راست، هیستوگرام مقادیر همان ویژگی نمایش داده میشود
اگر Pandas هر متغیر را در قطر اصلی با خودش رسم میکرد، قطر اصلی فقط از خطهای مستقیم تشکیل میشد و اطلاعات مفیدی نمیداد. بنابراین بهجای آن هیستوگرام هر ویژگی را نمایش میدهد؛ گزینههای دیگری نیز وجود دارند که در مستندات Pandas توضیح داده شدهاند.
با نگاه به نمودارهای پراکندگی همبستگی، امیدوارکنندهترین ویژگی برای پیشبینی قیمت میانهٔ خانه «درآمد میانه» به نظر میرسد؛ بنابراین نمودار این دو را بزرگتر بررسی میکنیم:
housing.plot(kind="scatter", x="median_income", y="median_house_value",
alpha=0.1, grid=True)
plt.show()
شکل ۲-۱۵. درآمد میانه در برابر قیمت میانهٔ خانه
نمودار چند نکته را آشکار میکند. نخست، همبستگی واقعاً نسبتاً قوی است: روند صعودی بهروشنی دیده میشود و نقاط بیش از حد پراکنده نیستند. دوم، سقف قیمتیای که قبلاً دیده بودید بهصورت خط افقی در ۵۰۰ هزار دلار کاملاً مشخص است. اما خطوط مستقیم کموضوح دیگری هم دیده میشوند: خط افقی نزدیک ۴۵۰ هزار دلار، خطی دیگر نزدیک ۳۵۰ هزار دلار، شاید یکی نزدیک ۲۸۰ هزار دلار و چند خط دیگر پایینتر. شاید بهتر باشد ناحیههای متناظر با این خطوط را حذف کنید تا الگوریتمها یاد نگیرند این ویژگیهای مصنوعی داده را بازتولید کنند.
شکل ۲-۱۶. ضریب همبستگی استاندارد چند مجموعهداده - منبع: Wikipedia، تصویر در مالکیت عمومی
آزمایش ترکیب ویژگیها
بخشهای قبلی چند روش برای کاوش داده و بهدستآوردن بینش نشان دادند. تعدادی خصوصیت غیرعادی داده را شناسایی کردید که شاید پیش از تغذیهٔ داده به الگوریتم یادگیری ماشین نیاز به پاکسازی داشته باشند، و چند همبستگی جالب میان ویژگیها - بهویژه با ویژگی هدف - پیدا کردید. همچنین دیدید بعضی ویژگیها توزیع چوله به راست دارند؛ بنابراین شاید بخواهید آنها را تبدیل کنید، مثلاً با محاسبهٔ لگاریتم یا جذر. جزئیات در هر پروژه بسیار متفاوت خواهد بود، اما ایدههای کلی مشابهاند.
آخرین کاری که ممکن است پیش از آمادهسازی داده برای الگوریتمهای یادگیری ماشین انجام دهید، آزمایش ترکیبهای گوناگون ویژگیهاست. برای نمونه، تعداد کل اتاقها در یک ناحیه بدون دانستن تعداد خانوارها چندان مفید نیست؛ چیزی که واقعاً اهمیت دارد تعداد اتاق بهازای هر خانوار است. بههمین شکل، تعداد کل اتاقخواب بهتنهایی اطلاعات محدودی دارد و احتمالاً بهتر است آن را نسبت به کل اتاقها بسنجید. جمعیت بهازای هر خانوار نیز ترکیب جالب دیگری است. ویژگیهای تازه را چنین میسازید:
housing["rooms_per_house"] = housing["total_rooms"] / housing["households"]
housing["bedrooms_ratio"] = housing["total_bedrooms"] / housing["total_rooms"]
housing["people_per_house"] = housing["population"] / housing["households"]
سپس ماتریس همبستگی را دوباره بررسی میکنید:
>>> corr_matrix = housing.corr()
>>> corr_matrix["median_house_value"].sort_values(ascending=False)
median_house_value 1.000000
median_income 0.688380
rooms_per_house 0.143663
total_rooms 0.137455
housing_median_age 0.102175
households 0.071426
total_bedrooms 0.054635
population -0.020153
people_per_house -0.038224
longitude -0.050859
latitude -0.139584
bedrooms_ratio -0.256397
Name: median_house_value, dtype: float64
نتیجه بد نیست. ویژگی جدید bedrooms_ratio نسبت به تعداد کل اتاقها یا اتاقخوابها همبستگی بسیار بیشتری با قیمت میانهٔ خانه دارد. ظاهراً خانههایی که نسبت اتاقخواب به کل اتاق پایینتری دارند معمولاً گرانترند. تعداد اتاق بهازای خانوار نیز از تعداد کل اتاقهای یک ناحیه اطلاعات بیشتری میدهد؛ روشن است که خانههای بزرگتر معمولاً گرانترند.
این مرحلهٔ کاوش لازم نیست کاملاً جامع باشد. هدف آن است که از ابتدا در مسیر درست قرار بگیرید و سریع بینشهایی کسب کنید که به ساخت نخستین نمونهٔ اولیهٔ نسبتاً خوب کمک کنند. البته فرایند تکرارشونده است: وقتی نمونهٔ اولیه راه افتاد، میتوانید خروجی آن را تحلیل کنید، بینشهای تازه به دست آورید و دوباره به مرحلهٔ کاوش بازگردید.
آمادهسازی داده برای الگوریتمهای یادگیری ماشین
اکنون زمان آمادهسازی داده برای الگوریتمهاست. بهتر است این کار را دستی انجام ندهید و بهجای آن توابعی برای تبدیل داده بنویسید. این کار چند فایده دارد:
- میتوانید همین تبدیلها را بهآسانی روی هر مجموعهدادهٔ دیگری بازتولید کنید؛ مثلاً دفعهٔ بعد که دادهٔ تازه دریافت میکنید.
- بهتدریج کتابخانهای از توابع تبدیل خواهید ساخت که در پروژههای آینده دوباره قابل استفاده است.
- میتوانید همین توابع را در سامانهٔ عملیاتی بهکار بگیرید تا دادهٔ جدید پیش از ورود به الگوریتمها همان تبدیلها را طی کند.
- میتوانید تبدیلهای مختلف را راحت آزمایش و تعیین کنید کدام ترکیب تبدیلها بهترین نتیجه را میدهد.