[机器学习] 基于torch的CNN图像分类

一、数据处理

1.1 数据格式说明

数据集分为10类,每一类下有10000张手绘图像数据(28*28大小),每类数据存放在一个.npy文件中。

.npy文件是NumPy库中用于存储多维数组数据的文件格式。NumPy是Python中用于科学计算的强大库,提供了高效的数组操作和数值计算功能。

它以二进制格式保存,可以保存多维数组数据,包括整数、浮点数和其他数据类型。.npy文件保存了数组的维度、数据类型和实际的数组数据。可以使用numpy.save()函数将数组保存为.npy文件,使用numpy.load()函数从.npy文件加载数组数据。

# 查看数据
path = "data/cat/cat.npy"
data_all = np.load(path)	# 所有数据
data = data_all[i, :] 		# i为第几个数据
data = data.reshape(28, 28)	# 将数据转为(28,28)维度
img = Image.fromarray(data) # 转为图片
img.show()

image-20230528195355988

1.2 Dataset类

在PyTorch中,Dataset类是一个抽象类,用于表示数据集的抽象接口。它提供了一种统一的方式来访问和操作数据,可以用于训练、验证和测试深度学习模型。通过继承它可以创建自定义的数据集类。自定义的数据集类需要实现两个主要的方法:__len__()__getitem__()

  • __len__()方法返回数据集的长度,即数据集中样本的数量。
  • __getitem__()方法根据给定的索引返回对应索引的数据样本。它通常会在该方法中读取数据、进行预处理和返回数据样本及其对应的标签等信息。
# 数据读取,继承dataset类
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import torch
from torch.utils.data import Dataset, ConcatDataset
from torchvision import transforms

# label为0-10,分别代表了下列标签:
label_names=['ambulance','apple','bear','bicycle','bird','bus','cat','foot','owl','pig']
# 数据转换器
data_transforms = transforms.Compose([
    transforms.ToTensor(),
    # 单通道归一化                          
    transforms.Normalize((0.5,),(0.5,))])

# dataset类,方便datasetloader读取并输入网络中
class MyDataset(Dataset):
    def __init__(self, label_index, transform = data_transforms):
        path = "data/quick_draw_data/"+label_names[label_index]+"/"+label_names[label_index]+".npy" 
        self.data = np.load(path)
        self.labels = [label_index]*len(self.data)
        self.transform = transform
        
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, idx):
        data = self.data[idx]
        image = Image.fromarray(data.reshape(28,28))  #将数据转为(28,28)维度
        image = self.transform(image)
        label = self.labels[idx]
        return image, label

# 批量读取数据并整合为一个数据集
datasets = [MyDataset(label_index) for label_index in range(10)]
combined_dataset = ConcatDataset(datasets)  # 整的数据集

由于我有10个.npy文件,故需要将数据集进行整合,如何划分为训练集、验证集和测试集:

# 数据划分,得到train_set, val_set, test_set
from torch.utils.data import random_split

lengths = [int(len(combined_dataset)*0.6), int(len(combined_dataset)*0.3), int(len(combined_dataset)*0.1)]
train_set, val_set, test_set = random_split(combined_dataset, lengths)

1.3 DataLoader

torch.utils.data.DataLoader是PyTorch中的一个数据加载器,用于批量加载数据并提供数据的迭代器。它是在训练深度学习模型时用于数据输入的常用工具之一。

DataLoader接受一个Dataset对象作为输入,并根据指定的批次大小batch_size、是否随机打乱数据shuffle等参数,将数据划分为小批量进行加载。每个小批量数据可以被用于模型的训练、验证或测试。

二、网络构建

2.1 网络结构:

# 构建CNN作为10-分类模型
from torch import nn
from torch.nn import Sequential, Conv2d, ReLU, MaxPool2d, Linear

class Net(nn.Module):
    def __init__(self,num_classes=10):
        super(Net, self).__init__()
        self.conv1 = Sequential(
            Conv2d(1, 10, kernel_size=5),
            MaxPool2d(2),
            ReLU()
        )
        self.conv2 = Sequential(
            Conv2d(10, 20, kernel_size=5),
            MaxPool2d(2),
            ReLU()
        )
        
        self.fc = Linear(320, num_classes)     
    
    # 前向过程
    def forward(self,x):
        batch_size = x.size(0)
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(batch_size, -1)  # Flatten
        x = self.fc(x)
        return x

2.2 训练方法

# 训练模型(单次,epoch_num为当前批次)
def train(epoch_num):
    print("当前批次:[%d]:" % (epoch_num+1))
    running_loss = 0.0
    loss_sum = 0.0
    for j,(batch_data,batch_label) in enumerate(train_loader):
        batch_data,batch_label=batch_data.to(device),batch_label.to(device)
        
        optimizer.zero_grad()
        output = model(batch_data)
        loss = loss_func(output, batch_label)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        # 每1000次打印一次loss
        if (j+1) % 1000 == 0:
            print('loss:%.3f' % (running_loss / (1000*64))) # batch——size = 64
            loss_sum += running_loss
            running_loss = 0.0
    torch.save(model, "models/model_{}.pth".format(epoch_num))
    return loss_sum/len(train_set)

# 测试模型
def test():
    correct=0
    total=0
    with torch.no_grad():
        for batch_data,batch_label in test_loader:
            batch_data,batch_label=batch_data.to(device),batch_label.to(device)
            output = model(batch_data)
            _,predicted=torch.max(output.data,dim=1)
            total+=batch_label.size(0)
            correct+=(predicted==batch_label).sum().item()
    print('Accuracy on test set:%.3f %% [%d in %d]' %(correct/total,correct,total))
    return correct/total

2.3 模型训练

from torch import optim
from torch.utils.data import DataLoader

model = Net()       # 创建模型
device = torch.device("cpu")
model.to(device)

batch_size = 64     # 批量训练大小
epoch_num = 10
learn_rate = 0.01 
loss_func = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learn_rate, momentum=0.5)

# 数据加载器
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_set,batch_size, shuffle=True)
    
loss_set = []
acc_set = []

for epoch in range(10):
    loss = train(epoch)
    acc = test()
    loss_set.append(loss)
    acc_set.append(acc)

image-20230530102356853

2.4 验证

# 验证模型
label_names=['ambulance','apple','bear','bicycle','bird','bus','cat','foot','owl','pig']
val_loader = DataLoader(val_set,10, shuffle=True)

# 数据均为十个一组
def result_show(data,label,prediction):
    for i in range(10):
        plt.figure()
        
        plt.subplot(1,2,1)
        img = data[i].reshape(28,28)
        _,index = torch.max(prediction[i].data,dim=0)
#         print(index.data)
        plt.title("predict:{},ture:{}".format(label_names[index],label_names[label[i]]))
        plt.imshow(img)
        
        plt.subplot(1,2,2)
        plt.bar(range(len(prediction[i].data)), prediction[i].data)
        
    plt.show()

for i,(data,label) in enumerate(val_loader):
    if (i == 2):
        break
    prediction = model(data)
    result_show(data,label,prediction)

image-20230530102507415

参考链接

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: PyTorch是一个基于Python的科学计算库,它可以作为一种深度学习框架来使用。而CNN(卷积神经网络)是一种常用的深度学习模型,用于图像识别和分类等任务。 要使用PyTorchCNN来实现MNIST分类,可以按照以下步骤进行: 1. 导入必要的库和数据集:首先需要导入PyTorch和MNIST数据集。 2. 定义模型:使用PyTorch定义一个CNN模型,包括卷积层、池化层、全连接层等。 3. 训练模型:使用训练集对模型进行训练,并调整模型参数以提高准确率。 4. 测试模型:使用测试集对训练好的模型进行测试,评估模型的准确率。 5. 保存模型:将训练好的模型保存下来,以便后续使用。 总之,使用PyTorchCNN实现MNIST分类是一种常见的深度学习任务,需要对深度学习模型和PyTorch框架有一定的了解。 ### 回答2: PyTorch是一个开源的机器学习框架,可以用来构建神经网络模型进行训练和推理。而CNN(卷积神经网络)是一种常用于图像分类任务的深度学习模型。 首先,我们可以使用PyTorch库来加载MNIST数据集,该数据集包含手写数字的图片以及对应的标签。接着,我们可以使用CNN模型来训练和测试这些数据。 在PyTorch中,我们可以使用torchvision库来加载MNIST数据集。通过以下代码,可以将训练集和测试集分别存储在train_set和test_set中: ```python import torchvision.datasets as datasets train_set = datasets.MNIST(root='./data', train=True, download=True) test_set = datasets.MNIST(root='./data', train=False, download=True) ``` 接下来,我们可以定义CNN模型。一个典型的CNN模型包含若干卷积层、池化层和全连接层。在PyTorch中,我们可以使用`torch.nn`来构建网络模型。 下面是一个简单的例子,定义了一个包含两个卷积层和一个全连接层的CNN模型: ```python import torch.nn as nn class CNNModel(nn.Module): def __init__(self): super(CNNModel, self).__init__() self.conv1 = nn.Conv2d(1, 16, kernel_size=5) self.conv2 = nn.Conv2d(16, 32, kernel_size=5) self.fc = nn.Linear(32*4*4, 10) def forward(self, x): x = nn.functional.relu(self.conv1(x)) x = nn.functional.max_pool2d(x, 2) x = nn.functional.relu(self.conv2(x)) x = nn.functional.max_pool2d(x, 2) x = x.view(-1, 32*4*4) x = self.fc(x) return x model = CNNModel() ``` 接下来,我们需要定义损失函数和优化器,用于训练模型。在这里,我们使用交叉熵损失函数和随机梯度下降(SGD)优化器: ```python import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) ``` 然后,我们可以开始训练模型。对于每个训练样本,我们将图片输入到模型中进行前向传播,计算预测值。然后,我们计算损失,并通过反向传播更新模型的权重。 ```python num_epochs = 10 for epoch in range(num_epochs): running_loss = 0.0 for i, (images, labels) in enumerate(train_set): optimizer.zero_grad() outputs = model(images.unsqueeze(0)) loss = criterion(outputs, labels.unsqueeze(0)) loss.backward() optimizer.step() running_loss += loss.item() if (i+1) % 100 == 0: print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_set)}], Loss: {running_loss/100:.4f}') running_loss = 0.0 ``` 最后,我们可以使用测试集来评估模型的性能。对于测试集中的每个样本,我们将图片输入到模型中进行前向传播,并与标签进行比较,计算准确率。 ```python correct = 0 total = 0 with torch.no_grad(): for images, labels in test_set: outputs = model(images.unsqueeze(0)) _, predicted = torch.max(outputs.data, 1) total += 1 correct += (predicted == labels).sum().item() accuracy = correct / total print(f'Accuracy on test set: {accuracy:.2%}') ``` 以上就是使用PyTorchCNN实现MNIST数字分类任务的简单示例。通过加载数据集、定义模型、训练和测试模型,我们可以使用PyTorch来构建和训练自己的深度学习模型。 ### 回答3: PyTorch是一个开源的深度学习框架,而CNN(卷积神经网络)是一种深度学习网络模型。下面是关于如何使用PyTorchCNN来实现MNIST分类任务的简要说明。 1. 导入所需的库和模块: ``` import torch from torch import nn from torch import optim import torch.nn.functional as F from torchvision import datasets, transforms ``` 2. 数据预处理: ``` transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) train_data = datasets.MNIST(root='data', train=True, download=True, transform=transform) test_data = datasets.MNIST(root='data', train=False, download=True, transform=transform) train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True) test_loader = torch.utils.data.DataLoader(test_data, batch_size=64, shuffle=False) ``` 3. 定义CNN模型: ``` class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1) self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1) self.fc1 = nn.Linear(32 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2, 2) x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2, 2) x = x.view(-1, 32 * 7 * 7) x = F.relu(self.fc1(x)) x = self.fc2(x) return x model = CNN() ``` 4. 定义损失函数和优化器: ``` criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) ``` 5. 训练模型: ``` n_epochs = 10 for epoch in range(n_epochs): for images, labels in train_loader: optimizer.zero_grad() output = model(images) loss = criterion(output, labels) loss.backward() optimizer.step() print('Epoch: {} Loss: {:.4f}'.format(epoch+1, loss.item())) ``` 6. 评估模型: ``` model.eval() correct = 0 total = 0 with torch.no_grad(): for images, labels in test_loader: output = model(images) _, predicted = torch.max(output.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy on the test set: {:.2f}%'.format(100 * correct / total)) ``` 通过上述步骤,我们可以使用PyTorchCNN成功实现对MNIST数据集的分类任务。通过训练和评估模型,我们可以得到准确率作为分类性能的评估指标。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值