برای متخصصین علم داده ، رسیدگی به داده های مفقود شده بخش مهمی از فرآیند پاکسازی داده ها و توسعه مدل است. در این پست ، ما در مورد چگونگی ساختن مدلهایی که می توانند برای جایگزینی مقادیر گمشده یا خراب در داده ها استفاده شوند ، بحث خواهیم کرد.
برای اهداف ما ، ما با مجموعه داده های نوشیدنی کار خواهیم کرد که در اینجا می توانید پیدا کنید.
برای شروع ، بیایید داده ها را به صورت دیتافریم در پانداز بخوانیم:
import pandas as pd
df = pd.read_csv("winemag-data-130k-v2.csv")
پنج ردیف اول را چاپ می کنیم.
print(df.head())
بیایید یک نمونه تصادفی 500 تایی از این داده ها بگیریم. این به سرعت بخشیدن به آموزش و آزمون مدل (model training and testing) کمک می کند ، به راحتی می توانید این مقدار نمونه را تغییر دهید:
import pandas as pd
df = pd.read_csv("winemag-data-130k-v2.csv").sample(n=500, random_state = 42)
حال ، از دستور info استفاده می کنیم که به ما کمک می کند کدام ستون ها مقادیر مفقود شده دارند:
print(df.info())
چندین ستون مقداری کمتر از 500 (غیر تهی) دارند که نشان از مقادیر مفقود شده دارند. ابتدا بیایید ساختن مدلی را که مقادیر “قیمت (price)” گم شده را با استفاده از “امتیاز (points)” جایگزاری می کند را در نظر بگیریم. برای شروع ، بیایید همبستگی (correlation) بین “قیمت” و “امتیاز” را چاپ کنیم:
print("Correlation: ", df['points'].corr(df['price']))
می بینیم که همبستگی مثبت ضعیفی وجود دارد. بیایید یک مدل رگرسیون خطی (linear regression model) ایجاد کنیم که از “امتیاز” برای پیش بینی “قیمت” استفاده می کند. ابتدا ماژول “LinearRegresssion” را از “scikit-Learn” وارد می کنیم:
from sklearn.linear_model import LinearRegression
می خواهیم داده های خود را برای آموزش و آزمون تقسیم کنیم ، اما برای پیش بینی های خود باید از قیمت های معتبر استفاده کنیم. پس دیتافریم را بر اساس مقادیر مثبت قیمت فیلتر می کنیم:
import numpy as np
df_filter = df[df['price'] > 0].copy()
اکنون لیست هایی که برای مقادیر پیش بینی و مقادیر واقعی هستند را می سازیم:
y_pred = []
y_true = []
برای اعتبار سنجی مدل از K-fold cross استفاده خواهیم کرد.
from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state = 42)
for train_index, test_index in kf.split(df_filter):
df_test = df_filter.iloc[test_index]
df_train = df_filter.iloc[train_index]
اکنون می توانیم ورودی و خروجی خود را تعریف کنیم:
for train_index, test_index in kf.split(df_filter):
...
X_train = np.array(df_train['points']).reshape(-1, 1)
y_train = np.array(df_train['price']).reshape(-1, 1)
X_test = np.array(df_test['points']).reshape(-1, 1)
y_test = np.array(df_test['price']).reshape(-1, 1)
حال مدل رگرسیون خود را فیت (fit) می کنیم.
for train_index, test_index in kf.split(df_filter):
۰۰۰
model = LinearRegression()
model.fit(X_train, y_train)
در کد زیر پیش بینی های خود را تولید و ذخیره می کنیم:
for train_index, test_index in kf.split(df_filter):
...
y_pred.append(model.predict(X_test)[0])
y_true.append(y_test[0])
حال بیایید عملکرد مدل خود را ارزیابی کنیم. بگذارید از خطای میانگین مربعات برای ارزیابی عملکرد مدل استفاده کنیم:
print("Mean Square Error: ", mean_squared_error(y_true, y_pred))
می بینیم که عملکرد خیلی عالی نیست. ما برای بهوبد می توانیم عملکرد را با آموزش در قیمت های محدود شده تا مرز میانگین قیمت به علاوه یک انحراف استاندارد بهبود ببخشیم:
df_filter = df[df['price'] <= df['price'].mean() + df['price'].std() ].copy()
...
print("Mean Square Error: ", mean_squared_error(y_true, y_pred))
در حالی که این ترفند به طور قابل توجهی عملکرد را بهبود می بخشد ، اما این روش به قیمت عدم توانایی تشخیص مقادیر دقیق نوشیدنی های بسیار گران قیمت تمام می شود. به جای مدل رگرسیون که از یک ویژگی (single feature) استفاده می کند، می توانیم از مدل های مبتنی بر درخت(tree base models) مانند جنگل های تصادفی (random forests) برای پیش بینی قیمت استفاده کنیم که می تواند از متغیرهای کمی و کیفی استفاده کند. بیایید یک مدل رگرسیون جنگلی تصادفی ایجاد کنیم که از “کشور” ، “استان” ، “تنوع” ، “کارخانه” و “امتیاز” برای پیش بینی “قیمت” نوشیدنی استفاده کند. ابتدا ، متغیرهای کیفی را به کد تبدیل می کنیم که توسط مدل جنگل های تصادفی قابل استفاده باشد:
df['country_cat'] = df['country'].astype('category')
df['country_cat'] = df['country_cat'].cat.codes
df['province_cat'] = df['province'].astype('category')
df['province_cat'] = df['province_cat'].cat.codes
df['winery_cat'] = df['winery'].astype('category')
df['winery_cat'] = df['winery_cat'].cat.codes
df['variety_cat'] = df['variety'].astype('category')
df['variety_cat'] = df['variety_cat'].cat.codes
بیایید اندازه نمونه تصادفی را به 5000 افزایش دهیم:
df = pd.read_csv("winemag-data-130k-v2.csv").sample(n=5000, random_state = 42)
در گام بعد ، ماژول رگرسیون جنگل تصادفی را از scikit-Learn واردمی کنیم. سپس لیستی از ویژگی هایی که برای آموزش مدل خود استفاده خواهیم کرد نیز تعریف کنیم:
from sklearn.ensemble import RandomForestRegressor
features = ['points', 'country_cat', 'province_cat', 'winery_cat', 'variety_cat']
حال مدل خود را با استفاده از یک جنگل تصادفی با n_estimators = 1000 و max_depth = 1000 موزش می دهیم. سپس پیش بینی هایی را تولید و آنها را در لیست جدیدی اضافه می کنیم:
for train_index, test_index in kf.split(df_filter):
df_test = df_filter.iloc[test_index]
df_train = df_filter.iloc[train_index]
X_train = np.array(df_train[features])
y_train = np.array(df_train['price'])
X_test = np.array(df_test[features])
y_test = np.array(df_test['price'])
model = RandomForestRegressor(n_estimators = 1000, max_depth = 1000, random_state = 42)
model.fit(X_train, y_train)
y_pred_rf.append(model.predict(X_test)[0])
y_true_rf.append(y_test[0])
در آخر ، بیایید خطای میانگین مربعات را برای هر دو مدل جنگل تصادفی و رگرسیون خطی ارزیابی کنیم:
print("Mean Square Error (Linear Regression): ", mean_squared_error(y_true, y_pred))
print("Mean Square Error (Random Forest): ", mean_squared_error(y_pred_rf, y_true_rf))
می بینیم که مدل جنگل های تصادفی از عملکرد بسیار بهتری برخوردار است. اکنون ، می خواهیم مقادیر قیمت گمشده را با استفاده از مدل هایمان پیش بینی کنیم:
df_missing = df[df['price'].isnull()].copy()
X_test_lr = np.array(df_missing['points']).reshape(-1, 1)
X_test_rf = np.array(df_missing[features])
X_train_lr = np.array(df_filter['points']).reshape(-1, 1)
y_train_lr = np.array(df_filter['price']).reshape(-1, 1)
X_train_rf = np.array(df_filter[features])
y_train_rf = np.array(df_filter['price'])
model_lr = LinearRegression()
model_lr.fit(X_train_lr, y_train_lr)
print("Linear regression predictions: ", model_lr.predict(X_test_lr)[0][0])
model_rf = RandomForestRegressor(n_estimators = 1000, max_depth = 1000, random_state = 42)
model_rf.fit(X_train_rf, y_train_rf)
print("Random forests regression predictions: ", model_rf.predict(X_test_rf)[0])
توصیه می کنم که در انتخاب ویژگی ها و تنظیم پارامترها بیش از اندازه بازی کنید تا ببینید آیا می توانید عملکرد را بهبود ببخشید. بعلاوه ، من شما را تشویق می کنم که از این الگو برای مقادیر گمشده دیگر از جمله “region_1” و “designation’” استفاده کنید.