pytorch 训练过程acc_Pytorch之Softmax多分类任务
在上一篇文章中,筆者介紹了什么是Softmax回歸及其原理。因此在接下來的這篇文章中,我們就來開始動手實現一下Softmax回歸,并且最后要完成利用Softmax模型對Fashion MINIST進行分類的任務。在開始實現Softmax之前,我們先來了解一下Fashion MINIST這一數據集。
1 數據集
1.1 FashionMNIST
數據集FashionMNIST雖然名字里面有'MNIST'這個詞,但是其與手寫體識別一點關系也沒有,僅僅只是因為FashionMNIST數據集在數據集規模、類別數量和圖片大小上與MINIST手寫體數據集一致。
圖 1. Fashion MINIST數據集如圖1所示便為Fashion MNIST數據集的部分可視化結果,其包含有訓練集6萬張和測試集1萬張,每張圖片的大小為[28,28]。在Pytorch中,我們可以通過如下代碼對其進行載入:
def?load_dataset():????mnist_train?=?torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',??train=True,?download=True,transform=transforms.ToTensor())
????mnist_test?=?torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',???train=False,?download=True,transform=transforms.ToTensor())
????return?mnist_train,?mnist_test
其中參數root表示指定數據集的保存目錄;train表示返回訓練集還是測試集;download表示數據集不存在時是否需要下載;transform表示指定一種轉換方法,而指定transforms.ToTensor()就是將尺寸為(H x W x C)且數據位于[0,255]的PIL圖片或者數據類型為np.unit8的numpy數組轉換為尺寸為(C x H x W)且數據類型為torch.float32,范圍在的Tensor。
同時,我們還可以通過代碼image= mnist_train[0][0]和label=mnist_train[0][1]來分別訪問一張圖片和其對應的標簽值。
1.2 構造數據集
在模型實際訓練過程中,數據讀取經常是訓練的性能瓶頸。同時,為了能夠更好的訓練模型我們通常會對數據進行打亂,以及分批(batch)的將數據輸入的模型中。在Pytorch中,我們可以通過DataLoader這個類來方便的完成上述功能。
start?=?time.time()train_iter?=?torch.utils.data.DataLoader(mnist_test,?batch_size=1024,?shuffle=True,?num_workers=2)
for?x_test,?y_test?in?train_iter:
????print(x_test.shape)
????print('%.2f?sec'?%?(time.time()?-?start))
#結果
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([1024,?1,?28,?28])
torch.Size([784,?1,?28,?28])
2.60?sec
其中batsh_size表示指定每次返回batsh_size個樣本;shuffle=True表示對數據集進行打亂;num_workers=2表示用兩個進程來讀取數據。
但需要注意的是,這里的數據集mnist_test是Pytorch內置的,那如果是我們自己讀入的數據集該怎么使用DataLoader呢?我們只需要首先將自己的數據集轉換成tensor,然后再通過TensorDataset這個類來構造一個數據集即可。
def?make_dataset():????x?=?torch.linspace(0,?100,?100,?dtype=torch.float32).reshape(-1,?2)
????y?=?torch.randn(50?)
????dataset?=?torch.utils.data.TensorDataset(x,?y)
????return?dataset
此時返回的dataset數據集也就同樣能夠通過DataLoader進行讀取。
2 Softmax多分類
在實現這個分類模型之前,我們先來介紹一下幾個需要用到的函數。
2.1 softmax計算實現
在上一篇文章中我們介紹了softmax的計算公式,其實現可以通過如下代碼來完成:
def?softmax(x):????s?=?torch.exp(x)
????return?s?/?torch.sum(s,?dim=1,?keepdim=True)#?此處觸發了廣播機制
a?=?torch.tensor([[1,2,3.],[2,3,1.]])
print(softmax(a))
#結果:
tensor([[0.0900,?0.2447,?0.6652],
????????[0.2447,?0.6652,?0.0900]])
其中torch.exp()為計算每個元素的指數次方;sum(s, dim=1, keepdim=True)表示計算得到每一行的和;最后是按位除操作。需要注意的是傳入的x必須是浮點類型的,不然會報錯。
2.2 交叉熵計算實現
假設我們現在有兩個樣本,其預測得到的概率分布為[0.1,0.3,0.6]和[0.5,0.4,0.1]。同時,正確的標簽分布為[0,0,1]和[0,1,0],則對應的交叉熵為。但是,我們在用代碼實現的時候完全不用這么麻煩,只需要通過正確的標簽找到預測概率分布中對應的值,再取對數即可。
例如[0,0,1]和[0,1,0]這兩個真實分布對應的標簽就應該是2和1(從0開始),因此我們只需要分別取[0.1,0.3,0.6]和[0.5,0.4,0.1]中第2個元素0.6和第1個原始0.4,再取對數就能實現交叉熵的計算。
上述過程通過如下代碼便可完成:
def?crossEntropy(logits,y):????c?=?-torch.log(logits.gather(1,y.reshape(-1,1)))
????return?torch.sum(c)#?注意這里返回的是和
logits?=?torch.tensor([[0.1,?0.3,?0.6],?[0.5,?0.4,?0.1]])
y?=?torch.LongTensor([2,?1])
c?=?crossEntropy(logits,y)
print(c)
#結果
tensor(1.4271)
其中.gather()就是根據指定維度和索引,選擇對應位置上的元素。同時,需要注意的是logits的每一行為一個樣本的概率分布,因此我們需要在行上進行索引操作,故gather()的第一個參數應該是1,這一點一定要注意。
2.3 準確率計算實現
在前面介紹softmax時說到,對于每個樣本的預測類別,我們會選擇對應概率值最大的類別作為輸出結果。因此,在計算預測的準確率時,我們首先需要通過torch.argmax()這個函數來返回預測得到的標簽。
y_true?=?torch.tensor([[2,1]])logits?=?torch.tensor([[0.1,0.3,0.6],[0.5,0.4,0.1]])
y_pred?=?logits.argmax(1)
print(y_pred)
#結果
tensor([2,?0])
最后,我們將預測得到的標簽同正確標簽進行對比即可求得準確率。
def?accuracy(y_true,logits):????acc?=?(logits.argmax(1)?==?y_true).float().mean()
????return?acc.item()
print(accuracy(y_true,logits))
#結果
0.5
2.4 評估模型
一般我們訓練得到一個模型后都需要對其在測試集上進行評估,也就是在測試集上計算其總的準確率。因此,我們首先需要計算得到所有預測對的樣本(而不僅僅只是一個batch),然后再除以總的樣本數即可。
def?evaluate(data_iter,?forward,?input_nodes,?w,?b):????acc_sum,?n?=?0.0,?0
????for?x,?y?in?data_iter:
????????logits?=?forward(x,?input_nodes,?w,?b)
????????acc_sum?+=?(logits.argmax(1)?==?y).float().sum().item()
????????n?+=?len(y)
????return?acc_sum?/?n
2.5 分類模型實現
w?=?torch.tensor(np.random.normal(0,?0.5,?[input_nodes,?output_nodes]),?????????????????dtype=torch.float32,?requires_grad=True)
b?=?torch.tensor(np.random.randn(output_nodes),?dtype=torch.float32,?requires_grad=True)
for?epoch?in?range(epochs):
????for?i,?(x,?y)?in?enumerate(train_iter):
????????logits?=?forward(x,?input_nodes,?w,?b)
????????l?=?crossEntropy(y,?logits)
????????l.backward()
????????gradientDescent([w,?b],?lr)
????????acc?=?accuracy(y,?logits)
????????if?i?%?50?==?0:
????????????print("Epoches[{}/{}]---batch[{}/{}]---acc{:.4}---loss?{:.4}".format(
????????????????epoches,?epoch,?len(mnist_train)?//?batch_size,?i,?acc,l))
????????????acc?=?evaluate(test_iter,?forward,?input_nodes,?w,?b)
????????????print("Epoches[{}/{}]--acc?on?test{:.4}".format(epochs,?epoch,?acc))
#?結果:
Epochs[8000/20]--acc?on?test0.8323
Epochs[8000/21]---batch[468/0]---acc0.8516---loss?47.13
Epochs[8000/21]---batch[468/50]---acc0.8203---loss?67.22
Epochs[8000/21]---batch[468/100]---acc0.9219---loss?38.74
Epochs[8000/21]---batch[468/150]---acc0.8516---loss?57.39
Epochs[8000/21]---batch[468/200]---acc0.8281---loss?74.76
Epochs[8000/21]---batch[468/250]---acc0.8672---loss?55.32
Epochs[8000/21]---batch[468/300]---acc0.8281---loss?60.19
可以看到,大約20輪迭代后,softmax模型在測試集上的準確率就達到了0.83左右。
3 總結
在這篇文章中,筆者首先介紹了FashionMNIST數據集。然后接著介紹了如何使用Pytorch中的DataLoader來構造訓練數據迭代器。最后,介紹了如何通過Pytorch來一步步的實現Softmax分類模型,包括如何實現softmax操作、如何快捷的計算交叉熵、如何計算模型的準確率等等。本次內容就到此結束,感謝您的閱讀!
本次內容就到此結束,感謝您的閱讀!如果你覺得上述內容對你有所幫助,歡迎關注并傳播本公眾號!若有任何疑問與建議,請添加筆者微信'nulls8'進行交流。青山不改,綠水長流,我們月來客棧見!
引用
[1]動手深度學習
[2]示例代碼:https://github.com/moon-hotel/DeepLearningWithMe
推薦閱讀
[1]想明白多分類必須得談邏輯回歸
[2]Pytorch之Linear與MSELoss
[3]Pytorch之擬合正弦函數你會嗎?
[4]你告訴我什么是深度學習
[5]《跟我一起深度學習》終于來了
總結
以上是生活随笔為你收集整理的pytorch 训练过程acc_Pytorch之Softmax多分类任务的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: linux内核怎么修改屏幕旋转方向_运维
 - 下一篇: Linux的实际操作:文件目录类实用指令