zoukankan      html  css  js  c++  java
  • 改进神经网络的学习方法

     

    防止输出层梯度饱和

    1.sigmoid+交叉熵 

    均方误差做代价函数时,输出层反向传播的误差$$delta ^{L} = (a-y)*{sigma}'$$

    当sigmoid函数饱和时,即使a与y相差很大,传播误差也很小,造成前期训练速度很慢。

    因此上一篇随笔中采用了交叉熵作为输出层代价函数。

    2.softmax+对数似然 

    使用softmax代替sigmoid作为输出层,激活值为

    输入样本的 log-likelihood 代价函数就是

    反向传播误差与sigmoid+交叉熵形式相同,但aj取值不同。

    下面的代码中添加了softmax,在小训练集上效果与方法1接近。

    防止过度拟合

    1.增加样本

    随着训练集样本从1000到5000到50000,测试数据的准确率会越来越高。

    当样本数无法增加时,可以采用图像平移、旋转来扩大样本数据。

    2.正则化

    常用L2 规范化,想法是增加一个额外的项到代价函数上,这个项叫做规范化项。

    下面是规范化交叉熵

    求偏导得到下面结果,权重更新方式不变。

    下面的代码中添加了L2 正则化,并修改了cost计算。

    权重初始化

    之前的初始化方式(np.random.randn(y, x))就是根据独立的均值为 0,标准差为 1 的高斯随机变量随机采样作为权重和偏差的初始值。

    单元输入加权和z有一个非常宽的高斯分布,输出σ(z)就会接近 1或者 0,表示我们的隐藏元会饱和。

    使用均值为0标准差为 1/√n的高斯分布(np.random.randn(y, x)/np.sqrt(x))初始化这些权重,能让我们的神经元更不可能饱和。

    下面的代码中添加了改进的权重初始化。

      1 # coding:utf8
      2 import cPickle
      3 import numpy as np
      4 import matplotlib.pyplot as plt
      5 
      6 class Network(object):
      7     def __init__(self, sizes):
      8         self.num_layers = len(sizes)
      9         self.sizes = sizes
     10         self.biases = [np.random.randn(y, 1) for y in sizes[1:]]  # L(n-1)->L(n)
     11         # self.weights = [np.random.randn(y, x)
     12         self.weights = [np.random.randn(y, x)/np.sqrt(x)  # improved weight initializer
     13                         for x, y in zip(sizes[:-1], sizes[1:])]
     14 
     15     def feedforward(self, a):
     16         for b_, w_ in zip(self.biases[:-1], self.weights[:-1]):
     17             a = self.sigmoid(np.dot(w_, a)+b_)
     18         a=self.sigmoid(np.dot(self.weights[-1], a)+self.biases[-1])
     19         # a=self.softmax(np.dot(self.weights[-1], a)+self.biases[-1])  # add for softmax
     20         return a
     21 
     22     def SGD(self, training_data, test_data,epochs, mini_batch_size, eta=1.0, lambda_=0.1):
     23         n_test = len(test_data)
     24         n = len(training_data)
     25         plt.xlabel('epoch')
     26         plt.ylabel('value')
     27         plt.title('cost')
     28         cy=[]
     29         cx=range(epochs)
     30         for j in cx:
     31             self.cost = 0.0
     32             np.random.shuffle(training_data)  # shuffle
     33             for k in xrange(0, n, mini_batch_size):
     34                 mini_batch = training_data[k:k+mini_batch_size]
     35                 self.update_mini_batch(mini_batch, eta,n)
     36             self.cost+=0.5*lambda_*sum(np.linalg.norm(w_)**2 for w_ in self.weights)
     37             cy.append(self.cost/n)
     38             print "Epoch {0}: {1} / {2}, {3} / {4}".format(
     39                     j, self.evaluate(training_data,1), n,self.evaluate(test_data), n_test)
     40         plt.plot(cx,cy)
     41         plt.scatter(cx,cy)
     42         plt.show()
     43 
     44     def update_mini_batch(self, mini_batch, eta, n, lambda_=0.1):
     45         for x, y in mini_batch:
     46             delta_b, delta_w = self.backprop(x, y)
     47             for i in range(len(self.weights)):  # L2 regularization
     48                 self.weights[i]-=eta/len(mini_batch)*(delta_w[i] +lambda_/n*self.weights[i])
     49             self.biases -= eta/len(mini_batch)*delta_b
     50             a=self.feedforward(x)
     51             cost=np.sum(np.nan_to_num(-y*np.log(a)-(1-y)*np.log(1-a)))
     52             self.cost += cost
     53 
     54     def backprop(self, x, y):
     55         b=np.zeros_like(self.biases)
     56         w=np.zeros_like(self.weights)
     57         a_ = x
     58         a = [x]
     59         for b_, w_ in zip(self.biases, self.weights):
     60             a_ = self.sigmoid(np.dot(w_, a_)+b_)
     61             a.append(a_)
     62         for l in xrange(1, self.num_layers):
     63             if l==1:
     64                 # delta= self.sigmoid_prime(a[-1])*(a[-1]-y)  # O(k)=a[-1], t(k)=y
     65                 delta= a[-1]-y  # cross-entropy
     66                 # delta=self.softmax(np.dot(w_, a[-2])+b_)  -y  # add for softmax
     67             else:
     68                 sp = self.sigmoid_prime(a[-l])   # O(j)=a[-l]
     69                 delta = np.dot(self.weights[-l+1].T, delta) * sp
     70             b[-l] = delta
     71             w[-l] = np.dot(delta, a[-l-1].T)
     72         return (b, w)
     73 
     74     def evaluate(self, test_data, train=0):
     75         test_results = [(np.argmax(self.feedforward(x)), y)
     76                         for (x, y) in test_data]
     77         if train:
     78             return sum(int(x == np.argmax(y)) for (x, y) in test_results)
     79         else:
     80             return sum(int(x == y) for (x, y) in test_results)
     81 
     82     def sigmoid(self,z):
     83         return 1.0/(1.0+np.exp(-z))
     84 
     85     def sigmoid_prime(self,z):
     86         return z*(1-z)
     87 
     88     def softmax(self,a):
     89         m = np.exp(a)
     90         return m / np.sum(m)
     91 
     92 def get_label(i):
     93     c=np.zeros((10,1))
     94     c[i]=1
     95     return c
     96 
     97 if __name__ == '__main__':
     98         def get_data(data):
     99             return [np.reshape(x, (784,1)) for x in data[0]]
    100 
    101         f = open('mnist.pkl', 'rb')
    102         training_data, validation_data, test_data = cPickle.load(f)
    103         training_inputs = get_data(training_data)
    104         training_label=[get_label(y_) for y_ in training_data[1]]
    105         data = zip(training_inputs,training_label)
    106         test_inputs = training_inputs = get_data(test_data)
    107         test = zip(test_inputs,test_data[1])
    108         net = Network([784, 30, 10])
    109         net.SGD(data[:5000],test[:5000],epochs=20,mini_batch_size=10, eta=0.5, lambda_=0.1)
    110         # Epoch 19: 4992 / 5000 (train data), 4507 / 5000 (test data)

     

  • 相关阅读:
    Linux 实战
    bash 环境配置及脚本
    Linux vi/vim
    Linux 正则表达式
    001 KNN分类 最邻近算法
    测序名解
    流式细胞术
    CircRNA 环化RNA
    笔记总结
    Flume
  • 原文地址:https://www.cnblogs.com/qw12/p/6111182.html
Copyright © 2011-2022 走看看