機器學習入門實戰——基於knn的airbnb房租預測
阿新 • • 發佈:2021-02-18
資料讀取
import pandas as pd features=['accommodates','bathrooms','bedrooms','beds','price','minimum_nights','maximum_nights','number_of_reviews'] dc_listings=pd.read_csv('listings.csv') dc_listings=dc_listings[features] print(dc_listings.shape) dc_listings.head()
執行結果:
K:候選物件個數,近鄰數(如找3個和自己最近的樣本)
先使用可容納旅客的數量(accommodates)做一個簡單計算,統計與可容納3個旅客相減的情況(當前要估計價格的可容納旅客數為3個)import numpy as np our_acc_value=3#房間數為3個 dc_listings['distance']=np.abs(dc_listings.accommodates-our_acc_value)#為dc_listings新增distance列,用於儲存當前房間數與3的差值 dc_listings.distance.value_counts().sort_index()#統計各差值的情況
輸出:
0.0 3370 1.0 17967 1.5 2 2.0 3865 3.0 1250 4.0 221 5.0 334 6.0 58 7.0 125 8.0 15 9.0 44 10.0 5 11.0 14 12.0 5 13.0 73 Name: distance, dtype: int64
原始資料統計過程中可能會存在一些規律,一般需要進行洗牌操作,打亂原有秩序(使用sample函式)
dc_listings=dc_listings.sample(frac=1,random_state=0)#洗牌 frac:抽取行的比例,1為100% random_state:0表示不得取重複資料 1表示可以取重複資料 dc_listings=dc_listings.sort_values('distance')#統計差值(房間數-3)的情況 將dc_listings按照distance列排序 將和房間數3最近的放在最前面 dc_listings.price.head()#取前5條的價格 由於資料時亂的,所以id和price均無規律
輸出結果:
2732 $129.00 14798 $249.00 27309 $170.00 20977 $169.00 11178 $100.00 Name: price, dtype: object
對價格進行型別轉換,去掉$符號,轉換成float,然後對前五個價格取均值,用前5個的均值來預測當前房價
dc_listings['price']=dc_listings.price.str.replace("\$|,",'').astype(float) mean_price=dc_listings.price.iloc[:5].mean() mean_price
輸出:163.4
拿75%的資料作為訓練集,25%的資料作為測試集來進行模型的評估,訓練集和測試集不可重複。
dc_listings.drop('distance',axis=1)#刪除distance列 train_df=dc_listings.copy().iloc[:20544]#27392*0.75行為訓練集 test_df=dc_listings.copy().iloc[20544:]#剩下的作為測試集(27392*0.25)
基於單變數預測價格
#new_listing_value:當前樣本的feature_clolumn(如accomodates)列屬性取值 #feture_column:計算房租使用的單屬性 def predict_price(new_listing_value,feature_column): temp_df=train_df#使用訓練集來預測測試集房租結果 dc_listings[feature_column]=train_df[feature_column].astype(float)#統一將格式轉換成float否則會報錯 temp_df['distance']=np.abs(train_df[feature_column]-new_listing_value) temp_df=temp_df.sort_values('distance') knn_5=temp_df.price.iloc[:5] predict_price=knn_5.mean() return(predict_price)
對測試集的每一條記錄使用accomodates屬性預測其房租價格
#new_listing_value的值即為accommodates的取值 test_df['predicted_price']=test_df.accommodates.apply(predict_price,feature_column='accommodates') test_df.predicted_price.head()
輸出:
14122 134.0 23556 418.0 16317 134.0 26230 134.0 19769 134.0 Name: predicted_price, dtype: float64
root mean square error(RMSE)均方根誤差
得到每個樣本的預測值後計算均方根誤差用於評估模型(值越小模型越好)
test_df['squared_error']=(test_df['predicted_price']-test_df['price'])**(2) mse=test_df['squared_error'].mean() rmse=mse**(1/2) rmse
輸出結果:
348.689169172284
試試不同的變數(屬性)
for feature in ['accommodates','bedrooms','bathrooms','number_of_reviews']: test_df['predicted_price']=test_df[feature].apply(predict_price,feature_column=feature) test_df['squared_error']=(test_df['predicted_price']-test_df['price'])**(2) mse=test_df['squared_error'].mean() rmse=mse**(1/2) print("RMSE for the {} column:{}".format(feature,rmse))
輸出:
RMSE for the accommodates column:348.689169172284 RMSE for the bedrooms column:344.64855009943 RMSE for the bathrooms column:361.1230782594195 RMSE for the number_of_reviews column:383.4946020709275
注:由於每個測試集中的樣本都要與訓練集中樣本一一比對,所以上述程式執行時間較長,需要耐心等待……
標準化
同時使用多個屬性——如房間數(個位數)和房間面積(幾十甚至上百)進行計算的時候,由於變數取值範圍的不同(取值範圍大的影響較大)會導致對計算結果的不良影響(如計算歐式距離時,房間面積差值平方計算結果通常較大,而房間數差值平方較小),而各個屬性是獨立的即它們是同等重要的,所以需要對資料進行標準化,如採用z-score標準化或歸一化等手段進行預處理
z-score 標準化(Z-score normalization)
要求資料總體均值μ=0 標準差σ=1
轉換公式如下:
其中μ為原始資料均值,