这篇文章写一下如何实现梯度下降算法
来实现一个简单的手写数字识别算法:
我们用的数据集是之间介绍过的MINIST数据集:
训练集(train):50000
验证集(validation):10000
测试(test):10000
下面来写一下如何具体的实现梯度下降算法
首先定义一个网络类:
class Network(object):
def __init__(self,sizes):
self.num_layers=len(sizes)
self.sizes=sizes
self.biases=[np.random.randn(y,1) for y in sizes[1:]]
self.weights=[np.random.randn(y,x) for x,y in zip(sizes[:-1],sizes[1:])]#zip对传入的可循环的两组量产生新的量
sizes:每层神经元的个数,例如:第一层2个神经元,第二层3个神经元
则:net=Network([2,3,1])
np.random.randn(y,1):随机从正态分布(均值0,方差1)中生成
net.weights[1]存储连接第二层和第三层的权重(Python索引从0开始数)
来看一下我们的网络结构:
net=Network([2,3,1])
#np.random.randn(y,1):随机从正态分布(均值0,方差1)中生成
#net.weights[1]存储连接第二层和第三层的权重(Python索引从0开始数)
print(net.num_layers)
print(net.sizes)
print(net.biases)
print(net.weights)
3表示有三层
[2,3,1]表示输入层神经元个数为2,隐藏层神经元个数为3,输出层神经元个数为1
array([[1.2437818],
[1.37606921],
[-0.14247446]]),array([[-0.88268682]])表示隐藏层三个神经元所对应的偏向和输出层神经元所对应的的偏向
表示隐藏层3个神经元分别和输入层两个神经元之间的权重以及输出层神经元和隐藏层三个神经元之间的权重
sigmoid funcition:
def feedforward(self,a):
"Return the output of the network if 'a' is inpit"
for b,w in zip(self.biases,self.weights):
a=sigmoid(np.dot(w,a)+b)
return a
随机梯度下降算法
def SGD(self,training_data,epochs,mini_batch_size,eta,test_data=None):
'''Train the neural network using mini-batch stochastic gradient descent.
The 'training_data' is a list of tuples'(x,y)'representing the training inputs
and the desired outputs. The other non-optional parameters are self-explanatory.
If 'test_data' is provided then the network will be evaluated against the test data
after each epoch, and partial progress printed out. This is useful for tracking progress
but slows things down substantially.'''
if test_data:n_test=len(test_data)
n=len(training_data)
for j in xrange(epochs):
random.shuffle(training_data)#打乱数据
mini_batchs=[
training_data[k:k+mini_batch_size]#从数据集中随机抽取一部分
for k in xrange(0,n,mini_batch_size)]
for mini_batch in mini_batchs:
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))
参数更新方程
def update_mini_batch(self,mini_batch,eta):
'''Update the network's weights and biases by applying gradient descent
using backpropagation to a single mini batch. The 'mini_batch' is a list of tuples
(x,y),and 'eta' is the learning rate.'''
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:
delta_nabla_b,delta_nabla_w=self.backprop(x,y)#backpropagation方法
nabla_b=[nb+dnb for nb,dnb in zip(nabla_b,delta_nabla_b)]
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)]
下面来说一下如何去github下载代码:
GitHub代码网址
可以参考我这一篇文章:
一招解决从GItHub下载文件过慢问题