此項目作為kaggle的入門項目,主要是利用回歸分析的算法來預(yù)測房價戒劫,初次接觸,目前以消化大神的項目代碼幫助自己提升婆廊,如有疑問迅细,可相互交流。
項目地址:https://www.kaggle.com/c/house-prices-advanced-regression-techniques
大神代碼:https://www.kaggle.com/apapiu/regularized-linear-models
此項目可以使用notebook去完成淘邻,當然用你熟悉的工具也可茵典。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt
from scipy.stats import skew
from scipy.stats.stats import pearsonr
%config InlineBackend.figure_format = 'retina' #set 'png' here when working on notebook
%matplotlib inline
# 利用pandas庫的read_csv函數(shù)讀取數(shù)據(jù),生成DataFrame格式數(shù)據(jù)宾舅,列名默認csv數(shù)據(jù)的第一行
train = pd.read_csv("../input/train.csv")
test = pd.read_csv("../input/test.csv")
# head函數(shù)可以查看下數(shù)據(jù)统阿,默認展示前5行
train.head()
# train.loc[:,'MSSubClass':'SaleCondition']表示獲取從MSSubClass到SaleCondition的列特征數(shù)據(jù),也就是去除無用的列特征id和預(yù)測值SalePrice列贴浙,從而構(gòu)造模型訓(xùn)練數(shù)據(jù)砂吞。為了便于后續(xù)數(shù)據(jù)預(yù)處理,測試集和訓(xùn)練集利用concat函數(shù)先合并崎溃。
all_data = pd.concat((train.loc[:,'MSSubClass':'SaleCondition'],
test.loc[:,'MSSubClass':'SaleCondition']))
##############
# 下面開始數(shù)據(jù)預(yù)處理階段
# 1、傾斜數(shù)值特征通過函數(shù)log(feature + 1) ,這樣使得特征更加標準正規(guī)盯质,有利于建立更加好模型袁串。
# 2、建立類別特征的虛擬變量呼巷,這個怎么理解呢囱修,分類特征取值大、中王悍、小破镰,那么把他們數(shù)值向量化區(qū)分,就可以用(1,0,0),(0,1,0),(0,0,1)去區(qū)分并代入模型計算压储。
# 3鲜漩、對Nan值用平均數(shù)替代。
##############
## 先展示一下訓(xùn)練集的預(yù)測值SalePrice集惋,通過log(x+1)函數(shù)轉(zhuǎn)換呈現(xiàn)的圖趨勢和沒轉(zhuǎn)換呈現(xiàn)的圖趨勢孕似,matplotlib.rcParams['figure.figsize']是設(shè)置圖片的大小
matplotlib.rcParams['figure.figsize'] = (12.0, 6.0)
prices = pd.DataFrame({"price":train["SalePrice"], "log(price + 1)":np.log1p(train["SalePrice"])})
# DataFrame類型數(shù)據(jù)展示直方圖
prices.hist()
## 數(shù)據(jù)預(yù)處理開始執(zhí)行第一步了,發(fā)現(xiàn)沒有刮刑,它是只對訓(xùn)練集執(zhí)行了此操作
train["SalePrice"] = np.log1p(train["SalePrice"])
## 同樣喉祭,一些數(shù)值傾斜特征也開始執(zhí)行第一步操作
## 先過濾出來數(shù)值特征
numeric_feats = all_data.dtypes[all_data.dtypes != "object"].index
## 去除行全是NULL值的养渴,并且列數(shù)據(jù)開始求其skew值,請自行百度skew的公式泛烙。
skewed_feats = train[numeric_feats].apply(lambda x: skew(x.dropna())) #compute skewness
## 篩選出skew值大于0.75的列數(shù)據(jù)理卑,下面是一個Series數(shù)據(jù)類型,index是列名
skewed_feats = skewed_feats[skewed_feats > 0.75]
## 獲取篩選出的列名
skewed_feats = skewed_feats.index
## 對篩選出來的執(zhí)行第一步操作
all_data[skewed_feats] = np.log1p(all_data[skewed_feats])
## get_dummies將類別變量轉(zhuǎn)換成新增的虛擬變量/指示變量蔽氨,也就是執(zhí)行第二步
all_data = pd.get_dummies(all_data)
## 平均值填充Null值
all_data = all_data.fillna(all_data.mean())
# 創(chuàng)建適合sklean的矩陣數(shù)據(jù)傻工,也就是訓(xùn)練集和測試集以及對應(yīng)的標簽
X_train = all_data[:train.shape[0]]
X_test = all_data[train.shape[0]:]
y = train.SalePrice
# 下面進入模型選擇階段以及調(diào)參階段,評估我們的模型好壞孵滞,用的是交叉驗證中rmse error指標中捆,從而更好的選擇參數(shù)。
from sklearn.linear_model import Ridge, RidgeCV, ElasticNet, LassoCV, LassoLarsCV
from sklearn.model_selection import cross_val_score
# 模型Ridge
## 5倍交叉驗證坊饶,注意回歸模型選擇scoring="neg_mean_squared_error"作為評估指標
def rmse_cv(model):
rmse= np.sqrt(-cross_val_score(model, X_train, y, scoring="neg_mean_squared_error", cv = 5))
return(rmse)
## 通過遍歷泄伪,選擇出Ridge模型的正則項最優(yōu)參數(shù)
alphas = [0.05, 0.1, 0.3, 1, 3, 5, 10, 15, 30, 50, 75]
cv_ridge = [rmse_cv(Ridge(alpha = alpha)).mean()
for alpha in alphas]
## 圖形展示
cv_ridge = pd.Series(cv_ridge, index = alphas)
cv_ridge.plot(title = "Validation - Just Do It")
plt.xlabel("alpha")
plt.ylabel("rmse")
# 查看交叉驗證下?lián)p失最小的平均值
cv_ridge.min()
# lasso模型
## 自帶交叉驗證,也就是內(nèi)置在Lasso模型匿级,為方便我們選出更好的alphas值蟋滴。
model_lasso = LassoCV(alphas = [1, 0.1, 0.001, 0.0005]).fit(X_train, y)
rmse_cv(model_lasso).mean()
## 獲取各個特征求出的參數(shù)
coef = pd.Series(model_lasso.coef_, index = X_train.columns)
print("Lasso picked " + str(sum(coef != 0)) + " variables and eliminated the other " + str(sum(coef == 0)) + " variables")
## 用圖展示那些特征參數(shù)的重要性
imp_coef = pd.concat([coef.sort_values().head(10),
coef.sort_values().tail(10)])
matplotlib.rcParams['figure.figsize'] = (8.0, 10.0)
imp_coef.plot(kind = "barh")
plt.title("Coefficients in the Lasso Model")
## 用點圖展示預(yù)測值和真實值的殘差
matplotlib.rcParams['figure.figsize'] = (6.0, 6.0)
# 這個大神先用的訓(xùn)練集預(yù)測值和訓(xùn)練集的真實值的殘差
preds = pd.DataFrame({"preds":model_lasso.predict(X_train), "true":y})
preds["residuals"] = preds["true"] - preds["preds"]
preds.plot(x = "preds", y = "residuals",kind = "scatter")
# xgboost 模型,待續(xù).......
看完痘绎,你可能還有一些疑問津函,比如log(price+1)有什么作用?skewed_feats = skewed_feats[skewed_feats > 0.75]等等,下面簡單闡述下若干疑點孤页。
log(price+1)有什么作用?
答:+1 為了防止有 price 為 0尔苦,取 log 是一種分布的變換,希望它服從正態(tài)分 布行施。更為一般的方法是 box-cox 轉(zhuǎn)換允坚,log 是其特例之一skewed_feats = skewed_feats[skewed_feats > 0.75],為什么這樣選擇數(shù)據(jù)蛾号?
答:skew 太高的情況下稠项,特征值會有較為嚴重的 shake up,特征的變化對于 模型的影響很大鲜结。這里選的是>0.75展运,選的大的,可以發(fā)現(xiàn)偏得很嚴重精刷。標準正態(tài)分布怎么理解拗胜?
答:標準正態(tài)分布說明,各個點的縱坐標與均值偏差不大(二維),這樣的話離散型弱贬养,即線性更強挤土,線性回歸更好。實際上误算,線性類模型都需要標準化仰美,標準化有很多不同的 方法迷殿,比如 min max 標準正態(tài)化等等,可以參考一下 sklearn.preprocessing 下面幾個標準化方法咖杂。標準化是為了讓特征取值差不多吧 如果特征一個特別大一個特別小 那擬 合時候 基本上起效果的就是特征值特別大的那個了?
答:主要目的是方便數(shù)值優(yōu)化庆寺,因為線性類模型都是涉及梯度的小的那個特征影響微乎其微。至于要不要標準正太分布 好像線性回歸 就 算不做標準正太的轉(zhuǎn)換 也能做吧 ?
答: 都需要標準化诉字,肯定能的懦尝。