一、数据来源

百度网盘 提取码:x0kd
数据集有2份,一份测试集,一份训练集。

二、分类实例:

2.1 自定义构建Dataset

训练数据一共有60000条,共有785个特征,其中一列标签为label。实际上是一个784(28*28)的图片信息。在处理过程中需要将其reshape。对数据的处理如果有传入torch自带的transform则使用该处理方式,否则将像素点/255.

class FMDataset(Dataset):
    def __init__(self, df, transform=None):
        self.df = df
        self.transform = transform
        self.images = df.iloc[:, 1:].values.astype(np.uint8)
        self.labels = df.iloc[:, 0].values

    def __len__(self):
        return len(self.images)

    def __getitem__(self, idx):
        image = self.images[idx].reshape(28, 28, 1)
        label = int(self.labels[idx])
        # 如果transform 为空,则简单处理,记得一定要将数据保存为张量
        if self.transform is not None:
            image = self.transform(image)
        else:
            image = torch.tensor(image / 255., dtype=torch.float)
        label = torch.tensor(label, dtype=torch.long)
        return image, label

2.2 模型设计

构造出卷积层-池化层-卷积层-池化层-输出层的设计结构。

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 32, 5),  # 卷积层
            nn.ReLU(),  # 激活函数
            nn.MaxPool2d(2, stride=2),  # 池化层
            nn.Dropout(0.3),  # 防止过拟合,将神经元中的30%部分节点不启用
            nn.Conv2d(32, 64, 5),
            nn.ReLU(),
            nn.MaxPool2d(2, stride=2),
            nn.Dropout(0.3)
        )

        self.fc = nn.Sequential(
            nn.Linear(64 * 4 * 4, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.conv(x)
        x = x.view(-1, 64 * 4 * 4)
        x = self.fc(x)
        return x

2.3 封装模型训练与测试

将模型的训练过程与测试过程封装成类

class run():
    def __init__(self):
        """
        初始化
        """
        self.dataloader()
        self._model()
        self._loss()
        self._optimizer()

    def dataloader(self):
        """
        构建数据dataloader
        :return:
        """
        data_transform = transforms.Compose([
            transforms.ToPILImage(),
            transforms.Resize(image_size),
            transforms.ToTensor()
        ])

        train_df = pd.read_csv("../FaceData/fashionMnist/fashion-mnist_train.csv")
        test_df = pd.read_csv("../FaceData/fashionMnist/fashion-mnist_test.csv")
        train_data = FMDataset(df=train_df, transform=data_transform)
        test_data = FMDataset(df=test_df, transform=data_transform)
        self.train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=num_workers,
                                       drop_last=True)
        self.test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)

    def _model(self):
        """
        :return:调用模型
        """
        model = Net()
        self.model = model
        # model.to(device)

    def _loss(self):
        """
        :return:使用损失函数
        """
        self.criterion = nn.CrossEntropyLoss()

    def _optimizer(self):
        """
        :return:设置优化器
        """
        self.optimizer = optim.Adam(self.model.parameters(), lr=0.001)

    def train(self, epoch):
        """
        封装训练过程
        :param epoch:
        :return:
        """
        self.model.train()  # 告诉模型这是在训练,及可使用net中的Dropout
        train_loss = 0
        for data, label in self.train_loader:
            # gpu版本可加入以下
            # data, label = data.cuda(), label.cuda()
            # 这里也可使用model.zero_grad(),两者等价,都是把每次训练的梯度设置为0
            self.optimizer.zero_grad()
            output = self.model(data)
            loss = self.criterion(output, label)
            loss.backward()
            self.optimizer.step()
            train_loss += loss.item() * data.size(0)
        train_loss = train_loss / len(self.train_loader.dataset)
        print("Epoch:{} \t Training Loss:{:.6f}".format(epoch, train_loss))

    def test(self, epoch):
        """
        封装测试过程
        :param epoch:
        :return:
        """

        self.model.eval()  # 告诉模型这是测试
        val_loss = 0
        gt_labels = []
        pred_labels = []
        with torch.no_grad():
            for data, label in self.test_loader:
                # gpu版本注销以下语句
                # data, label = data.cuda(), label.cuda()
                output = self.model(data)
                preds = torch.argmax(output, 1)
                # gpu使用以下语句
                # gt_labels.append(label.cpu().data.numpy())
                # pred_labels.append(preds.cpu().data.numpy())
                gt_labels.append(label.data.numpy())  # 真实标签
                pred_labels.append(preds.data.numpy())  # 预测标签
                loss = self.criterion(output, label)
                val_loss += loss.item() * data.size(0)
        val_loss = val_loss / len(self.test_loader.dataset)
        gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels)
        acc = np.sum(gt_labels == pred_labels) / len(pred_labels)
        print('Epoch:{} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))

三、完整代码

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project :pytorch 
@File    :FashionMNIST.py
@Author  :阿瓦达啃大瓜~
@Date    :2022/10/14 17:24
@fun FashionMNIST数据分类实例
'''

import os
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms

#  配置GPU
# device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
#  设置超参数

batch_size = 256
num_workers = 0
lr = 1e-4
epochs = 20
image_size = 28


# 读入csv数据,自行构建Dataset
class FMDataset(Dataset):
    def __init__(self, df, transform=None):
        self.df = df
        self.transform = transform
        self.images = df.iloc[:, 1:].values.astype(np.uint8)
        self.labels = df.iloc[:, 0].values

    def __len__(self):
        return len(self.images)

    def __getitem__(self, idx):
        image = self.images[idx].reshape(28, 28, 1)
        label = int(self.labels[idx])
        if self.transform is not None:
            image = self.transform(image)
        else:
            image = torch.tensor(image / 255., dtype=torch.float)
        label = torch.tensor(label, dtype=torch.long)
        return image, label


# 模型设计
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 32, 5),  # 卷积层
            nn.ReLU(),  # 激活函数
            nn.MaxPool2d(2, stride=2),  # 池化层
            nn.Dropout(0.3),  # 防止过拟合,将神经元中的30%部分节点不启用
            nn.Conv2d(32, 64, 5),
            nn.ReLU(),
            nn.MaxPool2d(2, stride=2),
            nn.Dropout(0.3)
        )

        self.fc = nn.Sequential(
            nn.Linear(64 * 4 * 4, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.conv(x)
        x = x.view(-1, 64 * 4 * 4)
        x = self.fc(x)
        return x


# 封装训练与测试
class run():
    def __init__(self):
        """
        初始化
        """
        self.dataloader()
        self._model()
        self._loss()
        self._optimizer()

    def dataloader(self):
        """
        构建数据dataloader
        :return:
        """
        data_transform = transforms.Compose([
            transforms.ToPILImage(),
            transforms.Resize(image_size),
            transforms.ToTensor()
        ])

        train_df = pd.read_csv("../FaceData/fashionMnist/fashion-mnist_train.csv")
        test_df = pd.read_csv("../FaceData/fashionMnist/fashion-mnist_test.csv")
        train_data = FMDataset(df=train_df, transform=data_transform)
        test_data = FMDataset(df=test_df, transform=data_transform)
        self.train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=num_workers,
                                       drop_last=True)
        self.test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)

    def _model(self):
        """
        :return:调用模型
        """
        model = Net()
        self.model = model
        # model.to(device)

    def _loss(self):
        """
        :return:使用损失函数
        """
        self.criterion = nn.CrossEntropyLoss()

    def _optimizer(self):
        """
        :return:设置优化器
        """
        self.optimizer = optim.Adam(self.model.parameters(), lr=0.001)

    def train(self, epoch):
        """
        封装训练过程
        :param epoch:
        :return:
        """
        self.model.train()  # 告诉模型这是在训练,及可使用net中的Dropout
        train_loss = 0
        for data, label in self.train_loader:
            # gpu版本可加入以下
            # data, label = data.cuda(), label.cuda()
            # 这里也可使用model.zero_grad(),两者等价,都是把每次训练的梯度设置为0
            self.optimizer.zero_grad()
            output = self.model(data)
            loss = self.criterion(output, label)
            loss.backward()
            self.optimizer.step()
            train_loss += loss.item() * data.size(0)
        train_loss = train_loss / len(self.train_loader.dataset)
        print("Epoch:{} \t Training Loss:{:.6f}".format(epoch, train_loss))

    def test(self, epoch):
        """
        封装测试过程
        :param epoch:
        :return:
        """

        self.model.eval()  # 告诉模型这是测试
        val_loss = 0
        gt_labels = []
        pred_labels = []
        with torch.no_grad():
            for data, label in self.test_loader:
                # gpu版本注销以下语句
                # data, label = data.cuda(), label.cuda()
                output = self.model(data)
                preds = torch.argmax(output, 1)
                # gpu使用以下语句
                # gt_labels.append(label.cpu().data.numpy())
                # pred_labels.append(preds.cpu().data.numpy())
                gt_labels.append(label.data.numpy())  # 真实标签
                pred_labels.append(preds.data.numpy())  # 预测标签
                loss = self.criterion(output, label)
                val_loss += loss.item() * data.size(0)
        val_loss = val_loss / len(self.test_loader.dataset)
        gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels)
        acc = np.sum(gt_labels == pred_labels) / len(pred_labels)
        print('Epoch:{} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))


if __name__ == '__main__':
    Run = run()
    for epoch in range(1, epochs + 1):
        Run.train(epoch)
        Run.test(epoch)

    # 模型保存
    # torch.save(Run.model, "save_path")

其运行结果如下:

pytorch的cls是什么_pytorch的cls是什么