使用python构建卷积神经网络实现猫狗的分类问题

使用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 %
    原文作者:wopoli
    原文地址: https://blog.csdn.net/wopoli/article/details/120085491
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞