此範例將使用BernoulliRBM特徵選取方法,提升手寫數字識別的精確率,伯努利限制玻爾茲曼機器模型(`BernoulliRBM
`)將可以對數據做有效的非線性 特徵提取的處理。 為了讓此模型訓練出來更為強健,將輸入的圖檔,分別做上左右下,一像素的平移,用以增加更多訓練資料, 訓練網路的參數是使用grid search演算法,但此訓練太耗費時間,因此不再這重現,。 此範例結果將比較, 1.使用原本的像素值做的邏輯回歸 2.使用BernoulliRBM做特徵選取的邏輯回歸 結果將顯示:使用BernoulliRBM將可以提升分類的準確度。
from __future__ import print_functionprint(__doc__)# Authors: Yann N. Dauphin, Vlad Niculae, Gabriel Synnaeve# License: BSDimport numpy as npimport matplotlib.pyplot as pltfrom scipy.ndimage import convolvefrom sklearn import linear_model, datasets, metricsfrom sklearn.model_selection import train_test_splitfrom sklearn.neural_network import BernoulliRBMfrom sklearn.pipeline import Pipeline
def nudge_dataset(X, Y):"""此副函式是用來將輸入資料的數字圖形,分別做上左右下一像素的平移,目的是製造更多的訓練資料讓模型訓練出來更強健"""direction_vectors = [[[0, 1, 0],[0, 0, 0],[0, 0, 0]],[[0, 0, 0],[1, 0, 0],[0, 0, 0]],[[0, 0, 0],[0, 0, 1],[0, 0, 0]],[[0, 0, 0],[0, 0, 0],[0, 1, 0]]]shift = lambda x, w: convolve(x.reshape((8, 8)), mode='constant',weights=w).ravel()X = np.concatenate([X] +[np.apply_along_axis(shift, 1, X, vector)for vector in direction_vectors])Y = np.concatenate([Y for _ in range(5)], axis=0)return X, Y# Load Datadigits = datasets.load_digits()X = np.asarray(digits.data, 'float32')X, Y = nudge_dataset(X, digits.target)X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001) # 將灰階影像降尺度降到[0,1]# 將資料切割成訓練集與測試集X_train, X_test, Y_train, Y_test = train_test_split(X, Y,test_size=0.2,random_state=0)# Models we will uselogistic = linear_model.LogisticRegression()rbm = BernoulliRBM(random_state=0, verbose=True)classifier = Pipeline(steps=[('rbm', rbm), ('logistic', logistic)])
# 參數選擇需使用cross-validation去比較# 此參數是使用GridSearchCV找出來的. Here we are not performing cross-validation to save time.#GridSratch 就是將參數設定好,跑過全部參數後去找結果最好的一組參數rbm.learning_rate = 0.06rbm.n_iter = 20#.n_components = 100 表示隱藏層單元為100,即表示萃取出100個特徵,特徵萃取的越多準確率會越高,但越耗時間rbm.n_components = 100logistic.C = 6000.0# Training RBM-Logistic Pipelineclassifier.fit(X_train, Y_train)# Training Logistic regressionlogistic_classifier = linear_model.LogisticRegression(C=100.0)logistic_classifier.fit(X_train, Y_train)
print()print("Logistic regression using RBM features:\n%s\n" % (metrics.classification_report(Y_test,classifier.predict(X_test))))print("Logistic regression using raw pixel features:\n%s\n" % (metrics.classification_report(Y_test,logistic_classifier.predict(X_test))))
圖1:使用RBM演算法後準確率為0.95
圖2:不使用任何特徵選取方法做的做的邏輯回歸準確率0.77
plt.figure(figsize=(4.2, 4))for i, comp in enumerate(rbm.components_):plt.subplot(10, 10, i + 1)plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r,interpolation='nearest')plt.xticks(())plt.yticks(())plt.suptitle('100 components extracted by RBM', fontsize=16)plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)plt.show()
圖3:使用RBM演算法,尋找出來的特徵
from __future__ import print_functionprint(__doc__)# Authors: Yann N. Dauphin, Vlad Niculae, Gabriel Synnaeve# License: BSDimport numpy as npimport matplotlib.pyplot as pltfrom scipy.ndimage import convolvefrom sklearn import linear_model, datasets, metricsfrom sklearn.model_selection import train_test_splitfrom sklearn.neural_network import BernoulliRBMfrom sklearn.pipeline import Pipeline################################################################################ Setting updef nudge_dataset(X, Y):"""This produces a dataset 5 times bigger than the original one,by moving the 8x8 images in X around by 1px to left, right, down, up"""direction_vectors = [[[0, 1, 0],[0, 0, 0],[0, 0, 0]],[[0, 0, 0],[1, 0, 0],[0, 0, 0]],[[0, 0, 0],[0, 0, 1],[0, 0, 0]],[[0, 0, 0],[0, 0, 0],[0, 1, 0]]]shift = lambda x, w: convolve(x.reshape((8, 8)), mode='constant',weights=w).ravel()X = np.concatenate([X] +[np.apply_along_axis(shift, 1, X, vector)for vector in direction_vectors])Y = np.concatenate([Y for _ in range(5)], axis=0)return X, Y# Load Datadigits = datasets.load_digits()X = np.asarray(digits.data, 'float32')X, Y = nudge_dataset(X, digits.target)X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001) # 0-1 scalingX_train, X_test, Y_train, Y_test = train_test_split(X, Y,test_size=0.2,random_state=0)# Models we will uselogistic = linear_model.LogisticRegression()rbm = BernoulliRBM(random_state=0, verbose=True)classifier = Pipeline(steps=[('rbm', rbm), ('logistic', logistic)])################################################################################ Training# Hyper-parameters. These were set by cross-validation,# using a GridSearchCV. Here we are not performing cross-validation to# save time.rbm.learning_rate = 0.06rbm.n_iter = 20# More components tend to give better prediction performance, but larger# fitting timerbm.n_components = 100logistic.C = 6000.0# Training RBM-Logistic Pipelineclassifier.fit(X_train, Y_train)# Training Logistic regressionlogistic_classifier = linear_model.LogisticRegression(C=100.0)logistic_classifier.fit(X_train, Y_train)################################################################################ Evaluationprint()print("Logistic regression using RBM features:\n%s\n" % (metrics.classification_report(Y_test,classifier.predict(X_test))))print("Logistic regression using raw pixel features:\n%s\n" % (metrics.classification_report(Y_test,logistic_classifier.predict(X_test))))################################################################################ Plottingplt.figure(figsize=(4.2, 4))for i, comp in enumerate(rbm.components_):plt.subplot(10, 10, i + 1)plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r,interpolation='nearest')plt.xticks(())plt.yticks(())plt.suptitle('100 components extracted by RBM', fontsize=16)plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)plt.show()