大家好,我是老班~ 今天給大家?guī)硪黄猭aggle案例文章:基于6大回歸模型預測航空公司機票的價格。 這篇文章涉及到的知識點會比較多,關(guān)鍵是數(shù)據(jù)預處理和特征工程部分: ![]() 導入庫![]() 數(shù)據(jù)基本信息先把數(shù)據(jù)導進來: df = pd.read_excel('data_air.xlsx')df.head() ![]() 查看數(shù)據(jù)的基本信息,包含:數(shù)據(jù)形狀、字段類型等 ![]()
具體字段的中文含義:
希望可以理解中文含義,幫助進行數(shù)據(jù)分析~ ![]() 數(shù)值型字段的描述統(tǒng)計信息,這里主要是針對Price字段: ![]() 缺失值處理通過上面的缺失值檢查,我們看到有兩個字段是存在缺失值的,進行可視化。 missingno是一個可視化缺失值得庫,方便使用,我們可以用pip install missingno 即可下載該庫 import missingno as msomso.bar(df,color='blue')plt.show() ![]() 缺失值刪除正常的字段是10683條,其中兩個字段是10682條;缺失值得占比很小,考慮直接刪除的數(shù)據(jù) ![]() 時間相關(guān)字段處理時間處理
對3個字段實施轉(zhuǎn)換: # 3個字段的轉(zhuǎn)換for col in ['Date_of_Journey','Dep_Time', 'Arrival_Time']: change_to_datetime(col) 查看轉(zhuǎn)換之后的字段類型:
Airline objectDate_of_Journey datetime64[ns]Source objectDestination objectRoute objectDep_Time datetime64[ns]Arrival_Time datetime64[ns]Duration objectTotal_Stops objectAdditional_Info objectPrice int64dtype: object 提取天和月乘客旅程日期中(Date_of_Journey)單獨提取天和月,作為兩個字段
最終生成了兩個新的字段: ![]() # 刪除字段df.drop('Date_of_Journey', axis=1, inplace=True) 起飛時間和抵達時間處理主要提取兩個時間中的“小時”和“分鐘”信息;同時刪除原字段: ![]() 分別調(diào)用函數(shù)來提取信息:
extract_hour(df,'Arrival_Time')extract_minute(df,'Arrival_Time')drop_col(df,'Arrival_Time')
![]() 航班持續(xù)時間duration1、將持續(xù)時間規(guī)范化處理,統(tǒng)一變成0h 1m # # 原文方法# duration=list(df['Duration'])# for i in range(len(duration)):# if len(duration[i].split(' '))==2:# pass# else:# if 'h' in duration[i]: # duration[i]=duration[i] + ' 0m' # else:# duration[i]='0h '+ duration[i] 下面是個人版本寫法: ![]() ![]() 2、從Duration字段中提取小時和分鐘: ![]()
3、字段類型轉(zhuǎn)化:查看dur_hour和dur_minute的字段類型變化 ![]() 字段編碼字段類型區(qū)分主要是區(qū)分object和非object類型的字段信息。 1、針對字符型的字段 column = [column for column in df.columns if df[column].dtype == 'object']column
2、數(shù)值型(連續(xù)型)字段 continuous_col = [column for column in df.columns if df[column].dtype != 'object']continuous_col
2種編碼技術(shù)Nominal data -- Data that are not in any order -->one hot encodingordinal data -- Data are in order --> labelEncoder
生成標稱型字段組成的數(shù)據(jù)![]() 不同字段編碼處理航空公司-Airline1、不同航空公司的數(shù)量統(tǒng)計: ![]() ![]() 2、查看航空公司與價格關(guān)系
![]() 3、2個明顯的結(jié)論 從上面的圖形中可以看出來:
4、實現(xiàn)獨熱編碼 由于航空公司屬性是一個標稱數(shù)據(jù)的字段,我們進行獨熱編碼,通過啞變量的方式來實現(xiàn): ![]() 停留地-Total_Stops旅行期間的總共停留地,實施上面的同樣操作: 1、和價格的關(guān)系 plt.figure(figsize=(15,8))sns.boxplot(x='Total_Stops', y='Price', data=df.sort_values('Price',ascending=False))plt.show() ![]() 2、實施硬編碼;區(qū)別于航空公司的獨熱編碼 ![]() 出發(fā)地source出發(fā)地和價格的關(guān)系:
![]() 獨熱編碼的過程: ![]() 目的地-destination目的地的數(shù)量統(tǒng)計: ![]() 目的地和價格的關(guān)系: ![]() 獨熱編碼的實現(xiàn): ![]() 路線Route1、不同路線的數(shù)量統(tǒng)計: ![]() 2、路線名稱提取 從上面的結(jié)果中看出來,最長的路線中有5個地名,我們一次提取。 沒有出現(xiàn)的數(shù)據(jù)則用NaN來表示: categorical['Route1']=categorical['Route'].str.split('→').str[0]categorical['Route2']=categorical['Route'].str.split('→').str[1]categorical['Route3']=categorical['Route'].str.split('→').str[2]categorical['Route4']=categorical['Route'].str.split('→').str[3]categorical['Route5']=categorical['Route'].str.split('→').str[4]categorical.head() ![]() 3、缺失值字段 ![]()
4、類型編碼LabelEncoder from sklearn.preprocessing import LabelEncoderle = LabelEncoder()for i in ['Route1', 'Route2', 'Route3', 'Route4', 'Route5']: categorical[i]=le.fit_transform(categorical[i]) categorical.head() ![]() 抵達時間/小時-Arrival_Time_hour抵達目的地時間和價格的關(guān)系:
![]() 建模數(shù)據(jù)刪除無效字段生成的全部字段信息: categorical.columnsIndex(['Airline', 'Source', 'Destination', 'Total_Stops', 'Additional_Info', 'Route1', 'Route2', 'Route3', 'Route4', 'Route5'], dtype='object') 將原始的無效字段直接刪除:
最終數(shù)據(jù)將多個DataFrame進行拼接,組成最終的建模,其中Price進行最終的輸出特征 final_df=pd.concat([categorical,Airline,source,destination,df[continuous_col]],axis=1)final_df.head() ![]() 離群點檢測對上面生成的最終數(shù)據(jù)進行離群點檢測: ![]() ![]() 對離群點填充均值,查看填充后的效果:
![]() 數(shù)據(jù)切分X=final_df.drop('Price',axis=1)y=final_df['Price']from sklearn.model_selection import train_test_splitX_train,X_test,y_train,y_test = train_test_split(X,y, test_size=0.20, random_state=123) 特征選擇本文中特征選擇使用的是 mutual_info_classif 庫:
![]() 評價指標本次建模中引入3個評價指標:
![]() from sklearn.metrics import r2_score,mean_absolute_error,mean_squared_errordef predict(ml_model): print('Model is: ', ml_model) model = ml_model.fit(X_train, y_train) print('Training score: ', model.score(X_train,y_train)) predictions = model.predict(X_test) print('Predictions: ', predictions) print('-----------------') r2score = r2_score(y_test, predictions) print('r2 score is: ', r2score) print('MAE:{}', mean_absolute_error(y_test,predictions)) print('MSE:{}', mean_squared_error(y_test,predictions)) print('RMSE:{}', np.sqrt(mean_squared_error(y_test,predictions))) # 真實值和預測值的差值 sns.distplot(y_test - predictions) 建模導入多種模型:
隨機森林回歸樹-RandomForestRegressor![]() 邏輯回歸-LogisticRegression ![]() K近鄰回歸-KNeighborsRegressor ![]() 決策樹回歸DecisionTreeRegressor ![]() 支持向量機回歸-SVR ![]() 梯度提升回歸-GradientBoostingRegressor ![]() 模型調(diào)優(yōu)-Hypertunning the model調(diào)優(yōu)尋參# 采用隨機搜索調(diào)優(yōu)from sklearn.model_selection import RandomizedSearchCV
# 建模擬合rf=RandomForestRegressor()rf_random=RandomizedSearchCV( estimator=rf, param_distributions=random_grid, cv=3, verbose=2, n_jobs=-1)rf_random.fit(X_train,y_train) 多次運行調(diào)優(yōu)后找到最佳的參數(shù)組合: ![]() 調(diào)優(yōu)后結(jié)果 ![]() 通過r2_score指標發(fā)現(xiàn):進行參數(shù)調(diào)優(yōu)后,模型的效果得到提升~ 補充:如何理解回歸模型的r2_score指標假設我們用表示數(shù)據(jù)真實的觀測值,用表示真實觀測值的平均值,用表示通過模型得到的預測值,則: 回歸平方和:SSRSSR可以表示為; ![]() 即估計值與平均值的誤差,反映自變量與因變量之間的相關(guān)程度的偏差平方和 殘差平方和:SSESSE可以表示為: ![]() 即估計值與真實值的誤差,反映的是整個模型擬合程度 總離差平方和:SST![]() R2_score計算公式R^2 score,即決定系數(shù),反映因變量的全部變異能通過回歸關(guān)系被自變量解釋的比例。計算公式: ![]() 也可以寫成: ![]() 進一步可以轉(zhuǎn)成: ![]() 此時分子就變成了我們常用的評價指標均方誤差MSE,分母就變成了方差Var。r2_score在0-1之間,越接近1越好。 兩種常見的求解r2的方式:
|
|