機器學習實戰二:波士頓房價預測 Boston Housing


波士頓房價預測 Boston housing

這是一個波士頓房價預測的一個實戰,上一次的Titantic是生存預測,其實本質上是一個分類問題,就是根據數據分為1或為0,這次的波士頓房價預測更像是預測一個連續值,當然這也是一個非常經典的機器學習案例Boston housing
如果想了解更多的知識,可以去我的機器學習之路 The Road To Machine Learning通道

@

活動背景

波士頓房地產市場競爭激烈,而你想成為該地區最好的房地產經紀人。為了更好地與同行競爭,你決定運用機器學習的一些基本概念,幫助客戶為自己的房產定下最佳售價。幸運的是,你找到了波士頓房價的數據集,里面聚合了波士頓郊區包含多個特征維度的房價數據。你的任務是用可用的工具進行統計分析,並基於分析建立優化模型。這個模型將用來為你的客戶評估房產的最佳售價。

數據介紹

在這里插入圖片描述
在這里插入圖片描述

詳細代碼解釋

導入Python Packages

首先導入需要的python包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
plt.style.use('ggplot')
%load_ext klab-autotime

讀入數據 Read-In Data

將housing,csv讀入

data = pd.read_csv('../data_files/2.Boston_housing/housing.csv')
data.info()
# No	屬性	數據類型	字段描述x
# 1	CRIM	Float	城鎮人均犯罪率
# 2	ZN	Float	占地面積超過2.5萬平方英尺的住宅用地比例
# 3	INDUS	Float	城鎮非零售業務地區的比例
# 4	CHAS	Integer	查爾斯河虛擬變量 (= 1 如果土地在河邊;否則是0)
# 5	NOX	Float	一氧化氮濃度(每1000萬份)
# 6	RM	Float	平均每居民房數
# 7	AGE	Float	在1940年之前建成的所有者占用單位的比例
# 8	DIS	Float	與五個波士頓就業中心的加權距離
# 9	RAD	Integer	輻射狀公路的可達性指數
# 10	TAX	Float	每10,000美元的全額物業稅率
# 11	PTRATIO	Float	城鎮師生比例
# 12	B	Float	1000(Bk - 0.63)^ 2其中Bk是城鎮黑人的比例
# 13	LSTAT	Float	人口中地位較低人群的百分數
# 14	MEDV	Float	(目標變量/類別屬性)以1000美元計算的自有住房的中位數

在這里插入圖片描述
在這里插入圖片描述
從這里可以看出來,數據一共有14個特征,並且沒有缺失值,所以我們可以不用缺失值處理,真不錯

從Package讀取Boston數據

其實在我們的sklearn庫中,就有波士頓房屋數據集,我們可以直接讀取數據集

from sklearn.datasets import load_boston
dir(load_boston())
print(load_boston().DESCR)

在這里插入圖片描述
這里也有對數據集詳細的介紹,除此之外,我們還需要將數據集轉化了類型,變為我們熟悉的pandas.core.frame.DataFrame,之后后面的操作就是一模一樣的了

X = load_boston().data
y = load_boston().target
df = pd.DataFrame(X, columns=load_boston().feature_names)
df.head()

在這里插入圖片描述

相關性檢驗

看看各個特征中是否有相關性,判斷一下用哪種模型比較合適

plt.figure(figsize=(12,8))
sns.heatmap(data.corr(), annot=True, fmt='.2f', cmap='PuBu')

在這里插入圖片描述

數據不存在相關性較小的屬性,也不用擔心共線性,所以我們可以用線性回歸模型去預測

data.corr()['MEDV'].sort_values()

在這里插入圖片描述

多變量研究

嘗試了解因變量和自變量、自變量和自變量之間的關系

sns.pairplot(data[["LSTAT","RM","PIRATIO","MEDV"]])

在這里插入圖片描述

划分訓練集和測試集

由於數據沒有null值,並且,都是連續型數據,所以暫時不用對數據進行過多的處理,不夠既然要建立模型,首先就要進行對housing分為訓練集和測試集,取出了大概百分之20的數據作為測試集,剩下的百分之70為訓練集

X ,y = data[data.columns.delete(-1)], data['MEDV']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=888)

查看訓練集和測試集的維度
在這里插入圖片描述

建立線性回歸模型

首先,我利用線性回歸模型對數據進行訓練,並預測測試集數據,對於具體的線性回歸的介紹,可以參考Linear Regression Machine Learning
在這里插入圖片描述

linear_model = LinearRegression()
linear_model.fit(X_train, y_train)
coef = linear_model.coef_#回歸系數
line_pre = linear_model.predict(X_test)
print('SCORE:{:.4f}'.format(linear_model.score(X_test, y_test)))
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test, line_pre))))
coef

根據結果來看,預測的score為76%左右,然后均方誤差RMSE大約是4.5,為了更好的看出預測數據的問題,我想試着可視化一下
在這里插入圖片描述

df_coef = pd.DataFrame()
df_coef['Title'] = data.columns.delete(-1)
df_coef['Coef'] = coef
df_coef

這是線性回歸的相關系數

在這里插入圖片描述

hos_pre = pd.DataFrame()
hos_pre['Predict'] = line_pre
hos_pre['Truth'] = y_test
hos_pre.plot(figsize=(18,8))

在這里插入圖片描述

  • 得出score為76%,從上圖得知預測的房價整體偏小,在10-35這個區間預測結果較為准確,超過這個區間預測價格偏小,可進一步對原始數據離群值做處理。
  • 數據比較干凈,練習起來缺少特征工程部分的工作,而且是預測性模型,相比分類問題少了模型選擇上的空間。

評價模型

在整個數據集上評價模型

plt.scatter(y_test, line_pre,label='y')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=4,label='predicted')

在這里插入圖片描述
然后在整個數據集中評價模型

line_pre_all = linear_model.predict(X)  #預測值
print('SCORE:{:.4f}'.format(linear_model.score(X,y)))
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y, line_pre_all))))
hos_pre_all = pd.DataFrame()
hos_pre_all['Predict'] = line_pre_all
hos_pre_all['Truth'] = y
hos_pre_all.plot(figsize=(18,8))

在這里插入圖片描述

plt.scatter(y, line_pre_all,label='y')
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4,label='predicted')

在這里插入圖片描述
由以上分析可知,模型在整個數據集中的評分比在測試集中要低

進一步探索和模型改進

  • 嘗試使用相關性最高的3個特征量重建模型,並與原模型進行比較
  • 嘗試使用其它多種算法分別建立模型,並比較模型

特征選擇重建模型

首先我嘗試相關性最高的三個特征重建模型,去與原模型比較一下

data.corr()['MEDV'].abs().sort_values(ascending=False).head(4)

由此我們得出了三個相關性最高的特征,我們將其作為自變量去建立模型
在這里插入圖片描述

X2 = np.array(data[['LSTAT','RM','PIRATIO']])
X2_train, X2_test, y_train, y_test = train_test_split(X2, y, random_state=1,test_size=0.2)
linear_model2 = LinearRegression()
linear_model2.fit(X2_train,y_train)
print(linear_model2.intercept_)
print(linear_model2.coef_)
line2_pre = linear_model2.predict(X2_test)  #預測值
print('SCORE:{:.4f}'.format(linear_model2.score(X2_test, y_test)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test, line2_pre))))#RMSE(標准誤差)

我們可以得到,對於預測測試集的數據的得分score明顯是沒有開始的線性回歸模型1高的,然后我們再看看,在整個數據集中它的表現
在這里插入圖片描述

line2_pre_all = linear_model2.predict(X2)  #預測值
print('SCORE:{:.4f}'.format(linear_model2.score(X2, y)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y, line2_pre_all))))#RMSE(標准誤差)

在這里插入圖片描述
這樣比較下來,第一個模型達到的分數,即使在整個數據集中73%,但是這個模型的得分大約是67.6%,由此可以得出,第一個模型還是比這個模型優的,接下來就需要嘗試更多的模型了

數據標准化

數據集的 標准化 對scikit-learn中實現的大多數機器學習算法來說是 常見的要求 。如果個別特征或多或少看起來不是很像標准正態分布(具有零均值和單位方差),那么它們的表現力可能會較差。
所以我這里首先對數據進行了一個標准化處理

from sklearn.preprocessing import StandardScaler
ss_x = StandardScaler()
X_train = ss_x.fit_transform(X_train)
X_test = ss_x.transform(X_test)
ss_y = StandardScaler()
y_train = ss_y.fit_transform(y_train.values.reshape(-1, 1))
y_test = ss_y.transform(y_test.values.reshape(-1, 1))

模型優化和改進

接下來我就開始嘗試多種模型,希望嘗試的模型有對我的算法有幫助

X ,y = data[data.columns.delete(-1)], data['MEDV']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=9)

GradientBoosting(梯度提升)

from sklearn import ensemble
#params = {'n_estimators': 500, 'max_depth': 4, 'min_samples_split': 1,'learning_rate': 0.01, 'loss': 'ls'}
#clf = ensemble.GradientBoostingRegressor(**params)
clf = ensemble.GradientBoostingRegressor()
clf.fit(X_train, y_train)
clf_pre=clf.predict(X_test) #預測值
print('SCORE:{:.4f}'.format(clf.score(X_test, y_test)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test, clf_pre))))#RMSE(標准誤差)

在這里插入圖片描述

Lasso 回歸 (Least Absolute Shrinkage and Selection Operator)

Lasso也是懲罰其回歸系數的絕對值。
與嶺回歸不同的是,Lasso回歸在懲罰方程中用的是絕對值,而不是平方。這就使得懲罰后的值可能會變成0

from sklearn.linear_model import Lasso

lasso = Lasso()
lasso.fit(X_train,y_train)
y_predict_lasso = lasso.predict(X_test)
r2_score_lasso = r2(y_test,y_predict_lasso)

print('SCORE:{:.4f}'.format( lasso.score(X_test, y_test)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test,y_predict_lasso))))#RMSE(標准誤差)
print('Lasso模型的R-squared值為:',r2_score_lasso)

ElasticNet 回歸

ElasticNet回歸是Lasso回歸和嶺回歸的組合

enet = ElasticNet()
enet.fit(X_train,y_train)
y_predict_enet = enet.predict(X_test)
r2_score_enet = r2(y_test,y_predict_enet)

print('SCORE:{:.4f}'.format( enet.score(X_test, y_test)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test,y_predict_enet))))#RMSE(標准誤差)
print("ElasticNet模型的R-squared值為:",r2_score_enet)

Support Vector Regression (SVR)

from sklearn.linear_model import ElasticNet
from sklearn.svm import SVR
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import r2_score as r2, mean_squared_error as mse, mean_absolute_error as mae

def svr_model(kernel):
    svr = SVR(kernel=kernel) 
    svr.fit(X_train, y_train)
    y_predict = svr.predict(X_test)

    # score(): Returns the coefficient of determination R^2 of the prediction.
    print(kernel,' SVR的默認衡量評估值值為:', svr.score(X_test,y_test))
    print(kernel,' SVR的R-squared值為:', r2(y_test, y_predict))
    print(kernel,' SVR的均方誤差(mean squared error)為:',mse(y_test, y_predict))
    print(kernel,' SVR的平均絕對誤差(mean absolute error)為:',mae(y_test,y_predict))
    # print(kernel,' SVR的均方誤差(mean squared error)為:',mse(scalery.inverse_transform(y_test), scalery.inverse_transform(y_predict)))
    # print(kernel,' SVR的平均絕對誤差(mean absolute error)為:',mae(scalery.inverse_transform(y_test),scalery.inverse_transform(y_predict)))
    
    return svr

linear 線性核函數

linear_svr = svr_model(kernel='linear') 

在這里插入圖片描述

poly 多項式核

poly_svr = svr_model(kernel='poly')  

在這里插入圖片描述

rbf(Radial Basis Function) 徑向基函數

rbf_svr = svr_model(kernel='rbf') 

在這里插入圖片描述

SVM(支持向量機)回歸-- 線性核

from sklearn.svm import SVR
linear_svr = SVR(kernel="linear")
linear_svr.fit(X_train, y_train)
linear_svr_pre = linear_svr.predict(X_test)#預測值
print('SCORE:{:.4f}'.format(linear_svr.score(X_test, y_test)))#模型評分
print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test, linear_svr_pre))))#RMSE(標准誤差)

在這里插入圖片描述

SVM(支持向量機)回歸-- 多項式核

在使用SVM回歸-- 多項式核的時候,首先要對數據進行一個標准化處理

from sklearn.preprocessing import StandardScaler ss_x = StandardScaler() X_train = ss_x.fit_transform(X_train) X_test = ss_x.transform(X_test) ss_y = StandardScaler() y_train = ss_y.fit_transform(y_train.values.reshape(-1, 1)) y_test = ss_y.transform(y_test.values.reshape(-1, 1))
再進行建立模型來預測

poly_svr = SVR(kernel="poly") poly_svr.fit(X_train, y_train) poly_svr_pre = poly_svr.predict(X_test)#預測值 print('SCORE:{:.4f}'.format(poly_svr.score(X_test, y_test)))#模型評分 print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test, poly_svr_pre))))#RMSE(標准誤差)
在這里插入圖片描述

決策樹回歸

from sklearn.tree import DecisionTreeRegressor tree_reg=DecisionTreeRegressor(max_depth=2) tree_reg.fit(X_train, y_train) tree_reg_pre = tree_reg.predict(X_test)#預測值 print('SCORE:{:.4f}'.format( tree_reg.score(X_test, y_test)))#模型評分 print('RMSE:{:.4f}'.format(np.sqrt(mean_squared_error(y_test,tree_reg_pre))))#RMSE(標准誤差)
在這里插入圖片描述

最后我們會發現,利用GBDT的得分居然高達90,這是我們得到最優的一個模型了,其次就是SVR回歸的多項式核,也大概達到了85,其他的並沒有線性回歸那么優,所以對於波士頓房價預測來說,利用GBDT是最好的,這是迄今為止我遇到最好的模型

總結

  • 可以發現,如果要用Gradient Boosting 算法的話,在sklearn包里調用是非常方便的,幾行代碼即可完成,大部分的工作是在數據特征提取
  • 數據分析過程中,特征設計是最重要的,現在kaggle競賽很流行使用GBDT(梯度提升決策樹Gradient Boosted Decision Tree) 算法,數據分析結果的優劣其實主要在特征上,行業中做項目也是如此
  • 不斷的在研究數據中培養對數據的敏感度十分重要

每日一句
Never had to laugh at other people.(沒經歷過才笑別人的疤)

如果需要數據和代碼,可以自提


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM