神经网络与深度学习入门记录001——经典数字分类网络

输入28*28像素大小的数字图片,输出对应数字

思路:
1、构建三层(输出层、隐藏层、输出层)神经网络,创建网络权重和偏置
2、输入测试数据、训练数据,确定小批量训练数量、学习速率、迭代期
3、从训练数据中随机分批次选择小批量数据进行训练
4、每次迭代期结束时,将测试数据应用到当前网络并输出测试结果

import random
import numpy as np
import sys
class Network(object):
    def __init__(self, sizes):#初始化Network
        self.num_layers = len(sizes) #网络的层数
        self.sizes = sizes          #每层神经元个数
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        #随机2、3层偏置
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(sizes[:-1], sizes[1:])]
        '''随机(1,2)、(2,3)层权值,weights中的每一个元素为y行x列矩阵,表示
        表示对应的神经连接的权重'''
    def feedforward(self, a):
        for b, w in zip(self.biases, self.weights):     #遍历网络权重和偏置
            a = sigmoid(np.dot(w, a)+b)
            #δ(z)计算输出a,a列表共10个数据,对应数字0~9的计算结果
        return a
    def SGD(self, training_data, epochs, mini_batch_size, eta,
            test_data=None):
        T=list(test_data)   #测试数据
        if test_data: n_test = len(T)   #测试数据不为零时,n_test为测试数据的数量
        ls=list(training_data)  #用于训练的总数据
        n = len(ls)     #训练数据的数量
        for j in range(epochs):     #训练迭代期
            random.shuffle(ls)      #打乱训练数据
            mini_batches = [
                ls[k:k+mini_batch_size]
                for k in range(0, n, mini_batch_size)]
            #获取mini_batch_size数量的小批量测试数据
            for mini_batch in mini_batches:     #遍历小批量数据
                self.update_mini_batch(mini_batch, eta)
                #对每个数据开始训练,更新weight和biase,eta为学习速率
            if T:   #测试数据不为空时,第j次迭代期后的成功率
                print ("Epoch {0}: {1} / {2}".format(
                    j, self.evaluate(T), n_test))
            else:
                print ("Epoch {0} complete".format(j))
    def update_mini_batch(self, mini_batch, eta):
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        #创建与weights、biases格式一致的零矩阵列表,用于累加梯度
        for x, y in mini_batch:
        #获取单个测试数据中的(x,y),x为输入,y为期望输出
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            #反向传播算法求出梯度
            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)]
            #累加b,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)]
        #更新网络的weights和biases
    def backprop(self, x, y):
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        activation = x
        activations = [x]   #存放每层激活值a=sigmoid(z)
        zs = []  #存放每一层的z=w·x+b
        for b, w in zip(self.biases, self.weights): #遍历网络权重和偏置
            z = np.dot(w, activation)+b     #计算每层带权输入z
            zs.append(z)
            activation = sigmoid(z)         #每层激活值a
            activations.append(activation)
        delta = self.cost_derivative(activations[-1], y) * \
            sigmoid_prime(zs[-1])                     #计算最后一层L的差值是δ=▽Ca⊙σ'(z)(反向传播公式1)
        nabla_b[-1] = delta         #储存最后一层的梯度分量b=δ
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())    #储存最后一层的梯度分量w
        for i in range(2, self.num_layers):     #反向传播
            z = zs[-i]              #取出l层的带权输入z
            sp = sigmoid_prime(z)   
            delta = np.dot(self.weights[-i+1].transpose(), delta) * sp  #计算l层的差值(反向传播公式2)
            nabla_b[-i] = delta     #储存l层的梯度分量b(反向传播公式3)
            nabla_w[-i] = np.dot(delta, activations[-i-1].transpose())      #储存l层的梯度分量w(反向传播公式4)
        return (nabla_b, nabla_w)
    #numpy.transpose()将矩阵转置
    def evaluate(self, test_data):
        test_results = [(np.argmax(self.feedforward(x)), y)
                        for (x, y) in test_data]
        '''self.feedforward(x):计算测试数据中输入x在当前网络中的实际输出
           np.argmax():找出实际输出中最大值的索引=0~9中最有可能的数字
           test_results中记录实际输出和期望输出'''
        return sum(int(x == y) for (x, y) in test_results)
        #逐个比较test_results中的实际输出x和期望输出y相等则int(x==y)值为1
        #sum()将测试数据中符合期望输出的个数累加完成后返回
    def cost_derivative(self, output_activations, y):
        return (output_activations-y)
def sigmoid(z):
    return (1.0/(1.0+np.exp(-z)))
def sigmoid_prime(z):       #sigmoid(z)的导数
    return sigmoid(z)*(1-sigmoid(z))
def main():
    import mnist_loader
    training_data,validation_data,test_data=mnist_loader.load_data_wrapper()
    #读入数据
    net=Network([784,30,10])
    #net网络输入:784个输入神经元(28*28像素),隐藏层30个神经元,10个输出神经元
    net.SGD(training_data,30,10,3.0,test_data=test_data)
    #调用函数训练样本
main()

函数记录:
np.random.randn(x,y):随机生成正态分布元素的x行y列矩阵
zip(x,y):拼接举证x,y,用于一次循环遍历两组数据
np.dot(x,y):x和y的点积
np.random.shuffle(x):打乱矩阵x元素
np.zeros(x.shape):生成x的同型零矩阵
np.argmax(x):输出列表中最大元素的索引
np.transpose()矩阵转置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值