Python機器學習實戰--美國房價預測
學了一段時間的Python機器學習,在DataCastle里看到一個關於預測美國房價的演算法競賽,正好可以動手實踐一下^--^:
1.數據來源及說明:
(1)數據來源:
比賽所用的數據取自於kaggle datasets,且對數據做了一些預處理使數據更加符合回歸分析比賽的要求。
(2)數據說明:
下載的競賽數據包含kc_train和kc_test兩個文件,分別是訓練集數據和測試集數據,兩者唯一的區別是測試集數據沒有房屋銷售價格,需要通過由訓練集數據所建立的模型,得出測試數據相應的房屋銷售價格預測值。
2.分析目的及分析過程:
(1)分析目的:
利用回歸分析的方法,從給定的房屋基本信息以及房屋銷售信息等,建立一個回歸模型預測房屋的銷售價格。
(2)分析過程:
- 數據導入及預處理
- 數據的探索性分析
- 數據建模
- 總結與思考
3.數據分析建模:
3.1 數據導入及預處理
3.1.1 數據導入:
先導入分析需要的python包:
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt%matplotlib inlineplt.style.use(ggplot)import seaborn as snssns.set_style(darkgrid) -- 設定繪圖的背景樣式sns.set_palette(muted) -- 設定圖表的顏色板
導入下載好的kc_train的csv文件:
df = pd.read_csv(C:/Users/Administrator/Desktop/kc_train.csv,encoding=utf_8)df.head()
3.1.2 查看數據集概況:
df.info()
訓練集一共10000行數據,包含14個數值型欄位,且每個欄位都沒有缺失,數據非常完整。
3.1.3 變數解釋:
- date: 「銷售日期」:2014年5月到2015年5月房屋出售時的日期
- price: 「銷售價格」:房屋交易價格,單位為美元,是目標預測值
- bed_num: 「卧室數」:房屋中的卧室數目
- bath_num: 「浴室數」:房屋中的浴室數目
- house_sqr: 「房屋面積」:房屋裡的生活面積
- park_sqr: 「停車面積」:停車坪的面積
- floor_num: 「樓層數」:房屋的樓層數
- score: 「房屋評分」:King County房屋評分系統對房屋的總體評分
- build_sqr「建築面積」:除了地下室之外的房屋建築面積
- under_sqr: 「地下室面積」:地下室的面積
- build_year: 「建築年份」:房屋建成的年份
- repair_year「修復年份」:房屋上次修復的年份
- latitude: "緯度":房屋所在緯度
- longitude:「經度」:房屋所在經度
3.1.4 數據的預處理:
因沒有缺失值,可以跳過缺失值處理這個工作,接下來刪除不必要的欄位,因為表中的經緯度是美國地區的,在分析中用不到這兩個變數,並且銷售日期也是沒用的,故進行刪除處理。
df.drop([date,latitude,longitude],axis =1,inplace=True)df.head()
3.2 數據的探索性分析
3.2.1 數值型變數的描述性統計:
df.describe()
10個自變數基本可以分為3類:
第一類:離散型變數:bed_num, bath_num, floor_num 這三個變數單位都是數目
第二類:連續型變數:house_sqr, park_sqr, build_sqr, under_sqr,單位都是面積
第三類:build_year, repair_year 這兩個時間變數
3.2.2 因變數的數據概況
觀察一下price的數據分布:
df.price.hist(bins =50)
price呈現典型的右偏分布,大部分房屋的價格都在70萬元以下,符合房價的一般規律。
再看一下price的離散程度:
sns.boxplot(y = price,data =df)
數據的離群值基本為100萬以上的數據,與上面的右偏分布相吻合。
3.2.3 自變數與因變數的相關性分析
繪製相關性矩陣熱力圖,比較各個變數之間的相關性:
internal_chars = [price,bed_num,bath_num,house_sqr,park_sqr,floor_num ,score,build_sqr,under_sqr,build_year,repair_year]corrmat = df[internal_chars].corr() --計算相關係數f, ax = plt.subplots(figsize=(10, 6)) -- 設置圖表尺寸大小plt.xticks(rotation=0)sns.heatmap(corrmat, square=False, linewidths=.5, annot=True) -- 設置熱力圖參數
可以看到與price相關性比較大的有浴室數目,房屋面積,得分以及建築面積。相關係數都在0.5以上,與建築年份以及修復年份關係很小,另外讓人感到意外的是,停車坪面積與price相關係數只有0.094,可能美帝的房子基本都有停車的地方,所以不太影響房價,而在中國,別說停車坪了,停車庫都很緊張。。。。
根據熱力圖已經初步篩選了bath_num , house_sqr , score, build_sqr這4個與price相關性比較大的變數,現在看一下它們與price的具體關係:
sns.boxplot(x=bath_num,y= price,data = df) --繪製分組箱線圖
根據箱圖可以看到浴室數目越多,房價越高。
sns.jointplot(house_sqr,price,data =df,kind=reg)--繪製散點圖
房屋面積和房價呈現一定的線性關係,且房屋面積近似服從正態分布。
sns.jointplot(score,price,data =df,kind=reg)
因為得分為離散型變數,繪製出的散點圖很像分類點線圖了,兩者也存在線性關係。
sns.jointplot(build_sqr,price,data =df,kind=reg)
建築面積和房價的關係類似上述的房屋價格,不過相關係數稍低一點。
3.3 數據建模
數據的探索性分析就到這裡,主要的工作還是數據建模,因為自變數和因變數基本都為連續型數值變數,得分和浴室數目也可看作連續型。所以建立「多元線性回歸模型」是最適合的。
3.3.1 特徵篩選:
雖然之前在探索性分析中我們已經篩選出了4個自變數,但這只是人工地進行篩選,並不科學,所以我們要用「機器學習」中的特徵選擇方法繼續篩選。通常,可以從兩個方面來選擇特徵:
- 特徵是否發散:如果一個特徵不發散,例如方差接近於0,也就是說樣本在這個特徵上基本上沒有差異,這個特徵對於樣本的區分並沒有什麼用。
- 特徵與因變數的相關性:這點比較顯見,與因變數相關性高的特徵,應當優選選擇。
特徵選擇的方法有很多,例如:
Filter 法:方差選擇,相關係數選擇,卡方檢驗,互信息法
Wrapper 法:遞歸特徵消除法
Embedded法:基於懲罰項的選擇,基於樹模型的選擇
在這裡不再詳細介紹了,小夥伴們想要了解更多,可以點擊這個鏈接:
使用sklearn做單機特徵工程 - jasonfreak - 博客園在這次建模中我們選用Wrapper 法 和 Filter 法進行特徵選擇:
1)使用 Wrapper 法篩選:
----遞歸消除特徵法是使用一個基模型來進行多輪訓練,每輪訓練後,消除若干權值係數的特徵,再基於新的特徵集進行下一輪訓練。使用feature_selection庫的RFE類來選擇特徵。
x= df.drop([date,price,latitude,longitude,build_year,repair_year],axis =1,inplace=False)x = np.array(x) --- 建立自變數的二位數組x
y = df[[price]]y = np.array(y) ---建立因變數的二維數組y
from sklearn.linear_model import LinearRegression --導入基模型from sklearn.feature_selection import RFE -- 導入RFE模塊model1 = LinearRegression() -- 建立一個線性模型rfe = RFE(model1,4) -- 進行多輪訓練,設置篩選特徵數目為4個rfe = rfe.fit(x,y) -- 模型的擬合訓練print(rfe.support_) -- 輸出特徵的選擇結果print(rfe.ranking_) -- 特徵的選擇排名
輸出結果中True為選擇的特徵變數,排名也是第1位,可以得出用Wrapper法篩選的特徵為:house_sqr , score, build_sqr, under_sqr這四個。
接下來我們利用「交叉檢驗」的方法看如果這四個變數進入模型,模型的性能怎麼樣。
---交叉檢驗的概念是將數據分成訓練集和測試集,取一部分訓練集數據得到回歸方程,並在測試集中進行檢驗,觀察正確度,以此來評判模型的好壞。
from sklearn.model_selection import cross_val_score -- 導入交叉檢驗的模塊x_test1 = df[[house_sqr,score,build_sqr,under_sqr]]x_test1 = np.array(x_test1) -- 建立自變數的二維數組y_test1 = df[[price]]y_test1 = np.array(y_test1) -- 建立因變數的二維數組model2 = LinearRegression() -- 建立線性模型model2.fit(x_test1,y_test1) -- 模型的擬合訓練scores = -cross_val_score(model2, x_test1, y_test1, cv=5, scoring= neg_mean_absolute_error)print(np.mean(scores)) -- 將數據集分為5份,分別進行5次回歸,返回得分
輸出:165188.009468,得分越高,說明模型的誤差越大,所以輸出的結果越小越好。
下面用Filter法進行特徵選擇:
from sklearn.feature_selection import SelectKBest, f_classifselector = SelectKBest(f_classif, k=4) -- 用f_classif方法,設定數目為4a=selector.fit(x,y)print(np.array(a.scores_),
,a.get_support()) -- 輸出得分及選擇的結果
得出用Filter法篩選的特徵為:bath_num, house_sqr , score, build_sqr這四個,發現這個結果與我們用人工篩選的結果一樣,我們再看看交叉檢驗結果如何:
x_test2 = df[[bath_num,house_sqr,score,build_sqr]]x_test2 = np.array(x_test2)y_test2 = df[[price]]y_test2 = np.array(y_test2)model3 = LinearRegression()model3.fit(x_test2,y_test2)scores = -cross_val_score(model3, x_test2, y_test2, cv=5, scoring= neg_mean_absolute_error)print(np.mean(scores))
輸出:164021.249177,比用Wrapper法的結果小,說明用Filter法篩選的效果更好。
故我們選擇bath_num, house_sqr , score, build_sqr這四個變數進入模型。
3.3.2 建立多元回歸模型
from sklearn.linear_model import LinearRegressionx = df[[bath_num,house_sqr,score,build_sqr]]x = np.array(x)y = df[[price]]y = np.array(y)model = LinearRegression()model.fit(x,y)a = model.intercept_ -- a為回歸方程的截距項b = model.coef_ -- b為回歸方程的回歸係數print(y = {} + {} * X.format(a,b))
設bath_num, house_sqr , score, build_sqr分別為x1, x2, x3, x4,
所得出的回歸方程為: y = -30381 x1+252 x2+ 118436 x3 - 83 x4 - 676578
我們將回歸方程導入數據集中,看看預測的效果怎麼樣:
df[price_pre] = df.apply(lambda x:x.bath_num*-30381 + x.house_sqr*251 + x.score*118436 + x.build_sqr*-83- 676578,axis=1)df_select = df[[price,price_pre]]df_select.head()
查看前5條數據,發現除了第二條數據的預測結果偏差比較大以外,其它的誤差還能接受。
接下來我們將這個回歸方程導入到測試集(kf_test)數據中,預測測試集的房價。
test = pd.read_csv(C:/Users/Administrator/Desktop/kc_test.csv,encoding=utf_8)test[price_predict] = test.apply(lambda x:x.bath_num*-30381 + x.house_sqr*251 + x.score*118436 + x.build_sqr*-83- 676578,axis=1)test.head()
到這一步,基本的數據建模工作已經完成了。
4.總結和思考
這次做的房價預測讓我對Python的機器學習有了初步的了解,其次這個預測項目還有很多地方需要改進,比如建模前沒有怎麼對數據進行預處理,這是建模前非常重要的一步,還有對於參數,特徵及模型的調優, 不過隨著對機器學習的不斷深入,以後也會對這個項目進行相應的改進,不斷提高模型的準確度。
另外在學習過程中發現自己對概率統計知識還是比較匱乏的,對於機器演算法的原理還需要去不斷深入了解。後續也會加強這方面的學習。
今天的分享就到這啦~~
推薦閱讀:
※爆款遊戲《貪吃蛇大作戰》的 Python 實現
※簡述 Python 類中的 __init__、__new__、__call__ 方法
※excel中想實現使用Python代替VBA,請問應該怎麼做?
※爬蟲圖解:輪子哥關注了哪些人
※K-means演算法