日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

深度学习pytorch--softmax回归(二)

發布時間:2023/12/3 pytorch 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度学习pytorch--softmax回归(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

softmax回歸的從零開始實現

    • 實驗前思考
    • 獲取和讀取數據
      • 獲取數據集
      • 查看數據集
        • 查看下載后的.pt文件
        • 查看mnist_train和mnist_test
      • 讀取數據集
        • 查看數據迭代器內容
    • 初始化模型參數
    • 定義softmax函數
    • 定義模型
    • 定義損失函數
    • 計算分類準確率
    • 模型評價--準確率
    • 開始訓練
    • 可視化
    • 總結
    • 完整代碼

實驗前思考

  • 本文不使用框架解決多分類問題。
  • 一定要先明白實驗原理??煽床┛蜕疃葘W習pytorch–softmax回歸(一)
  • 一定要先弄清楚數據是怎么用Tensor表示的。

獲取和讀取數據

這里使用Fashion-MNIST為例,訓練集60000張,測試集10000張,設置batch_size大小為256。

獲取數據集

如果沒有下載的話,將download設置為True。

mnist_train=torchvision.datasets.FashionMNIST('./Datasets/FashionMNIST',train=True,download=False,transform=transforms.ToTensor()) mnist_test=torchvision.datasets.FashionMNIST('./Datasets/FashionMNIST',train=False,download=False,transform=transforms.ToTensor())

查看數據集

查看下載后的.pt文件

要使用的是processed文件夾下的training.pt和test.pt文件,包含了數據以及其標簽,用元組的形式存儲。
形如:

(tensor([],dtype=torch.unit8),tensor([]))
  • 第一個tensor表示數據的數量,形狀為torch.Size([60000,28,28]),60000表示.pt文件包含1000張圖片,28為寬和高都是28個像素,每個像素用一個數字表示(也可以說是圖像的特征)。
  • 第二個tensor表示每張圖片的真實標簽(0-9)。形狀為torch.Size([60000]),每個數字代表真實標簽。

上次線性回歸的數據集是自己手工構造的tensor,這次是圖片的tensor表示。

查看mnist_train和mnist_test

查看經過torchvision.datasets.FashionMNIST處理后的mnist_train和mnist_test,

print(mnist_train) #查看mnist_train print(type(mnist_train)) #查看它的類型 print(len(mnist_train), len(mnist_test)) feature, label = mnist_train[0] #訪問數據集的任一個樣本 print(feature.shape, label) # Channel x Height x Width

輸出:

Dataset FashionMNISTNumber of datapoints: 60000Root location: ./Datasets/FashionMNISTSplit: TrainStandardTransformTransform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 60000 10000 torch.Size([1, 28, 28]) 9

由上面代碼可見,torchvision.datasets.FashionMNIST將原來存儲在一個張量的訓練數據分成了60000份,可迭代訪問或下標訪問mnist.train。

  • feature為單張圖片的tensor表示,形狀為torch.Size([1, 28, 28]),其中1為通道數量.
  • label為int類型,表示真實標簽。

讀取數據集

DataLoader將之前的數據做成一個批量、隨機打亂且可以通過多進程加速讀取的迭代器。

batch_size=256 num_workers=0 #多進程加速數據讀取,0則不需要額外的進程 train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers) test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)

查看數據迭代器內容

for X,y in train_iter:print(X.size())print(y.size())break

輸出:

torch.Size([256, 1, 28, 28]) torch.Size([256])

一個X表示256個樣本的特征(也就是softmax回歸(一)中公式里的4個x,這里是28*28個x),一個y表示其每個樣本的標簽。

說明DataLoader只是將原來單個數據的張量通過增加一個維度合成了256個數據的張量。通俗地講就是將256個1*28*28的張量放在一起,然后外面加一層[]。以后升維和降維要有這個思維。

關于該數據集的詳細使用可看博客深度學習pytorch–MNIST數據集

初始化模型參數

由于像素(特征)有28*28=786個,所以輸入層為一個786長度的向量。
由于為10分類任務,所以輸出層的輸出個數為10。

因此,根據softmax回歸(一)的公式,可以推出 權重為參數為784X10的矩陣,偏置為1X10的矩陣。
上述分析的時候,腦子一定要有神經網絡圖和公式,就會覺得很明朗。根據公式還能夠發現一點,不管是單樣本還是批量樣本,權重的形狀是不發生改變的。

num_inputs=784 #28*28個像素(特征) num_outputs=10 #分類的個數#權重初始化為均值為0,標準差為0.01的分布。 W=torch.tensor(np.random.normal(0,0.01,(num_inputs,num_outputs)),dtype=torch.float,requires_grad=True) b=torch.zeros(num_outputs,dtype=torch.float,requires_grad=True) #偏置初始化為0

得到權重形狀為torch.Size([786,10])的W和一個形狀為torch.Size(1,10])的偏置b。

定義softmax函數

首先,想一下,根據公式,softmax函數的輸入和輸出是什么?
輸入是網絡輸出層的結果,也就是每個樣本10個輸出。此處為批量處理,所以根據softmax回歸(一)的公式,可以知道模型輸出為一個256*10的矩陣。256為樣本數量,10為10個分類的輸出。
輸出是根據softmax公式將其轉化成概率的形式。

def softmax(X): #X為一個形狀為256*10的二維張量X_exp=X.exp() #矩陣中每個元素取指數partition=X_exp.sum(dim=1,keepdim=True) #每行進行求和,并且保持維度不變,不懂的話可以看博客return X_exp/partition #實現softmax公式,用了廣播機制

先隨意定義一個X測試一下函數,下面的sum(dim=1)表示每一行相加,并且降低一個維度。如果dim=0則表示每一列相加。

X = torch.rand((2, 5)) X_prob = softmax(X) print(X_prob, X_prob.sum(dim=1))

輸出:

tensor([[0.2206, 0.1520, 0.1446, 0.2690, 0.2138],[0.1540, 0.2290, 0.1387, 0.2019, 0.2765]]) tensor([1., 1.])

從輸出可以看到softmax函數定義的代碼沒有問題。

定義模型

定義模型之前想一想模型是什么,模型的輸入是什么,輸出是什么?
模型是一層神經網絡+一層softmax函數,
模型的輸入是迭代器的X,表示256個圖片的像素(數據特征),形狀為torch.Size([256, 1, 28, 28]),其中1表示通道數量
模型的輸出是softmax函數的輸出,形狀為torch.Size([256, 10]),256表示batch_size(256)個樣本,10表示每個樣本對每個分類的概率分布情況。

def net(X):O=torch.mm(X.view(-1, num_inputs),W)+b #如果最后一個維度變了則,按以前的元素順序來組合。return softmax(O)

由于迭代器中X的形狀不對應神經網絡輸入層該有的形狀,所以通過view把X從torch.Size([256, 1, 28, 28])變成torch.Size([256, 784])。
以前不理解為什么經常要像這樣用view,現在思路很清晰。主要有2點原因:

  • 1.腦子一定要有神經網絡結構(此處只有一層786輸入,10輸出),可以在紙上畫一畫。
  • 2.張量降維和升維的思維一定要正確,升維就是加括號,降維就是減少中括號,沒有改變內容,不要被形狀的數字給迷惑了。

定義損失函數

本實驗采用交叉熵損失函數。
輸入為預測結果y_hat和真實標簽y。
其中y_hat為torch.Size([256, 10])的張量,y為torch.Size([256])的張量。
輸出為運算結果。

def cross_entropy(y_hat,y): #y_hat為模型輸出(所有樣本對所有樣本的softmax概率值),y為標簽(真實值)return - torch.log(y_hat.gather(1, y.view(-1, 1)))

真正計算的時候還需要用.sum()將張量中的元素相加才是損失函數值。
對比之后用框架實現該實驗后的loss值才發現在計算完log之后少乘了 預測標簽概率值 。算啦,不重要,以后有機會再回來改叭。
這里用到了gather函數,這個函數的作用就是找出y_hat中對應真實標簽的概率,舉例如下:

y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]]) y = torch.LongTensor([0, 2]) y_hat.gather(1, y.view(-1, 1))

輸出:

tensor([[0.1000],[0.5000]])

0.1就是將真實標簽中的0作為索引,在y_hat中得到的,相當于y_hat[0][0]。
0.5就是將真實標簽中的2作為索引,在y_hat中得到的,相當于y_hat[1][2]。

計算分類準確率

先計算預測正確的個數,也就是判斷每個樣本預測最大概率的標簽是否和真實標簽y相等就可以了。
再除以預測總數,就得到準確率。
下面的代碼用的是y_hat處理后的張量和y張量中的每個元素比較,通過float()將true和false分別轉換為1,0,再通過mean()求和平均

def accuracy(y_hat, y):return (y_hat.argmax(dim=1) == y).float().mean().item()

其中dim=1表示每行,dim=0表示每列。

模型評價–準確率

根據上面的思想,可以評價模型net在測試集上的準確率。

def evaluate_accuracy(data_iter,net): #在所有樣本上的準確率acc_sum,n=0.0,0for X,y in data_iter:acc_sum+=(net(X).argmax(dim=1) == y).float().sum().item()n+=y.shape[0] #獲取總數量(此處每批256)return acc_sum / n

其中net(X)就是y_hat,因為都表示模型的輸出,形狀為torch.Size([256, 10])。

開始訓練

訓練步驟:

  • 迭代數據
  • 將數據導入模型得到輸出
  • 計算損失函數
  • 反向傳播計算梯度
  • 使用優化算法更新參數
  • 梯度清零

每個epoch過后將訓練好的參數在測試集上計算一下準確率。

num_epochs=5 lr=0.1 for epoch in range(num_epochs):train_loss_sum=0.0train_acc_sum=0.0n=0 #用來計算數據總數for X,y in train_iter:y_hat=net(X) loss=cross_entropy(y_hat,y).sum() #計算損失函數loss.backward() #反向傳播#參數更新sgd([W,b],lr,batch_size)#梯度清零W.grad.data.zero_()b.grad.data.zero_()train_loss_sum+=loss.item()train_acc_sum+=(y_hat.argmax(dim=1) == y).sum().item()n+=y.shape[0]test_acc=evaluate_accuracy(test_iter,net)print('epoch {}, loss {:.4f}, train acc {:.3f}, test acc {:.3f}'.format(epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc))

可視化

對訓練結果進行可視化。
下圖第一行文本為真實標簽。
第二行文本為模型預測結果。
第三行為圖像輸出(預先給定的圖像)。

def use_svg_display():"""Use svg format to display plot in jupyter"""display.set_matplotlib_formats('svg')def get_fashion_mnist_labels(labels):text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_fashion_mnist(images, labels):use_svg_display()# 這里的_表示我們忽略(不使用)的變量_, figs = plt.subplots(1, len(images), figsize=(12, 12))for f, img, lbl in zip(figs, images, labels):f.imshow(img.view((28, 28)).numpy())f.set_title(lbl)f.axes.get_xaxis().set_visible(False)f.axes.get_yaxis().set_visible(False)plt.show()X, y = iter(test_iter).next() true_labels = get_fashion_mnist_labels(y.numpy()) pred_labels = get_fashion_mnist_labels(net(X).argmax(dim=1).numpy()) titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)] show_fashion_mnist(X[0:9], titles[0:9])

總結

  • 所謂特征就是每個像素的的tensor表示。
  • 提取特征就是通過一個權重w與特征x相乘,權重越大則說明該像素的特征提取得越多。
  • 張量降維和升維的思維要正確,升維就是加括號,降維就是減少中括號,沒有改變內容,不要被形狀的數字給迷惑了。
  • 寫函數或者模型的時候,先想一想要實現什么功能,再想一想輸入和輸出是什么。

完整代碼

#softmax回歸的從零開始實現(MINST數據集) import torch import torchvision import numpy as np import torchvision.transforms as transforms import matplotlib.pyplot as plt from IPython import display#獲取數據集 mnist_train=torchvision.datasets.FashionMNIST('./Datasets/FashionMNIST',train=True,download=False,transform=transforms.ToTensor()) mnist_test=torchvision.datasets.FashionMNIST('./Datasets/FashionMNIST',train=False,download=False,transform=transforms.ToTensor())#讀取數據集 batch_size=256 num_workers=0 #多進程加速數據讀取,0則不使用多進程 train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers) test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)#初始化模型參數 num_inputs=784 #28*28個像素(特征) num_outputs=10 #分類的個數W=torch.tensor(np.random.normal(0,0.01,(num_inputs,num_outputs)),dtype=torch.float,requires_grad=True) b=torch.zeros(num_outputs,dtype=torch.float,requires_grad=True)#定義模型 def softmax(X):X_exp=X.exp() #矩陣中每個元素取指數partition=X_exp.sum(dim=1,keepdim=True) #每行進行求和,并且保持維度不變,不懂的話可以看博客return X_exp/partition #實現softmax公式,用了廣播機制def net(X):O=torch.mm(X.view(-1, num_inputs),W)+breturn softmax(O)#定義損失函數 def cross_entropy(y_hat,y): #y_hat為模型輸出(所有樣本對所有樣本的softmax概率值),y為標簽(真實值)return - torch.log(y_hat.gather(1, y.view(-1, 1)))#模型評價 def evaluate_accuracy(data_iter,net): #在所有樣本上的準確率acc_sum,n=0.0,0for X,y in data_iter:acc_sum+=(net(X).argmax(dim=1) == y).float().sum().item()n+=y.shape[0] #獲取總數量(此處每批256)return acc_sum / n#定義優化算法 def sgd(params,lr,batch_size):for param in params:param.data-=lr*param.grad/batch_size #除以batch_size之后計算批量loss的時候就不用求平均了,只需要sum() #開始訓練 num_epochs=5 lr=0.1 for epoch in range(num_epochs):train_loss_sum=0.0train_acc_sum=0.0n=0 #用來計算數據總數for X,y in train_iter:y_hat=net(X) loss=cross_entropy(y_hat,y).sum() #計算損失函數loss.backward() #反向傳播#參數更新sgd([W,b],lr,batch_size)#梯度清零W.grad.data.zero_()b.grad.data.zero_()train_loss_sum+=loss.item()train_acc_sum+=(y_hat.argmax(dim=1) == y).sum().item()n+=y.shape[0]test_acc=evaluate_accuracy(test_iter,net)print('epoch {}, loss {:.4f}, train acc {:.3f}, test acc {:.3f}'.format(epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc)) #可視化 def use_svg_display():"""Use svg format to display plot in jupyter"""display.set_matplotlib_formats('svg')def get_fashion_mnist_labels(labels):text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_fashion_mnist(images, labels):use_svg_display()# 這里的_表示我們忽略(不使用)的變量_, figs = plt.subplots(1, len(images), figsize=(12, 12))for f, img, lbl in zip(figs, images, labels):f.imshow(img.view((28, 28)).numpy())f.set_title(lbl)f.axes.get_xaxis().set_visible(False)f.axes.get_yaxis().set_visible(False)plt.show()X, y = iter(test_iter).next() true_labels = get_fashion_mnist_labels(y.numpy()) pred_labels = get_fashion_mnist_labels(net(X).argmax(dim=1).numpy()) titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)] show_fashion_mnist(X[0:9], titles[0:9])

總結

以上是生活随笔為你收集整理的深度学习pytorch--softmax回归(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。