使用卷积神经网络(CNN)对Fashion Mnist数据集进行分类 【日常生活物品 十类别】

新的改变

这里是一个入门卷积神经网络,深度学习的简单小项目,
主要使用了全连接神经网络对Fashion Mninst中的物体进行分类,物体包括拖鞋,靴子,T恤等等;
采用pytorch框架,python3.6版本编程实现;
可学习熟悉 torch中对于数据的批量读取写入操作
torch 定义学习网络的方式,
以及后期数据输出可视化的过程。
参考书籍:PyTorch 深度学习入门与实战 孙玉林

全部代码

import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score,confusion_matrix,classification_report
import matplotlib.pyplot as plt
import seaborn as sns
import copy
import time
import torch
import torch.nn as nn
from torch.optim import Adam
import torch.utils.data as Data
from torchvision import transforms
from torchvision.datasets import FashionMNIST

train_data = FashionMNIST(
    root = "./data/FashionMNIST",
    train = True,
    transform = transforms.ToTensor(),
    download = False
)

train_loader = Data.DataLoader(
    dataset = train_data,
    batch_size = 64,
    shuffle = False,
    #num_workers = 2,
)

print("Train_loader 的batch数量为:",len(train_loader))

for step,(b_x,b_y) in enumerate(train_loader):
    if step > 0:
        break

batch_x = b_x.squeeze().numpy()
batch_y = b_y.numpy()
class_label = train_data.classes
class_label[0] = "T-shirt"
plt.figure(figsize = (12,5))
for ii in np.arange(len(batch_y)):
    plt.subplot(4,16,ii+1)
    plt.imshow(batch_x[ii,:,:],cmap = plt.cm.gray)
    plt.title(class_label[batch_y[ii]],size = 9)
    plt.axis("off")
    plt.subplots_adjust(wspace = 0.05)

#plt.show()
test_data = FashionMNIST(
    root="./data/FashionMNIST",
    train = False,
    download = False
)
test_data_x = test_data.data.type(torch.FloatTensor) / 255.0
test_data_x = torch.unsqueeze(test_data_x,dim = 1)
test_data_y = test_data.targets
print("test_data_x.shape:",test_data_x.shape)
print("test_data_y.shape:",test_data_y.shape)

class MyConvNet(nn.Module):
    def __init__(self):
        super(MyConvNet,self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels = 1,
                out_channels = 16,
                kernel_size = 3,
                stride = 1,
                padding = 1,
            ),
            nn.ReLU(),
            nn.AvgPool2d(
                kernel_size = 2,
                stride = 2)
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(16,32,3,1,0),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
        )
        self.classifier = nn.Sequential(
            nn.Linear(32*6*6,256),
            nn.ReLU(),
            nn.Linear(256,128),
            nn.ReLU(),
            nn.Linear(128,10)
        )

    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0),-1)
        output = self.classifier(x)
        return  output

myconvnet = MyConvNet()
print(myconvnet)

def train_model(model,traindataloader,train_rate,criterion,optimizer,num_epochs = 25):
    batch_num = len(traindataloader)
    train_batch_num = round(batch_num * train_rate)
    best_model_wts = copy.deepcopy(model.state_dict())
    best_acc = 0.0
    train_loss_all = []
    train_acc_all = []
    val_loss_all = []
    val_acc_all = []
    since = time.time()
    for epoch in range(num_epochs):
        print('Epoch {}/{}'.format(epoch,num_epochs-1))
        print('-'*10)

        train_loss = 0.0
        train_corrects = 0
        train_num = 0

        val_loss = 0.0
        val_correct = 0
        val_num = 0
        for step,(b_x,b_y) in enumerate(traindataloader):
            if step < train_batch_num:
                model.train()
                output = model(b_x)
                pre_lab = torch.argmax(output,1)
                loss =  criterion(output, b_y)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                train_loss += loss.item()
                train_corrects += torch.sum(pre_lab == b_y.data)
                train_num += b_x.size(0)
            else:
                model.eval()
                output = model(b_x)
                pre_lab = torch.argmax(output,1)
                loss = criterion(output,b_y)
                val_loss += loss.item()
                val_correct += torch.sum(pre_lab == b_y.data)
                val_num += b_y.size(0)

        train_loss_all.append(train_loss / train_num)
        train_acc_all.append(train_corrects.double().item()/train_num)
        val_loss_all.append(val_loss / val_num)
        val_acc_all.append(val_correct.double().item() / val_num)
        print("{} Train Loss:{:.4f}  Train Acc: {:.4f}" .format(epoch,train_loss_all[-1],train_acc_all[-1]))
        print('{} Val Loss: {:.4f} val Acc: {:.4f}' .format(epoch,val_loss_all[-1],val_acc_all[-1]))

        if val_loss_all[-1] > best_acc:
            best_acc = val_acc_all[-1]
            best_model_wts = copy.deepcopy(model.state_dict())
        time_use = time.time() - since
        print("Train and val complete in {:.0f}m {:.0f}s".format(time_use // 60,time_use % 60))

    model.load_state_dict(best_model_wts)
    train_process = pd.DataFrame(
        data = {"epoch":range(num_epochs),
                "train_loss_all": train_loss_all,
                "val_loss_all":val_loss_all,
                "train_acc_all":train_acc_all,
                "val_acc_all":val_acc_all}
        )
    return model,train_process

optimizer = torch.optim.Adam(myconvnet.parameters(),lr = 0.0003)
criterion = nn.CrossEntropyLoss()
myconvnet,train_process = train_model(
    myconvnet,train_loader,0.8,criterion,optimizer,num_epochs=25
)
plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.plot(train_process.epoch,train_process.train_loss_all,"ro-",label = "Train_loss")
plt.plot(train_process.epoch,train_process.val_loss_all,"bs-",label = "Val loss")
plt.legend()
plt.xlabel("epoch")
plt.ylabel("Loss")

plt.subplot(1,2,2)
plt.plot(train_process.epoch,train_process.train_acc_all,"ro-",label = "Train_acc")
plt.plot(train_process.epoch,train_process.val_acc_all,"bs-",label = "Val acc")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.legend()

myconvnet.eval()
output = myconvnet(test_data_x)
pre_lab = torch.argmax(output,1)
test_data_ya = test_data_y.detach().numpy()
pre_laba = pre_lab.detach().numpy()
acc = accuracy_score(test_data_ya,pre_laba)
print("ACC Test:",acc)
plt.figure(figsize=(12,12))
conf_mat = confusion_matrix(test_data_ya,pre_laba)
df_cm = pd.DataFrame(conf_mat, index = class_label,columns = class_label)
heatmap = sns.heatmap(df_cm,annot = True,fmt = "d", cmap = "YlGnBu")
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(),rotation = 0, ha = "right")
plt.ylabel('True label')
plt.xlabel("Predicted label")
plt.show()




输出结果

整体网络结构
在这里插入图片描述
训练截图[部分]
训练耗时大概15分钟 cpu-3500x gpu-1080ti,内存16g 3200mhz
在这里插入图片描述

数据集图片示例:
在这里插入图片描述
训练时损失下降趋势:
准确率上升趋势:
在这里插入图片描述
关联性热力图:(可分析得出 靴子和滑板鞋,T-shirt和shirt属于相互误判比较多的类别)
在这里插入图片描述
完结,撒花!

  • 5
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值