天天看點

kaggel入門比賽_HousePrices一.處理資料,準備模組化二.Modeling

@update 2016.11.28,自己嘗試了一些缺失值填補的方法,調sklearn寫了一些特征變換和特征選擇的算法

下一步:繼續特征規約,開始模型調參

kaggle入門系列比賽HousePrices,該比賽是一個經典的回歸問題,預測房價,這個比賽我用來熟悉kaggle,熟悉基本的資料挖掘流程,主要是特征工程,包括常見的缺失值填補,categorial特征的處理,其實主要就是熟悉用python的pandas包對資料進行預處理。

第一次嘗試的過程我主要是參考了Regularized Linear Models這篇kernel,它對資料的處理就是一些最基本的做法,作為入門、熟悉基本流程是很好的一篇kernel。

一.處理資料,準備模組化

1.資料變換

特征中的屬性分為兩種,定性的和定量的。對定量的屬性我們可以有很多種距離度量方式。而對定性的屬性我們一般用标簽來表示之,這對于常見的機器學習算法而言是不好處理的,常見的做法是轉化為數值屬性,但是如何轉化?如何單純的轉化為數字的話會影響一些以距離度量為依據的算法的準确性。一般我們使用pandas的get_dummies()将其每個屬性值轉化為一個二進制屬性次元,值對應為0/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:缺失值處理的幾種常見方法:

1.删除帶缺失值的資料:适用于資料量足夠大的時候; 2.均值/衆數填補:簡單常用; 3.建立模型,如線性回歸,随機森林:利用的是屬性之間的相關性,如果屬性之間相關性過高,則該屬性沒有意義,而若相關性過低,無法準确預測該缺失值。一般情況下介于兩者之間 4.當作特殊情況,取特殊值填入:适用于缺失值很多,或缺失值本身有一定意義的情況。 對HousePrices的處理,我使用了上述2、3、4三種,對如Alley這樣的用的是4,對一些與輸出相關性高的features使用3,剩下的使用2。在這樣的處理下最後得分有提升。雖然理論解釋有待考證。

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的坑裡爬出來,找一個資料量稍微大點的坑撲進去- -

繼續閱讀