劉子潔
Jul 12, 2023

[機器學習] 建⽴個⼈化房屋預測模型,提前洞悉房市場動向 !

透過房價預估模型,我們可以進一步理解不動產市場,並以此做出更好的買賣決策。

前言

這些房子究竟值多少錢?我們可能需要購買自己的住所,可能需要商業用途,或者只是單純對不動產市場感興趣。因此瞭解房價的變得格外重要。透過預測房價,我們可以獲得更清晰的市場價格瞭解,更好的進行買賣決策。在這篇文章裡我會以台中市當作示範,分享我如何製作一個房價預測的模型,並解釋其方法與流程。

製作流程

前三個步驟會花費整個專案80%左右的時間,接下來我會進一步針對每個流程進行解釋以及程式碼說明。

資料來源

爬取自 : 內政部不動產交易實價查詢服務網

台中市中心區 : 東區、西區、南區、北區、中區、西屯區、北屯區、南屯區 八個行政區民國101年8月至111年12月的資料。

附上:台中市房價資料爬蟲程式碼

爬蟲下來的資料一共有14個欄位,有目標變數"價格"和其他13個特徵值。

先載入資料處理時會使用到的套件和匯入資料,會先進行資料預處理和探索式資料分析。

特徵(Feature)

經度、緯度、屋齡、面積、建物類型、用途、樓別/樓高、佈局、電梯、管理員、車位數量、行政區、交易年份。

先觀察一下這些特徵欄位中的資料長什麼樣子,思考接下來的特徵工程要怎麼處理,數值型的資料就比較簡單,只需處理離群值和缺值就好,其他類別型資料像是建物類型、用途可能需要對做一些簡化,(例如將括號中的字處理掉),樓別/樓高也需要將這一個欄位拆成不同的兩個欄位來處理,佈局也是要拆成房、廳、衛三個欄位,這些可能是接下來需要特別注意的部分。

資料預處理(Data Preprocessing)

我們首先先查看一下每個欄位的資料類別,這次的資料一共有234904筆,其中有缺值的欄位 : 屋齡 、建物類型、用途、佈局 一共四個欄位。

特別需要注意的是 面積與價格 兩筆資料都是類別型而不是數值型的,原因是有些原始資料數值比較大,有用到逗號,我們必須先將它們的逗號去除並轉成浮點數。

將逗號去除,並轉成浮點數

處理重複值、缺失值

紅色方框中的是有缺值的欄位

有空值的欄位一共有4種, 屋齡 、建物類型、用途、佈局,其中屋齡的缺值非常多,一共54227筆,但如果直接將有空值的資料都刪除,那我們會損失很多可以用的資訊,所以屋齡的空值打算留到最後其他欄位都處理好了用機器學習的方法來預測屋齡的空值。

建物類型和用途補眾數 ,佈局則將空的欄位直接刪除

建物類型有2筆缺值,用途一共有14筆缺值,在資料總數233196筆資料情況下其實可以選擇直接去除空值,但我這邊的選擇使用.value_counts()查看它們出現過最多的值來填補,幾房幾衛幾廳是房價的重要指標之一,缺少這些數值也很難進行房價預測,所以將缺值直接刪除。

處理離群值

接著查看一下資料的分佈情況,面積在Q3的情況下只有58.9825,但最大值卻有38035,代表這個特徵含有離群值,車位和價格也是,所以也需要處理他們之間的離群值,這些離群值大部分都是來自同樣的資料,都是一些豪宅,條件比較極端的資料,這些不在我們這次預測房價的目標裡面,所以需要將這些資料先移除,我選擇將將範圍訂在上界Q3+1.5倍IQR裡。

在移除極端價格和面積的資料後,車位原先極端的資料也一起被處理掉了。

探索式資料分析 EDA

我們可以畫出直方圖了解到價格的分佈情況,資料是呈現右偏的,大部分的房價都集中在相對較低的價位,而一小部分極高的房價拉長了分佈的情況。

繪製折線圖來看行政區之間價格與年度的差異

接著查看價格與年度之間的關係,我們可以得知中區的價格一直都是最低的,其次是北區;最高的則是南屯區,且房價都有逐步在往上升,102 年價格最高的大約 800 多萬,110 年增加至近 1200 萬。

是什麼造成房價差異如此之大?

推測可能是以下幾種原因:

a.地理位置:我們首先猜測是地理原因,中區和北區相對於其他地區,地理位置較偏遠或較不便利,並且交通設施可能較不發達。這可能導致較少人願意在這些區域購買房產,進而影響房價。

b.市場需求:中區的市場需求相對較低。下面是在1111依地區搜尋的結果,可以看到光南屯區的職缺就是中區的5倍,買房需求就會相對減少,對於房地產市場的競爭也會降低,進而影響房價。

中區的搜尋結果
南屯區的搜尋結果

買房時,購買的地區考量也是一個重要考量因素,如果希望壓低房價也可以在中區進行選擇。

接著我想知道市區之間建物類型的關係怎麼樣,但在畫圖前先將資料整理簡化成比較清楚的樣子,這邊在做的事情就只是將很少出現的欄位合併成其他,然後將有括號中的字整理乾淨。

北屯和西屯都是以住宅大樓為主,也都是台中市的主要擴展區域,隨著城市發展也進行了大規模的都市化建設。住宅大樓能夠在提供更多居住空間,符合現代都市化的趨勢。

特徵工程

現在目前data的樣子

前面已經對資料完成預處理了(除了屋齡的空值),接下來要著重的部分是類別型欄位的處理,"建物類型"在畫熱力圖時已經做過處理了,用途的欄位也進行相同的處理就好,然後將 樓高/樓別的欄位拆分,佈局也需要拆分成房、衛、廳三個欄位,接著對全部的欄位進行編碼。

用途

將資料整理乾淨並簡化

第二行程式碼前面有加一個波浪符,是將沒有包含 住家用、住商用、商業用、辦公用、其他 這些資料都改成'其他'

為什麼要將資料簡化? 簡化後有什麼好處嗎?

可以減少特徵空間的維度,欄位中可能包含許多冗長或不必要的資料,這些資料可能對機器學習模型的訓練效果沒有幫助,反而會增加計算複雜度和過度擬合的風險。

樓別/樓高

先將兩筆資料拆分

接著我們先處理樓別,這個欄位算是在製作這個專案覺得最難處理的欄位了,資料裡面包含著很多雜訊,不同的數值就有267筆,我們直接看出現次數最少的100筆觀察一下。

用value_counts()方法查看,發現欄位中包含非常多不同的樓層和雜訊

處理的方式是將每筆資料用split拆開後取第一項替代原本的資料。

我們經過處理後成功從267種簡化成43種不同的資料

但是這43種看起來還是很雜亂,所以還需要再簡化,決定用樓層的高度來進行分組,分成 低層、中層、高層、其他、全層。

最後的資料就變得簡單、乾淨多了,最後編碼時也不會造成資料維度過高。

樓高的部分就乾淨很多了,用unique()方法查看只有一個 ‘(空白)’ 需要處理,其他都是樓層數,跟上面一樣依照樓層高低來分組就好了。

佈局

用split()方法拆分再分別放入新的房、衛、廳 欄位
處理到目前資料的樣子

我們目前已經完成對每一個欄位的清洗和處理了,接著將類別型的資料做編碼,然後預測屋齡的缺值,就完成全部的資料處理了,最後就可以製作我們的房價預估模型。

類別變數編碼

在對欄位進行編碼前,要思考一下欄位中的資料有沒有存在具有一定的順序關係,如果沒有順序之間的關係,使用One-Hot Encoding,新增n個欄位,每個欄位利用0與1表示原本的特徵特徵是不是這個類別;如果存在順序間的關係,則使用Label Encoding轉換為有序的數字表示。

我們的類別型變數只有建物類型、用途、行政區沒辦法比較之間的大小關係,要用到One-Hot Encoding,其餘的特徵:電梯、管理員、樓別、樓高則用Label Encoding。

這邊可以用get_dummies()方法我們要的特徵欄位進行One-Hot Encoding,接著利用創立字典和map()方法的方式將要Label Encoding的欄位轉換為有序的數字表示。

在One-Hot Encoding中,當有n個類別時,只需要保留n-1個類別的欄位。這是因為當n-1個欄位都為0時,剩下的那個類別的欄位值就可以被隱含地表示出來,這邊選擇刪除的是出現最少次的變數。

預測屋齡缺失值

首先我們先將屋齡有缺值的資料分開,上面的Age_Na是屋齡缺值的資料,我們晚一點用它的其他特徵項來預測缺值,在那之前我們要先使用Age_not_Na這筆資料來訓練我們的預測模型。

再將Age_not_Na這筆資料拆分特徵變數X 和 目標變數y,接著我們使用隨機森林模型來訓練,

拆分成訓練集和測試集,接著對資料進行擬合

我們得到的R方分數高達0.9,這是一個很好的結果,我們可以使用這個模型來對Age_Na進行預測了。

預測完後再將原先拆分的Age_Na和Age_not_Na整合在一起,完成我們最終要拿來預測房價的資料集。

房價預測模型

這邊選擇使用隨機森林模型,我們的資料筆數有20萬筆,選擇隨機森林的好處可以不用對資料進行特徵縮放,也能一定程度的避免過度擬合的問題,後續也會用交叉折疊來測試是否有過度擬合。

拆分成訓練集和測試集後,最終的R平方得分高達0.9,能夠解釋資料中90%的變異,是非常不錯的一個結果,但也可能存在過度擬合的問題,所以我們會用交叉摺疊5次的方式來看平均得到的R方得分來評估。

交叉折疊5次後得到的平均R方得分還是有0.81,雖然數字有降低,但依舊是一個還不錯的分數,也代表我們的模型並沒有過度擬合的問題。

RMSE在160萬左右,假設誤差遵循常態分佈,大約68%的情況平均誤差大概會是160萬,RMSE的好或壞,很大程度上需要考慮到我們預測目標的尺度,相對於房價的整體範圍數百萬到數千萬來說,160萬的誤差是一個可以接受的範圍。

預測房價

最後我們來試著自行設定條件預估看看房價吧!這邊設定條件在 : 西屯區、屋齡 30、面積 75坪、有電梯和管理員、車位 1、樓別:中層、樓高:高層、5房 2廳 2衛、住宅大樓、住家用。

最終的預測價格為1523.07萬元,考慮到RMSE的誤差,實際價格大概會介於1362.68萬~1683.46萬元的範圍之間。

總結

透過對資料的處理和轉換,我們已經成功地完成了一個房價預測模型,這個模型有一定的預測準確度,大部分的時間都花在特徵工程上面,模型的參數並沒有怎麼調整,所以還是有其他可以再改進的地方。

從R平方分數來看,我們的模型解釋了資料中90%的變異性,而從RMSE來看,我們的模型預測的誤差僅為160萬,考慮到資料中的房價是從幾百萬到幾千萬的範圍而言是可接受的範圍。在整體趨勢預測上做得相當準確。這個模型的整體在預測房價這個具有高度變異性和複雜性的事情上,是有很好的表現的。

感謝閱讀到這邊,以下是完整程式碼的連結 : https://drive.google.com/file/d/1DkbKKRSv7xvUbo3TdK4vphRybMzAm0CB/view?usp=sharing