神经网络学习日记(二)——全连接神经网络及Pytorch代码实现

本文是笔者为了完成毕业设计而进行学习的一个个人学习日记

图片和链接均源自网络,侵删

FCNN网络结构

**全连接神经网络(Fully Connected Neueral Network,FCNN)**是一种多层感知机结构。每一层的每一个节点与下一层的每一个节点相连接,并伴有运算关系。一个标准的FCNN由输入层、隐藏层(中间层)和输出层构成,一个简单的单隐藏层的FCNN如下图:

fcnn_struct

全连接神经网络结构:https://blog.csdn.net/weixin_39723464/article/details/85531726

基于PyTorch+FCNN的代码实现

在PyTorch中有可以快速实现神经网络的类和方法。主要基于torch库中的Module类对网络进行定义,首先加载模块需要用到的库:

import torch
import torch.nn as nn
import torch.nn.functional as F

FCNN类的定义

我们需要定义一个神经网络的FCNN类,该类继承自torch.nn的Module类。在声明时,需要重写__init__forward这两个方法。下面是一个简单的单隐藏层FCNN类的定义:

class FCNN(nn.Module):
    def __init__(self, input_size=3, hidden_size=4, output_size=2):
        """
        继承Module类,将各层线性连接,形成全连接层
        :param int input_size: 输入层节点数
        :param int hidden_size: 隐藏层节点数
        :param int output_size: 输出层节点数
        """
        super(FCNN, self).__init__()  # 调用父类的构造函数
        self.input_to_hidden = nn.Linear(input_size, hidden_size, dtype=float)  # 输入层到隐藏层
        self.hidden_to_output = nn.Linear(hidden_size, output_size, dtype=float)  # 隐藏层到输出层

        # self.dropout = nn.Dropout(p=0.3)  # dropout训练,防止过拟合

    def forward(self, net_input):
        """
        前向传播
        :param list[float] input: 神经网络输入
        :return: Tensor
        """
        net_input = torch.as_tensor(network_input, dtype=float)
        net_hidden = F.relu(self.input_to_hidden(net_hidden))  # 使用relu激活函数
        # if self.training is True:  # 预测时关闭dropout
        #     net_hidden = self.dropout(net_hidden)
        net_output = self.hidden_to_output(hidden)  # 输出层不使用激活函数
        return net_output

该代码定义了一个单隐藏层,默认输入、隐藏、输出层节点数为3、4、2的全连接神经网络。各层通过nn.Linear方法进行线性连接,并且可以根据需要添加多层隐藏层以及dropout层(防止过拟合)。在隐藏层使用ReLU激活函数,而在输出层不使用激活函数。可以根据需要修改代码。

在调用时,可以使用一个变量model储存,输入各层的节点数,将网络保存在模型中。

model = FCNN(3, 4, 2)  # 模型建立

模型训练(正向/反向传播)

训练模型需要用到几个参数:模型本身,训练集数据加载器,训练参数。并且在开始一轮训练之前,使用model.train()方法将模型设置为训练模式。定义训练模型的方法函数如下:

def train(model, train_loader):
    """
    训练模型,计算误差反向传播,并返回训练损失值
    :param FCNN model: 网络模型
    :param DataLoader train_loader: 训练集数据加载器
    :return: float
    """
    global optimizer, criterion  # 优化器,损失函数
    model.train()  # 训练模式
	
    train_loss = 0.0  # 统计loss值
    for i, (inputs, labels) in enumerate(train_loader):
        outputs = model(inputs).to(torch.float)  # 正向传播计算预测值
        loss = criterion(outputs, labels)  # 计算loss值
        optimizer.zero_grad()    # 梯度归零
        loss.backward()   # 反向传播计算梯度
        optimizer.step()  # 梯度下降更新参数
        
        train_loss += loss.item()  # 获得该batch的loss值(float)
	
    train_loss /= len(train_loader)  # 计算平均loss值
    return train_loss

在调用时,需要先定义优化器optimizer和损失函数criterion,例如:

optimizer = torch.optim.Adam(model.parameters(), lr=0.001)  # Adam优化器
criterion = nn.MSELoss(reduction='mean')  # MSE损失函数
# -----------------其他代码-----------------
train_loss = train(model, train_loader)  # 训练模型

模型测试

每一轮训练后都需要同步对测试集进行测试,时刻观察模型是否有欠拟合/过拟合现象。同样的,在测试之前,需要用model.eval()方法将模型设置为评估模式。定义测试模型的方法函数如下:

def test(model, test_loader):
    """
    将训练结果对测试集进行测试,返回测试损失值
    :param FCNN model: 网络模型
    :param DataLoader test_loader: 测试集数据加载器
    :return: float
    """
    global criterion  # 损失函数
    model.eval()  # 评估模式
    
    test_loss = 0.0  # 统计loss值
    with torch.no_grad():
        for i, (inputs, labels) in enumerate(test_loader):
            # 一次取batch_size个数据进行比对
            outputs = model(inputs).to(torch.float)  # 计算预测值
            loss = criterion(outputs, labels)  # 计算损失值
            
            test_loss += loss.item()  # 获得该batch的loss值(float)
	
    test_loss /= len(test_loader)  # 计算平均loss值
    return test_loss

由于不需要进行反向传播,因此只要从外部调用损失函数criterion计算loss值即可。

方法调用

定义完模型及其训练和测试方法后,下面是调用的完整代码:

import ...

"""
数据加载
train_loader = ...
test_loader = ...
"""

model = FCNN(3, 4, 2)  # 模型建立
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)  # Adam优化器
criterion = nn.MSELoss(reduction='mean')  # MSE损失函数

epochs = 100  # 训练次数
for no_epoch in range(epochs):
    train_loss = train(model, train_loader)  # 训练模型
    test_loss = test(model, test_loader)  # 测试模型
    # 输出结果
    print(f"{np_epoch + 1} Train Loss: {train_loss} | Test Loss: {test_loss}")

个人神经网络学习日记:
神经网络学习日记(一)——神经网络基本概念
神经网络学习日记(二)——全连接神经网络及Pytorch代码实现
神经网络学习日记(三)——CNN卷积神经网络
神经网络学习日记(四)——RNN、LSTM、BiLSTM、GRU
神经网络学习日记(五)——数据加载器(DataLoader)的调用

由于是第一次写博客,不知道是否有侵犯其他人文章版权的问题,如果有请务必联系我,谢谢!

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值