1. 程式人生 > >模型融合之Bagging,及scikit learning

模型融合之Bagging,及scikit learning

小編昨天第一次參加了校園招聘會面試,應聘的是機器學習和資料探勘,當然只學了兩個月的知識是遠遠不能應對面試官的一頓吊打。因此,回來好好反思自己的學習方法。還是平時學習沒有得到即使的反饋,以及實踐練習。所以,痛定思痛,決定以部落格的形式來檢驗自己是否有沒有掌握好內容,希望大家能給予監督和反饋。

最近一直看機器學習中的Bagging(bootstrap aggregatin的縮寫)的方法,Bagging是屬於機器學習中模型融合的一種方法。大家都知道,決策樹是一個可讀性很強、分類快,同時不需要對資料進行歸一化還有縮放的處理。但是決策樹有個不足的地方就是非常容易過擬合,所以必須要採取一些方法進行剪枝。

而bagging方法的出現,可以完美地解決了決策樹過擬合的問題,同時bagging的使用也會使分類器分類效果得到了顯著的提高。bagging演算法原理舉個例子如下:

    1.假設有1000個樣本,70%的樣本作為訓練集,30%的樣本作為測試集。 

    2.從訓練集700條裡樣本隨機抽出500條樣本,用來訓練,於是生成了一條決策樹。

    3.然後有放回的再從700條樣本在隨機抽出500條樣本,用來訓練,於是又生成了一條決策樹

    4.同上,假設我以又放回的步驟隨機抽取100次,這樣我就生成了100條決策樹了

    5.這100條決策樹對測試集的每一個樣本都進行測試,然後通過投票的方式決定測集樣本的預測結果。如果一個樣本被這100條決策樹投票,即預測分類,被分為1的票數有80票,被分為0的有20票,顯然,這個樣本的預測結果為1。

    這種民主公平、集思廣益的方法是不是很贊!就算在一棵決策樹上發生了過擬合,也不會在整個集合裡發生了過擬合,就好比你一個全力人支援川普大叔當選總統,也必定有人給他反對票,然而群眾的智慧最後還是調和了個體的偏見。

來看看python的scikit learn怎麼去實現它吧!我們先去scikit learn的文件看看。
scikit learn文件
首先它是模型融合的其中一種方法,所以bagging是屬於sklearn.ensemble的,bagging有兩種,一種是用於迴歸的BaggingRegressor,另一種是用於分類的BaggingClassifier,用的時候一定要用對。
先看看引數吧:
引數圖
常用的引數有:

  1.base_estimator :基本的估計器,就是你要用到的演算法,如果該引數沒有賦值,預設為決策樹。這個資訊告訴我們bagging,不僅可以用在決策樹上,還可以用於其他的演算法模型上。

   2.n_estimators:基本估計器的個數,就是你要產生多少個子模型,用在決策樹時,即表示產生多少條決策樹用來融合。

    3.max_samples :從X(訓練集)中選取用於訓練的樣本數,預設為1.0,此處有點疑問。這個1.0是抽取一條樣本還是比例為1的樣本樹?文件說max_samples的值取int 型時為抽取樣本的數目,取float型時為 max_samples的值乘以樣本的總數,我想問的是:假設max_samples=0.3,是抽取30%的樣本嗎?那萬一取1.3呢?

至於其他的引數,小編還沒有好好去理解過。這裡有個的小案例,由於我用網格搜尋去獲取最優的超引數時,程式跑了很久都沒有結果。所以把資料來源的網址、以及決策樹和隨機森林的方式實現廣告識別的程式碼在此處帖一帖。
[資料網址,點選下載](http://archive.ics.uci.edu/ml/machine-learning-databases/internet_ads/)
程式碼如下:
#決策樹實現廣告識別
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import train_test_split
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV


#讀取資料
df = pd.read_csv("ad.data", header=None, low_memory=False)
explanatory_variable_columns = set(df.columns.values)
response_variable_column = df[len(df.columns.values)-1]

#填充預設值,以及將標籤數字化
explanatory_variable_columns.remove(len(df.columns.values)-1)
y = [1 if e == 'ad.' else 0 for e in response_variable_column]
X = df.loc[:, list(explanatory_variable_columns)]
X.replace(to_replace=' *\?', value=-1, regex=True, inplace=True)

#交叉驗證
X_train, X_test, y_train, y_test = train_test_split(X, y)

#網格搜尋引數設定
pipeline = Pipeline([
('clf', DecisionTreeClassifier(criterion='entropy'))])
parameters = {
'clf__max_depth': (150, 155, 160),
'clf__min_samples_split': (1, 2, 3),
'clf__min_samples_leaf': (1, 2, 3)}

#網格搜尋
grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1, verbose=1, sc
oring='f1')
grid_search.fit(X_train, y_train)

#獲取最優引數
print('最佳效果:%0.3f' % grid_search.best_score_)
print('最優引數:')
best_parameters = grid_search.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
    print('\t%s: %r' % (param_name, best_parameters[param_name]))

#預測以及分類器引數報告
predictions = grid_search.predict(X_test)
print(classification_report(y_test, predictions))
#這裡用隨機森林實現
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.cross_validation import train_test_split
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV
import zipfile


df = pd.read_csv("ad.data", header=None, low_memory=False)
explanatory_variable_columns = set(df.columns.values)

response_variable_column = df[len(df.columns.values)-1]
# The last column describes the targets
explanatory_variable_columns.remove(len(df.columns.values)-1)
y = [1 if e == 'ad.' else 0 for e in response_variable_column]
X = df.loc[:, list(explanatory_variable_columns)]
X.replace(to_replace=' *\?', value=-1, regex=True, inplace=True)

X_train, X_test, y_train, y_test = train_test_split(X, y)
pipeline = Pipeline([
('clf', RandomForestClassifier(criterion='entropy'))
])
parameters = {
'clf__n_estimators': (5, 10, 20, 50),
'clf__max_depth': (50, 150, 250),
'clf__min_samples_split': (1, 2, 3),
'clf__min_samples_leaf': (1, 2, 3)
}

grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1, verbose=1, sc
oring='f1')
grid_search.fit(X_train, y_train)

print('最佳效果:%0.3f' % grid_search.best_score_)
print('最優引數:')
best_parameters = grid_search.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
    print('\t%s: %r' % (param_name, best_parameters[param_name]))
predictions = grid_search.predict(X_test)
print(classification_report(y_test, predictions))

至於那個bagging的方法就大家去實現了。同時想了個問題,如果我用了BaggingClassifier的方法來實現廣告識別的話,那麼網格搜尋時,是不是既有隨機森林的引數需要查詢,又有BaggingClassifier()的引數需要查詢??