LeNet:第一个卷积神经网络

LeNet官网Demo示例

比较基础,不多赘述~~

模型构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class LeNet(nn.Module):
def __init__(self):
super(LeNet,self).__init__()
# 输入特征层的channel(in_channels)与卷积核的channel相同:就是说卷积核中有几个矩阵与输入特征的channel数量保持一致
# 输出的特征矩阵channel(out_channels)与卷积核个数相同
self.conv1 = nn.Conv2d(in_channels=3,out_channels=16,kernel_size=5)
self.pool1 = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(in_channels=16,out_channels=32,kernel_size=5)
self.pool2 = nn.MaxPool2d(2,2)
# 经卷积后的矩阵尺寸大小:N = (W - F + 2 * P) / S + 1
# 输入图片大小: W * W
# FilterSize大小为 F * F
# 步长为 S
# padding 的像素数为 P
self.fc1 = nn.Linear(32 * 5 * 5,120)
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)

def forward(self,x):
x = F.relu(self.conv1(x))
x = self.pool1(x)
x = F.relu(self.conv2(x))
x = self.pool2(x)
x = x.view(-1,32 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

模型训练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# ********************************************************************************************************************
# Created: 2024/07/24
# Filename: train.py
# Author: ___ ___ ___ ___ ___ ___ _ ___
# / __| / _ \ | \ | __| | _ \ | __| _ | | / _ \
# | (__ | (_) | | |) | | _| | / | _| | || || (_) |
# \___| \___/ |___/ |___| |_|_\ _|_|_ _\__/ \__\_\
# _|"""""|_|"""""|_|"""""|_|"""""|_|"""""|_| """ |_|"""""|_|"""""|
# "`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
# Email: 72110902110jq@gmail.com
# Group: GUET
# Create By: coderfjq
# Purpose:
# Copyright: GUET-406 - All Rights Reserved
# LastModify: 2024/07/24
# ********************************************************************************************************************
# This code sucks, you know it and I know it.
# Move on and call me an idiot later.

from torchvision import transforms
import torchvision
import torchvision.transforms as transforms
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
import numpy as np

from 深度学习基础学习.day04.LeNet_model import LeNet

transform = transforms.Compose([
transforms.ToTensor(),
# transforms:包含图像变换方法,例如归一化、调整尺寸等。这里我们将图像归一化到均值为 0.5,标准差为 0.5。
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

# 加载CIFAR-10训练和测试数据集
# trainloader和testloader:用于批量加载 CIFAR-10 数据集,提高效率
trainset = torchvision.datasets.CIFAR10(
root="./data",
train=True,
download=False,
transform=transform
)

testset = torchvision.datasets.CIFAR10(
root="./data",
train=False,
download=False,
transform=transform
)

trainloader = torch.utils.data.DataLoader(
trainset,
batch_size=36,
shuffle=True,
num_workers=0
)


testloader = torch.utils.data.DataLoader(
testset,
batch_size=10000,
shuffle=False,
num_workers=0
)

# 将 testloader 转化成可迭代的迭代器
test_data_iter = iter(testloader)
test_images,test_label = next(test_data_iter)

# CIFAR-10的类名
classes = ('飞机', '汽车', '鸟', '猫', '鹿',
'狗', '青蛙', '马', '船', '卡车')

# def imshow(img):
# img = img / 2 +0.5
# npimg = img.numpy()
# plt.imshow(np.transpose(npimg,(1,2,0)))
# plt.show()
#
# # print labels
# print(''.join('%5s' % classes[test_label[j]] for j in range(4)))
# # show images
# imshow(torchvision.utils.make_grid(test_images))

net = LeNet()

loss_func = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(),lr = 0.001)

epochs = 5

for epoch in range(1,epochs+1):

running_loss = 0

for step,data in enumerate(trainloader,start = 0):

inputs, labels = data

# 梯度清零(可以看作初始化)
optimizer.zero_grad()

# 前向传播
output = net(inputs)
loss = loss_func(output,labels)

# 反向传播
loss.backward()

#
optimizer.step()

running_loss += loss.item()
if step % 500 == 499 :
with torch.no_grad():
output1 = net(test_images) # output1 = [batch,10]
predict_y = torch.max(output1,dim = 1)[1] # [1]中的1表示这是它的标签类别,就是index,[0]表示它确切的预测概率值
# (predict_y == test_label).sum()是一个tensor
accurancy = (predict_y == test_label).sum().item() / test_label.size(0)

print('[%d, %5d] train_loss: %.3f test_accuracy: %.3f'%(epoch,step + 1,running_loss /500,accurancy))
running_loss = 0

print("训练结束")

save_path = './LeNet.pth'
torch.save(net.state_dict(),save_path)

注意: * 图片输入时的格式为:[H,W,C],通过transforms.ToTensor()方法将其转变为[C,H,W] * 该数据集为彩色图片,最后一层之所以没有调用softmax函数是因为在训练过程中调用损失函数nn.CrossEntropyLoss()时,内部已经实现了softmax的效果,比直接调用效果更好 * 卷积层需要注意两点:1.卷积核的channel与输入特征层的channel相同 ,见下图,就是说输入特征矩阵彩色图片in_channel=3,则一个卷积核也有三个特征矩阵2.输出的特征矩阵channel.与卷积核个数相同,见下图,就是说卷积核个数有两个,生成的输出特征矩阵也有两个 pkbd236.png 代码详解


LeNet:第一个卷积神经网络
https://fu-jingqi.github.io/2024/07/25/LeNet:第一个卷积神经网络/
作者
coderfjq
发布于
2024年7月25日
许可协议