scikit-learn学习之神经网络算法

    xiaoxiao2023-07-06  142

    目录(?)[+]

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

    本系列博客主要参考 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.MLPClassifier,neural_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 #coding:utf-8  ''''' Created on 2016/4/27  @author: Gamer Think '''  import numpy as np    #定义双曲函数和他们的导数  def tanh(x):      return np.tanh(x)    def tanh_deriv(x):      return 1.0 - np.tanh(x)**2    def logistic(x):      return 1/(1 + np.exp(-x))    def logistic_derivative(x):      return logistic(x)*(1-logistic(x))    #定义NeuralNetwork 神经网络算法  class NeuralNetwork:      #初始化,layes表示的是一个list,eg[10,10,3]表示第一层10个神经元,第二层10个神经元,第三层3个神经元      def __init__(self, layers, activation='tanh'):          """         :param layers: A list containing the number of units in each layer.         Should be at least two values         :param activation: The activation function to be used. Can be         "logistic" or "tanh"         """          if activation == 'logistic':              self.activation = logistic              self.activation_deriv = logistic_derivative          elif activation == 'tanh':              self.activation = tanh              self.activation_deriv = tanh_deriv            self.weights = []          #循环从1开始,相当于以第二层为基准,进行权重的初始化          for i in range(1, len(layers) - 1):              #对当前神经节点的前驱赋值              self.weights.append((2*np.random.random((layers[i - 1] + 1, layers[i] + 1))-1)*0.25)              #对当前神经节点的后继赋值              self.weights.append((2*np.random.random((layers[i] + 1, layers[i + 1]))-1)*0.25)            #训练函数   ,X矩阵,每行是一个实例 ,y是每个实例对应的结果,learning_rate 学习率,       # epochs,表示抽样的方法对神经网络进行更新的最大次数      def fit(self, X, y, learning_rate=0.2, epochs=10000):          X = np.atleast_2d(X) #确定X至少是二维的数据          temp = np.ones([X.shape[0], X.shape[1]+1]) #初始化矩阵          temp[:, 0:-1] = X  # adding the bias unit to the input layer          X = temp          y = np.array(y) #把list转换成array的形式            for k in range(epochs):              #随机选取一行,对神经网络进行更新              i = np.random.randint(X.shape[0])               a = [X[i]]                #完成所有正向的更新              for l in range(len(self.weights)):                  a.append(self.activation(np.dot(a[l], self.weights[l])))              #              error = y[i] - a[-1]              deltas = [error * self.activation_deriv(a[-1])]                #开始反向计算误差,更新权重              for l in range(len(a) - 20, -1): # we need to begin at the second to last layer                  deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_deriv(a[l]))              deltas.reverse()              for i in range(len(self.weights)):                  layer = np.atleast_2d(a[i])                  delta = np.atleast_2d(deltas[i])                  self.weights[i] += learning_rate * layer.T.dot(delta)            #预测函数                  def predict(self, x):          x = np.array(x)          temp = np.ones(x.shape[0]+1)          temp[0:-1] = x          a = temp          for l in range(0, len(self.weights)):              a = self.activation(np.dot(a, self.weights[l]))          return a  

    五:基于NeuralNetwork的XOR(异或)示例

    代码如下:

    [python]  view plain  copy <span style="font-size:18px;">#coding:utf-8  ''''' Created on 2016/4/27  @author: Gamer Think '''    import numpy as np  from NeuralNetwork import NeuralNetwork  ''''' [2,2,1] 第一个2:表示 数据的纬度,因为是二维的,表示两个神经元,所以是2 第二个2:隐藏层数据纬度也是2,表示两个神经元  1:表示输入为一个神经元 tanh:表示用双曲函数里的tanh函数 '''  nn = NeuralNetwork([2,2,1], 'tanh')  X = np.array([[00], [01], [10], [11]])  y = np.array([0110])  nn.fit(X, y)  for i in [[00], [01], [10], [1,1]]:      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 <span style="font-size:18px;">import numpy as np  from sklearn.datasets import load_digits  from sklearn.metrics import confusion_matrix,classification_report  from sklearn.preprocessing import LabelBinarizer  from sklearn.cross_validation import train_test_split  from NeuralNetwork import NeuralNetwork    digits = load_digits()  X = digits.data  y = digits.target  X -= X.min()  X /= X.max()    nn =NeuralNetwork([64,100,10],'logistic')  X_train, X_test, y_train, y_test = train_test_split(X, y)  labels_train = LabelBinarizer().fit_transform(y_train)  labels_test = LabelBinarizer().fit_transform(y_test)  print "start fitting"  nn.fit(X_train,labels_train,epochs=3000)  predictions = []  for i in range(X_test.shape[0]):      o = nn.predict(X_test[i])      predictions.append(np.argmax(o))  print confusion_matrix(y_test, predictions)  print classification_report(y_test, predictions) </span>   输出结果:

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

    [python]  view plain  copy <span style="font-family:Microsoft YaHei;font-size:18px;">from sklearn.neural_network import BernoulliRBM  X = [[0,0],[1,1]]  y = [0,1]  clf = BernoulliRBM().fit(X,y)  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 <span style="font-family:Microsoft YaHei;font-size:18px;">import numpy as np  import matplotlib.pyplot as plt    from scipy.ndimage import convolve  from sklearn import linear_model, datasets, metrics  from sklearn.cross_validation import train_test_split  from sklearn.neural_network import BernoulliRBM  from sklearn.pipeline import Pipeline      ###############################################################################  # Setting up    def 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 = [          [[010],           [000],           [000]],            [[000],           [100],           [000]],            [[000],           [001],           [000]],            [[000],           [000],           [010]]]        shift = lambda x, w: convolve(x.reshape((88)), 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 Data  digits = 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 scaling    X_train, X_test, Y_train, Y_test = train_test_split(X, Y,                                                      test_size=0.2,                                                      random_state=0)    # Models we will use  logistic = 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.06  rbm.n_iter = 20  # More components tend to give better prediction performance, but larger  # fitting time  rbm.n_components = 100  logistic.C = 6000.0    # Training RBM-Logistic Pipeline  classifier.fit(X_train, Y_train)    # Training Logistic regression  logistic_classifier = linear_model.LogisticRegression(C=100.0)  logistic_classifier.fit(X_train, Y_train)    ###############################################################################  # Evaluation    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))))    ###############################################################################  # Plotting    plt.figure(figsize=(4.24))  for i, comp in enumerate(rbm.components_):      plt.subplot(1010, i + 1)      plt.imshow(comp.reshape((88)), cmap=plt.cm.gray_r,                 interpolation='nearest')      plt.xticks(())      plt.yticks(())  plt.suptitle('100 components extracted by RBM', fontsize=16)  plt.subplots_adjust(0.080.020.920.850.080.23)    plt.show()</span>   显示结果:

    附:博主对于前边的原理其实很是明白了,但是对于scikit-learn实现手写数字识别系统这个代码优点迷乱,如果路过大神明白的,可以给小弟指点迷津

    scikit-learn博主使用的是0.17版本,是稳定版,当然现在有0.18发行版,两者还是有区别的,感兴趣的可以自己官网上查看 [python]  view plain  copy <span style="font-family:Microsoft YaHei;font-size:18px;">import numpy as np  from sklearn.datasets import load_digits  from sklearn.metrics import confusion_matrix,classification_report  from sklearn.preprocessing import LabelBinarizer  from sklearn.cross_validation import train_test_split  from NeuralNetwork import NeuralNetwork    digits = load_digits()  X = digits.data  y = digits.target  X -= X.min()  X /= X.max()    nn =NeuralNetwork([64,100,10],'logistic')  X_train, X_test, y_train, y_test = train_test_split(X, y)  labels_train = LabelBinarizer().fit_transform(y_train)  labels_test = LabelBinarizer().fit_transform(y_test)  print "start fitting"  nn.fit(X_train,labels_train,epochs=3000)  predictions = []  for i in range(X_test.shape[0]):      o = nn.predict(X_test[i])      predictions.append(np.argmax(o))  print confusion_matrix(y_test, predictions)  print classification_report(y_test, predictions) </span>   转载请注明出处 http://blog.csdn.net/gamer_gyt 相关资源:敏捷开发V1.0.pptx
    最新回复(0)