3.4~3.5 — 梯度下降算法的实现
mnist 手写数字识别
import numpy as np
class Network(object): #Network:神经网络类
#初始化函数
def __init__(self, sizes): #sizes: 网络的规模 例如: 上图的神经网络规模就是:[3, 4, 1]
self.num_layers = len(sizes) #多少层神经网络 上图3层
slef.sizes = sizes
#下一句的解释:np.random.randn(y,1) 生成高斯分布的随机数,(y, 1): 其规模是y列表,生成1组。
#[y for y in range] 快速列表生成器, 生成sizes[1:]规模的列表, 其中sizes[1:]是sizes除去第一个元素后面的元素。按上图就是[4,1]
self.biases = [np.random.randn(y,1) for y in sizes[1:]]
#其中zip():按照给的参数, 两两对应,组合生成新数据 x:[3,4], y:[4,1]
self.weights = [np.random.randn(y,x) for x, y in zip(sizes[:-1], sizes[1:])]
#a 是input向量, 返回下一个节点的值
def feedforward(self, a):
for b, w in zip(self.biases, self.weights):
a = sigmoid(np.dot(w, a) + b) #np.dot()点积 w1.a1 + w2.a2 ...
return a #输出, 下一个节点的值
#随机梯度下降算法
# 训练集, 训练多少轮, 一轮有多少实例, 学习率
def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None)
"""training_data is a list of tuples (x, y)"""
if test_data: n_test = len(test_data);
n = len(training_data)
for j in xrange(epochs):
random.shuffle(training_data) # shuffle:打乱洗牌,把training_data 打乱
#xrange(0, n, mini_batch_size) 从0->n, 每次步进mini_batch_size大小
mini_batches = [traning_data[k:k+mini_batch_size] for k in xrange(0, n, mini_batch_size)]
self.update_mini_batch(mini_batch, eta)
if test_data:
print "Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)
else:
print "Epoch {0} complete".format(j)
在 update_mini_batch() 函数中做的事情就是:
梯度下降更新:
随机梯度下降更新:(优选,下面的函数就是实现了该方程)
def update_mini_batch(self, mini_batch, eta):
"""在一轮mini_batch 训练中,使用backpropagation 的方法梯度下降更新 w, b"""
#backpropagation:计算cost() 函数对于w, b 的偏导数的方法
#初始化偏导叠加值(方程中最后面的那个)
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
for x, y in mini_batch:
# 求b, w 的 偏导数
delta_nabla_b, delta_nabla_w = self.backprop(x, y)
nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] 将每个遍历(x,y)cost的关于b偏导叠加: sum(deltaC/deltaw)
nabla_w = [nw + dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)]
self.biases = [b-(eta/len(mini_batch))*nb for b, nb in zip(self.biases, nabla_b)]
#一轮mini_batch 遍历完成累加起来的变化量才更新到 w, b 中。