@update 2016.11.28,自己嘗試了一些缺失值填補的方法,調sklearn寫了一些特徵變換和特徵選擇的算法
下一步:繼續特徵規約,開始模型調參
kaggle入門系列比賽HousePrices,該比賽是一個經典的迴歸問題,預測房價,這個比賽我用來熟悉kaggle,熟悉基本的數據挖掘流程,主要是特徵工程,包括常見的缺失值填補,categorial特徵的處理,其實主要就是熟悉用python的pandas包對數據進行預處理。
第一次嘗試的過程我主要是參考了Regularized Linear Models這篇kernel,它對數據的處理就是一些最基本的做法,作爲入門、熟悉基本流程是很好的一篇kernel。
一.處理數據,準備建模
1.數據變換
all_data = pd.get_dummies(all_data) #直接對整個DataFrame中所有類別屬性做dummies
對於定量屬性,一個可能需要的操作就是規範化。但規範化不是必須的,當所使用的算法不是依據距離屬性作爲度量時,不需要做歸一化。在上述提到的Regularized Linear Models的做法中,值得一提的是通過對數據的繪圖(也可以通過scipy包的)發現預測屬性是偏態分佈的。這種偏態分佈(數據不均衡)會影響算法準確性,作者通過對偏態數據做log變換改善數據傾斜度。
skewed_feats = train[numeric_feats].apply(lambda x: skew(x.dropna())) #compute skewness<pre name="code" class="python">all_data[skewed_feats] = np.log1p(all_data[skewed_feats])
@2016.11.28:對categorical的處理也就是get_dummies了,目前沒有用到別的優化。
值得一提的是,雖然log變換使數據趨於正態分佈,這種優化是針對於線性迴歸的(因爲線性迴歸後續的一些檢驗是基於正態分佈假設的),但是我在實踐中發現對tree-based的模型,也是通過log變換會使得分提高,why?
2.缺失值填補
常見的缺失值填補方法,見這篇數據挖掘之缺失值填補常見手段。
我們首先嚐試一個最基本的填補方法,即均值填補
all_data = all_data.fillna(all_data.mean())
@2016.11.28:缺失值處理的幾種常見方法:
3.維度規約
特徵維度過高可能會引起維數災難,原因在於:1,這些特徵之間可能存在多重共線性,從而導致空間的不穩定;2,高維空間本身具有稀疏性,一維正態分佈有68%的值落於正負標準差之間,而在十維空間上只有0.02%;三是由於過多的屬性 會使挖掘需要很長時間。當前這些現象對不同的算法而言也是不同的,比如對L1(Lasso)而言,大量屬性時效果很好,因爲它可以有效忽略掉噪聲變量,而對一些模型而言過多的屬性則容易過擬合。
@2016.11.28:做到這一步我就迷幻了,因爲我試了好幾種維度變換的方法,都是提交的得分效果變差... 一度導致我不想做下去,可能自己對這方面的理論缺失,經驗又太少,做起來有點迷茫吧,anyway,還是要繼續,於是今晚看了一些kernel,發現幾乎沒有對features做類似PCA這樣的維度變換的,不造爲什麼。
關於特徵選擇倒是有人做,我試了一下添加了兩個合成特徵,提交結果還是有提升噠,更神奇的是有一個合成的features[1stFlr_2ndFlr_Sf = ['1stFlrSF'] + ['2ndFlrSF']]。它居然在訓練好的lasso模型上係數是最高的,所以說領域知識,或者說特徵工程真的很重要的。
下一步可以試一下特徵選擇,比如說利用random forest的特徵重要度,kernel上大部分都是用lassocv自動完成特徵選擇,but anyway還是xgboost性能好些吧。
@update2016.11.29:試了一下模型選擇,sklearn.feature_selection中的RFECV和SelectFromModel,前者是利用模型的準確度(具體可以選擇sklearn提供的scoring標準)來遞歸的減少特徵直到選出最優特徵子集,後者則是根據模型中的estimator.feature_importances_屬性(所以輸入的模型必須有這個屬性)來選擇特徵子集。我大概試了下兩者的性能都不好,其中我又SelectFromModel結合RandomForest試了下,簡直可怕,看代碼和輸出:
from sklearn.model_selection import cross_val_score
import numpy as np
def rmse_cv(model,X_train,y):
rmse= np.sqrt(-cross_val_score(model, X_train, y, scoring="neg_mean_squared_error", cv=3,n_jobs=-1))
return(rmse)
from sklearn.feature_selection import SelectFromModel
# u can see from 'SelectFromModel' that this method use model result to select features, 'Wrapper'
# estimator: a supervised model with fit() method
def fea_sel_tree(train_x,train_y,estimator):
estimator = estimator.fit(train_x,train_x)
print 'feature importances in this model',
print sorted(estimator.feature_importances_,reverse=True)
model = SelectFromModel(estimator,prefit = True)
after_sel = model.transform(train_x)
return pd.DataFrame(after_sel)
import xgboost as xgb
from sklearn.ensemble import RandomForestRegressor
esti = RandomForestRegressor(n_estimators=360, max_depth=2,n_jobs=-1,random_state=0)
train_after = fea_sel_tree(alldata_newfea.iloc[:1460],y,esti)
model_xgb = xgb.XGBRegressor(n_estimators=360, max_depth=2, learning_rate=0.1)
print rmse_cv(model_xgb,train_after.iloc[:1460],y)
輸出:(可怕feature importances in this model [0.98394303690584572, 0.0095377084732799645, 0.0065192546208747695, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
rmse: [ 0.28251422 0.300882 0.28558193] #注:正常的rmse至少是0.13左右的吧
直接加了個特徵選擇降這麼多,可怕,但是其實從feature importance可以看出來,290多個features直接只剩3個了,各種不靠譜。
於是我在想,可能model的參數不太靠譜,於是我想先不加特徵規約了,先model調參吧。
# 上述完整代碼參見:點擊打開鏈接
二.Modeling
#具體的建模過程
@2016.11.28:model部分基本上一直堅信xgboost - -,但是沒有調參,下一步可以進行,不過感覺調參真是一條艱難的道路- -
然後下一步可能可以試一下集成模型,這也是個調參的坑啊。。。我還沒想好要不要從HousePrices的坑裏爬出來,找一個數據量稍微大點的坑撲進去- -