【機器學習報告】我用鏈家的資料做了一個超過鏈家模型的二手房房價預測模型
阿新 • • 發佈:2021-01-15
我用鏈家的資料做的二手房房價預測模型,打敗了鏈家自己的模型
前言
在二手房交易市場中,普遍存在掛盤價與成交價偏差大的問題,如何精準預測二手房成交價成為一大難題。本模型的目標是訓練出一個根據二手房相關特徵來資料預測二手房成交價的模型,保證預測準確度要優於網站的預測模型,並給二手房出售標價提供參考價值。
(好吧這其實是我這學期資料探勘課的大作業)
資料準備
爬蟲準備
- 資料來源: 資料來自鏈家的官方交易網站https://bj.lianjia.com/chengjiao/,為了保證資料量足夠大,我們的任務瞄準了北京的二手房成交資訊。
- 資料獲取: 使用python編寫非同步爬蟲指令碼,該多執行緒指令碼大大減少了爬蟲所需的時間,使用了aiohttp、asyncio、lxml等相關庫
- 獲取分佈合理的資料集: 考慮到網站上只列出了100頁具有相同約束的交易記錄,總計達3000條記錄,這對於訓練資料集來說太小了。因此,我們選擇使用幾個屬性的組合來擴充套件網站提供的記錄。用價格和麵積相結合,可以得到56*100頁的資料量,同時也保證了資料分佈的流暢性。
特徵展示
- 決策變數:
- 特徵變數:
變數統計性描述
- 決策變數 total_price 成交價:對0-1500萬的房屋繪製直方圖和密度圖,我們可以發現數據是比較均勻的,絕大部分處於100-500萬。
- average_price 小區交易成交均價:對小區交易成交均價繪製直方圖和密度圖,均價集中在1-7萬。
- district 所在行政區:對所在行政區繪製柱狀圖,可以看出我們的資料分佈在北京各個行政區,較為平衡。其中,在昌平區和朝陽區的交易二手房較多。
- date_of_deal 成交日期:通過成交日期的柱狀圖,我們可以看出大部分資料是分佈在2019、2020年,其他年份的資料是較少的。
- completion_year 建成年限:通過柱狀圖可以看出,房屋的建成年限集中分佈在1990年到2014年。
- 成交價與建築面積的相關性分析:通過散點圖,我們可以看出成交價與建築面積呈現明顯的正相關趨勢,這暗示建築面積是個強相關變數。
資料處理
資料清洗與異常值過濾
- 去除資料中house_type為車位的資料
- 去除total_price、average_price、built_up_area為空資料
- 去除built_up_area > 10000 and built_up_area < 5的資料
- 去除total_price > 10億的資料
資料截斷
對於迴歸問題,考慮到資料的分佈以及模型訓練的有效性,我們將目標鎖定為:
- 售價小於2000萬的樣本
- 包含成交10個及以上的小區樣本
- 成交年份在2019至2020年的樣本
- 最終我們得到共77766條有效樣本
資料集劃分:
- 考慮到資料和模型的時效性,我們將成交於2020年的樣本隨機劃分為7比3的份額,將2019年資料與70%的2020年資料作為訓練集,30%的2020年資料作為驗證集。
- 最終我們得到65897個訓練樣本,11869個驗證樣本。
- 訓練集與驗證集total_price、build_up_area資料分佈(藍色為訓練集,綠色為驗證集),兩個資料集分佈相似,符合劃分預期,可以用來訓練模型。
特徵處理
- 對於小區特徵:考慮到小區數量繁多,特徵較為離散,我們將小區名稱前兩個字元與開發商名稱合併作為新的小區名稱後,進行離散處理。PS:由於處理後特徵仍然非常稀疏,小區數量多,前期我們並未在模型中加入該特徵。在後期通過神經網路將該特徵處理成8維的embedding加入到模型中去。
- 對於地區特徵:離散處理 PS: 在後期通過神經網路將該特徵處理成4維的embedding加入到模型中去。
- 除house_type、built_up_area、average_price、property_cost等連續特徵,其餘特徵一律離散化後作為類別特徵處理。
模型與分析
第一輪迭代
- 我們嘗試了多種模型,並經過了大量的調參工作,最終各個模型的表現如下:
(缺失資料將在之後補齊)
- 其中神經網路結構如下
- Xgboost最優引數如下:
xgb.XGBRegressor(objective ='reg:linear',
colsample_bytree = 0.8,
subsample = 0.8,
learning_rate = 0.01,
max_depth = 8,
reg_alpha = 0.5,
reg_lambda = 0.5,
n_estimators = 10000)
- Lightbgm最優引數如下:
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'regression',
'metric': 'mae',
'num_leaves': 80,
'max_depth':-1,
'min_data_in_leaf':150,
'learning_rate': 0.01,
'feature_fraction': 0.8,
'bagging_fraction': 0.8,
'bagging_freq': 3,
'lambda_l1': 0.5, 'lambda_l2': 0.5, }
- 由於計算機與模型效能原因,我們沒有嘗試使用GDBT。根據上述結果發現,三種迴歸的表現結果相近,決策樹、隨機森林等基礎樹模型的表現與梯度提升樹模型的Xgboost、lightgmb而言其擬合能力較差,而神經網路使用MAE作為loss時網路受離群值影響較大,使用MSE作loss時模型又不能很好的收斂。因此我們選擇了效能表現最好的xgboost、lightgmb作為我們的baseline模型。
- 以lightgbm為例,我們列出了各個特徵的在最優模型中的重要程度,Feature importance越大表示該特徵作用越大,其中0 1 3 分別為特徵室、廳、衛。
- 通過特徵重要圖發現,average_price、built_up_area、property_cost等連續特徵的重要性明顯高於其他離散特徵,對模型對房價的預測起著決定性作用。這與我們之前的資料分析與推測相符,更大的面積、小區均價意味著更高的房價,更高的物業費用往往意味著更高檔的小區。成交日期的重要性也比較靠前,說明2019年與2020年的北京房價整體上存在差異。
第二輪迭代
- 至此我們已經將所有處理的特徵進行了使用,並對特徵的重要性進行了合理性分析,驗證了模型的有效性,那麼如何進一步提高模型的效能,或者說加入更多的重要特徵呢。注意到,我們的資料集中含有房屋所在小區的特徵,這一特徵意義重要,在中國,一個小區包含著其學區資訊、交通訊息已經小區開發商資訊等多元資訊,買家在考慮房屋面積等決定性因素的情況,極大程度也受小區的多維屬性的影響。但由於小區這一離散特徵類別太多(2127個),如果直接處理成01特徵feed給模型顯然是不合理的。那麼如果給特徵降維成了是否能合理使用該特徵關鍵。
- 將小區特徵轉變為embedding向量:我們利用神經網路去訓練各個小區的embedding特徵,與上述神經網路改變如下:
- 為了突出小區特徵的重要性,我們將小區特徵的embedding設定為8維,地區特徵的embedding設定為4維,其餘均減少至兩維。
- 將連續特徵中與小區相關的特徵全部提出,如average_price、property_cost等。具體模型示意圖如下:
- 將模型訓練至收斂,知道loss不再下降即停止。將模型中的小區embedding引數取出([2127,8]),至此我們將所有小區都轉換成了一個8維的特徵,我們將該特徵應用於原來的最優模型上,觀察模型的效能變化。
- 效果分析:
- 該神經網路最後在驗證集上的MAE達到28.3748,僅略低於之前全特徵訓練的27.1561,說明即使去掉average_price、property_cost等重要的離散特徵,模型仍然能通過小區特徵學到這些屬性。該embedding方法很有可能是有效的。
- 我們將小區的8維特徵加入原有的特徵集合後,使用相同的引數,lightgbm模型在驗證集上的MAE從原來的25.5下降至24.3,誤差減少了1.2。顯然該效能的提升不僅證明了小區特徵的作用,同樣也證明了通過這種方式訓練的小區特徵具有一定的有效性,這讓我們非常喜悅,接著我們同樣將訓練好的4維的小區特徵替換掉原有的小區01特徵後,MAE又從24.3下降至23.98,誤差減少了0.3。但當我們嘗試將其他離散特徵替換成embedding時,模型的效能沒有再發生變化。經過引數調優後最終模型效果如下:
-
我們再一次檢視各個特徵的重要程度如下:
-
注意name_x表示小區的第x維度特徵,地區特徵同理。可以發現built_up_area仍然是最重要的特徵,而average_price、property_cost被小區特徵稀釋,但小區特徵的重要性僅次於這兩者而超過了所有的其他離散特徵,可以推斷emedding後的小區特徵與原本的average_price、property_cost等刻畫小區屬性的特徵存在互補作用。而原本不重要的地區特徵,也浮現在中上游。這證明了該特徵降維方式的有效性。
-
Embedding到底學到了什麼?為了探究這兩組embedding特徵到底學到了什麼?我們對其做了可解釋性的分析:
- 小區embedding特徵:我們將2127個小區的特徵進行了K-means聚類,將他們聚成20個子類,並觀察每個子類的房價分佈:
- 通過作出箱線圖並按房屋售價中位數進行排列,我們可以發現,在這個20個聚類中,各個聚類的房價分佈均不相同,但從低到高覆蓋了形成了整一個房價區間分佈,因此可以判斷,小區embedding特徵中包含了影響小區房價的重要資訊,進一步證明了該特徵的有效性。
- 地區特徵:我們將14個北京地區的4維特徵用PCA降維至2維,並展示在2維座標系中,結果如下:
- 僅通過該圖我們可能無法得到結論,但如果我們對比北京的地區分佈以及房價圖:
- 我們可以發現:西城、東城、海淀、朝陽這四個北京中心地區,其房價價格在北京地區中最高且相互差距較大,共同分佈散落在原點周圍。而對於石景山、豐臺這兩地區,兩者相互比鄰,且房價段位趨同,在座標系同樣分佈緊密。對於大興、昌平、門頭溝、順義、房山、通州這幾個外圍地區,地理位置相似(環繞主城區),共同分佈在座標軸中心位置,而對於亦莊、平谷、密雲等邊緣地區,房價較低,因此在座標系上的分佈較為離群,更加偏離原點。
- 因此這個由地區embedding特徵降維得到的2維座標系,集合了各個地區地理位置、房價的資訊,分佈與真實的地區房價和地理位置相近,具有較強的有效性。
- 小區embedding特徵:我們將2127個小區的特徵進行了K-means聚類,將他們聚成20個子類,並觀察每個子類的房價分佈:
模型融合
至此我們得到了最終的特徵集合和模型,因此我們考慮使用模型融合來進一步提高我們的模型泛化能力,具體做法如下:
K折驗證
- 2020年成交的資料隨機分成5份,每次訓練用2019年的資料加上4份2020年的資料作為訓練集,以另一份2020年的資料作為驗證集,同時訓練lightgbm、xgboost模型,當200輪內驗證集上的MAE不再下降則停止並儲存最優模型。以下僅展示lightgbm的訓練結果:
- 至此我們得到了10個模型,5個lightgbm和5個xgboost模型,當我們需要對房價預測時,我們僅需將10個模型的結果平均即可。
PK鏈家模型
為了證明我們模型的先進性與應用性,我們希望能讓我們的模型與鏈家網站的房價預測模型來一場競賽。
鏈家估價模型
- 使用者給出房屋的小區、建成年代、面積、戶型、朝向、樓層以及一些標籤特徵後,模型會給使用者提供一個合理的參考價格。這是鏈家官方的模型介面,由於鏈家官方擁有大量的充分的歷史資料,因此具有一定的資料優勢,挑戰鏈家的官方模型具有一定的挑戰性。我們將比較兩個模型在最新的房屋成交資料(保證我們的模型和鏈家的模型都沒有見過,防止答案洩漏)上的預測表現,來比較兩個模型的效能。
測試集準備
- 我們通過爬蟲,重新抓取了鏈家網站上北京12月份最新的二手房成交記錄,共2430條有效有效資料,測試集的total_price分佈如下:
模型PK
- 同樣通過爬蟲技術,我們將測試集的成交房屋的特徵資訊通過爬蟲的方式上傳至鏈家的二手房估價網站,並抓取其預測結果並儲存。
- 我們的模型預測結果獲取:通過相同的特徵處理,將測試集的資料轉化成我們模型熟悉的特徵形式,利用預先訓練好的10個模型,各自預測後作平均作為最後的預測結果,以此進行模型融合。
- 計算並評價模型的效能:最終我們得到兩個模型在測試集上的預測結果並計算其平均誤差MAE:
- 結果現實鏈家的模型在測試集上的MAE為35.3764,而我們的模型在測試集上的MAE為22.4501,比鏈家模型的誤差低了13萬,這是一個巨大的差距,特別是對於房價來說。
- 為了證明我們的模型全方位超過鏈家的模型,我們將展示兩個模型在每一個二手房價位的預測誤差,結果如下:
- 測試集的分佈由綠色柱狀圖表示:測試集在250至700萬分布較多,這也是北京主要的二手房交易價格區間。
- 通過該圖我們可以發現,在0-2000萬的二手房價格區間,我們模型的誤差全部低於鏈家模型。如果計算偏差率,對於低價位的房屋我們模型的預測偏差率遠低於鏈家模型,並且對於高價位的二手房,我們的誤差仍然保持著大幅度的領先,這說明,我們的模型的有足夠的泛化能力,可以較為準確預測較大房價區間的二手房。
- 事實證明,我們的模型相較於鏈家模型具有一定的先進性,在給二手房買賣雙方提供參考售價參考時,我們的模型具有更強的準確性與應用性。
程式碼開源
爬蟲程式碼和其他程式碼將在展示後開源在個人github