mini-batch方法 实现一个基本的神经网络训练过程 代码详解

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

# 读入数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)

network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

iters_num = 10000  # 适当设定循环的次数
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1)

for i in range(iters_num):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    # 计算梯度
    #grad = network.numerical_gradient(x_batch, t_batch)
    grad = network.gradient(x_batch, t_batch)
    
    # 更新参数
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]
    
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
    
    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)
        print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))

# 绘制图形
markers = {'train': 'o', 'test': 's'}
x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc', linestyle='--')
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

这段代码实现了一个基本的神经网络训练过程,使用了 MNIST 数据集进行手写数字分类。主要功能包括数据加载、网络训练、梯度计算和参数更新。具体功能的解释如下:

1. 导入数据

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
  • load_mnist 是一个用来加载 MNIST 数据集的函数。MNIST 数据集包含 60000 张训练图片和 10000 张测试图片,每张图片是 28x28 的灰度图像,表示数字 0 到 9。
  • normalize=True 表示对图像进行归一化处理,使得每个像素值在 [0, 1] 范围内。
  • one_hot_label=True 表示标签是 One-Hot 编码格式,即每个标签是一个 10 维的向量,只有对应数字位置为 1,其他为 0。

2. 网络设置

network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
  • TwoLayerNet 是一个两层神经网络类,input_size=784 表示输入层有 784 个神经元(28x28 的图像展开成一个向量),hidden_size=50 表示隐藏层有 50 个神经元,output_size=10 表示输出层有 10 个神经元(对应 10 个数字类别)。

3. 超参数设置

iters_num = 10000  # 适当设定循环的次数
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
  • iters_num = 10000:训练的总迭代次数。
  • train_size = x_train.shape[0]:训练集的样本数。
  • batch_size = 100:每次使用 100 个样本来进行训练,即每个 mini-batch 包含 100 个数据。
  • learning_rate = 0.1:学习率,用来控制每次更新权重时的步长。

4. 训练过程

for i in range(iters_num):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    # 计算梯度
    grad = network.gradient(x_batch, t_batch)
    
    # 更新参数
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]
    
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
    
    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)
        print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))
  • 迭代训练:通过 for i in range(iters_num) 循环进行训练,每次循环代表一次迭代。
  • 批量选择数据batch_mask 随机选择 100 个训练样本。
  • 计算梯度:调用 network.gradient(x_batch, t_batch) 计算当前批次数据的梯度。
  • 更新参数:使用计算出的梯度更新网络的权重和偏置。更新规则是 parameter -= learning_rate * gradient,即梯度下降法。
  • 计算损失:通过 network.loss(x_batch, t_batch) 计算当前批次的损失并保存到 train_loss_list 中。
  • 计算并打印准确率:每完成一个 epoch(通过 i % iter_per_epoch == 0 检查),计算训练集和测试集的准确率,并打印。

这段代码实现了神经网络的训练过程,并绘制了训练和测试准确率的变化曲线。下面是对代码每个部分的详细解释:

4.1 初始化变量
train_loss_list = []
train_acc_list = []
test_acc_list = []
  • train_loss_list 用于保存每次训练的损失值(loss),记录训练过程中损失的变化。
  • train_acc_list 用于保存每个 epoch 后的训练准确率。
  • test_acc_list 用于保存每个 epoch 后的测试准确率。
iter_per_epoch = max(train_size / batch_size, 1)
  • 计算每个 epoch 内需要多少次迭代才能遍历整个训练集。train_size 是训练数据的样本数量,batch_size 是每次训练时使用的样本数量。iter_per_epoch 表示每个 epoch 内的迭代次数。
4.2 训练过程
for i in range(iters_num):
  • 循环 iters_num 次,每次循环表示进行一次迭代。iters_num 是总的训练迭代次数。
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
  • batch_mask = np.random.choice(train_size, batch_size):从训练集 x_train 中随机选取 batch_size 个样本,batch_mask 是选择的样本索引。
  • x_batcht_batch 分别是选中的训练样本和对应的标签。x_batch 是输入数据,t_batch 是标签。
    # 计算梯度
    #grad = network.numerical_gradient(x_batch, t_batch)
    grad = network.gradient(x_batch, t_batch)
  • 计算梯度:network.gradient(x_batch, t_batch) 计算当前批次数据(x_batch, t_batch)的梯度。梯度表示损失函数相对于网络参数(权重和偏置)的变化率,反映了如何更新参数以最小化损失。
    # 更新参数
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]
  • 使用梯度下降法更新网络的参数。通过对每个参数(W1, b1, W2, b2)应用梯度更新公式:
  • 其中,eta 是学习率(learning_rate),决定每次更新的步长。
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
  • 计算当前批次的损失(loss),并将其添加到 train_loss_list 中。
4.3 每个 epoch 后的评估
    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)
        print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))
  • 每当一个 epoch(即遍历完整个训练集)结束时,计算训练集和测试集上的准确率。
    • network.accuracy(x_train, t_train):计算训练集上的准确率。
    • network.accuracy(x_test, t_test):计算测试集上的准确率。
  • 将训练准确率和测试准确率分别存储在 train_acc_listtest_acc_list 中,并打印出每个 epoch 的准确率。
总结:
  • 代码通过循环进行网络的训练,并在每个 epoch 后计算并输出训练和测试的准确率。
  • 使用梯度下降法更新网络的权重和偏置,并通过损失函数(如交叉熵损失)计算每个批次的损失。

5. 绘制准确率图形

markers = {'train': 'o', 'test': 's'}
x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc', linestyle='--')
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()
  • 使用 matplotlib 绘制训练和测试准确率的变化曲线。
  • train_acc_listtest_acc_list 保存了每个 epoch 时的训练和测试准确率。
  • 使用 plt.plot 绘制图形,train acc 用圆圈标记,test acc 用方块标记。
  • plt.ylim(0, 1.0) 设置 y 轴范围为 0 到 1,表示准确率的范围。
  • plt.legend(loc='lower right') 设置图例的位置。

总结:

这段代码实现了一个基于两层神经网络的手写数字分类任务,通过 MNIST 数据集进行训练和测试。核心过程包括:

  1. 加载 MNIST 数据集;
  2. 创建并初始化两层神经网络;
  3. 使用批量梯度下降法更新网络参数;
  4. 在每个 epoch 结束时计算并输出训练和测试的准确率;
  5. 最后绘制训练和测试准确率的变化曲线。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿崽meitoufa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值