最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

09 Softmax 回歸 + 損失函數(shù) + 圖片分類數(shù)據(jù)集【動手學(xué)深度學(xué)習(xí)v2

2023-07-31 02:33 作者:風(fēng)神ねこ  | 我要投稿

為老師講的手動實(shí)現(xiàn)代碼添加了更詳盡的注釋和可讀性加強(qiáng)!

1.數(shù)據(jù)讀取

import torch

import torchvision

from torch.utils import data

from torchvision import transforms

import pandas as pd

def load_data_fashion_mnist(batch_size):

? ? '''技巧:及時(shí)封裝以前的函數(shù),避免出現(xiàn)代碼堆積,是一個(gè)值得學(xué)習(xí)的好習(xí)慣'''

? ? # 使用totensor將圖像從PIL類型轉(zhuǎn)換為32位數(shù)浮點(diǎn),并且會自動除以255歸一化至[0,1]

? ? trans=transforms.ToTensor()

? ? mnist_train=torchvision.datasets.FashionMNIST(root='./data',train=True,transform=trans,download=True) #train為True表示下載訓(xùn)練集

? ? mnist_test=torchvision.datasets.FashionMNIST(root='./data',train=False,transform=trans,download=True)

? ? return (data.DataLoader(mnist_train,batch_size,True,num_workers=4),data.DataLoader(mnist_test,batch_size,True,num_workers=4))

batch_size=256 #每次讀取256批次圖片

train_iter,test_iter=load_data_fashion_mnist(batch_size) #獲取兩個(gè)dataloader


2.展平圖像與初始化參數(shù)

視為28*28=784的向量,故輸入是784,由于數(shù)據(jù)集有10個(gè)類別,所以網(wǎng)絡(luò)輸出維度是10

num_inputs=784

num_outputs=10

W=torch.normal(0,0.01,size=(num_inputs,num_outputs),requires_grad=True) #權(quán)重矩陣784x10

b=torch.zeros(num_outputs,requires_grad=True) #偏差矩陣 10x1

3.定義softmax算符:

這里要掌握張量計(jì)算的方法

當(dāng)調(diào)?sum運(yùn)算符時(shí),我們可以指定保持在原始張量的軸數(shù),?不折疊求和的維度,如對(3,2)進(jìn)行按列求和,會得到(2,),設(shè)置keepdim為True就是(1,2)即一行,分別是兩列的和

def softmax(X):

? ? X_exp=torch.exp(X) #對每個(gè)元素進(jìn)行指數(shù)計(jì)算 這里X輸入是

? ? partition=X_exp.sum(1,keepdim=True) #這里是對行求和,獲得的是每行的和

? ? return X_exp/partition

4. 定義模型

1. 例如batch_size=256,則X這里是(256,784)代表256張圖片 每個(gè)圖片有28x28個(gè)像素(被展平成784)

2. 權(quán)重矩陣為(784,10)代表對每種輸出的各特征權(quán)重

3. 因此256x784@784x10==256x10 即每張圖片會輸出十個(gè)類別的置信度,如衣服20% T恤60%……大衣5%,對十個(gè)輸出會加上一個(gè)bias,通過廣播機(jī)制作用到所有圖片

def net(X):

? ? return softmax(torch.matmul(X.reshape((-1,W.shape[0])),W)+b)

定義交叉熵?fù)p失

交叉熵只在意真實(shí)值的預(yù)測概率,因此這里是抽取每一行對應(yīng)是真實(shí)類別的預(yù)測概率的那個(gè)值,拿出來求負(fù)對數(shù)


例如第一個(gè)樣本應(yīng)該是2類(設(shè)共三類,從0-2),并預(yù)測概率是0.7,第二個(gè)樣本應(yīng)該是1類,預(yù)測是1類概率為0.5,則交叉熵?fù)p失為

$$-log(0.7) 和 -log(0.5)$$

def cross_entropy(y_pred,y_true):

? ? return -torch.log(y_pred[range(len(y_pred)),y_true]) #這里必須用range,相當(dāng)于遍歷每行,對該行找對應(yīng)的那個(gè)類的預(yù)測概率

#如果用y_pred[:,y_true] 相當(dāng)于返回指定的列,而不是概率

計(jì)算準(zhǔn)確率

def accuracy(y_pred,y_true):

? ? '''計(jì)算準(zhǔn)確率'''

? ? if len(y_pred.shape)>1 and y_pred.shape[1]>1:

? ? ? ? '''如果其是二維數(shù)組,即行數(shù)大于一(多個(gè)樣本),且有多列(多分類)'''

? ? ? ? y_pred=y_pred.argmax(axis=1) #對每行獲取其最大值的索引

? ? result=(y_pred==y_true) #在對應(yīng)位置比較是否預(yù)測正確,比如[2,3,4],[2,3,5]結(jié)果就是[True,True,False]

? ? return result.sum()

評估在任意模型上的準(zhǔn)確率

def evaluate_accuracy(net,data_iter):

? ? '''計(jì)算模型在指定數(shù)據(jù)集上的模型精度'''

? ? if isinstance(net,torch.nn.Module):

? ? ? ? net.eval() #設(shè)置為評估模式

? ? metric=Accumulator(2) #正確預(yù)測數(shù),預(yù)測總數(shù)

? ? for X,y in data_iter: #這里y是對應(yīng)的類別標(biāo)簽,因此后面numel實(shí)際是返回了這批樣本個(gè)數(shù)

? ? ? ? metric.add(accuracy(net(X),y),y.numel()) #numel number of element 返回元素總數(shù),例如2x3矩陣返回就是6個(gè)元素

? ? ? ? #這里表示把這批樣本預(yù)測的正確率和個(gè)數(shù)累加到accumulator中

? ? return metric[0]/metric[1] #預(yù)測正確數(shù)除以預(yù)測總數(shù)


#--------------實(shí)現(xiàn)accumulator-------------------

class Accumulator:

? ? def __init__(self,n) -> None:

? ? ? ? self.data=[0.0]*n

? ? def add(self,*args):

? ? ? ? self.data=[a+float(b) for a,b in zip(self.data,args)] #其實(shí)就是準(zhǔn)確率相加 樣本個(gè)數(shù)相加

? ? ? ? #如 (0.5,6)+(0.2,8)-->(0.7,14)

? ? def reset(self):

? ? ? ? self.data=[0.0]*len(self.data)

? ? def __getitem__(self,idx):

? ? ? ? return self.data[idx] #定義方括號索引

回歸訓(xùn)練和可視化

def train_epoch_ch3(net, train_iter, loss, updater):

? ? """訓(xùn)練模型?個(gè)迭代周期(定義?第3章) """

? ? # 將模型設(shè)置為訓(xùn)練模式

? ? if isinstance(net, torch.nn.Module):

? ? ? ? net.train() #開啟訓(xùn)練模式

? ? # 累計(jì)訓(xùn)練損失總和、訓(xùn)練準(zhǔn)確度總和、樣本數(shù)

? ? metric = Accumulator(3)

? ? for X, y in train_iter:

? ? # 計(jì)算梯度并更新參數(shù)

? ? ? ? y_hat = net(X) #計(jì)算預(yù)測值

? ? ? ? l = loss(y_hat, y) #交叉熵?fù)p失函數(shù)計(jì)算損失

? ? if isinstance(updater, torch.optim.Optimizer):

? ? ? ? # 使?PyTorch內(nèi)置的優(yōu)化器和損失函數(shù)

? ? ? ? updater.zero_grad() #例如小批量隨機(jī)梯度下降,需要手動清空梯度

? ? ? ? l.mean().backward()

? ? ? ? updater.step()

? ? else:

? ? ? ? # 使?定制的優(yōu)化器和損失函數(shù)

? ? ? ? l.sum().backward()

? ? ? ? updater(X.shape[0]) #根據(jù)批次大小update

? ? metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())

? ? # 返回訓(xùn)練損失和訓(xùn)練精度,即損失值除以訓(xùn)練樣本數(shù)和精度處于訓(xùn)練樣本數(shù)

? ? return metric[0] / metric[2], metric[1] / metric[2]



def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save

? ? """訓(xùn)練模型(定義?第3章) """

? ? result=[] #記錄損失,訓(xùn)練集精度,驗(yàn)證集精度

? ? for epoch in range(num_epochs):

? ? ? ? train_metrics = train_epoch_ch3(net, train_iter, loss, updater) #返回訓(xùn)練損失和訓(xùn)練精度

? ? ? ? test_acc = evaluate_accuracy(net, test_iter) #在驗(yàn)證集上的精度

? ? ? ? result.append([train_metrics[0],train_metrics[1],test_acc])

? ? result_df=pd.DataFrame(result,columns=['train loss','train accuracy','test accuracy'],index=range(1,len(result)+1))

? ? result_df.plot(xlabel='epoch',title='Softmax Regression Result')

? ? return result_df


def stochastic_gradient_descent(params,eta,batch_size):

? ? '''小批量隨機(jī)梯度下降'''

? ? with torch.no_grad(): #更新時(shí)不參與梯度計(jì)算

? ? ? ? for param in params:

? ? ? ? ? ? param-=eta*param.grad/batch_size #和公式相同

? ? ? ? ? ? param.grad.zero_() #清除梯度(避免累計(jì)梯度)

? ? ?

def updater(batch_size):

? ? return stochastic_gradient_descent([W,b],lr,batch_size)


lr=0.1 ?

num_epochs=10

result=train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,updater)





09 Softmax 回歸 + 損失函數(shù) + 圖片分類數(shù)據(jù)集【動手學(xué)深度學(xué)習(xí)v2的評論 (共 條)

分享到微博請遵守國家法律
吴堡县| 新乐市| 阿勒泰市| 杭州市| 广元市| 玛纳斯县| 湖口县| 夹江县| 富源县| 都昌县| 南皮县| 霍林郭勒市| 基隆市| 花莲县| 读书| 吴忠市| 东乡族自治县| 岳阳市| 志丹县| 拉萨市| 蒙自县| 河池市| 竹北市| 广安市| 鄂州市| 宜宾市| 瑞金市| 准格尔旗| 平定县| 屏东市| 凤台县| 丰城市| 阳高县| 建水县| 庆云县| 尉氏县| 闽侯县| 汽车| 屏山县| 塔城市| 乐平市|