pytorch不同方法搭建CNN测试(mnist测试+自己数据集测试)

CNN搭建方法原文链接:https://www.jb51.net/article/138245.htm

数据集及程序打包百度云:
https://pan.baidu.com/s/1xfqM-Dxn-ZUE7LXbOESMPg
提取码:aotu

1.mnist数据集测试
mnist数据集只是为了测试方法,效果不好,可以自己调参数,改变结构之类的。(需要注意的是自己下载的mnist数据集应该怎么建立文件进行存储然后读取)

# -*- coding: utf-8 -*-
"""
Created on Wed May 27 23:36:25 2020

@author: 小小飞在路上
"""

import torch
import torch.nn.functional as F
from collections import OrderedDict
from torch import optim
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms,datasets


# Method 1 -----------------------------------------
#这种方法比较常用,早期的教程通常就是使用这种方法

class Net1(torch.nn.Module):
    def __init__(self):
        super(Net1, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 32, 3, 2, 2)
        self.dense1 = torch.nn.Linear(32 * 7 * 7, 128)
        self.dense2 = torch.nn.Linear(128, 10)
 
    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), 2)
        res= x.view(x.size(0), -1)
        x = F.relu(self.dense1(res))
        out = self.dense2(x)
        return out,res
 

## Method 2 ------------------------------------------
##这种方法利用torch.nn.Sequential()容器进行快速搭建,模型的各层被顺序添加到容器中。缺点是每层的编号是默认的阿拉伯数字,不易区分。
#
class Net2(torch.nn.Module):
    def __init__(self):
        super(Net2, self).__init__()
        self.conv = torch.nn.Sequential(
            torch.nn.Conv2d(1, 32, 3, 2, 2),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2))
        self.dense = torch.nn.Sequential(
            torch.nn.Linear(32 * 7 * 7, 128),
            torch.nn.ReLU(),
            torch.nn.Linear(128, 10)
        )
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res
 

## Method 3 -------------------------------
##这种方法是对第二种方法的改进:通过add_module()添加每一层,并且为每一层增加了一个单独的名字。
#
class Net3(torch.nn.Module):
    def __init__(self):
        super(Net3, self).__init__()
        self.conv=torch.nn.Sequential()
        self.conv.add_module("conv1",torch.nn.Conv2d(1, 32, 3, 2, 2))
        self.conv.add_module("relu1",torch.nn.ReLU())
        self.conv.add_module("pool1",torch.nn.MaxPool2d(2))
        self.dense = torch.nn.Sequential()
        self.dense.add_module("dense1",torch.nn.Linear(32 * 7 * 7, 128))
        self.dense.add_module("relu2",torch.nn.ReLU())
        self.dense.add_module("dense2",torch.nn.Linear(128, 10))
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res
 

# Method 4 ------------------------------------------
#是第三种方法的另外一种写法,通过字典的形式添加每一层,并且设置单独的层名称。
class Net4(torch.nn.Module):
    def __init__(self):
        super(Net4, self).__init__()
        self.conv = torch.nn.Sequential(
            OrderedDict(
                [
                    ("conv1", torch.nn.Conv2d(1, 32, 3, 2, 2)),
                    ("relu1", torch.nn.ReLU()),
                    ("pool", torch.nn.MaxPool2d(2))
                ]
            ))
 
        self.dense = torch.nn.Sequential(
            OrderedDict([
                ("dense1", torch.nn.Linear(32 * 7 * 7, 128)),
                ("relu2", torch.nn.ReLU()),
                ("dense2", torch.nn.Linear(128, 10))
            ])
        )
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res

if __name__=="__main__":
    EPOCH = 1               # train the training data n times, to save time, we just train 1 epoch
    batch_size = 64
    LR = 0.001              # learning rate
    DOWNLOAD_MNIST = False
    
    data_tf = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize([0.5], [0.5])])
    
    # 数据集的下载器
    train_dataset = datasets.MNIST(
        root='./data', train=True, transform=data_tf)
    test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf)
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
#测试四种方法
    CNN=[Net1(),Net2(),Net3(),Net3()]
    name=['Net1','Net2','Net3','Net4']
    loss_func=nn.CrossEntropyLoss()
    
    i=0
    for cnn in CNN:
        optimizer=optim.Adam(cnn.parameters(),lr=LR)
        print('method:',name[i])
        for epoch in range(2):
            train_loss = 0.
            train_acc = 0.
            for step, (b_x, b_y) in enumerate(train_loader):   # gives batch data, normalize x when iterate train_loader
                output = cnn(b_x.float())[0]               # cnn output
        
                loss = loss_func(output, b_y.long())   # cross entropy loss
                train_loss += loss.item()
                pred = torch.max(output, 1)[1]
                train_correct = (pred == b_y).sum()
                train_acc += train_correct.item()
                optimizer.zero_grad()           # clear gradients for this training step
                loss.backward()                 # backpropagation, compute gradients
                optimizer.step()                # apply gradients
            
            print('Epoch:  {:} |Train Loss: {:.6f}  |Acc: {:.6f}'.format(epoch+1,train_loss / (len(
                train_loader)), train_acc / (len(train_loader))))
        
        cnn.eval()
        eval_loss = 0.
        eval_acc = 0.
        for batch_x, batch_y in test_loader:
            output_te = cnn(batch_x.float())[0] 
            loss_te = loss_func(output_te, batch_y)
            eval_loss += loss_te.item()
            pred_te = torch.max(output_te, 1)[1]
            num_correct = (pred_te == batch_y).sum()
            eval_acc += num_correct.item()
        print('Test Loss: {:.6f}, Acc: {:.6f}'.format(eval_loss / (len(
             test_loader)), eval_acc / (len(test_loader))))
        i+=1

结果
pytorch不同方法搭建CNN测试(mnist测试+自己数据集测试)_第1张图片

2.自己数据集测试

# -*- coding: utf-8 -*-
"""
Created on Tue Jun  9 12:03:08 2020

@author: 小小飞在路上
"""
import torch
import numpy as np
import pandas as pd
from torch.utils.data import DataLoader
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split
from torch.utils.data import Dataset
from torch import optim

import torch.nn as nn

import torch.nn.functional as F
from collections import OrderedDict     

#读取自己数据需要增加这一部分
class data_loader(Dataset):
    def __init__(self, samples, labels, t):
        self.samples = samples
        self.labels = labels
        self.T = t

    def __getitem__(self, index):
        sample, target = self.samples[index], self.labels[index]
        if self.T:
            return self.T(sample), target
        else:
            return sample, target

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


# Method 1 ------------------------------------------
#这种方法比较常用,早期的教程通常就是使用这种方法。

class Net1(torch.nn.Module):
    def __init__(self):
        super(Net1, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 16, [1,3], 1, [1,2])
        self.dense1 = torch.nn.Linear(16 * 1 * 12, 128)
        self.dense2 = torch.nn.Linear(128, 12)
 
    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), 2)
        res= x.view(x.size(0), -1)
        x = F.relu(self.dense1(res))
        out = self.dense2(x)
        return out,res
 
 
 
# Method 2 ------------------------------------------
#这种方法利用torch.nn.Sequential()容器进行快速搭建,模型的各层被顺序添加到容器中。缺点是每层的编号是默认的阿拉伯数字,不易区分。

class Net2(torch.nn.Module):
    def __init__(self):
        super(Net2, self).__init__()
        self.conv = torch.nn.Sequential(
            torch.nn.Conv2d(1, 16, [1,3], 1, [1,2]),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2))
        self.dense = torch.nn.Sequential(
            torch.nn.Linear(16 * 1 * 12, 128),
            torch.nn.ReLU(),
            torch.nn.Linear(128, 12)
        )
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res
# Method 3 -------------------------------
#这种方法是对第二种方法的改进:通过add_module()添加每一层,并且为每一层增加了一个单独的名字。

class Net3(torch.nn.Module):
    def __init__(self):
        super(Net3, self).__init__()
        self.conv=torch.nn.Sequential()
        self.conv.add_module("conv1",torch.nn.Conv2d(1, 16, [1,3], 1, [1,2]))
        self.conv.add_module("relu1",torch.nn.ReLU())
        self.conv.add_module("pool1",torch.nn.MaxPool2d(2))
        self.dense = torch.nn.Sequential()
        self.dense.add_module("dense1",torch.nn.Linear(16 * 1 * 12, 128))
        self.dense.add_module("relu2",torch.nn.ReLU())
        self.dense.add_module("dense2",torch.nn.Linear(128, 12))
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res
 
# Method 4 ------------------------------------------
#是第三种方法的另外一种写法,通过字典的形式添加每一层,并且设置单独的层名称。
class Net4(torch.nn.Module):
    def __init__(self):
        super(Net4, self).__init__()
        self.conv = torch.nn.Sequential(
            OrderedDict(
                [
                    ("conv1", torch.nn.Conv2d(1, 16, [1,3], 1, [1,2])),
                    ("relu1", torch.nn.ReLU()),
                    ("pool", torch.nn.MaxPool2d(2))
                ]
            ))
 
        self.dense = torch.nn.Sequential(
            OrderedDict([
                ("dense1", torch.nn.Linear(16 * 1 * 12, 128)),
                ("relu2", torch.nn.ReLU()),
                ("dense2", torch.nn.Linear(128, 12))
            ])
        )
 
    def forward(self, x):
        conv_out = self.conv(x)
        res = conv_out.view(conv_out.size(0), -1)
        out = self.dense(res)
        return out,res
if __name__=="__main__":
#参数设置
    EPOCH = 1              
    batch_size = 128
    LR = 0.001  
    
    url = 'data.csv'
    data = pd. read_csv(url, sep=',',header=None)
    data=np.array(data)
    data=shuffle(data)
    X1=data[:,:23]
    Y1=data[:,23]
            
    labels1=np.asarray(pd.get_dummies(Y1),dtype=np.int8)
    Y=np.argmax(labels1,axis=1)
    
    X_train1,X_test1,Y_train1,Y_test1=train_test_split(X1,Y,test_size=0.001,random_state=20)
    
    X_train=X_train1.reshape((-1,1,1,23))
    X_test=X_test1.reshape((-1,1,1,23))
    
#增加读取数据代码的使用
    transform = None
    train_dataset = data_loader(X_train, Y_train1, transform)
    test_dataset = data_loader(X_test, Y_test1, transform)
    
#别的部分正常使用就行
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
    
#测试四种方法
    CNN=[Net1(),Net2(),Net3(),Net3()]
    name=['Net1','Net2','Net3','Net4']
    loss_func=nn.CrossEntropyLoss()
    
    i=0
    for cnn in CNN:
        optimizer=optim.Adam(cnn.parameters(),lr=LR)
        print('method:',name[i])
        for epoch in range(3):
            train_loss = 0.
            train_acc = 0.
            for step, (b_x, b_y) in enumerate(train_loader):   # gives batch data, normalize x when iterate train_loader
                output = cnn(b_x.float())[0]               # cnn output
        
                loss = loss_func(output, b_y.long())   # cross entropy loss
                train_loss += loss.item()
                pred = torch.max(output, 1)[1]
                train_correct = (pred == b_y).sum()
                train_acc += train_correct.item()
                optimizer.zero_grad()           # clear gradients for this training step
                loss.backward()                 # backpropagation, compute gradients
                optimizer.step()                # apply gradients
            
            print('Epoch:  {:} |Train Loss: {:.6f}  |Acc: {:.6f}'.format(epoch,train_loss / (len(
                X_train)), train_acc / (len(X_train))))
        
        cnn.eval()
        eval_loss = 0.
        eval_acc = 0.
        for batch_x, batch_y in test_loader:
            output_te = cnn(batch_x.float())[0] 
            loss_te = loss_func(output_te, batch_y)
            eval_loss += loss_te.item()
            pred_te = torch.max(output_te, 1)[1]
            num_correct = (pred_te == batch_y).sum()
            eval_acc += num_correct.item()
        print('Test Loss: {:.6f}, Acc: {:.6f}'.format(eval_loss / (len(
             X_test)), eval_acc / (len(X_test))))
        i+=1

结果
pytorch不同方法搭建CNN测试(mnist测试+自己数据集测试)_第2张图片
一般功能函数测试程序分开比较方便,也顺眼,我为了测试的的人方便,自己也不用额外说明才整体写一块(自己的程序不建议这样,会显得很乱)。

你可能感兴趣的:(深度学习,pytorch,深度学习)