天天看點

Pytorch實作手寫數字mnist識别

import torch
import torchvision as tv
import torchvision.transforms as transforms
import torch.nn as nn
import torch.optim as optim
import argparse
# 定義是否使用GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 定義網絡結構
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Sequential(     #input_size=(1*28*28)
            nn.Conv2d(, , , , ), #padding=2保證輸入輸出尺寸相同
            nn.ReLU(),      #input_size=(6*28*28)
            nn.MaxPool2d(kernel_size=, stride=),#output_size=(6*14*14)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(, , ),
            nn.ReLU(),      #input_size=(16*10*10)
            nn.MaxPool2d(, )  #output_size=(16*5*5)
        )
        self.fc1 = nn.Sequential(
            nn.Linear( *  * , ),
            nn.ReLU()
        )
        self.fc2 = nn.Sequential(
            nn.Linear(, ),
            nn.ReLU()
        )
        self.fc3 = nn.Linear(, )

    # 定義前向傳播過程,輸入為x
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        # nn.Linear()的輸入輸出都是次元為一的值,是以要把多元度的tensor展平成一維
        x = x.view(x.size()[], -)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x
#使得我們能夠手動輸入指令行參數,就是讓風格變得和Linux指令行差不多
parser = argparse.ArgumentParser()
parser.add_argument('--outf', default='./model/', help='folder to output images and model checkpoints') #模型儲存路徑
parser.add_argument('--net', default='./model/net.pth', help="path to netG (to continue training)")  #模型加載路徑
opt = parser.parse_args()

# 超參數設定
EPOCH =    #周遊資料集次數
BATCH_SIZE =       #批處理尺寸(batch_size)
LR =         #學習率

# 定義資料預處理方式
transform = transforms.ToTensor()

# 定義訓練資料集
trainset = tv.datasets.MNIST(
    root='./data/',
    train=True,
    download=True,
    transform=transform)

# 定義訓練批處理資料
trainloader = torch.utils.data.DataLoader(
    trainset,
    batch_size=BATCH_SIZE,
    shuffle=True,
    )

# 定義測試資料集
testset = tv.datasets.MNIST(
    root='./data/',
    train=False,
    download=True,
    transform=transform)

# 定義測試批處理資料
testloader = torch.utils.data.DataLoader(
    testset,
    batch_size=BATCH_SIZE,
    shuffle=False,
    )

# 定義損失函數loss function 和優化方式(采用SGD)
net = LeNet().to(device)
criterion = nn.CrossEntropyLoss()  # 交叉熵損失函數,通常用于多分類問題上
optimizer = optim.SGD(net.parameters(), lr=LR, momentum=)

# 訓練
if __name__ == "__main__":

    for epoch in range(EPOCH):
        sum_loss = 
        # 資料讀取
        for i, data in enumerate(trainloader):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)

            # 梯度清零
            optimizer.zero_grad()

            # forward + backward
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            # 每訓練100個batch列印一次平均loss
            sum_loss += loss.item()
            if i %  == :
                print('[%d, %d] loss: %.03f'
                      % (epoch + , i + , sum_loss / ))
                sum_loss = 
        # 每跑完一次epoch測試一下準确率
        with torch.no_grad():
            correct = 
            total = 
            for data in testloader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = net(images)
                # 取得分最高的那個類
                _, predicted = torch.max(outputs.data, )
                total += labels.size()
                correct += (predicted == labels).sum()
            print('第%d個epoch的識别準确率為:%d%%' % (epoch + , ( * correct / total)))
    #torch.save(net.state_dict(), '%s/net_%03d.pth' % (opt.outf, epoch + 1))
           

繼續閱讀