【神经网络与深度学习】BP算法学习

相关背景知识

1. XOR问题,即线性不可分问题。

2. 多层感知机MLP:在网络中加入一个或多个隐藏层来克服线性模型的限制, 使其能处理更普遍的函数关系类型。

3. 激活函数

ReLU函数

ReLU(x) = max(x, 0)

sigmoid函数

sigmoid(x) = \frac{1}{1+exp(-x)}

tanh函数

tanh(x) = \frac{1-exp(-2x)}{1+exp(2x)}

多层前馈网络

多层感知机是一种多层前馈网络, 由多层神经网络构成,每层网络将输出传递给下一层网络。神经元间的权值连接仅出现在相邻层之间,不出现在其他位置。如果每一个神经元都连接到上一层的所有神经元(除输入层外),则成为全连接网络。
 

BP算法

多层前馈网络的反向传播 (BP)学习算法是梯度下降法在多层前馈网中的应用。

正向传播:输入信号从输入层经隐层,传向输出层,若输出层得到了期望的输出,则学习算法结束;否则,转至反向传播。

反向传播:将误差(样本输出与网络输出之差)按原联接通路反向计算,由梯度下降法调整各层节点的权值和阈值,使误差减小。

算法实现

参考书目:《动手学深度学习》第二版

多层感知机从零开始实现

书中如下所示代码在实现过程中存在问题,报错内容为不存在“train_ch3”和“predict_ch3”。

d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
d2l.predict_ch3(net, test_iter)

为解决上述问题,编写如下代码,定义train_ch3和predict_and_evaluate两个函数。

def train_ch3(net, train_iter, test_iter, loss_fn, num_epochs, updater):
    # 初始化动画绘图工具
    animator = d2l.Animator(xlabel='epoch', ylabel='loss', xlim=[0, num_epochs], ylim=[0.2, 0.9])
    for epoch in range(num_epochs):
        # 每个epoch开始前,将梯度清零
        updater.zero_grad()
        # 在当前epoch内遍历所有批次
        for i, (X, y) in enumerate(train_iter):
            # 前向传播计算预测值
            y_hat = net(X)
            # 将one-hot编码转换为类别索引(如果已经是类别索引则不需要此步骤)
            # y = y.argmax(dim=1)
            # 计算损失(对于CrossEntropyLoss,通常不需要手动转换为类别索引)
            l = loss_fn(y_hat, y)
            # 反向传播求梯度
            l.mean().backward()  # 对每个批次的损失求平均后反向传播
            # 更新参数
            updater.step()
            # 记录训练损失
            animator.add(epoch + (i + 1) / len(train_iter), (l.mean().item(), None))
        # 每个epoch结束时,在测试集上评估模型
        test_acc = d2l.evaluate_accuracy_gpu(net, test_iter)
        animator.add(epoch + 1, (None, test_acc))
    # 显示最终信息
    print(f'loss {l.mean().item():.3f}, accuracy on test set: {test_acc:.2f}')

def predict_and_evaluate(net, data_iter):
    correct = 0
    total = 0
    with torch.no_grad():
        for X, y in data_iter:
            # 获取预测类别
            predictions = torch.argmax(net(X), dim=1)
            # 计算正确预测的数量
            correct += (predictions == y).sum().item()
            total += len(y)
    # 计算并返回准确率
    return correct / total

在上述修改的基础上,编写如下代码,实现一个简单的多层感知机。

import random
import torch
from torch import nn
from d2l import torch as d2l

# 激活函数(ReLU)
def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X, a)

# 模型
def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)  # 这里“@”代表矩阵乘法
    return (H@W2 + b2)

if __name__ == '__main__':
    batch_size = 256
    train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

    # 参数初始化
    num_inputs, num_outputs, num_hiddens = 784, 10, 256
    W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True) * 0.01)
    b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
    W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True) * 0.01)
    b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
    params = [W1, b1, W2, b2]

    # 使用新定义的函数评估模型在测试集上的表现
    test_accuracy = predict_and_evaluate(net, test_iter)
    print(f'Accuracy on the test set: {test_accuracy:.2f}')

    # 损失函数 #交叉熵
    loss = nn.CrossEntropyLoss(reduction='none')

    # 训练
    num_epochs, lr = 10, 0.1
    updater = torch.optim.SGD(params, lr=lr)
    train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)

    # 训练结束后,在测试集上评估模型
    test_accuracy = predict_and_evaluate(net, test_iter)
    print(f'Accuracy on the test set: {test_accuracy:.2f}')

运行上述代码,输出的主要结果为:

Accuracy on the test set: 0.07
loss 2.220, accuracy on test set: 0.29
Accuracy on the test set: 0.29

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值