基于Pytorch的Fashion MNIST数据集分类-CNN滑积神经网络

框架:Pytorch

数据集:Fashion MNIST(手写数字识别的进阶)

网络:卷积神经网络(CNN)又名滑积神经网络

目的:熟悉Pytorch框架,  搭建简易滑积神经网络

结构:

Image for post

代码:

引用

import torch 
import torch.nn as nn
import torchvision.datasets as dsets
from skimage import transform
import torchvision.transforms as transforms
from torch.autograd import Variable
import pandas as pd;
import numpy as np;
from torch.utils.data import Dataset, DataLoader
from vis_utils import *
import random;
import math;

 

超参数 

num_epochs = 5;
batch_size = 100;
learning_rate = 0.001;

这块黑色的我不知道怎么去掉~哎呀呀,小黑屏幕,哎呀呀,你也去不掉呀,你是咋出来的呢,我也不知道呀!小白菜呀,地里黄呀,小黑屏呀,去不掉呀。嘿嘿!嘿嘿!嘿嘿嘿!

 

定义数据集

Pytorch中自带数据集Dataset不包括Fashion MNIST,因此需要自定义Fashion MNIST数据集。自定义数据集需继承父类Dataset,并重载父类成员中的两个私有成员函数,

其中__len__应该返回数据集的大小,而__getitem__应该编写支持数据索引的函数。

def getitem(self, index):
def len(self):
class FashionMNISTDataset(Dataset):
    '''Fashion MNIST Dataset'''

    def __init__(self, csv_file, transform=None): #初始化函数,主要用于数据的加载,pandas读取数据为dataframe,转成numpy数组来进行索引 。
        """
        Args:
            csv_file (string): csv file地址
            transform (callable): Optional transform to apply to sample
        """

        '''iloc:分割矩阵,data:表格数据。X:样本,Y:标签且在0列。
           取样本:行全取、列从第1到结束。取标签:行全取,列取0。'''
        data = pd.read_csv(csv_file); #从csv文件加载数据,使用Pandas读入
        self.X = np.array(data.iloc[:, 1:]).reshape(-1, 1, 28, 28).astype(float);
        self.Y = np.array(data.iloc[:, 0]); #数据转换为numpy数组从而索引

        del data;  # 结束data对数据的引用,节省空间
        self.transform = transform; #transform默认值为None

    def __len__(self): #样本长度,即数据集总数,dataloader需使用。
        return len(self.X);

    def __getitem__(self, idx):  #返回单张图片。输入索引,返回该样本及其标签。如果定义transform,转换样本并返回。
        item = self.X[idx];
        label = self.Y[idx];

        if self.transform:
            item = self.transform(item);

        return (item, label); #样本和标签

 

划分样本集和测试集

train_dataset = FashionMNISTDataset(csv_file='fashionmnist/fashion-mnist_train.csv');
test_dataset = FashionMNISTDataset(csv_file='fashionmnist/fashion-mnist_test.csv')

加载数据

train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True);
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                          batch_size=batch_size,
                                          shuffle=True);

构建滑积网络

网络继承nn.Module,编写__init__及forward函数。使用nn模块定义网络层:(卷积-归一化-激活-池化)-(卷积-归一化-激活-池化)-全连接层(10类别输出)

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=5, padding=2),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(16, 32, kernel_size=5, padding=2),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(2))
        self.fc = nn.Linear(7*7*32, 10)
        
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return out

 

网络实例化

cnn = CNN();

定义损失函数

criterion = nn.CrossEntropyLoss();

选取优化器

  多分类因为使用Softmax回归,将神经网络前向传播得到的结果变成概率分布,所以使用交叉熵损失。 Pytorch将 nn.LogSoftmax() 和 nn.NLLLoss()整合成NN.CrossEntropyLoss()即为交叉熵。

optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate);

模型训练

注意:loss.data[0]是pytorch0.3.1版本代码,0.5以上版本会报错,应替换成loss.data.item()。下面代码已替换完成。

下图中一个重中之重的概念是Variable。

losses = [];  #记录损失函数
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = Variable(images.float())
        labels = Variable(labels)
        
        # Forward + Backward + Optimize
        
        #清零
        optimizer.zero_grad()
      
        #前向
        outputs = cnn(images)

        #损失函数
        loss = criterion(outputs, labels)

        #后向传播
        loss.backward()

        #优化器迭代
        optimizer.step()
        
        #损失函数矩阵
        #losses.append(loss.data.item());
        losses.append(loss.data.item());

        #打印
        if (i+1) % 100 == 0:
            print ('Epoch : %d/%d, Iter : %d/%d,  Loss: %.4f' 
                   %(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.data.item()))

猜你喜欢

转载自blog.csdn.net/weixin_42133481/article/details/114400394