Softmax回歸多分類網絡(PyTorch實現)


Softmax回歸多分類網絡(PyTorch實現)

雖然說深度學習的教程已經爛大街了,基礎理論也比較容易掌握,但是真正讓自己去實現的時候還是有一些坑。一方面教程不會涉及太多具體的工程問題,另一方面啃PyTorch的英文文檔還是有點麻煩。記錄一下,就當是作業報告了。

獲取數據集

首先導入所需要的包:

import torch
import torch.nn as nn
import torch.utils.data as Data
import numpy as np
import matplotlib.pyplot as plt

所用的數據集共有500條,輸入特征feature_n = 8,輸出類別lables_n = 4。取前兩行數據看看數據的格式:

x1 x2 x3 x4 x5 x6 x7 x8 class label
0.4812 0.7790 0.8904 0.7361 0.9552 0.2119 0.7992 0.2409 4
0.4472 0.5985 0.7859 0.5035 0.6912 0.4038 0.0787 0.2301 1

我們將前400條數據作為訓練集,后100條數據作為測試集。

定義一個函數用於從文件中獲取此數據集:

def get_data(filename):
    dataset = np.loadtxt(filename)   
    x_train = dataset[0:400,0:8]
    raw_y_train = dataset[0:400,8:]
    x_test = dataset[400:,0:8]
    raw_y_test = dataset[400:,8:]
    
    y_train = np.zeros((400,4),dtype = np.int)
    y_test = np.zeros((100,4),dtype = np.int)

    y_train = raw_y_train - 1
    y_test = raw_y_test - 1

    #for i in range(400):
    #    y_train[i,int(raw_y_train[i])-1]=1
    
    #for j in range(100):
    #    y_test[j,int(raw_y_test[j])-1]=1
        
    return x_train,y_train,x_test,y_test

從原理上講Softmax分類器的輸出個數應與class label的數量相同,理想情況下正確的那一項為1,其他為0。那么class label4時,理想預測值應為[0, 0, 0, 1] ,而數據集中給出的值為[4] 。如果是用NumPy手動搭建網絡和寫Softmax函數,那么就需要把y_train處理成二維矩陣。

但是對於PyTorch中提供的損失函數torch.nn.CrossEntropyLoss()來說,數據格式稍有不同。torch.nn.CrossEntropyLoss()第一個參數y_predbatch_size * labels_n大小的矩陣,第二個參數y是一維的batch_size大小的向量,且數據范圍為[0, labels_n -1],所以要在y_train的基礎上減1,把標簽1/2/3/4變成0/1/2/3 。

設置批訓練

讀取進來的數據集還是ndarray格式的,我們先將它們轉化為tensor

x_train,y_train,x_test,y_test = get_data('dataset.txt')    
x_train = torch.from_numpy(x_train).type(torch.FloatTensor)
y_train = torch.from_numpy(y_train).type(torch.LongTensor)

注意對轉換后的數據格式有要求。這也是損失函數torch.nn.CrossEntropyLoss()的要求,預測概率必須為float,正確標簽必須為long

之后建立訓練集並加載,測試集同理 :

train_set = Data.TensorDataset(x_train,y_train)

train_loader = Data.DataLoader(
            dataset=train_set,
            batch_size=BATCH_SIZE,
            shuffle=True
            )

在《動手學習深度學習》書中采用了自己手寫的迭代器進行批訓練的數據迭代。我個人覺得PyTorch提供的DataLoader工具更加簡單好用。

定義模型

采用PyTorch提供的快速搭建法進行搭建神經網絡,包含隱藏層和輸出層共2層。需要注意一點,損失函數torch.nn.CrossEntropyLoss()中已經包含了Softmax函數,所以我們的神經網絡直接線性輸出即可。

net = nn.Sequential(
            nn.Linear(8,50),
            nn.ReLU(),
            nn.Linear(50,4)
            )

之后定義一些訓練模型的函數和參數:

EPOCH = 5000
BATCH_SIZE = 100
LR = 0.01
LOSS_FUNC = nn.CrossEntropyLoss() 
OPTIMIZER = torch.optim.SGD(net.parameters(), lr=LR)  

神經網絡建立后本身會對參數w、b進行初始化。因為我也不知道應該初始化為多少比較合適,所以在此不進行顯式的初始化而采用其默認的。

訓練模型

for epoch in range(1,EPOCH+1):
    loss_sum = 0.0
    for step,(x,y) in enumerate(train_loader):
        y_pred = net(x)
        y = y.squeeze() #修正標簽格式
        loss = LOSS_FUNC(y_pred,y)
        loss_sum += loss
        OPTIMIZER.zero_grad()
        loss.backward()
        OPTIMIZER.step()
    print("epoch: %d, loss: %f" %(epoch,loss_sum/BATCH_SIZE))

之前說過損失函數對數據格式有要求。我們的標簽y實際上還是二維矩陣,大小為batch_size * 1,所以在計算損失函數前需要進行降維。

測試模型

acc_sum = 0.0
acc_sum += (net(x_test).argmax(dim=1) == y_test.squeeze()).sum()     
print("test accuracy: %f" %(acc_sum/100)) 

用測試集進行測試可知准確率能達到93%。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM