- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
📌第P2周:彩色图片识别📌
🍺 要求:
- 学习如何编写一个完整的深度学习程序
- 手动推导卷积层与池化层的计算过程
🔔本次的重点在于学会构建CNN网络
我的环境:
1.代码:
一、 前期准备
- 设置GPU
如果设备上支持GPU就使用GPU,否则使用CPU
2. 导入数据
使用dataset下载CIFAR10数据集,并划分好训练集与测试集
使用dataloader加载数据,并设置好基本的batch_size
3. 数据可视化
squeeze()函数的功能是从矩阵shape中,去掉维度为1的。例如一个矩阵是的shape是(5, 1),使用过这个函数后,结果为(5, )。
二、构建简单的CNN网络
对于一般的CNN网络来说,都是由特征提取网络和分类网络构成,其中特征提取网络用于提取图片的特征,分类网络用于将图片进行分类。
三、 训练模型
- 设置超参数
- 编写训练函数
3. 编写测试函数
四、 结果可视化
五总结
1.在编写训练和测试的函数那里有两段是自己尝试在去编写,可能会有点乱,不过可以很好的和原代码作为比较,发现自己哪里有问题。
3.对卷积计算的过程有了清晰的了解。N=(W-F+2P)/S+1
2.自己在pycharm上动手写了一下,与源代码不同的是,并没有编写一个训练和测试的函数,而是自己将它作为一部分,放入了epoch循环里面了。附源码。另外还有如何替换自己的数据集源码。
@Time:2024/4/1016:10
#1.设置gpu
import torch
import matplotlib.pyplot as plt
device = torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’)
print(device)
#2.导入数据
import torchvision
train_ds = torchvision.datasets.CIFAR10(‘./data’,train=True,transform=torchvision.transforms.ToTensor(),download=False)
test_ds = torchvision.datasets.CIFAR10(‘./data’,train=False,transform=torchvision.transforms.ToTensor(),download=False)#这个train = False
“”"
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
import torch
import os
数据集根目录
dataset_root = ‘./your_dataset_root’
数据预处理
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
加载数据集
train_dataset = ImageFolder(root=os.path.join(dataset_root, ‘train’), transform=transform)
test_dataset = ImageFolder(root=os.path.join(dataset_root, ‘test’), transform=transform)
“”"
batch_size = 32
train_dl = torch.utils.data.DataLoader(train_ds,batch_size=batch_size,shuffle=True)
test_dl = torch.utils.data.DataLoader(test_ds,batch_size)
imgs,labels = next(iter(train_dl))
print(labels.shape)
import torch.nn.functional as F
import torch.nn as nn
num_classes = 10 # 图片的类别数
class Model(nn.Module):
def init(self):
super().init()
# 特征提取网络
self.conv1 = nn.Conv2d(3, 64, kernel_size=3) # 第一层卷积,卷积核大小为33
self.pool1 = nn.MaxPool2d(kernel_size=2) # 设置池化层,池化核大小为22
self.conv2 = nn.Conv2d(64, 64, kernel_size=3) # 第二层卷积,卷积核大小为33
self.pool2 = nn.MaxPool2d(kernel_size=2)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3) # 第二层卷积,卷积核大小为33
self.pool3 = nn.MaxPool2d(kernel_size=2)
# 分类网络
self.fc1 = nn.Linear(512, 256)
self.fc2 = nn.Linear(256, num_classes)
# 前向传播
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = self.pool3(F.relu(self.conv3(x)))
x = torch.flatten(x, start_dim=1)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
model = Model().to(device)
loss_fn = nn.CrossEntropyLoss()
learn_rate = 1e-2
opt = torch.optim.SGD(model.parameters(),lr=learn_rate)
#编写训练损失函数
def train(dataloader,model,loss_fn,optimizer):
size = len(dataloader.dataset)
num_batches = len(dataloader)
train_loss,train_acc =0,0
for X,y in dataloader:
X,y =X.to(device),y.to(device)
pred = model(X)
loss = loss_fn(pred,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_acc +=(pred.argmax(1)==y).type(torch.float).sum().item()
train_loss +=loss.item()
train_acc /= size
train_loss /= num_batches
return train_acc,train_loss
def test(dataloader, model, loss_fn):
size = len(dataloader.dataset) # 测试集的大小,一共10000张图片
num_batches = len(dataloader) # 批次数目,313(10000/32=312.5,向上取整)
test_loss, test_acc = 0, 0
# 当不进行训练时,停止梯度更新,节省计算内存消耗
with torch.no_grad():
for imgs, target in dataloader:
imgs, target = imgs.to(device), target.to(device)
# 计算loss
target_pred = model(imgs)
loss = loss_fn(target_pred, target)
test_loss += loss.item()
test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()
test_acc /= size
test_loss /= num_batches
return test_acc, test_loss
epochs = 3
train_acc=[]
train_loss = []
test_acc= []
test_loss = []
best_accuracy = 0.0 # 初始化最佳准确率为0
for epoch in range(epochs):
model.train()
epoch_train_acc,epoch_train_loss = train(train_dl,model,loss_fn,opt)
model.eval()
epoch_test_acc,epoch_test_loss =test(test_dl,model,loss_fn)
train_acc.append(epoch_train_acc)
train_loss.append(epoch_train_loss)
test_acc.append(epoch_test_acc)
test_loss.append(epoch_test_loss)
template = (‘Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}’)
print(template.format(epoch + 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))
if epoch_test_acc > best_accuracy:
best_accuracy = epoch_test_acc
torch.save(model.state_dict(), ‘best_model.pth’) # 保存当前最佳模型权重
print(‘Best model weights saved successfully.’)
print(‘Done’)
保存模型权重
torch.save(model.state_dict(), ‘model.pth’)
print(‘Model weights saved successfully.’)
for epoch in range(epochs):
train_acc1 =0
train_loss1 =0
for X,y in train_dl:
X,y = X.to(device),y.to(device)
pred = model(X)
loss = loss_fn(pred,y)
opt.zero_grad()
loss.backward()
opt.step()
train_acc1 +=(pred.argmax(1)==y).type(torch.float).sum().item()
train_loss1 += loss.item()
train_acc1 /=len(train_dl.dataset)
train_loss1 /= len(train_dl)
train_acc.append(train_acc1)
train_loss.append(train_loss1)
print(f'Epoch:{epoch+1},Train_acc:{train_acc},Tran_loss:{train_loss}')