IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 神经网络(network2版)(西瓜书版) -> 正文阅读

[人工智能]神经网络(network2版)(西瓜书版)

基于network1版,将其中的权值和偏置更新公式改写成了西瓜书上的公式

代码目录结构:

?其中mnist.pkl.gz文件和mnist_loader.py文件与network1版中的完全一致

""" network2.py文件代码(与network1的区别在于backprop()函数) """
import random

import numpy as np

def sigmoid(Z):
    return 1.0 / (1 + np.exp(-Z))  #此处是e的矩阵次方


class Network(object):
    #网络初始化
    def __init__(self,sizes):
        self.num_layers = len(sizes) #sizes列表的数据表示各层神经元个数(从下层到上层) 输入层784 隐层30 输出层10;len(sizes)表示此神经网络的总层数(3层)
        self.sizes = sizes
        self.biases = [np.random.randn(y,1) for y in sizes[1:]]    #返回一个y*1的随机矩阵  偏置b初始化[30*1, 10*1],因为b是一个数,所以是*1,因为第一层(输入层)没有偏置,所以下标从1开始
        self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])]
        #权重w初始化[30*784, 10*30],因为第一层(输入层)没有权重,所以y下标从1开始,又因为每个神经元的权重w是个向量,因为输入层有784个属性值要输入到隐层,所以隐层的每个w是784维的;因为隐层有30个属性值要输入到输出层,所以输出层的w的是30维的   zip()函数用法:https://www.runoob.com/python/python-func-zip.html
        #上边的weights矩阵是已每个输入为行向量拼构成的矩阵,而下面的mini_batch一小批样本矩阵是由列向量(每个样本的属性是一个784*1的列向量)构成的,目的是方便做矩阵乘法运算


    #随机梯度下降算法
    def SGD(self, training_data, epochs, mini_batch_size, eta, test_data = None):  #epochs表示训练的总次数, mini_batch_size表示把样本分批后每批有mini_batch_size个样本,一份一份训练,eta表示学习率 #默认没有test_data,但输入也可以有test_data,此写法可提高代码的扩展性
        training_data = list(training_data) #五万个样本
        n = len(training_data)              #训练样本的总个数

        if test_data: #如果有测试样本
            test_data = list(test_data)    #一万个测试样本
            n_test = len(test_data)

        for j in range(epochs):            #训练epochs次
            random.shuffle(training_data)  #shuffle() 方法将序列的所有元素随机排序。https://www.runoob.com/python/func-number-shuffle.html     此处是为了提高样本的随机性,已此增强泛化性
            mini_batches = [training_data[k: k + mini_batch_size] for k in range(0, n, mini_batch_size)]    #将五万个样本分成(50000/mini_batch_size)批,每批里有mini_batch_size个样本(mini_batches里有(50000/mini_batch_size)个列表),分别运行
            """上行代码等价于
            mini_batches = []
            for k in range(0, n, mini_batch_size):
                mini_batches.append(training_data[k: k + mini_batch_size])
            """
            lastsumE = 0                       #此次迭代所有样本的累计误差
            for mini_batch in mini_batches:    #mini_batch一小批(10个)样本构成的列表,其中每个样本都是一个元组(每个元组长度为2,第一部分为784*1的特征向量,第二部分为10*1的标记向量),即列表里包含10个元组
                sumE = self.updata_mini_batch(mini_batch, eta) #一批一批运行,每运行一批(updata_mini_batch函数执行一次),所有神经元的w和b全都更新一次,返回这一小批的累计误差
                lastsumE = lastsumE + sumE
            #测试
            print("此次训练后所有样本的累计误差为:"+str(lastsumE))
            if test_data:
                print("第{}次迭代 : 预测正确{}次 / 预测总次数为{}".format(j, self.evaluate(test_data), n_test))
            else:
                print("Epoch {} complete".format(j))


    #小批量梯度下降算法(先算出10个样本所得到的平均梯度,再更新一次所有神经元的w和b,而非每算一个样本所得到的梯度就更新一次所有神经元的w和b)
    def updata_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]
        E = 0       #单个样本的误差
        sumE = 0    #一小批样本的累计误差
        for x, y in mini_batch:     #一个一个样本(一批总共10个样本)进行反向传播计算出每个样本对于所有神经元的w,b更新公式中的梯度,并累加起来  (x, y)是一个样本元组,x是特征向量(784*1),y是标记向量(10*1)
            delta_nabla_b, delta_nabla_w,E = self.backprop(x, y, E)
            sumE = sumE + E
            nabla_b = [nb +dnb for nb, dnb in zip(nabla_b,delta_nabla_b)]     #nabla_b是前一个样本算出的梯度,delta_nabla_b是当前样本算出的梯度。因为是小批量梯度下降算法,所以此处是梯度的累加,后面计算时还要 除 len(mini_batch)来得到平均梯度
            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)]    #更新偏置值(/len(mini_batch)*nw即平均梯度)
        self.biases = [b - (eta / len(mini_batch)) * nb for b, nb in zip(self.biases, nabla_b)]      #更新权值值
        #只不过更新w和b,是一批一批更新的(先算出10个样本所得到的平均梯度,再更新一次所有神经元的w和b,而非每算一个样本所得到的梯度就更新一次所有神经元的w和b)。因为如果每有一个样本都要更新一次所有神经元的偏置和权重,计算量太大,此处是先算出10个样本所得到的的平均梯度,用平均梯度更新一次所有神经元的w和b的
        return sumE     #返回此批样本的累计误差

    #标准BP算法(从后向前层算出通过一个训练样本所得到的每个神经元的w和b的更新公式中的梯度)
    def backprop(self, x, y, E):
        nabla_b = [np.zeros(b.shape) for b in self.biases]  #zeros()函数用法:https://blog.csdn.net/lens___/article/details/83927880
        nabla_w = [np.zeros(w.shape) for w in self.weights] #每一个神经元w,b更新要用的梯度,初始化为0

        #以下4行为西瓜书p102图5.7的公式,计算预测值
        alpha = np.dot(self.weights[0],x)           # w:30*748  x:748*1  alpha:30*1
        boy = sigmoid(alpha - self.biases[0])       #boy:30*1
        beta = np.dot(self.weights[1],boy)          #beta:10*1
        predictY = sigmoid(beta - self.biases[1])   #predictY:10*1
        #计算误差(观察用)
        E = sum(sum((predictY - y)*(predictY - y)))/2   #单个样本的误差(因为输出层的每个神经元都有误差,所以要sum)   p102式(5.4)

        #计算4个更新公式中的梯度
        g = predictY * (1 - predictY) * (y - predictY)      #g:10*1  p103式(5.10)
        e = boy *(1 - boy) * (np.dot(self.weights[1].T,g))  #e:30*1  p104式(5.15)
        # 保存梯度
        nabla_w[1] = -np.dot(g,boy.T)   #nabla_w[1]:10*30   p103式(5.11)
        nabla_b[1] = g                  #nabla_b[1]:10*1    p103式(5.12)
        nabla_w[0] = -np.dot(e,x.T)     #nabla_w[0]:30*748  p103式(5.13)
        nabla_b[0] = e                  #nabla_b[0]:30*1    p103式(5.14)
        return (nabla_b, nabla_w,E)    #返回每一个神经元w,b更新要用的梯度和此样本的误差

    # 估值函数
    def evaluate(self, test_data):
        test_results = [(np.argmax(self.feedforward(x)), y) for (x, y) in test_data]   #feedforward(x)是预测标记,y是真实标记
        return sum(int(predict_y == y) for (predict_y, y) in test_results)      #返回预测正确的总次数        此处是通过下标来比较的,因为给的测试数据的标记比较特殊(独热码),是10个数中数字为1的下标

    # 前向运算(通过输入层输入的x,直接计算出输出层输出的值)
    def feedforward(self, a):
        for b, w in zip(self.biases, self.weights):  # 从biases和weights中取出一一对应的b和w  zip()函数用法:https://www.runoob.com/python/python-func-zip.html
            a = sigmoid(np.dot(w, a) + b)
        return a    #a:10*1  输出层每个神经元最后的输出值的意义是该值为1的概率(因为激活函数用的是sigmoid()函数)




""" test.py文件代码 """
from BPNetwork_better import mnist_loader
from BPNetwork_better import  network1
from BPNetwork_better import  network2

training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
training_data = list(training_data)  #training_data是一个长度为5万的列表,即training_data列表里有五万个长度为2的元组,每个元组是一个样本,且每个元组里有该样本的特征向量和标记向量

net = network2.Network([784, 30, 10])   #初始化每层(从下往上)的神经元个数,此句其实是new了一个对象
net.SGD(training_data, 30, 10, 0.3, test_data = test_data)  #30表示训练的总次数,10表示把样本分批后每批有10个样本,一份一份训练,0.3表示学习率

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 15:47:40  更:2021-09-20 15:50:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/22 0:33:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码