pytorch深度學習 3層全連接層,使用MNIST,圖片訓練、識別、測試全過程示例

請一定要看代碼中的解釋,一定要理解深度學習的原理,一定要理解pytorch的實現方法。

一些簡介:MNIST、經典的手寫數字圖片,Fashion-MNIST是MNIST的更新版,意在取代MNIST。從0-9共10個類別。

整體上我並沒有用程序設計模塊化的寫法,直接一溜煙下來的。

整個程序的流程:

1.得到MNIST圖片訓練材料作爲training set、

2.transform圖片使得其更好投喂進pytorch網絡。

3.進行3輪訓練。

4.用training set作爲test set,進行accuracy的測試。

 

另外我寫了兩個函數爲顯示更清楚

import torch
from torch import nn
from torch.nn import functional as F
from torch import optim

import torchvision# this is used for vision task for pytorch
from matplotlib import pyplot as plt

#set print line width.
torch.set_printoptions(linewidth=120)

#to show loss picture
def plot_curve(data):
    fig=plt.figure()
    plt.plot(range(len(data)),data,color='blue')
    plt.legend(['loss_value'],loc='upper right')
    plt.xlabel('step')
    plt.ylabel('value')
    plt.show()

#designed to show picture meterial
def plot_image(img,label,name):
    #create a figure
    fig=plt.figure()
    #set subplot figure
    for i in range(6):
        plt.subplot(2,3,i+1)
        plt.tight_layout()
        plt.imshow(img[i][0]*0.3081+0.1307,cmap='gray',interpolation='none')
        plt.title("{}:{}".format(name,label[i].item()))
        #add xticks and yticks
        plt.xticks([])
        plt.yticks([])
    #show the whole picture
    plt.show()

#designed to transform y into one hot vector
def one_hot(lable,depth=10):
    out=torch.zeros(lable.size(0),depth)
    idx=torch.LongTensor(lable).view(-1,1)
    out.scatter_(dim=1,index=idx,value=1)
    return out

#batch size if the total data number every batch.
batch_size=512
#e.g:   we have 100 pieces of data totally,
# and we are to do three batches,
# and we get batch size pieces of data per batch.


#ETL process. Extract data, Transform data and Load data.

#extract and transform
training_set=torchvision.datasets.MNIST('mnist_data',train=True,download=True,
                                transform=torchvision.transforms.Compose([
                                    torchvision.transforms.ToTensor(),
                                    torchvision.transforms.Normalize(
                                        (0.1307,),(0.3081,))
                                ]))
test_set=torchvision.datasets.MNIST('mnist_data/',train=False,download=True,
                               transform=torchvision.transforms.Compose([
                                   torchvision.transforms.ToTensor(),
                                   torchvision.transforms.Normalize(
                                       (0.1307,),(0.3081,)
                                   )
                               ]))
#len(training_set), you can get the number of training_set
#train_set.train_labels, you can get lable set of data
#train_set.train_labels.bincount(), you can get number of data of each class.
#note: if numbera of each label are equal, we call it balanced, otherwise it's unbalanced.

#images,labels=next(iter(train_loader))   they are a batch, many many images and lebels.

#batch_size the data number extracted from the whole dataset.
#load training set.
train_loader=torch.utils.data.DataLoader(training_set,batch_size=batch_size,shuffle=True)
#load test set.
test_loader=torch.utils.data.DataLoader(test_set,batch_size=batch_size,shuffle=False)

#just sample a little bit for a look
x,y=next(iter(train_loader))
#x is images, y is result
plot_image(x,y,'image_sample')

#define neural network
class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        #define three layers,
        # fc stands for fully connected layer. conv is for convolution layer(nn.Con2d()
        self.fc1=nn.Linear(28*28,256)
        self.fc2 = nn.Linear(256, 64)
        self.fc3 = nn.Linear(64, 10)
    def forward(self, x):
        x=F.relu(self.fc1(x))
        x=F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


#define neuron network used for predicting
net =Net()
#define optimizer for forward prop and backward prop
optimizer=optim.SGD(net.parameters(),lr=0.01,momentum=0.9)

#this list is to store loss in each epoch
train_loss=[]

#start training. 3 batches, 512 per batch
for epoch in range(3):
    for batch_idx,(x,y) in enumerate(train_loader):
        # transformation: [b,1,28,28]====> [b,feature]
        x=x.view(x.size(0),28*28)
        out=net(x)
        y_onehot=one_hot(y)
        loss=F.mse_loss(out,y_onehot)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        #record loss
        train_loss.append(loss.item())
#print loss curve
plot_curve(train_loss)


#test model
total_correct=0
for x,y in test_loader:
    x=x.view(x.size(0),28*28)
    out=net(x)
    predict=out.argmax(dim=1)
    correct=predict.eq(y).sum().float().item()
    total_correct+=correct


total_data=len(test_loader.dataset)
accuracy=total_correct/total_data
print('test accuracy:{}'.format(accuracy))

#do practical predict

x,y=next(iter(test_loader))
out=net(x.view(x.size(0),28*28))
predict=out.argmax(dim=1)
plot_image(x,predict,'test')

我是在cpu上運行的,相對來說慢一些。

 

一些運行結果:

這是看一下加載的訓練圖片和label

 

這是一個epoch的loss曲線,看上去還行

控制檯會顯示出用了test_set的accuracy。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章