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 - 博客園?

www.cnblogs.com圖標

在這次建模中我們選用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演算法

TAG:Python | 數據挖掘 | 數據分析 |