多层神经网络详细解析(每一行都详细注释)

本文详细介绍了如何使用Python编程实现一个包含Sigmoid激活函数的前馈神经网络,涉及神经网络的结构初始化、前向传播、反向传播算法以及性能评估,通过scikit-learn库和matplotlib进行数据处理和可视化。
摘要由CSDN通过智能技术生成

学习的过程就像收集龙珠,每一颗都是困难,但是收集齐了就可以召唤出成功。

学习目标:

[1].使用类的方法封装多层神经网络
[2].使用函数实现神经网络的正向计算、反向传播


代码运行需要的库

scikit-learn
numpy
matplotlib

学习内容:

import numpy as np
from sklearn import datasets, linear_model#内置数据集,用于练习和测试机器学习模型
from sklearn.metrics import accuracy_score #线性模型的模块,包括逻辑回归
import matplotlib.pyplot as plt
def sigmoid(X):
    return 1.0/(1 + np.exp(-X))#定义sigmoid激活函数
class NN_Model:#用于初始化类的实例
    def __init__(self,nodes = None):
        self.epsilon = 0.01 #学习率
        self.n_epoch = 1000 #迭代数
        if not nodes:#根据传入的 nodes 参数来初始化神经网络的结构。
            self.nodes = [2, 6, 2]#如果没有提供nodes参数,则默认输入层2个节点,隐藏层6个节点,输出层2个节点
        else:
            self.nodes = nodes
    def init_weight(self):#初始化神经网络的权重
        W = []#存储权重的列表
        B = []#存储偏置的列表
        n_lay = len(self.nodes)#获取神经网络的层数
        for i in range(n_lay-1):#遍历神经网络的每一层,除了输出层
            w = np.random.randn(self.nodes[i], self.nodes[i+1])/np.sqrt(self.nodes[i])#用高斯分布随机初始化权重并缩放
            b = np.random.randn(1, self.nodes[i+1])#随机初始化偏置
            W.append(w)#将初始化的权重添加到列表中
            B.append(b)#将初始化的偏置添加到列表中
        self.W = W#将权重列表保存在类的属性中
        self.B = B#将偏置列表保存在类的属性中
    def forward(self,X):#向前传播方法。目的是将输入数据传递到网络中,经过每一层的计算,最终得到网络的输出。
        Z = []#是一个列表,储存每一层的输出
        x0 = X#当前层的输入,初始化为X
        for i in range(len(self.nodes) - 1):#遍历神经网路的每一层,除了输出层
            z = sigmoid(np.dot(x0, self.W[i]) + self.B[i])#向前传播计算
            x0 = z#更新x0,当前层的输出,便于下一层输入
            Z.append(z)#将当前层的输出添加到列表中
        self.Z = Z#将所有层的输出保存到类的属性中
        return Z[-1]#返回输出层的输出,即神经网络的最终输出
    def backpropagation(self, X, y, n_epoch = None, epsilon = None):#反向传播方法,用于训练神经网络
        if not n_epoch: n_epoch = self.n_epoch#检查n_epoch是否为 None,是则使用默认值,否则使用传入的值
        if not epsilon: epsilon = self.epsilon#检查epslion是否为 None,是则使用默认值,否则使用传入的值
        self.X = X #存储输入数据
        self.Y = y #存储标签数据
        for i in range(n_epoch): #正向计算每个神经元的输出
            self.forward(X) #调用前面的函数进行计算,向前传播
            self.evaluate() #调用后面的函数进行计算,计算网格的输出误差
            W = self.W #获取权重
            B = self.B #获取偏置
            Z = self.Z #获取每一层的输出
            D = [] #存储每一层的误差
            d0 = y #初始误差为标签
            n_layer = len(self.nodes) #神经网络的层数
            for j in range(n_layer - 1, 0, -1): #从输出层到输入层,逐层计算每一层的误差
                jj = j-1#用于索引权重和输出列表的索引
                z = self.Z[jj]#获取当前层的输出
                if j == n_layer - 1:#如果是输出层,计算输出层的误差
                    d = z*(1-z)*(d0 - z)#输出层误差公式
                else:#如果是隐藏层,计算隐藏层的误差
                    d = z*(1-z)*np.dot(d0, W[j].T)#隐藏层误差公式
                d0 = d#更新当前层的误差,用于下一层的计算
                D.insert(0, d)#将当前层的误差插入到误差列表的开头
            for j in range(n_layer - 1, 0, -1): #从输出层到输入层,逐层更新权重和偏置//采用的是梯度下降法
                jj = j - 1#用于索引权重、偏置和输出列表的索引
                if jj != 0:#更新隐藏层和输出层的权重
                    W[jj] += epsilon * np.dot(Z[jj-1].T, D[jj])
                else:#更新输入层的权重
                    W[jj] += epsilon * np.dot(X.T, D[jj])#更新公式
                    B[jj] += epsilon * np.sum(D[jj], axis = 0)
    def evaluate(self):#评估神经网络在当前训练轮次中的性能
        z = self.Z[-1]#获取输出层的输出
        L = np.sum((z - self.Y)**2)#计算均方误差
        y_pred = np.argmax(z,axis = 1)#获取预测类别
        y_true = np.argmax(self.Y, axis = 1)#获取真实类别
        acc = accuracy_score(y_true, y_pred)#计算分类准确率
        print("L = %f, acc = %f" % (L, acc))#打印均方误差和准确率

至此,多层神经网络封装为类任务结束!!!

下面生成一些数据来进行验证一下

np.random.seed(0)#设置随机种子,以确保实验的可重复性
X, y = datasets.make_moons(200, noise = 0.2)#生成包含 200 个样本的 moons 数据集,噪声为 0.2
t = np.zeros((X.shape[0], 2))#创建一个独热编码的标签矩阵
t[np.where(y==0), 0] = 1
t[np.where(y==1), 1] = 1
nn = NN_Model([2, 6, 4, 2])#创建神经网络模型,定义了输入层、两个隐藏层和输出层的节点数
nn.init_weight()#初始化神经网络的权重和偏置
nn.backpropagation(X, t, 2000)#使用反向传播算法进行训练,迭代 2000 次
y_res = nn.forward(X)#使用训练好的神经网络进行前向传播,得到预测结果
y_pred = np.argmax(y_res, axis = 1)#获取预测类别
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))#创建包含两个子图的画布
ax1.scatter(X[:, 0], X[:, 1], c = y, cmap = plt.cm.Spectral, marker='^')#在第一个子图中绘制真实值的散点图
ax1.set_title("真实值")
ax2.scatter(X[:, 0], X[:, 1], c = y_pred, cmap = plt.cm.Spectral)#在第二个子图中绘制预测值的散点图
ax2.set_title("预测值")
plt.subplots_adjust(wspace=0.4)#调整子图之间的间距
plt.show()#绘图

可以得到结果如下图:
插入图片描述

总结

这段代码实现了一个简单的前馈神经网络(Feedforward Neural Network),通过反向传播算法进行训练。以下是数学原理的简要介绍:

  1. Sigmoid 激活函数:

    def sigmoid(X):
        return 1.0/(1 + np.exp(-X))
    

    Sigmoid 函数用于引入非线性变换,将输入映射到 (0, 1) 的范围内,用于激活神经网络的每一层。

  2. 神经网络结构:

    nn = NN_Model([2, 6, 4, 2])
    

    这定义了神经网络的结构,包括输入层 2 个节点、两个隐藏层(分别有 6 个和 4 个节点)以及输出层 2 个节点。

  3. 初始化权重和偏置:

    nn.init_weight()
    

    权重和偏置是神经网络的参数,通过高斯分布随机初始化,并根据节点数量进行缩放。

  4. 前向传播:

    y_res = nn.forward(X)
    

    前向传播是通过神经网络从输入到输出的计算过程。对于每一层,计算输入与权重的乘积,加上偏置,并通过激活函数得到输出。

  5. 反向传播:

    nn.backpropagation(X, t, 2000)
    

    反向传播是通过梯度下降法更新权重和偏置,以最小化损失函数。该算法计算输出误差,然后反向传播误差,根据梯度更新权重和偏置。

  6. 评估性能:

    nn.evaluate()
    

    评估方法计算均方误差和准确率,用于监控神经网络在训练过程中的性能。

  7. 数据集生成和可视化:

    X, y = datasets.make_moons(200, noise=0.2)
    

    使用 scikit-learn 中的 make_moons 函数生成包含 200 个样本的二类数据集,其中噪声为 0.2。通过 Matplotlib 绘制真实值和预测值的散点图,用于可视化模型性能。

整个过程涉及到神经网络的前向传播和反向传播,通过不断调整权重和偏置,使得神经网络的输出更好地匹配真实标签,从而实现模型的训练。这是基本的神经网络训练流程,数学原理主要涉及到梯度下降、链式法则等基础数学知识。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值