python深度学习算法实践——神经网络的训练

神经网络的训练

训练流程

神经网络的训练流程

  1. 准备数据集
  2. 随机划分mini-batch
  3. 计算损失函数L对参数W,b的梯度
  4. 更新参数,将权重参数沿梯度方向进行微小更新
  5. 重复上述过程,记录每个平均损失函数,训练集准确率,测试集准确率的值
代码结构

代码结构

  • data文件夹存储数据集
  • functions.py 存储了sigmoig,softmax等众多基础函数
  • layers.py 包含了神经网络各环节正向传播与反向传播的调用函数,为实现反向传播法计算梯度提供基础
  • two_layer_net.py 存储了设计了两层神经网络的结构,存储了预测与训练所需要的直接调用的代码
  • train_neuralnet.py 是调用上述代码进行预测与数据记录、可视化的主进程
核心代码详解
two_layer_net.py
# coding: utf-8
import os
import struct
import numpy as np
from layers import *
from collections import OrderedDict


class TwoLayerNet:

    def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01):
        # 初始化权重
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) 
        self.params['b2'] = np.zeros(output_size)

        # 生成层
        self.layers = OrderedDict()
        self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1'])
        self.layers['Relu1'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2'])

        self.lastLayer = SoftmaxWithLoss()
    
    def load_mnist(self, path=".\\data", kind='train'): # kind是train或test
        labels_path = os.path.join(path, '%s-labels.idx1-ubyte' % kind) # 标签文件路径
        images_path = os.path.join(path, '%s-images.idx3-ubyte' % kind) # 图像文件路径
        with open(labels_path, 'rb') as lbpath:
            magic, n = struct.unpack('>II', lbpath.read(8)) # 读取文件头
            labels = np.fromfile(lbpath, dtype=np.uint8) # 读取标签

        with open(images_path, 'rb') as imgpath:
            magic, num, rows, cols = struct.unpack('>IIII', imgpath.read(16)) # 读取文件头
            images = np.fromfile(imgpath, dtype=np.uint8).reshape(len(labels), 784) # 读取图像并转换为784维向量
        
        return images, labels
        
    def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)
        
        return x
        
    # x:输入数据, t:监督数据
    def loss(self, x, t):
        y = self.predict(x)
        return self.lastLayer.forward(y, t)
    
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        if t.ndim != 1 : t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
        
    # x:输入数据, t:监督数据
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        
        grads = {}
        grads['W1'] = self.gradient(loss_W, self.params['W1'])
        grads['b1'] = self.gradient(loss_W, self.params['b1'])
        grads['W2'] = self.gradient(loss_W, self.params['W2'])
        grads['b2'] = self.gradient(loss_W, self.params['b2'])
        
        return grads
        
    def gradient(self, x, t):
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.lastLayer.backward(dout)
        
        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 设定
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

        return grads 

这段代码用于创建一个具有两个隐藏层的神经网络。这个类包含了初始化网络、加载MNIST数据集、前向传播、计算损失、计算准确率、计算数值梯度等方法。

  1. __init__ 方法:初始化网络,包括设置权重和偏置,创建层,并设置最后一层为 SoftmaxWithLoss

  2. load_mnist 方法:加载MNIST数据集,包括训练集和测试集。数据集的标签和图像分别存储在 .idx1-ubyte.idx3-ubyte 文件中。

  3. predict 方法:进行前向传播,计算输出。在 predict 方法中,使用了 OrderedDict 来存储网络层,这样可以保证前向传播和反向传播的顺序。

  4. loss 方法:计算损失,使用 SoftmaxWithLoss 层。

  5. accuracy 方法:计算准确率。

  6. numerical_gradient 方法:计算数值梯度,用于调试。

  7. gradient 方法:计算梯度,用于反向传播。

train_neuralnet.py

这段代码实现了一个简单的两层神经网络(TwoLayerNet),并使用MNIST数据集进行训练和测试。以下是代码的详细解释:

  1. 导入必要的库

    import numpy as np
    from two_layer_net import TwoLayerNet
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation
    
  2. 初始化网络

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

    这里初始化了一个两层神经网络,输入层大小为784(对应28x28的MNIST图像),隐藏层大小为50,输出层大小为10(对应10个类别)。

  3. 加载MNIST数据集

    x_train, t_train = network.load_mnist(kind="train")
    x_test, t_test   = network.load_mnist(kind="t10k")
    

    使用TwoLayerNet类中的load_mnist方法加载训练集和测试集。

  4. 设置训练参数

    iters_num = 10000
    train_size = x_train.shape[0]
    batch_size = 100
    learning_rate = 1e-3
    iter_per_epoch = train_size / batch_size
    
  5. 初始化记录训练和测试准确率的列表

    train_loss_list = []
    train_acc_list = []
    test_acc_list = []
    
  6. 开始训练循环

    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={}".format(train_acc), "test_acc={}".format(test_acc))
    
    • 每次迭代中,随机选择一个批次的数据进行训练。
    • 计算梯度并更新网络参数。
    • 记录损失值。
    • 每经过一个epoch(即遍历一次整个训练集),计算并记录训练集和测试集的准确率。
  7. 绘制训练和测试准确率的变化图

    fig, ax = plt.subplots()
    line1, = ax.plot(range(len(train_acc_list)), train_acc_list, label='Train Accuracy', linestyle='-')
    line2, = ax.plot(range(len(test_acc_list)), test_acc_list, label='Test Accuracy', linestyle='--')
    ax.set_xlabel('Epoch')
    ax.set_ylabel('Accuracy')
    ax.set_title('Training and Testing Accuracy')
    ax.legend()
    plt.grid()
    plt.show()
    
  8. 保存网络参数

    np.savetxt(".\\data\\W1.txt", network.params["W1"])
    np.savetxt(".\\data\\b1.txt", network.params["b1"])
    np.savetxt(".\\data\\W2.txt", network.params["W2"])
    np.savetxt(".\\data\\b2.txt", network.params["b2"])
    

    将训练好的网络参数保存到文件中。

总结来说,这段代码实现了一个简单的两层神经网络,并使用MNIST数据集进行训练和测试,同时记录并绘制了训练和测试准确率的变化。

数据集与完整代码请关注公众号"逃离小星球"发送关键字“code101”获取!
感谢支持!

  • 40
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逃离小星球

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

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

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

打赏作者

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

抵扣说明:

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

余额充值