本文是笔者进行神经网络学习的个人学习日记
图片和链接均源自网络,侵删
1 全连接神经网络结构
全连接神经网络(Fully Connected Neural Network,FCNN)是一种多层感知机结构。每一层的每一个节点与下一层的每一个节点相连接,并伴有运算关系。一个标准的FCNN由输入层、隐藏层(中间层)和输出层构成,一个简单的单隐藏层的FCNN如下图:
全连接神经网络结构:https://blog.csdn.net/weixin_39723464/article/details/85531726
2 基于PyTorch+FCNN的代码实现
在PyTorch中有可以快速实现神经网络的类和方法。主要基于torch库中的Module
类对网络进行定义,首先加载模块需要用到的库:
import torch
import torch.nn as nn
import torch.nn.functional as F
2.1 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) # 模型建立
2.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) # 训练模型
2.3 模型测试
每一轮训练后都需要同步对测试集进行测试,时刻观察模型是否有欠拟合/过拟合现象。同样的,在测试之前,需要用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值即可。
2.4 方法调用
定义完模型及其训练和测试方法后,下面是调用的完整代码:
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}")
个人神经网络学习日记:
【神经网络学习日记(1)】神经网络基本概念
【神经网络学习日记(2)】全连接神经网络(FCNN)及Pytorch代码实现
【神经网络学习日记(3)】卷积神经网络(CNN)
【神经网络学习日记(4)】循环神经网络(RNN、LSTM、BiLSTM、GRU)
【神经网络学习日记(5)】数据加载器(DataLoader)的调用
【神经网络学习日记(6)】Transformer结构详解
【神经网络学习日记(7)】Transformer的应用(BERT、Longformer、LLM)
【神经网络学习日记(8)】一些图神经网络的简单介绍(GCN、GAT、rGCN)
文中引用部分都尽可能写出了,如果有侵犯其他人文章版权的问题,请务必联系我,谢谢!