1.使用make_blobs來生成數據集,然后對數據集進行預處理
#導入數據集生成器 from sklearn.datasets import make_blobs #導入數據集拆分工具 from sklearn.model_selection import train_test_split #導入預處理工具 from sklearn.preprocessing import StandardScaler #導入多層感知器神經網絡 from sklearn.neural_network import MLPClassifier #導入畫圖工具 import matplotlib.pyplot as plt
#生成樣本數量200,分類為2,標准差為5的數據集
X,y = make_blobs(n_samples=200,centers=2,cluster_std=5)
#將數據集拆分為訓練集和測試集
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=38)
#對數據進行預處理
scaler = StandardScaler().fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
#將處理后的數據形態進行打印
print('\n\n\n')
print('代碼運行結果')
print('====================================\n')
#將處理后的數據形態進行打印
print('訓練數據集:{}'.format(X_train_scaled.shape),' 標簽形態:{}'.format(X_test_scaled.shape))
print('\n====================================')
print('\n\n\n')
代碼運行結果 ==================================== 訓練數據集:(150, 2) 標簽形態:(50, 2) ====================================
#訓練原始數據集
plt.scatter(X_train[:,0],X_train[:,1])
#經過預處理的訓練集
plt.scatter(X_train_scaled[:,0],X_train_scaled[:,1],marker='^',edgecolor='k')
#添加圖題
plt.title('training set & scaled training set')
#顯示圖片
plt.show()

- 這里可以看到,StandardScaler將訓練集的數據變得更加"聚攏"
#導入網格搜索
from sklearn.model_selection import GridSearchCV
#設定網格搜索的模型參數字典
params = {'hidden_layer_sizes':[(50,),(100,),(100,100)],'alpha':[0.0001,0.01,0.1]}
#建立網格搜索模型
grid = GridSearchCV(MLPClassifier(max_iter=1600,random_state=38),param_grid=params,cv=3,iid=False)
#擬合數據
grid.fit(X_train_scaled,y_train)
#將結果進行打印
print('\n\n\n')
print('代碼運行結果')
print('====================================\n')
print('模型最佳得分:{:.2f}'.format(grid.best_score_),' 模型最佳參數:{}'.format(grid.best_params_))
print('\n====================================')
print('\n\n\n')
代碼運行結果
====================================
模型最佳得分:0.81 模型最佳參數:{'alpha': 0.0001, 'hidden_layer_sizes': (50,)}
====================================
#打印模型在測試集中的得分
print('\n\n\n')
print('代碼運行結果')
print('====================================\n')
print('測試集得分:{}'.format(grid.score(X_test_scaled,y_test)))
print('\n====================================')
print('\n\n\n')
代碼運行結果 ==================================== 測試集得分:0.82 ====================================
- 可以看到這種做法得到的模型分數很高,但是仔細想想這種做法是錯誤的,我們在交叉驗證中,將訓練集又拆分成了training fold和validation fold,但用StandardScaler進行預處理的時候,是使用training fold 和 validation fold 一起進行的擬合.這樣一來,交叉驗證的得分就是不准確的.
2.使用管道模型(Pipeline)
#導入管道模型
from sklearn.pipeline import Pipeline
#建立包含預處理和神經網絡的管道模型
pipeline = Pipeline([('scaler',StandardScaler()),('mlp',MLPClassifier(max_iter=1600,random_state=38))])
#用管道模型對訓練集進行擬合
pipeline.fit(X_train,y_train)
#打印管道模型的分數
print('使用管道模型的MLP模型評分:{:.2f}'.format(pipeline.score(X_test,y_test)))
使用管道模型的MLP模型評分:0.82
- 我們在管道模型Pipeline中使用了兩個方法,一個是用來進行數據預處理的StandardScaler.另一個是最大迭代數為1600的MLP多層感知器神經網絡.
3.使用管道模型進行網格搜索
GridSearchCV拆分的訓練集和驗證集,不是train_test_split拆分的訓練集和測試集,而是在train_test_split拆分的訓練集上再進行拆分,所得到的的結果
#設置參數字典--------(mlp__是用於指定pipeline中的mlp算法)
params = {'mlp__hidden_layer_sizes':[(50,),(100,),(100,100)],'mlp__alpha':[0.0001,0.001,0.01,0.1]}
#建立包含預處理和神經網絡的管道模型
pipeline = Pipeline([('scaler',StandardScaler()),('mlp',MLPClassifier(max_iter=1600,random_state=38))])
#將管道模型加入網格搜索
grid = GridSearchCV(pipeline,param_grid=params,cv=3,iid=False)
#對訓練集進行擬合
grid.fit(X_train,y_train)
#打印模型交叉驗證分數.最佳參數和測試集得分
print('\n\n\n')
print('代碼運行結果')
print('====================================\n')
print('交叉驗證最高分:{:.2f}'.format(grid.best_score_))
print('模型最有參數:{}'.format(grid.best_params_))
print('測試集得分:{}'.format(grid.score(X_test,y_test)))
print('\n====================================')
print('\n\n\n')
代碼運行結果
====================================
交叉驗證最高分:0.80
模型最有參數:{'mlp__alpha': 0.0001, 'mlp__hidden_layer_sizes': (50,)}
測試集得分:0.82
====================================
- 在hidden_layer_sizes和alpha前面都添加了mlp__這樣一個前綴,這樣做是為了pipeline中有多個算法,我們需要讓pipeline知道這個參數是傳給哪一個算法的.
#打印管道模型中的步驟
print('\n\n\n')
print('代碼運行結果')
print('====================================\n')
print(pipeline.steps)
print('\n====================================')
print('\n\n\n')
代碼運行結果
====================================
[('scaler', StandardScaler(copy=True, with_mean=True, with_std=True)), ('mlp', MLPClassifier(activation='relu', alpha=0.0001, batch_size='auto', beta_1=0.9,
beta_2=0.999, early_stopping=False, epsilon=1e-08,
hidden_layer_sizes=(100,), learning_rate='constant',
learning_rate_init=0.001, max_iter=1600, momentum=0.9,
n_iter_no_change=10, nesterovs_momentum=True, power_t=0.5,
random_state=38, shuffle=True, solver='adam', tol=0.0001,
validation_fraction=0.1, verbose=False, warm_start=False))]
====================================
總結 :
除了能夠將更多的算法進行整合,實現代碼的簡潔之外,管道模型還可以避免我們在預處理過程中,使用不當的方式對訓練集和驗證集進行錯誤的預處理.通過使用管道模型,可以在網格搜索每次拆分訓練集與驗證集之前,重新對訓練集和驗證集進行預處理操作,避免了模型過擬合的情況.
文章引自 : 《深入淺出python機器學習》
