Step 1: 檢視源數(shù)據(jù)集
import numpy as np
import pandas as pd
1.1 讀入數(shù)據(jù)
file=open("D:/python練習(xí)/housing.csv")
train_df=pd.read_csv(file)
1.2 檢視原數(shù)據(jù)
train_df.head(5)
每一行都表示一個街區(qū)愚铡。共有 10 個屬性:經(jīng)度蛉签、維度胡陪、房屋年齡中位數(shù)、總房間數(shù)碍舍、臥室數(shù)量柠座、人口數(shù)、家庭數(shù)片橡、收入中位數(shù)妈经、房屋價值中位數(shù)、離大海距離捧书。
train_df.info()
可以看出total_bedrooms這一項有缺失值吹泡,后面要進行處理。ocean_proximity這一項的數(shù)據(jù)類型為類別型數(shù)據(jù)经瓷。
train_df.ocean_proximity.value_counts()
value_counts()方法查看都有什么類型爆哑,每個類都有多少街區(qū)
train_df.describe()
畫出每個數(shù)值屬性的柱狀圖
%matplotlib inline
from matplotlib import pyplot as plt
plt.style.use('ggplot')
train_df.hist(bins=50,figsize=(16,9))
從柱狀圖中可以發(fā)現(xiàn)以下問題:
1.這些屬性的量度不一樣了嚎,在后面需要進行特征縮放
2.許多柱狀圖的尾巴過長,對某些機器學(xué)習(xí)的算法檢測規(guī)律會變得更難萝勤,所以在后面要處理成正態(tài)分布。
3.房屋年齡中位數(shù)和房屋價值中位數(shù)也被設(shè)了上限敌卓。后者可能是個嚴重的問題伶氢,因為它是你的目標(biāo)屬性(你的標(biāo)簽)。你的機器學(xué)習(xí)算法可能學(xué)習(xí)到價格不會超出這個界限癣防。你需要與下游團隊核實蜗巧,這是否會成為問題。如果他們告訴你他們需要明確的預(yù)測值蕾盯,即使超過 500000幕屹,你則有兩個選項:1)對于設(shè)了上限的標(biāo)簽,重新收集合適的標(biāo)簽级遭;2)將這些街區(qū)從訓(xùn)練集移除(也從測試集移除望拖,因為若房價超出 500000,你的系統(tǒng)就會被差評)挫鸽。
4.收入數(shù)據(jù)經(jīng)過了縮放處理说敏。
Step 2: 創(chuàng)建測試集
目的:防止數(shù)據(jù)透視偏差。如果一開始就看過測試集丢郊,就會不經(jīng)意間按照其中的規(guī)律選擇合適的算法盔沫,當(dāng)再用測試集進行評估時医咨,就會導(dǎo)致結(jié)果比較樂觀,而實際部署時就比較差了架诞。
from sklearn.model_selection import train_test_split
train_set,test_set=train_test_split(train_df,test_size=0.2,random_state=42)
train_test_split函數(shù)用于將矩陣隨機劃分為訓(xùn)練子集和測試子集腋逆,并返回劃分好的訓(xùn)練集測試集樣本和訓(xùn)練集測試集標(biāo)簽。test_size:如果是浮點數(shù)侈贷,在0-1之間,表示樣本占比等脂;如果是整數(shù)的話就是樣本的數(shù)量俏蛮。random_state:是隨機數(shù)的種子。產(chǎn)生總是相同的洗牌指數(shù)上遥;如果沒有這個每次運行會產(chǎn)生不同的測試集搏屑,多次之后會得到整個數(shù)據(jù)集。
train_set.head(5)
不足之處:目前都是采用的純隨機抽樣,如果數(shù)據(jù)量比較小模软,可能會產(chǎn)生偏差携狭。所以需要關(guān)注比較重要的屬性逛腿,對其進行分層抽樣单默,比如說收入中位數(shù)。從直方圖中可以看出枚抵,大多數(shù)的值在2-5(萬美元)汽摹,進行分層抽樣時保證每一層都要有足夠多的數(shù)據(jù)逼泣,這就意味著嗜憔,層數(shù)不能過多吉捶。后面的代碼將收入中位數(shù)除以1.5(以限制分類的數(shù)量)呐舔,創(chuàng)建收入類別屬性魂挂,用ceil對值舍入(產(chǎn)生離散的分類)押赊,并將大于5的分類歸入到分類5。inplace=True原數(shù)組內(nèi)容被改變揭斧。
train_df["income_cat"]=np.ceil(train_df.median_income/1.5)
train_df["income_cat"].where(train_df["income_cat"]<5,5.0,inplace=True)
train_df["income_cat"].head(5)
train_df["income_cat"].value_counts()/len(train_df)
from sklearn.model_selection import StratifiedShuffleSplit
split=StratifiedShuffleSplit(n_splits=1,test_size=0.2,random_state=42)
for train_index,test_index in split.split(train_df,train_df["income_cat"]):
start_train_set=train_df.loc[train_index]
start_test_set=train_df.loc[test_index]
start_train_set.head(5)
for set in(start_train_set,start_test_set):
set.drop(["income_cat"],axis=1,inplace=True)
start_test_set.head(5)
需要刪除income_cat屬性旦万,使數(shù)據(jù)回到初始狀態(tài)成艘。
Step 3: 數(shù)據(jù)探索及可視化
目的:以上只是粗略的查看了統(tǒng)計信息淆两,還需要從樣本中發(fā)現(xiàn)更多的信息秋冰。如果訓(xùn)練集非常大剑勾,可能還需要采樣一個探索集暂刘。如果比較小捂刺,可以建立一個副本芝发。
housing=start_train_set.copy()
3.1 地理數(shù)據(jù)可視化
原因:樣本中有經(jīng)度和緯度,所以考慮創(chuàng)建散點圖
housing.plot(kind="scatter",x="longitude",y="latitude",alpha=0.4,figsize=(15, 10)
)
高密度區(qū)域:灣區(qū)腹殿、洛杉磯和圣迭戈等
housing.plot(kind="scatter",x="longitude",y="latitude",alpha=0.5,
s=housing.population/50,label="population",
c=housing.median_house_value,cmap=plt.get_cmap('jet'),colorbar=True,
figsize=(15, 10))
plt.legend()
加入人口信息,用點的大小來展示(s)自沧。加入房價信息拇厢,用顏色的深淺來表示(c)孝偎,用預(yù)先定義的顏色圖“jet”,范圍從藍色到紅色爷抓,即低價到高價果复。從圖中可以發(fā)現(xiàn)房價和位置(沿海地區(qū))以及人口密度存在聯(lián)系据悔。
import seaborn as sns
sns.set(style = "whitegrid")#設(shè)置樣式
x = housing.longitude#X軸數(shù)據(jù)
y = housing.latitude#Y軸數(shù)據(jù)
z = housing.median_income#用來調(diào)整各個點的大小s
cm = plt.get_cmap('jet')
fig,ax = plt.subplots(figsize = (15,10))
#注意s離散化的方法极颓,因為需要通過點的大小來直觀感受其所表示的數(shù)值大小
#參數(shù)是X軸數(shù)據(jù)兵琳、Y軸數(shù)據(jù)躯肌、各個點的大小清女、各個點的顏色
bubble = ax.scatter(x, y , s = housing.population/50, c = z, cmap = cm, linewidth = 0.5, alpha = 0.5)
ax.grid()
fig.colorbar(bubble)
ax.set_xlabel('longitude', fontsize = 15)#X軸標(biāo)簽
ax.set_ylabel('latitude', fontsize = 15)#Y軸標(biāo)簽
plt.show()
利用seaborn作圖也可以達到同樣效果。加入人口信息曙博,用點的大小來展示(s)父泳。加入收入信息惠窄,用顏色的深淺來表示(c)睬捶,用預(yù)先定義的顏色圖“jet”擒贸,范圍從藍色到紅色,即低價到高價案淋。從圖中可以發(fā)現(xiàn)收入和位置(沿海地區(qū))以及人口密度存在一定的聯(lián)系誉碴,但是效果不是十分明顯黔帕。
3.2 查看特征之間的相關(guān)性
corr_matrix=housing.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)
用熱力圖的方式展現(xiàn)相關(guān)性。annot(annotate的縮寫):默認取值False思瘟;如果是True滨攻,在熱力圖每個方格寫入數(shù)據(jù);vmax,vmin:分別是熱力圖的顏色取值最大和最小范圍,默認是根據(jù)data數(shù)據(jù)表里的取值確定漂坏。
import seaborn as sns
fig=plt.figure(figsize=(12,8),dpi=80)
sns.heatmap(housing.corr(),annot =True,vmin = 0, vmax = 1)
用可視化的方式展現(xiàn)相關(guān)性,因為屬性過多拒啰,所以選取部分屬性剩失。
from pandas.tools.plotting import scatter_matrix
attributes=["median_house_value","median_income","total_rooms","housing_median_age" ]
scatter_matrix(housing[attributes],figsize=(12,8))
對角線表示每個屬性的柱狀圖拴孤。圖中可以看出收入對房價的影響還是比較大的甲捏,所以可以放大進行研究芒粹。
housing.plot(kind="scatter",x="median_income",y="median_house_value",alpha=0.5,figsize=(12,8))
可以看出相關(guān)性還是很高的估脆。其次,可以看到一些直線:500000,450000,350000,280000美元棺聊,可能是收集資料時設(shè)立的邊界。
3.3 屬性組合試驗
有一些屬性贞谓,比如總房間數(shù)限佩,在不知道街區(qū)有多少戶的情況下用處不大。同理總臥室數(shù)和總?cè)丝跀?shù)裸弦。
housing["rooms_per_household"]=housing.total_rooms/housing.households
housing["bedrooms_per_room"]=housing.total_bedrooms/housing.total_rooms
housing["population_per_household"]=housing.population/housing.households
corr_matrix =housing.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)
間數(shù)和臥室數(shù)更有信息祟同。而且每戶的房間數(shù)越多,意味著房屋更大理疙,房價越高晕城,比單純的看總房間數(shù)更有信息。
Step 4: 數(shù)據(jù)預(yù)處理
目的:為機器學(xué)習(xí)算法準(zhǔn)備數(shù)據(jù)。
housing=start_train_set.drop("median_house_value",axis=1)
housing_copy=housing.copy()
housing_labels=start_train_set.median_house_value.copy()
print(housing.head(5))
print(housing_labels.head(5))
將訓(xùn)練集中預(yù)測量和標(biāo)簽分開览闰,因為之后對其要進行不同的轉(zhuǎn)換;drop()創(chuàng)建備份际邻,不影響原數(shù)據(jù)集。
4.1 數(shù)據(jù)清洗
目的:處理缺省值。因為很多機器學(xué)習(xí)算法對缺省值比較敏感(例如LR和SVM,決策樹和樸素貝葉斯相對好一點)
思路:1)去掉缺失的行數(shù)據(jù)dropna()螟炫;2)去掉缺失的列drop()折晦;3)進行賦值fillna(),可以是0、平均數(shù)和中位數(shù)魂莫。
median=housing.total_bedrooms.median()
housing.total_bedrooms=housing.total_bedrooms.fillna(median)
housing.isnull().sum().sum()
4.2 處理文本和類別屬性
housing=pd.get_dummies(housing)
housing.head(5)
pandas自帶的get_dummies方法,可以幫你一鍵做到One-Hot逾一⊥艏耄可以看出類別屬性ocean_proximity被我們分成了5個column,每一個代表一個category捻撑。是就是1,不是就是0鳖枕。
4.3 特征縮放
當(dāng)輸入的屬性量度不同時彭谁,會影響機器學(xué)習(xí)算法的性能。比如總房間數(shù)分布范圍在6-39320唱矛,收入中位數(shù)在0-15碧囊。兩種方法:歸一化和標(biāo)準(zhǔn)化吴叶。歸一化將數(shù)值縮放到0-1之間,標(biāo)準(zhǔn)化不會限定到某個范圍,對一些算法有影響静浴,像神經(jīng)網(wǎng)絡(luò)算法輸入值就必須是0-1。但是異常值對標(biāo)準(zhǔn)化的影響較小。
numeric_cols=housing_copy.columns[housing_copy.dtypes!="object"]
print(numeric_cols)
numeric_col_means = housing.loc[:, numeric_cols].mean()
numeric_col_std = housing.loc[:, numeric_cols].std()
housing.loc[:, numeric_cols] = (housing.loc[:, numeric_cols] - numeric_col_means) /numeric_col_std
housing.head()
housing_labels=(housing_labels-housing_labels.mean())/housing_labels.std()
housing_labels.head()
Step 5:模型選擇和訓(xùn)練
5.1 在訓(xùn)練集上訓(xùn)練和評估
from sklearn.linear_model import LinearRegression
lin_reg=LinearRegression()
將DF轉(zhuǎn)化為Numpy Array
X_train=housing.values
X_test=housing_labels.values
print(X_train)
print(X_test)
先訓(xùn)練一個線性回歸模型
lin_reg.fit(X_train,X_test)
訓(xùn)練完成硼身,用交叉驗證法進行模型評估。交叉驗證的基本思想是將訓(xùn)練數(shù)據(jù)集分為k份针姿,每次用k-1份訓(xùn)練模型,用剩余的1份作為驗證集筒饰。按順序訓(xùn)練k次后缴啡,計算k次的平均誤差來評價模型(改變參數(shù)后即為另一個模型)的好壞。
from sklearn.model_selection import cross_val_score
lin_reg_scores=cross_val_score(lin_reg,X_train,X_test,scoring="neg_mean_squared_error",cv=10)
lin_reg_rmse_scores=np.sqrt(-lin_reg_scores)
print(lin_reg_rmse_scores.mean())
均方根誤差(RMSE)瓷们,回歸任務(wù)可靠的性能指標(biāo)业栅。
利用決策樹模型試試看
from sklearn.tree import DecisionTreeRegressor
tree_reg=DecisionTreeRegressor()
tree_reg.fit(X_train,X_test)
tree_reg_scores=cross_val_score(tree_reg,X_train,X_test,scoring="neg_mean_squared_error",cv=10)
tree_reg_rmse_scores=np.sqrt(-tree_reg_scores)
print(tree_reg_rmse_scores.mean())
可以看出決策樹模型的誤差大于線性回歸,性能更差一點∶危現(xiàn)在選擇用隨機森林嘗試一下碘裕。
from sklearn.ensemble import RandomForestRegressor
RF_reg=RandomForestRegressor()
RF_reg.fit(X_train,X_test)
RF_reg_scores=cross_val_score(RF_reg,X_train,X_test,scoring="neg_mean_squared_error",cv=10)
RF_reg_rmse_scores=np.sqrt(-RF_reg_scores)
print(RF_reg_rmse_scores.mean())
隨機森林速度慢一點,誤差更小攒钳,明顯更有希望帮孔。
5.2 利用網(wǎng)格搜索對模型進行微調(diào)
只要提供超參數(shù)和試驗的值,網(wǎng)格搜索就可以使用交叉驗證試驗所有可能超參數(shù)值的組合夕玩。
from sklearn.model_selection import GridSearchCV
param_grid = [
{'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]},
{'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},
]
forest_reg = RandomForestRegressor()
grid_search = GridSearchCV(forest_reg, param_grid, cv=5,
scoring='neg_mean_squared_error')
grid_search.fit(X_train,X_test)
首先調(diào)第一行的參數(shù)為n_estimators和max_features你弦,即有34=12種組合,然后再調(diào)第二行的參數(shù)燎孟,即23=6種組合禽作,具體參數(shù)的代表的意思以后再講述】常總共組合數(shù)為12+6=18種組合旷偿。每種交叉驗證5次,即18*5=90次模型計算爆侣,雖然運算量比較大萍程,但運行完后能得到較好的參數(shù)
grid_search.best_params_
可以看到最好參數(shù)中30是選定參數(shù)的邊緣,所以可以再選更大的數(shù)試驗兔仰,可能會得到更好的模型茫负,還可以在8附近選定參數(shù),也可能會得到更好的模型乎赴。
grid_search.best_estimator_
得到最佳的估計器
5.3 用測試集去評估系統(tǒng)
from sklearn.metrics import mean_squared_error
final_model = grid_search.best_estimator_
X_test = start_test_set.drop("median_house_value", axis=1)
y_test = start_test_set["median_house_value"].copy()
median=X_test.total_bedrooms.median()
X_test.total_bedrooms=X_test.total_bedrooms.fillna(median)
X_test=pd.get_dummies(X_test)
numeric_col_means = X_test.loc[:, numeric_cols].mean()
numeric_col_std = X_test.loc[:, numeric_cols].std()
X_test.loc[:, numeric_cols] = (X_test.loc[:, numeric_cols] - numeric_col_means) /numeric_col_std
y_test=(y_test-y_test.mean())/y_test.std()
final_predictions = final_model.predict(X_test)
final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
print(final_rmse)
把測試集進行預(yù)處理忍法,導(dǎo)入到系統(tǒng)中,誤差為0.462982088615榕吼,模型的表現(xiàn)還不錯饿序。