文章目录
前言
本文介绍深度学习卷积神经网络(CNN)模型及其应用实战。本文主要介绍算法的应用–利用深度学习卷积神经网络构建猫狗识别模型。
一、构建数据集类
构建用于处理猫狗分类数据集的PyTorch数据集类。
1.导入模块
导入所需的Python模块和库,包括PyTorch的数据处理模块、操作系统路径处理模块、PIL库用于图像处理、以及PyTorch中的数据转换模块。
代码如下(示例):
import torch.utils.data
import os
import torch
import torch.utils.data as data
from PIL import Image
import torchvision.transforms as Trans
2.设置图片尺寸和转换
img_size 设置了图片的尺寸,tran 定义了图片转换的操作序列,包括调整大小、中心裁剪和转换为张量。
代码如下(示例):
img_size = 200
tran = Trans.Compose([
Trans.Resize(img_size),
Trans.CenterCrop([img_size, img_size]),
Trans.ToTensor()
])
3.设数据集类 DogsVSCatsDataset:
init 方法:根据传入的 mode 和 dir 参数初始化数据集。如果是训练模式 (‘train’),则加载训练集数据;如果是测试模式 (‘test’),则加载测试集数据。每个模式下都会读取相应文件夹中的图像文件,并根据文件名判断是猫还是狗,将其存入 img_list 和 img_label 中。
getitem 方法:根据索引 item 返回数据集中的一个样本。在训练模式下,返回经过预定义转换 (tran) 处理后的图像及其对应的标签;在测试模式下,仅返回经过转换处理后的图像。
len 方法:返回整个数据集的大小,即样本数量。
代码如下(示例):
class DogsVSCatsDataset(data.Dataset):
def __init__(self, mode, dir):
# 初始化函数,定义了数据集的大小、图像列表、标签列表、转换方式和模式
def __getitem__(self, item):
# 获取数据函数,根据模式返回图像及其标签(训练模式)或仅返回图像(测试模式)
def __len__(self):
# 返回数据集大小
])
4.数据处理细节:
训练模式中,图像文件命名规则为 cat.* 或 dog.*,通过文件名切分来确定标签,cat 对应标签 1,dog 对应标签 0。
测试模式中,没有有意义的标签,因此用 2 来占位。
5.异常处理:
如果传入的 mode 不是 ‘train’ 或 ‘test’,则会打印 “没有这个mode” 提示信息。
全部代码如下:
import torch.utils.data
import os #文件操作模块
import torch
import torch.utils.data as data #用于继承一个父类(data.Dataset)里的函数
from PIL import Image
import torchvision.transforms as Trans #在定义图片转换的格式时,会用到相关的函数
img_size = 200 #设置图片尺寸
tran = Trans.Compose([Trans.Resize(img_size), Trans.CenterCrop([img_size, img_size]), Trans.ToTensor()]) #封装, 对后面读取的图片的格式转换
class DogsVSCatsDataset(data.Dataset):
def __init__(self, mode, dir):
self.data_size = 0 #数据集的大小
self.img_list=[] #用于存图
self.img_label =[]#标签
self.trans=tran #转换的属性设置
self.mode =mode #下面打开集的模式
if self.mode =='train':
dir += '/train/' #更新地址
for file in os.listdir(dir): #遍历
self.img_list.append(dir+file) #存图
self.data_size += 1
name = file.split(sep='.') #将 该文件名拆分,便于判断是cat还是dog
label_x =0
if name[0] =='cat':
label_x =1
self.img_label.append(label_x)#设置入相对于的标签;cat:1; dog:0
elif self.mode == 'test':
dir +='/test/'
for file in os.listdir(dir):#同理
self.img_list.append(dir+file)
self.data_size +=1
self.img_label.append(2)#无意义的标签
else:
print("没有这个mode")
def __getitem__(self,item): #获取数据
if self.mode =='train':
img =Image.open(self.img_list[item])
label_y = self.img_label[item]
return self.trans(img), torch.LongTensor([label_y]) #返回该图片的地址和标签
elif self.mode=='test':
img =Image.open(self.img_list[item])
return self.trans(img)
else:
print("None")
def __len__(self):
return self.data_size
二、定义构建卷积神经网络模型
定义了一个简单的卷积神经网络模型(Net),用于猫狗分类任务。
1.导入模块
导入了PyTorch所需的模块,包括张量操作、神经网络函数、神经网络模块以及数据处理模块。
代码如下(示例):
import torch
import torch.nn.functional as F
import torch.nn as nn
import torch.utils.data as data
2.定义神经网络模型 Net
代码如下(示例):
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(3, 16, 3, padding=1)
self.conv2 = torch.nn.Conv2d(16, 16, 3, padding=1)
self.fc1 = torch.nn.Linear(50*50*16, 128)
self.fc2 = torch.nn.Linear(128, 64)
self.fc3 = torch.nn.Linear(64, 2)
def forward(self, x):
# 定义前向传播过程
def forward(self, x):
x = self.conv1(x) # 第一层卷积
x = F.relu(x) # 激活函数 ReLU
x = F.max_pool2d(x, 2) # 池化层,大小为2x2的最大池化
x = self.conv2(x) # 第二层卷积
x = F.relu(x) # 激活函数 ReLU
x = F.max_pool2d(x, 2) # 池化层,大小为2x2的最大池化
x = x.view(x.size(0), -1) # 将特征图展平成一维向量
x = F.relu(self.fc1(x)) # 第一个全连接层,并使用ReLU激活函数
x = F.relu(self.fc2(x)) # 第二个全连接层,并使用ReLU激活函数
x = self.fc3(x) # 第三个全连接层,输出未经过激活函数
return F.softmax(x, dim=1) # 使用softmax函数进行分类,dim=1表示按行计算softmax
这个模型通过卷积层提取图像特征,通过池化层降低特征图的维度,然后通过全连接层进行分类。
使用ReLU作为激活函数,softmax函数作为最后的分类激活函数,输出每个类别的概率分布。
三、训练模型
构建简单的训练脚本,用于训练猫狗分类任务的神经网络模型
1.导入模块和类
代码如下(示例):
from getdata import DogsVSCatsDataset as DVCD
from torch.utils.data import DataLoader as DataLoader
from network import Net
import torch
from torch.autograd import Variable
import torch.nn as nn
- from getdata import DogsVSCatsDataset as DVCD:导入了数据集类
- DogsVSCatsDataset,该类用于加载和处理猫狗分类数据集。
- from torch.utils.data import DataLoader as DataLoader:导入了数据加载器类DataLoader,用于批量加载数据。
- from network import Net:导入了神经网络模型类 Net,该类在 network.py 文件中定义。
- 其他导入的模块包括PyTorch核心模块、自动求导模块、神经网络模块等。
2.设置路径和参数:
代码如下(示例):
dataset_dir = 'C:/Users/86131/PycharmProjects/pythonProject/newnew/data/train' # 数据集路径
model_dir = './model/' # 网络参数保存位置
workers = 10 # 线程数量
batch_size = 16 # 一次训练所选取的样本数
lr = 0.001 # 学习率
nepoch = 1 # 训练的次数
数据集信息如下:
3.定义训练函数 train()
代码如下(示例):
def train():
datafile = DVCD('train', dataset_dir) # 实例化数据集对象
dataloader = DataLoader(datafile, batch_size=batch_size, shuffle=True, num_workers=workers, drop_last=True) # 创建数据加载器
print('Dataset loaded! length of train set is {0}'.format(len(datafile)))
model = Net() # 实例化一个网络
model = nn.DataParallel(model) # 多GPU并行化
model.train() # 将模型设置为训练模式
optimizer = torch.optim.Adam(model.parameters(), lr=lr) # Adam优化器
Lossfuc = torch.nn.CrossEntropyLoss() # 交叉熵损失函数
cnt = 0 # 记录训练图片数量
for epoch in range(nepoch): # 遍历每个epoch
for img, label in dataloader: # 遍历每个batch
img, label = Variable(img), Variable(label) # 将数据转为PyTorch的Variable类型
out = model(img) # 前向传播,计算输出
loss = Lossfuc(out, label.squeeze()) # 计算损失
loss.backward() # 反向传播,计算梯度
optimizer.step() # 更新网络参数
optimizer.zero_grad() # 梯度清零
cnt += 1
print('Epoch:{0}, Frame:{1}, train_loss {2}'.format(epoch, cnt*batch_size, loss/batch_size))
torch.save(model.state_dict(), '{0}/model.pth'.format(model_dir)) # 保存训练好的模型参数
四、应用模型
用于加载训练好的模型,并使用该模型对测试集中的随机一张图片进行分类和可视化展示
1.导入模块和类
代码如下(示例):
from getdata import DogsVSCatsDataset as DVCD
from network import Net
from torch.autograd import Variable
import numpy as np
import torch.nn.functional as F
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
import os
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" # 防止打印图片出错
2.设置环境变量
设置环境变量,防止在某些系统上使用matplotlib时出现问题。
代码如下(示例):
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" # 防止打印图片出错
3.定义路径和常量
代码如下(示例):
data_dir = '.../newnew/data/test' # 测试集路径
model_file = './model/model.pth' # 模型文件路径
N = 10 # 随机选择测试图片的数量
测试集如下:
4.加载模型
代码如下(示例):
model = Net() # 实例化一个网络模型
model = nn.DataParallel(model) # 多GPU并行化
model.load_state_dict(torch.load(model_file)) # 加载模型参数
model.eval() # 将模型设置为评估模式
datafile = DVCD('test', data_dir) # 实例化测试数据集对象
5.随机测试
代码如下(示例):
index = np.random.randint(0, datafile.data_size, 1)[0] # 随机选择一个索引
img = datafile.__getitem__(index) # 获取对应索引的图片及其标签
6.处理测试图片并进行预测
代码如下(示例):
img = img.unsqueeze(0) # 在第0维增加一个维度,变成(batch_size, channels, height, width)
img = Variable(img) # 将数据转为PyTorch的Variable类型
out = model(img) # 输入模型,进行前向传播,得到输出
out = F.softmax(out, dim=1) # 对输出进行softmax处理,得到分类概率
7.输出预测结果
代码如下(示例):
print(out.data)
if out[0, 0] > out[0, 1]:
print("the picture is a cat")
else:
print("the picture is a dog")
8.可视化展示测试图片
代码如下(示例):
img = Image.open(datafile.img_list[index]) # 打开对应索引的原始图像
plt.figure('image') # 创建一个新的图像窗口
plt.imshow(img) # 显示图片
plt.show() # 显示图像窗口
运行结果
总结
代码展示了一个简单的卷积神经网络结构,包括卷积层、池化层和全连接层,并使用PyTorch进行训练和预测。这些组件和操作是构建深度学习图像分类模型的基础,通过逐步调整网络结构和超参数,可以优化模型性能和准确率。