閱讀391 返回首頁    go 阿裏雲 go 技術社區[雲棲]


scikit-learn學習之神經網絡算法


目錄(?)[+]

======================================================================

本係列博客主要參考 Scikit-Learn 官方網站上的每一個算法進行,並進行部分翻譯,如有錯誤,請大家指正 

轉載請注明出處,謝謝  

======================================================================


scikit-learn博主使用的是0.17版本,是穩定版,當然現在有0.18發行版,兩者還是有區別的,感興趣的可以自己官網上查看

scikit-learn0.17(and 之前)上對於Neural Network算法 的支持僅限於 BernoulliRBM

scikit-learn0.18上對於Neural Network算法有三個  neural_network.BernoulliRBM ,neural_network.MLPClassifierneural_network.MLPRgression 

具體可參考:點擊閱讀


1:神經網絡算法簡介

2:Backpropagation算法詳細介紹

3:非線性轉化方程舉例

4:自己實現神經網絡算法NeuralNetwork

5:基於NeuralNetwork的XOR實例

6:基於NeuralNetwork的手寫數字識別實例

7:scikit-learn中BernoulliRBM使用實例

8:scikit-learn中的手寫數字識別實例


一:神經網絡算法簡介

1:背景

以人腦神經網絡為啟發,曆史上出現過很多版本,但最著名的是backpropagation

2:多層向前神經網絡(Multilayer  Feed-Forward Neural Network)

                                                          

多層向前神經網絡組成部分

輸入層(input layer),隱藏層(hiddenlayer),輸出層(output layer)

   每層由單元(units)組成
   輸入層(input layer)是由訓練集的實例特征向量傳入
   經過連接結點的權重(weight)傳入下一層,一層的輸出是下一層的輸入
   隱藏層的個數是任意的,輸出層和輸入層隻有一個
   每個單元(unit)也可以被稱作神經結點,根據生物學來源定義
   上圖稱為2層的神經網絡(輸入層不算)
   一層中加權的求和,然後根據非線性的方程轉化輸出
   作為多層向前神經網絡,理論上,如果有足夠多的隱藏層(hidden layers)和足夠大的訓練集,可以模擬出任何方程

3:設計神經網絡結構

    3.1使用神經網絡訓練數據之前,必須確定神經網絡層數,以及每層單元個數
    3.2特征向量在被傳入輸入層時通常被先標準化(normalize)和0和1之間(為了加強學習過程)
    3.3離散型變量可以被編碼成每一個輸入單元對應一個特征可能賦的值
        比如:特征值A可能取三個值(a0,a1,a2),可以使用三個輸入單元來代表A
                    如果A=a0,那麼代表a0的單元值就取1,其他取0
                    如果A=a1,那麼代表a1的單元值就取1,其他取0,以此類推
    3.4神經網絡即可以用來做分類(classification)問題,也可以解決回歸(regression)問題
         3.4.1對於分類問題,如果是2類,可以用一個輸入單元表示(0和1分別代表2類)
                                         如果多於兩類,每一個類別用一個輸出單元表示
                所以輸入層的單元數量通常等於類別的數量 
        3.4.2沒有明確的規則來設計最好有多少個隱藏層
               3.4.2.1根據實驗測試和誤差,以及準確度來實驗並改進

4:算法驗證——交叉驗證法(Cross- Validation)


解讀: 有一組輸入集A,B,可以分成三組,第一次以第一組為訓練集,求出一個準確度,第二次以第二組作為訓練集,求出一個準確度,求出準確度,第三次以第三組作為訓練集,求出一個準確度,然後對三個準確度求平均值


二:Backpropagation算法詳細介紹

                                                            


1:通過迭代性來處理訓練集中的實例

2:輸入層輸入數

           經過權重計算得到第一層的數據,第一層的數據作為第二層的輸入,再次經過權重計算得到結果,結果和真實值之間是存在誤差的,然後根據誤差,反向的更新每兩個連接之間的權重

3:算法詳細介紹

      輸入:D : 數據集,| 學習率(learning rate),一個多層前向神經網絡

    輸出:一個訓練好的神經網絡(a trained neural network)
    3.1初始化權重(weights)和偏向(bias):隨機初始化在-1到1之間,或者-0.5到0.5之間,每個單元有一個偏向
    3.2對於每一個訓練實例X,執行以下步驟:
         3.2.1:由輸入層向前傳送,輸入->輸出對應的計算為:
                              
                                         
                   計算得到一個數據,經過f 函數轉化作為下一層的輸入,f函數為:
          3.2.2:根據誤差(error)反向傳送
                     對於輸出層(誤差計算):  Tj:真實值,Qj表示預測值
 
                     對於隱藏層(誤差計算):  Errk 表示前一層的誤差, Wjk表示前一層與當前點的連接權重
                       
                     權重更新:  l:指學習比率(變化率),手工指定,優化方法是,隨著數據的迭代逐漸減小
                     偏向更新:  l:同上
       3.3:終止條件
           3.3.1權重的更新低於某個閥值
           3.3.2預測的錯誤率低於某個閥值
           3.3.3達到預設一定的循環次數

4:結合實例講解算法

                                                                  

                                                                  

                                                                

              0.9對用的是L,學習率


三:非線性轉化方程舉例

在二中Activation Function對計算結果進行轉換,得到下一層的輸入,這裏用到的f函數就是非線性轉換函數,Sigmoid函數(S曲線)用來做f函數,Sigmoid函數是一類函數,隻要S曲線滿足一定的性質就可以作為activation Function函數

Sigmoid函數:

                                                                       

常見的Sigmoid函數

1:雙曲函數(參考百科,下麵以tan函數為例)

                


雙曲函數的導數為:

                                                         


2:邏輯函數(Logistic函數)

                                                                    

邏輯函數的導數形式為:

                                                             


四:自己實現神經網絡算法NeuralNetwork

建立NeuralNetwork.py,添加以下代碼

[python] view plain copy
  1. #coding:utf-8  
  2. ''''' 
  3. Created on 2016/4/27 
  4.  
  5. @author: Gamer Think 
  6. '''  
  7. import numpy as np  
  8.   
  9. #定義雙曲函數和他們的導數  
  10. def tanh(x):  
  11.     return np.tanh(x)  
  12.   
  13. def tanh_deriv(x):  
  14.     return 1.0 - np.tanh(x)**2  
  15.   
  16. def logistic(x):  
  17.     return 1/(1 + np.exp(-x))  
  18.   
  19. def logistic_derivative(x):  
  20.     return logistic(x)*(1-logistic(x))  
  21.   
  22. #定義NeuralNetwork 神經網絡算法  
  23. class NeuralNetwork:  
  24.     #初始化,layes表示的是一個list,eg[10,10,3]表示第一層10個神經元,第二層10個神經元,第三層3個神經元  
  25.     def __init__(self, layers, activation='tanh'):  
  26.         """ 
  27.         :param layers: A list containing the number of units in each layer. 
  28.         Should be at least two values 
  29.         :param activation: The activation function to be used. Can be 
  30.         "logistic" or "tanh" 
  31.         """  
  32.         if activation == 'logistic':  
  33.             self.activation = logistic  
  34.             self.activation_deriv = logistic_derivative  
  35.         elif activation == 'tanh':  
  36.             self.activation = tanh  
  37.             self.activation_deriv = tanh_deriv  
  38.   
  39.         self.weights = []  
  40.         #循環從1開始,相當於以第二層為基準,進行權重的初始化  
  41.         for i in range(1, len(layers) - 1):  
  42.             #對當前神經節點的前驅賦值  
  43.             self.weights.append((2*np.random.random((layers[i - 1] + 1, layers[i] + 1))-1)*0.25)  
  44.             #對當前神經節點的後繼賦值  
  45.             self.weights.append((2*np.random.random((layers[i] + 1, layers[i + 1]))-1)*0.25)  
  46.       
  47.     #訓練函數   ,X矩陣,每行是一個實例 ,y是每個實例對應的結果,learning_rate 學習率,   
  48.     # epochs,表示抽樣的方法對神經網絡進行更新的最大次數  
  49.     def fit(self, X, y, learning_rate=0.2, epochs=10000):  
  50.         X = np.atleast_2d(X) #確定X至少是二維的數據  
  51.         temp = np.ones([X.shape[0], X.shape[1]+1]) #初始化矩陣  
  52.         temp[:, 0:-1] = X  # adding the bias unit to the input layer  
  53.         X = temp  
  54.         y = np.array(y) #把list轉換成array的形式  
  55.   
  56.         for k in range(epochs):  
  57.             #隨機選取一行,對神經網絡進行更新  
  58.             i = np.random.randint(X.shape[0])   
  59.             a = [X[i]]  
  60.   
  61.             #完成所有正向的更新  
  62.             for l in range(len(self.weights)):  
  63.                 a.append(self.activation(np.dot(a[l], self.weights[l])))  
  64.             #  
  65.             error = y[i] - a[-1]  
  66.             deltas = [error * self.activation_deriv(a[-1])]  
  67.   
  68.             #開始反向計算誤差,更新權重  
  69.             for l in range(len(a) - 20, -1): # we need to begin at the second to last layer  
  70.                 deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_deriv(a[l]))  
  71.             deltas.reverse()  
  72.             for i in range(len(self.weights)):  
  73.                 layer = np.atleast_2d(a[i])  
  74.                 delta = np.atleast_2d(deltas[i])  
  75.                 self.weights[i] += learning_rate * layer.T.dot(delta)  
  76.       
  77.     #預測函數              
  78.     def predict(self, x):  
  79.         x = np.array(x)  
  80.         temp = np.ones(x.shape[0]+1)  
  81.         temp[0:-1] = x  
  82.         a = temp  
  83.         for l in range(0, len(self.weights)):  
  84.             a = self.activation(np.dot(a, self.weights[l]))  
  85.         return a  


五:基於NeuralNetwork的XOR(異或)示例

代碼如下:

[python] view plain copy
  1. <span style="font-size:18px;">#coding:utf-8  
  2. ''''' 
  3. Created on 2016/4/27 
  4.  
  5. @author: Gamer Think 
  6. '''  
  7.   
  8. import numpy as np  
  9. from NeuralNetwork import NeuralNetwork  
  10. ''''' 
  11. [2,2,1] 
  12. 第一個2:表示 數據的緯度,因為是二維的,表示兩個神經元,所以是2 
  13. 第二個2:隱藏層數據緯度也是2,表示兩個神經元  
  14. 1:表示輸入為一個神經元 
  15. tanh:表示用雙曲函數裏的tanh函數 
  16. '''  
  17. nn = NeuralNetwork([2,2,1], 'tanh')  
  18. X = np.array([[00], [01], [10], [11]])  
  19. y = np.array([0110])  
  20. nn.fit(X, y)  
  21. for i in [[00], [01], [10], [1,1]]:  
  22.     print(i,nn.predict(i)) </span>  


([0, 0], array([ 0.02150876]))
([0, 1], array([ 0.99857695]))
([1, 0], array([ 0.99859837]))
([1, 1], array([ 0.04854689]))


六:基於NeuralNetwork的手寫數字識別示例

代碼如下:


[python] view plain copy
  1. <span style="font-size:18px;">import numpy as np  
  2. from sklearn.datasets import load_digits  
  3. from sklearn.metrics import confusion_matrix,classification_report  
  4. from sklearn.preprocessing import LabelBinarizer  
  5. from sklearn.cross_validation import train_test_split  
  6. from NeuralNetwork import NeuralNetwork  
  7.   
  8. digits = load_digits()  
  9. X = digits.data  
  10. y = digits.target  
  11. X -= X.min()  
  12. X /= X.max()  
  13.   
  14. nn =NeuralNetwork([64,100,10],'logistic')  
  15. X_train, X_test, y_train, y_test = train_test_split(X, y)  
  16. labels_train = LabelBinarizer().fit_transform(y_train)  
  17. labels_test = LabelBinarizer().fit_transform(y_test)  
  18. print "start fitting"  
  19. nn.fit(X_train,labels_train,epochs=3000)  
  20. predictions = []  
  21. for i in range(X_test.shape[0]):  
  22.     o = nn.predict(X_test[i])  
  23.     predictions.append(np.argmax(o))  
  24. print confusion_matrix(y_test, predictions)  
  25. print classification_report(y_test, predictions) </span>  



七:scikit-learn中的BernoulliRBM使用實例

[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">from sklearn.neural_network import BernoulliRBM  
  2. X = [[0,0],[1,1]]  
  3. y = [0,1]  
  4. clf = BernoulliRBM().fit(X,y)  
  5. print clf</span>  

輸出結果為:

BernoulliRBM(batch_size=10, learning_rate=0.1, n_components=256, n_iter=10,
       random_state=None, verbose=0)


注意此模塊不支持predict函數,這與以往的算法有很大的不同


八:scikit-learn中的手寫數字識別實例


[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">import numpy as np  
  2. import matplotlib.pyplot as plt  
  3.   
  4. from scipy.ndimage import convolve  
  5. from sklearn import linear_model, datasets, metrics  
  6. from sklearn.cross_validation import train_test_split  
  7. from sklearn.neural_network import BernoulliRBM  
  8. from sklearn.pipeline import Pipeline  
  9.   
  10.   
  11. ###############################################################################  
  12. # Setting up  
  13.   
  14. def nudge_dataset(X, Y):  
  15.     """ 
  16.     This produces a dataset 5 times bigger than the original one, 
  17.     by moving the 8x8 images in X around by 1px to left, right, down, up 
  18.     """  
  19.     direction_vectors = [  
  20.         [[010],  
  21.          [000],  
  22.          [000]],  
  23.   
  24.         [[000],  
  25.          [100],  
  26.          [000]],  
  27.   
  28.         [[000],  
  29.          [001],  
  30.          [000]],  
  31.   
  32.         [[000],  
  33.          [000],  
  34.          [010]]]  
  35.   
  36.     shift = lambda x, w: convolve(x.reshape((88)), mode='constant',  
  37.                                   weights=w).ravel()  
  38.     X = np.concatenate([X] +  
  39.                        [np.apply_along_axis(shift, 1, X, vector)  
  40.                         for vector in direction_vectors])  
  41.     Y = np.concatenate([Y for _ in range(5)], axis=0)  
  42.     return X, Y  
  43.   
  44. # Load Data  
  45. digits = datasets.load_digits()  
  46. X = np.asarray(digits.data, 'float32')  
  47. X, Y = nudge_dataset(X, digits.target)  
  48. X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001)  # 0-1 scaling  
  49.   
  50. X_train, X_test, Y_train, Y_test = train_test_split(X, Y,  
  51.                                                     test_size=0.2,  
  52.                                                     random_state=0)  
  53.   
  54. # Models we will use  
  55. logistic = linear_model.LogisticRegression()  
  56. rbm = BernoulliRBM(random_state=0, verbose=True)  
  57.   
  58. classifier = Pipeline(steps=[('rbm', rbm), ('logistic', logistic)])  
  59.   
  60. ###############################################################################  
  61. # Training  
  62.   
  63. # Hyper-parameters. These were set by cross-validation,  
  64. # using a GridSearchCV. Here we are not performing cross-validation to  
  65. # save time.  
  66. rbm.learning_rate = 0.06  
  67. rbm.n_iter = 20  
  68. # More components tend to give better prediction performance, but larger  
  69. # fitting time  
  70. rbm.n_components = 100  
  71. logistic.C = 6000.0  
  72.   
  73. # Training RBM-Logistic Pipeline  
  74. classifier.fit(X_train, Y_train)  
  75.   
  76. # Training Logistic regression  
  77. logistic_classifier = linear_model.LogisticRegression(C=100.0)  
  78. logistic_classifier.fit(X_train, Y_train)  
  79.   
  80. ###############################################################################  
  81. # Evaluation  
  82.   
  83. print()  
  84. print("Logistic regression using RBM features:\n%s\n" % (  
  85.     metrics.classification_report(  
  86.         Y_test,  
  87.         classifier.predict(X_test))))  
  88.   
  89. print("Logistic regression using raw pixel features:\n%s\n" % (  
  90.     metrics.classification_report(  
  91.         Y_test,  
  92.         logistic_classifier.predict(X_test))))  
  93.   
  94. ###############################################################################  
  95. # Plotting  
  96.   
  97. plt.figure(figsize=(4.24))  
  98. for i, comp in enumerate(rbm.components_):  
  99.     plt.subplot(1010, i + 1)  
  100.     plt.imshow(comp.reshape((88)), cmap=plt.cm.gray_r,  
  101.                interpolation='nearest')  
  102.     plt.xticks(())  
  103.     plt.yticks(())  
  104. plt.suptitle('100 components extracted by RBM', fontsize=16)  
  105. plt.subplots_adjust(0.080.020.920.850.080.23)  
  106.   
  107. plt.show()</span>  

顯示結果:





附:博主對於前邊的原理其實很是明白了,但是對於scikit-learn實現手寫數字識別係統這個代碼優點迷亂,如果路過大神明白的,可以給小弟指點迷津


scikit-learn博主使用的是0.17版本,是穩定版,當然現在有0.18發行版,兩者還是有區別的,感興趣的可以自己官網上查看
[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">import numpy as np  
  2. from sklearn.datasets import load_digits  
  3. from sklearn.metrics import confusion_matrix,classification_report  
  4. from sklearn.preprocessing import LabelBinarizer  
  5. from sklearn.cross_validation import train_test_split  
  6. from NeuralNetwork import NeuralNetwork  
  7.   
  8. digits = load_digits()  
  9. X = digits.data  
  10. y = digits.target  
  11. X -= X.min()  
  12. X /= X.max()  
  13.   
  14. nn =NeuralNetwork([64,100,10],'logistic')  
  15. X_train, X_test, y_train, y_test = train_test_split(X, y)  
  16. labels_train = LabelBinarizer().fit_transform(y_train)  
  17. labels_test = LabelBinarizer().fit_transform(y_test)  
  18. print "start fitting"  
  19. nn.fit(X_train,labels_train,epochs=3000)  
  20. predictions = []  
  21. for i in range(X_test.shape[0]):  
  22.     o = nn.predict(X_test[i])  
  23.     predictions.append(np.argmax(o))  
  24. print confusion_matrix(y_test, predictions)  
  25. print classification_report(y_test, predictions) </span>  


轉載請注明出處 https://blog.csdn.net/gamer_gyt

最後更新:2017-06-25 22:04:20

  上一篇:go  python字符串(2)
  下一篇:go  Java並發/多線程教程——1