使用python构建卷积神经网络实现猫狗的分类问题
需求:使用卷积神经网络实现猫狗的二分类问题。
使用的语言:python
使用的工具:pytorch、pyCharm
数据集:链接:https://pan.baidu.com/s/1zfPFfmAjQ6ERJSQ4zEQHbw
提取码:vkk5
1、导入数据集
# 导入包
import os # 用于当前文件
# 用于构建神经网络
import torch
from torch import nn, optim
from torch.nn import functional as F
from torch.utils import data
from torchvision import datasets
from torchvision import transforms
ImageSize = 224 # 定义图片大小
train_dir = './train/' # 定义训练集存储路径
test_dir = './test/' # 定义测试集存储路径
# 定义数据集预处理方法
data_transform = transforms.Compose([
transforms.Resize((ImageSize, ImageSize)), # 重新调整图片大小
transforms.ToTensor(), # 将图片转换为Tensor数组
transforms.Normalize((0.1307,), (0.3081,)) # 归一化操作
])
# datasets.ImageFolder(dir, transform):导入数据集
# dir:数据集存储路径
# transform:数据集预处理方法
datasets_train = datasets.ImageFolder(train_dir, data_transform)
datasets_test = datasets.ImageFolder(test_dir, data_transform)
# data.DataLoader(datasets, batch_size, shuffle=True, num_workers=0):加载数据集
# datasers:导入的数据集
# batch_size:每次调用的图片数量
train_loader = data.DataLoader(datasets_train, batch_size=10, shuffle=True, num_workers=0)
test_loader = data.DataLoader(datasets_test, batch_size=5, shuffle=True, num_workers=0)
2、构建卷积神经网络
# 构建CNN神经网络
class CNN(nn.Module):
# 构造方法,用于创建卷积神经网络需要使用到的模块
def __init__(self):
super(CNN, self).__init__() # 继承父类的构造方法
self.c1 = nn.Conv2d(3, 16, (3, 3)) # 定义第一个卷积层,输入3个节点输出16个节点,3*3的卷积
self.c2 = nn.Conv2d(16, 32, (3, 3)) # 定义第二个卷积层,输入16个节点,输出32个节点,3*3的卷积
self.c3 = nn.Conv2d(32, 64, (3, 3)) # 定义第三个卷积层,输入32个节点,输出64个节点,3*3的卷积
self.b1 = nn.BatchNorm2d(16, affine=False) # 定义第一个归一化层
self.b2 = nn.BatchNorm2d(32, affine=False) # 定义第二个归一化层
self.b3 = nn.BatchNorm2d(64, affine=False) # 定义第三个归一化层
self.fc1 = nn.Linear(331776, 32) # 定义第一个全连接层
self.fc2 = nn.Linear(32, 2) # 定义第二个全连接层
# 构建计算数据集中一张图片数据数量的函数
def num_flat_features(self, x):
"""
计算数据集中数据数量的函数
:param x: 输入数据集
:return:
num_features:数据集中数据数量
"""
size = x.size()[1:] # 获取一个图片数据的大小
num_features = 1 # 初始化数量
for s in size:
num_features *= s
return num_features
# 构建前向传播函数
def forward(self, x):
"""
构建前向传播函数
:param x: 需要计算的数据
:return:
y_hat: 预测值
"""
p1 = F.relu(self.c1(x)) # 第一个卷积层的运算,先卷积,然后激活
b1 = self.b1(p1) # 第一个归一化层运算
p2 = F.relu(self.c2(b1)) # 第二个卷积层的运算,先卷积,然后激活
b2 = self.b2(p2) # 第二个归一化层运算
p3 = F.relu(self.c3(b2)) # 第三个卷积层的运算,先卷积,然后激活
b3 = self.b3(p3) # 第三个归一化层运算
m1 = F.max_pool2d(b3, 3, stride=3) # 最大池化层,(3, 3)的卷积核,步长为3
v1 = m1.view(-1, self.num_flat_features(m1)) # 将二维向量变为一维向量
h1 = self.fc1(v1) # 第一个全连接层
y_hat = torch.sigmoid(self.fc2(h1)) # 第二个全连接层的计算
# 返回预测值
return y_hat
3、构建训练模型
# 构建训练模型
def trainModul(loader, module, criterion, optimizer, epochs=1):
"""
构建训练模型
:param loader: 数据集
:param module: 训练模型
:param criterion: 损失函数
:param optimizer: 优化函数
:param epochs: 迭代轮数
:return:
model:训练后的模型
"""
correct = 0 # 存储正确标签数
total = 0 # 存储标签总数
# 使用for循环进行迭代
for epoch in range(epochs):
for i, data in enumerate(loader): # 使用for循环读取数据
x, y = data # x:数据, y:真实值
y_hat = module(x) # 前向传播,计算预测值
loss = criterion(y_hat, y) # 计算损失值
optimizer.zero_grad() # 清空导数
loss.backward() # 后向传播
optimizer.step() # 优化参数
predicted = torch.max(y_hat.data, 1) # 选择最大概率的数输出
total += y.size(0) # 计算总数
correct += (predicted.indices == y).sum() # 累加正确标签数
if i % 10 == 9: # 每迭代10次,输出一次损失值和准确率
print('[Epoch:%d, Batch:%5d] Loss:%.3f' % (epoch + 1, i + 1, loss)) # 输出损失值
print(correct) # 输出正确标签数
print(total) # 输出标签总数
print('ACCuracy on the test set: %0.3f %%' % (100 * correct / total)) # 输出准确率
print('ACCuracy on the test set: %0.3f %%' % (100 * correct / total)) # 输出准确率
print('Finished Training')
return module # 返回训练好的模型
4、测试训练后的模型准确率的函数
# 构建测试函数
def test(loader, model):
"""
测试函数
:param loader: 测试数据集
:param model: 模型
:return:
"""
correct = 0 # 存储正确标签数
total = 0 # 存储标签总数
for data in loader:
x, y = data # 获取数据及数据标签
y_hat = model(x) # 获取预测概率
predicted = torch.max(y_hat.data, 1) # 选择最大概率的数输出
total += y.size(0) # 计算总数
correct += (predicted.indices == y).sum() # 累加正确标签数
print('ACCuracy on the test set: %0.3f %%'%(100 * correct/total)) # 输出准确率
5、训练模型
cnn = CNN() # 构建神经网络
criterion = nn.CrossEntropyLoss() # 定义损失函数
optimizer = optim.SGD(cnn.parameters(), lr=0.0001, momentum=0.9) # 定义优化函数
# 调用训练模型
mpdule = trainModul(train_loader, cnn, criterion, optimizer, epochs=3)
# 测试训练后的模型
test(test_loader, cnn)
6、训练结果
[Epoch:3, Batch: 1800] Loss:0.578
tensor(40453)
54000
ACCuracy on the test set: 74.913 %
ACCuracy on the test set: 74.913 %
Finished Training
ACCuracy on the test set: 73.450 %