构建神经网络的一般步骤如下:
确定网络的结构:这包括输入层、输出层和隐藏层的数量以及每层中的节点数等。
收集和准备数据:这包括收集训练数据、清洗数据、转换数据格式等。
初始化权重:权重是神经元之间的连接强度,需要在训练前随机初始化。
前向传播计算:根据输入数据和权重计算输出结果。
计算损失函数:损失函数衡量预测输出和真实输出之间的误差。
反向传播计算:反向传播是一种优化算法,用于调整权重以最小化损失函数。
更新权重:根据反向传播算法计算出的梯度更新权重,以优化模型。
重复以上步骤:反复执行前向传播和反向传播,调整权重,直到损失函数收敛。
测试和评估模型:使用测试数据集对模型进行评估和测试。
使用模型进行预测:使用已训练的模型对新数据进行预测。
构建神经网络
import torch
import torch.nn as nn
from torch import optim
from torchvision import datasets, transforms
from torch.nn.functional import conv2d, cross_entropy
class SimpleCNN(nn.Module):
def __init__(self, in_channel=1):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(in_channel, 4, 5, 2, 0)
self.relu1 = nn.ReLU()
self.conv2 = nn.Conv2d(4, 8, 3, 2, 0)
self.relu2 = nn.ReLU()
self.linear = nn.Linear(200, 10)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.conv2(x)
x = self.relu2(x)
x = x.view(-1, 200)
x = self.linear(x)
return x
这个程序定义了一个简单的CNN模型 SimpleCNN
,用于进行图像分类任务。它包含以下几个部分:
torch
、nn
、optim
、datasets
、transforms
和 nn.functional
。SimpleCNN
的类,继承了 nn.Module
。__init__
函数中定义模型的结构。这个模型包含两层卷积层和一个全连接层:
in_channel
,输出通道数为 4,卷积核大小为 5x5,步长为 2,填充为 0。forward
函数中实现模型的前向传播过程。将输入 x
依次经过卷积层、ReLU激活函数、卷积层、ReLU激活函数和全连接层处理,最终输出分类结果。#测试
model = SimpleCNN()
data = torch.randn(3, 1, 28, 28)
output = model(data)
output.shape
torch.Size([3, 10])
卷积层计算
(28-5)/2+1=12
(12-3)/2+1=5
3×1×28×28
3×4×12×12
3×8×5×5
3×200
3×10
神经网络模型
model
SimpleCNN(
(conv1): Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
(relu1): ReLU()
(conv2): Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
(relu2): ReLU()
(linear): Linear(in_features=200, out_features=10, bias=True)
)
for key, value in model._modules.items():
print(key, value)
conv1 Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
relu1 ReLU()
conv2 Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
relu2 ReLU()
linear Linear(in_features=200, out_features=10, bias=True)
model = SimpleCNN()
model.parameters()
for p in model.parameters():
print(p.shape)
torch.Size([4, 1, 5, 5])
torch.Size([4])
torch.Size([8, 4, 3, 3])
torch.Size([8])
torch.Size([10, 200])
torch.Size([10])
导入数据集
train_batch_size = 100 #一共60000个数据,100个数据一组,一共600组(N=100)
test_batch_size = 100 #一共10000个数据,100个数据一组,一共100组(N=100)
# 训练集
train_loader = torch.utils.data.DataLoader(
datasets.MNIST(
'./data',train=True,download=True,
transform=transforms.Compose([
transforms.ToTensor(), #转为tensor
transforms.Normalize((0.5),(0.5)) #正则化
])
),
batch_size = train_batch_size, shuffle=True #打乱位置
)
# 测试集
test_loader = torch.utils.data.DataLoader(
datasets.MNIST(
'./data',train=False,download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5),(0.5))
])
),
batch_size = test_batch_size, shuffle=False
)
这段代码主要用于加载 MNIST 数据集,并生成对应的数据加载器 train_loader
和 test_loader
。具体包含以下几个步骤:
train_batch_size
,设为 100。test_batch_size
,也设为 100。torch.utils.data.DataLoader
函数生成训练集加载器 train_loader
,加载器将使用 datasets.MNIST
函数加载 MNIST 数据集,并进行以下操作:
./data
。transforms.Compose
序列变换操作,包括:
transforms.ToTensor()
:将数据转为 Tensor 类型。transforms.Normalize((0.5),(0.5))
:将数据进行正则化。train_batch_size
的批次,进行随机打乱。torch.utils.data.DataLoader
函数生成测试集加载器 test_loader
,加载器将使用 datasets.MNIST
函数加载 MNIST 数据集,并进行相同的处理流程,但测试集不需要随机打乱。这样生成的 train_loader
和 test_loader
可以用于对数据进行批量加载,方便后续的模型训练和评估。
训练测试
alpha = 0.1 #学习率
epochs = 100 #训练次数
interval = 100 #打印间隔
for epoch in range(epochs):
optimizer = optim.SGD(model.parameters(), lr=0.1)
for i, (data, label) in enumerate(train_loader):
output = model(data)
optimizer.zero_grad() #梯度归零
loss = cross_entropy(output, label) #交叉熵函数
loss.backward() #反向求导
optimizer.step() #更新参数
if i % interval == 0:
print("Epoch %03d [%03d/%03d]\tLoss:%.4f"%(epoch, i, len(train_loader), loss.item()))
correct_num = 0
total_num = 0
with torch.no_grad():
for data, label in test_loader:
output = model(data)
pred = output.max(1)[1]
correct_num += (pred == label).sum().item()
total_num += len(data)
acc = correct_num / total_num
print('...Testing @ Epoch %03d\tAcc:%.4f'%(epoch, acc))
Epoch 000 [000/600] Loss:2.2848
Epoch 000 [100/600] Loss:0.4144
Epoch 000 [200/600] Loss:0.2014
Epoch 000 [300/600] Loss:0.2790
Epoch 000 [400/600] Loss:0.1858
Epoch 000 [500/600] Loss:0.1649
...Testing @ Epoch 000 Acc:0.9538
Epoch 001 [000/600] Loss:0.1593
Epoch 001 [100/600] Loss:0.2436
Epoch 001 [200/600] Loss:0.0649
Epoch 001 [300/600] Loss:0.2830
Epoch 001 [400/600] Loss:0.1208
Epoch 001 [500/600] Loss:0.0937
...Testing @ Epoch 001 Acc:0.9678
Epoch 002 [000/600] Loss:0.1210
Epoch 002 [100/600] Loss:0.0737
Epoch 002 [200/600] Loss:0.0857
Epoch 002 [300/600] Loss:0.0712
Epoch 002 [400/600] Loss:0.2700
Epoch 002 [500/600] Loss:0.0849
...Testing @ Epoch 002 Acc:0.9708
Epoch 003 [000/600] Loss:0.1094
Epoch 003 [100/600] Loss:0.0727
Epoch 003 [200/600] Loss:0.1756
Epoch 003 [300/600] Loss:0.1473
Epoch 003 [400/600] Loss:0.1013
Epoch 003 [500/600] Loss:0.0879
...Testing @ Epoch 003 Acc:0.9741
Epoch 004 [000/600] Loss:0.1503
Epoch 004 [100/600] Loss:0.0832
Epoch 004 [200/600] Loss:0.0731
Epoch 004 [300/600] Loss:0.1040
Epoch 004 [400/600] Loss:0.0720
Epoch 004 [500/600] Loss:0.0490
...Testing @ Epoch 004 Acc:0.9745
Epoch 005 [000/600] Loss:0.0720
Epoch 005 [100/600] Loss:0.1124
Epoch 005 [200/600] Loss:0.0674
Epoch 005 [300/600] Loss:0.0477
Epoch 005 [400/600] Loss:0.1164
Epoch 005 [500/600] Loss:0.0662
...Testing @ Epoch 005 Acc:0.9758
Epoch 006 [000/600] Loss:0.0445
Epoch 006 [100/600] Loss:0.0500
Epoch 006 [200/600] Loss:0.0236
Epoch 006 [300/600] Loss:0.1068
Epoch 006 [400/600] Loss:0.0767
Epoch 006 [500/600] Loss:0.0549
...Testing @ Epoch 006 Acc:0.9800
Epoch 007 [000/600] Loss:0.0539
Epoch 007 [100/600] Loss:0.0319
Epoch 007 [200/600] Loss:0.1369
Epoch 007 [300/600] Loss:0.0301
Epoch 007 [400/600] Loss:0.0881
Epoch 007 [500/600] Loss:0.0642
...Testing @ Epoch 007 Acc:0.9792
Epoch 008 [000/600] Loss:0.0564
Epoch 008 [100/600] Loss:0.0845
Epoch 008 [200/600] Loss:0.1877
Epoch 008 [300/600] Loss:0.0963
Epoch 008 [400/600] Loss:0.0671
Epoch 008 [500/600] Loss:0.1053
...Testing @ Epoch 008 Acc:0.9757
Epoch 009 [000/600] Loss:0.0117
Epoch 009 [100/600] Loss:0.0201
Epoch 009 [200/600] Loss:0.1933
Epoch 009 [300/600] Loss:0.0726
Epoch 009 [400/600] Loss:0.0449
Epoch 009 [500/600] Loss:0.1415
...Testing @ Epoch 009 Acc:0.9807
Epoch 010 [000/600] Loss:0.0505
Epoch 010 [100/600] Loss:0.0410
Epoch 010 [200/600] Loss:0.0325
Epoch 010 [300/600] Loss:0.0403
Epoch 010 [400/600] Loss:0.0249
Epoch 010 [500/600] Loss:0.0682
...Testing @ Epoch 010 Acc:0.9805
Epoch 011 [000/600] Loss:0.0816
Epoch 011 [100/600] Loss:0.1179
Epoch 011 [200/600] Loss:0.1244
Epoch 011 [300/600] Loss:0.0465
Epoch 011 [400/600] Loss:0.1324
Epoch 011 [500/600] Loss:0.0763
...Testing @ Epoch 011 Acc:0.9799
……
这段代码实现了简单 CNN 模型的训练和测试,具体实现步骤如下:
alpha
,设为 0.1。epochs
,设为 100。interval
,设为 100。range
函数循环 epochs
次,进行模型训练和测试。optimizer
,使用随机梯度下降法(SGD)优化器,对模型参数进行更新。train_loader
中的数据,对数据进行前向传播,计算损失函数(交叉熵函数),通过反向传播求解梯度,并通过优化器对模型参数进行更新。interval
打印一次训练进度,输出当前训练的 epoch、批次、总批次数和当前损失函数值,以及测试集的准确率。torch.no_grad()
防止梯度更新,在测试集加载器 test_loader
中进行数据的前向传播,计算模型的预测值和真实值,计算模型的准确率并输出。这样就完成了模型的训练和测试,通过输出可以了解模型的训练进度和测试效果。
构建神经网络
Model = nn.Sequential(
nn.Conv2d(1, 4, 5, 2, 0),
nn.ReLU(),
nn.Conv2d(4, 8, 3, 2, 0),
nn.ReLU(),
nn.Flatten(),
nn.Linear(200, 10)
)
神经网络模型
Model
Sequential(
(0): Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
(1): ReLU()
(2): Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
(3): ReLU()
(4): Flatten(start_dim=1, end_dim=-1)
(5): Linear(in_features=200, out_features=10, bias=True)
)
#测试
data = torch.randn(3, 1, 28, 28)
output = Model(data)
output.shape
torch.Size([3, 10])
for p in Model.parameters():
print(p.shape)
torch.Size([4, 1, 5, 5])
torch.Size([4])
torch.Size([8, 4, 3, 3])
torch.Size([8])
torch.Size([10, 200])
torch.Size([10])
训练测试
alpha = 0.1 #学习率
epochs = 100 #训练次数
interval = 100 #打印间隔
for epoch in range(epochs):
optimizer = optim.SGD(Model.parameters(), lr=0.1)
for i, (data, label) in enumerate(train_loader):
output = Model(data)
optimizer.zero_grad() #梯度归零
loss = cross_entropy(output, label) #交叉熵函数
loss.backward() #反向求导
optimizer.step() #更新参数
if i % interval == 0:
print("Epoch %03d [%03d/%03d]\tLoss:%.4f"%(epoch, i, len(train_loader), loss.item()))
correct_num = 0
total_num = 0
with torch.no_grad():
for data, label in test_loader:
output = Model(data)
pred = output.max(1)[1]
correct_num += (pred == label).sum().item()
total_num += len(data)
acc = correct_num / total_num
print('...Testing @ Epoch %03d\tAcc:%.4f'%(epoch, acc))
Epoch 000 [000/600] Loss:2.3005
Epoch 000 [100/600] Loss:0.3855
Epoch 000 [200/600] Loss:0.2832
Epoch 000 [300/600] Loss:0.3216
Epoch 000 [400/600] Loss:0.2495
Epoch 000 [500/600] Loss:0.0687
...Testing @ Epoch 000 Acc:0.9554
Epoch 001 [000/600] Loss:0.1364
Epoch 001 [100/600] Loss:0.2104
Epoch 001 [200/600] Loss:0.1206
Epoch 001 [300/600] Loss:0.0859
Epoch 001 [400/600] Loss:0.1187
Epoch 001 [500/600] Loss:0.1903
...Testing @ Epoch 001 Acc:0.9668
Epoch 002 [000/600] Loss:0.1893
Epoch 002 [100/600] Loss:0.1033
Epoch 002 [200/600] Loss:0.1633
Epoch 002 [300/600] Loss:0.1038
Epoch 002 [400/600] Loss:0.1250
Epoch 002 [500/600] Loss:0.2345
...Testing @ Epoch 002 Acc:0.9725
Epoch 003 [000/600] Loss:0.0566
Epoch 003 [100/600] Loss:0.1781
Epoch 003 [200/600] Loss:0.0779
Epoch 003 [300/600] Loss:0.2852
Epoch 003 [400/600] Loss:0.0428
Epoch 003 [500/600] Loss:0.1369
...Testing @ Epoch 003 Acc:0.9714
Epoch 004 [000/600] Loss:0.1098
Epoch 004 [100/600] Loss:0.1288
Epoch 004 [200/600] Loss:0.1078
Epoch 004 [300/600] Loss:0.1325
Epoch 004 [400/600] Loss:0.0649
Epoch 004 [500/600] Loss:0.0683
...Testing @ Epoch 004 Acc:0.9739
Epoch 005 [000/600] Loss:0.0984
Epoch 005 [100/600] Loss:0.1322
Epoch 005 [200/600] Loss:0.0641
Epoch 005 [300/600] Loss:0.0769
Epoch 005 [400/600] Loss:0.1507
Epoch 005 [500/600] Loss:0.0377
...Testing @ Epoch 005 Acc:0.9742
Epoch 006 [000/600] Loss:0.0954
Epoch 006 [100/600] Loss:0.0889
Epoch 006 [200/600] Loss:0.0666
Epoch 006 [300/600] Loss:0.0448
Epoch 006 [400/600] Loss:0.0285
Epoch 006 [500/600] Loss:0.0581
...Testing @ Epoch 006 Acc:0.9773
Epoch 007 [000/600] Loss:0.0305
Epoch 007 [100/600] Loss:0.0651
Epoch 007 [200/600] Loss:0.1007
Epoch 007 [300/600] Loss:0.1537
Epoch 007 [400/600] Loss:0.0233
Epoch 007 [500/600] Loss:0.0925
...Testing @ Epoch 007 Acc:0.9750
Epoch 008 [000/600] Loss:0.1807
Epoch 008 [100/600] Loss:0.0373
Epoch 008 [200/600] Loss:0.0600
Epoch 008 [300/600] Loss:0.2233
Epoch 008 [400/600] Loss:0.0469
Epoch 008 [500/600] Loss:0.0817
...Testing @ Epoch 008 Acc:0.9795
Epoch 009 [000/600] Loss:0.1331
Epoch 009 [100/600] Loss:0.1417
Epoch 009 [200/600] Loss:0.0429
Epoch 009 [300/600] Loss:0.0552
Epoch 009 [400/600] Loss:0.0117
Epoch 009 [500/600] Loss:0.0611
...Testing @ Epoch 009 Acc:0.9780
Epoch 010 [000/600] Loss:0.0386
Epoch 010 [100/600] Loss:0.2372
Epoch 010 [200/600] Loss:0.0092
Epoch 010 [300/600] Loss:0.0623
Epoch 010 [400/600] Loss:0.0530
Epoch 010 [500/600] Loss:0.0345
...Testing @ Epoch 010 Acc:0.9797
Epoch 011 [000/600] Loss:0.1051
Epoch 011 [100/600] Loss:0.0507
Epoch 011 [200/600] Loss:0.1075
Epoch 011 [300/600] Loss:0.0414
Epoch 011 [400/600] Loss:0.0256
Epoch 011 [500/600] Loss:0.0631
...Testing @ Epoch 011 Acc:0.9778
Epoch 012 [000/600] Loss:0.0873
Epoch 012 [100/600] Loss:0.0693
Epoch 012 [200/600] Loss:0.0779
Epoch 012 [300/600] Loss:0.2842
Epoch 012 [400/600] Loss:0.0314
Epoch 012 [500/600] Loss:0.0197
...Testing @ Epoch 012 Acc:0.9778
……
见《PyTorch应用实战二:实现卷积神经网络进行图像分类》
序号 | 文章目录 | 直达链接 |
---|---|---|
1 | PyTorch应用实战一:实现卷积操作 | https://want595.blog.csdn.net/article/details/132575530 |
2 | PyTorch应用实战二:实现卷积神经网络进行图像分类 | https://want595.blog.csdn.net/article/details/132575702 |
3 | PyTorch应用实战三:构建神经网络 | https://want595.blog.csdn.net/article/details/132575758 |
4 | PyTorch应用实战四:基于PyTorch构建复杂应用 | https://want595.blog.csdn.net/article/details/132625270 |
5 | PyTorch应用实战五:实现二值化神经网络 | https://want595.blog.csdn.net/article/details/132625348 |
6 | PyTorch应用实战六:利用LSTM实现文本情感分类 | https://want595.blog.csdn.net/article/details/132625382 |