[整理]卷积神经网络用于图像分类

本文介绍了如何在小规模图像分类任务中使用卷积神经网络,包括预处理技术、模型构建(如ConvNet)、防止过拟合的方法(dropout和正则化),以及训练过程中的损失和精度监控。
摘要由CSDN通过智能技术生成

最近又温习了一遍卷积神经网络用作图像分类,声明:以下代码有AI辅助生成,用作整理复习用途。
当遇到图像分类任务时,如果训练集规模不大的时候,可以先考虑卷积神经网络效果是否足够,如果还不够再去考虑使用一些更复杂的网络。
如果遇到了训练集loss很低,而测试集或验证集效果较差,很大可能是因为过拟合了,可以通过dropout,添加正则项等方法改进。
如果训练集都没有收敛,可能是因为参数量过少等原因,可以提升模型的复杂度。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
import torch
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
import matplotlib.pyplot as plt
import os 
from PIL import Image
# 定义数据预处理
class UserDataset(Dataset):
    def __init__(self, root_dir, transform=None):
        self.root_dir = root_dir
        self.transform = transform
       # 获取所有类别名称
       # 从类别映射成编号
       # 存储图像路径和对应的标签
=      # 将图像路径和对应标签的索引存储为元组
       # 根据自己的数据集格式进行调整
    def __len__(self):
        return len(self.images)
    def __getitem__(self, idx):
        img_path, label = self.images[idx]
        #print(img_path)
        img = Image.open(img_path).convert('RGB')
        #print(img)
        if self.transform:
            img = self.transform(img)
        #print(img)
        return img, label

# 设置数据集根目录
root_dir = ''
val_dir = ''
test_dir = ''
# 定义转换
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.RandomHorizontalFlip(),  # 添加随机水平翻转
    transforms.RandomVerticalFlip(),  # 添加随机垂直翻转
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),  # 添加颜色抖动
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 创建自定义数据集
traindataset = UserDataset(root_dir, transform=transform)
valdataset=   UserDataset(val_dir, transform=transform)
train_loader = torch.utils.data.DataLoader(traindataset, batch_size=32, shuffle=True)
val_loader = torch.utils.data.DataLoader(valdataset, batch_size=32, shuffle=True)

num_classes=4 #自定义
# 定义CNN网络模型
class ConvNet(nn.Module):
    def __init__(self, dropout_rate=0.2):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(16)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(32)
        self.fc1 = nn.Linear(32 * 56 * 56, 64) #参数可调
        self.dropout = nn.Dropout(dropout_rate) #加入Dropout,缓解过拟合
        self.fc2 = nn.Linear(64, num_classes)
        # 使用kaiming初始化
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)
    def forward(self, x):
        x = self.pool(nn.functional.relu(self.bn1(self.conv1(x))))
        x = self.pool(nn.functional.relu(self.bn2(self.conv2(x))))
        x = x.view(-1, 32 * 56 * 56)
        x = nn.functional.relu(self.fc1(x)) # 32*56*56-》64 
        x = self.dropout(x)  # 应用Dropout
        x = self.fc2(x)       #64-》numclasses
        return x 
model = ConvNet()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

# 训练模型
epochs=[]
loss_list=[]
acc_list=[]
num_epochs = 100

for epoch in range(num_epochs):
    epochs.append(epoch+1)
    running_loss = 0.0
    print(epoch)
    for inputs, labels in train_loader:
        #print(inputs.shape)
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    model.eval()  # 评估
    correct = 0
    total = 0
    with torch.no_grad():  # 不需要计算梯度
        for images, labels in val_loader:
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    val_accuracy = 100 * correct / total
    print('Epoch [{}/{}], Loss: {:.4f}, Validation Accuracy: {:.2f}%'
          .format(epoch+1, num_epochs, running_loss/len(train_loader), val_accuracy))
    loss_list.append(running_loss/len(train_loader))
    acc_list.append(val_accuracy)
torch.save(model.state_dict(), 'model.pth')
plt.plot(epochs, loss_list, label='Loss', color='blue')
# 绘制准确率曲线
plt.plot(epochs, acc_list, label='Accuracy', color='red')

# 添加标题和标签
plt.title('Loss and Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Value')
plt.savefig('loss_accuracy_plot.png')



  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
卷积神经网络是一种用于图像分类深度学习模型。它通过多个卷积层和池化层来提取图像的特征,并通过全连接层进行分类卷积神经网络的发展历程可以追溯到LeNet-5模型,它是最早用于手写数字识别的卷积神经网络模型。随后,AlexNet模型在ImageNet图像分类竞赛中取得了巨大的成功,引领了卷积神经网络的发展潮流。之后,VGGNet、GoogLeNet和ResNet等模型相继提出,不断优化和改进了卷积神经网络的结构和性能。这些模型通过增加网络的深度、使用更小的卷积核和引入残差连接等方法,取得了更好的图像分类结果。 为了避免过拟合问题,卷积神经网络采用了一些方法。其中,数据增广是一种常用的方法,通过对训练图像进行一系列的变换和扩充,增加了训练数据的多样性。另外,Dropout是一种有效的正则化方法,它在训练过程中随机地将一部分神经元的输出置为0,从而减少了神经网络的复杂性,防止过拟合。 尽管深度神经网络在理论上有更好的性能,但实际上,随着网络的加深,训练集准确率可能会下降。这是因为网络的深度增加会导致梯度消失或梯度爆炸的问题,使得网络难以训练。因此,并不是网络越深越好,需要在网络的深度和性能之间进行权衡和调整。 总结来说,卷积神经网络是一种用于图像分类深度学习模型,它通过多个卷积层和池化层提取图像特征,并通过全连接层进行分类。在发展过程中,不断优化和改进的卷积神经网络模型取得了显著的性能提升。为了避免过拟合问题,卷积神经网络采用了数据增广和Dropout等方法。同时,需要权衡网络的深度和性能,以克服梯度消失或梯度爆炸的问题。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* *3* [用于图像分类的经典的卷积神经网络CNN](https://blog.csdn.net/ch18328071580/article/details/94960064)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值