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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

backward理解

發(fā)布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 backward理解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

backward:自動求梯度。計算小批量隨機梯度。

當(dāng)模型和損失函數(shù)形式較為簡單時,上面的誤差最小化問題的解可以直接用公式表達(dá)出來。這類解 叫作解析解(analytical solution)。本節(jié)使用的線性回歸和平方誤差剛好屬于這個范疇。然而,大多數(shù) 深度學(xué)習(xí)模型并沒有解析解,只能通過優(yōu)化算法有限次迭代模型參數(shù)來盡可能降低損失函數(shù)的值。這類解叫作數(shù)值解(numerical solution)

在求數(shù)值解的優(yōu)化算法中,小批量隨機梯度下降(mini-batch stochastic gradient descent)在深度學(xué)習(xí)中被廣泛使用。它的算法很簡單:1.先選取一組模型參數(shù)的初始值,如隨機選取;2.接下來對參數(shù)進(jìn)行多次迭代,使每次迭代都可能降低損失函數(shù)的值。

在每次迭代中,先隨機均勻采樣一個由固定數(shù)目訓(xùn)練數(shù)據(jù)樣本所組成的小批量(mini-batch)B,然后求小批量中數(shù)據(jù)樣本的平均損失有關(guān)模型參數(shù)的導(dǎo) 數(shù)(梯度),最后用此結(jié)果與預(yù)先設(shè)定的一個正數(shù)的乘積作為模型參數(shù)在本次迭代的減小量。

?在上式中,|B| 代表每個小批量中的樣本個數(shù)(批量大小,batch size),η 稱作學(xué)習(xí)率(learning rate)并取正數(shù)。需要強調(diào)的是,這里的批量大小和學(xué)習(xí)率的值是人為設(shè)定的,并不是通過模型訓(xùn)練學(xué) 出的,因此叫作超參數(shù)(hyperparameter)。我們通常所說的“調(diào)參”指的正是調(diào)節(jié)超參數(shù),例如通過反復(fù)試錯來找到超參數(shù)合適的值。在少數(shù)情況下,超參數(shù)也可以通過模型訓(xùn)練學(xué)出。

梯度累積

所謂梯度累積,其實很簡單,我們梯度下降所用的梯度,實際上是多個樣本算出來的梯度的平均值,以 batch_size=128 為例,你可以一次性算出 128 個樣本的梯度然后平均,我也可以每次算 16 個樣本的平均梯度,然后緩存累加起來,算夠了 8 次之后,然后把總梯度除以 8,然后才執(zhí)行參數(shù)更新。當(dāng)然,必須累積到了 8 次之后,用 8 次的平均梯度才去更新參數(shù),不能每算 16 個就去更新一次,不然就是 batch_size=16 了。

定義優(yōu)化函數(shù)

以下的?sgd?函數(shù)實現(xiàn)了上一節(jié)中介紹的小批量隨機梯度下降算法。它通過不斷迭代模型參數(shù)來優(yōu)化 損失函數(shù)。這里自動求梯度模塊計算得來的梯度是一個批量樣本的梯度和。我們將它除以批量大小來得到平均值。

def sgd(params, lr, batch_size):'''小批量隨機梯度下降params: 權(quán)重lr: 學(xué)習(xí)率batch_size: 批大小'''for param in params:param.data -= lr * param.grad / batch_size

在訓(xùn)練中,我們將多次迭代模型參數(shù)。在每次迭代中,我們根據(jù)當(dāng)前讀取的小批量數(shù)據(jù)樣本(特征 X 和標(biāo)簽 y ),通過調(diào)用反向函數(shù) backward 計算小批量隨機梯度,并調(diào)用優(yōu)化算法 sgd 迭代模型參數(shù)。由于我們之前設(shè)批量大小 batch_size 為10,每個小批量的損失 l 的形狀為(10, 1)。回憶一下自動 求梯度一節(jié)。由于變量?l?并不是一個標(biāo)量,所以我們可以調(diào)用?.sum()?將其求和得到一個標(biāo)量,再運行 l.backward() 得到該變量有關(guān)模型參數(shù)的梯度。注意在每次更新完參數(shù)后不要忘了將參數(shù)的梯度清零。(如果不清零,PyTorch默認(rèn)會對梯度進(jìn)行累加)

對于這種我們自己定義的變量,我們稱之為葉子節(jié)點(leaf nodes),而基于葉子節(jié)點得到的中間或最終變量則可稱之為結(jié)果節(jié)點

x = torch.tensor(1.0, requires_grad=True) y = torch.tensor(2.0, requires_grad=True) z = x**2+y z.backward() print(z, x.grad, y.grad)>>> tensor(3., grad_fn=<AddBackward0>) tensor(2.) tensor(1.)

z對x求導(dǎo)為:2,z對y求導(dǎo)為:1

可以z是一個標(biāo)量,當(dāng)調(diào)用它的backward方法后會根據(jù)鏈?zhǔn)椒▌t自動計算出葉子節(jié)點的梯度值

求一個矩陣對另一矩陣的導(dǎo)數(shù)束手無策。

對矩陣求和不就是等價于z點乘一個一樣維度的全為1的矩陣嗎?即??,而這個I也就是我們需要傳入的grad_tensors參數(shù)。(點乘只是相對于一維向量而言的,對于矩陣或更高為的張量,可以看做是對每一個維度做點乘)

【點乘:對兩個向量執(zhí)行點乘運算,就是對這兩個向量對應(yīng)位一一相乘之后求和的操作】

?如:

x = torch.tensor([2., 1.], requires_grad=True) y = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)z = torch.mm(x.view(1, 2), y) print(f"z:{z}") z.backward(torch.Tensor([[1., 0]]), retain_graph=True) print(f"x.grad: {x.grad}") print(f"y.grad: {y.grad}")>>> z:tensor([[5., 8.]], grad_fn=<MmBackward>) x.grad: tensor([[1., 3.]]) y.grad: tensor([[2., 0.],[1., 0.]])

結(jié)果解釋如下:

查看梯度以及參數(shù)更新的問題?

import torch import torch.nn as nn import numpy as np import torch.optim as optim from torchsummary import summary import os from torch.utils.data.dataset import Dataset from torch.utils.data import DataLoader from tqdm import tqdm# 設(shè)置一下數(shù)據(jù)集 數(shù)據(jù)集的構(gòu)成是隨機兩個整數(shù),形成一個加法的效果 input1 + input2 = label class TrainDataset(Dataset):def __init__(self):super(TrainDataset, self).__init__()self.data = []for i in range(1,1000):for j in range(1,1000):self.data.append([i,j])def __getitem__(self, index):input_data = self.data[index]label = input_data[0] + input_data[1]return torch.Tensor(input_data),torch.Tensor([label])def __len__(self):return len(self.data)class TestNet(nn.Module):def __init__(self):super(TestNet, self).__init__()self.net1 = nn.Linear(2,1)def forward(self, x):x = self.net1(x)return xdef train():traindataset = TrainDataset()traindataloader = DataLoader(dataset = traindataset,batch_size=1,shuffle=False)testnet = TestNet().cuda()myloss = nn.MSELoss().cuda()optimizer = optim.SGD(testnet.parameters(), lr=0.001 )for epoch in range(100):for data,label in traindataloader :print("\n=====迭代開始=====")data = data.cuda()label = label.cuda()output = testnet(data)print("輸入數(shù)據(jù):",data)print("輸出數(shù)據(jù):",output)print("標(biāo)簽:",label)loss = myloss(output,label)optimizer.zero_grad()for name, parms in testnet.named_parameters(): print('-->name:', name)print('-->para:', parms)print('-->grad_requirs:',parms.requires_grad)print('-->grad_value:',parms.grad)print("===")loss.backward()optimizer.step()print("=============更新之后===========")for name, parms in testnet.named_parameters(): print('-->name:', name)print('-->para:', parms)print('-->grad_requirs:',parms.requires_grad)print('-->grad_value:',parms.grad)print("===")print(optimizer)input("=====迭代結(jié)束=====")if __name__ == '__main__':os.environ["CUDA_VISIBLE_DEVICES"] = "{}".format(3)train()

?

?

?

?

參考自:動手學(xué)深度學(xué)習(xí)(Pytorch)第2章深度學(xué)習(xí)基礎(chǔ)-上 - 知乎

Pytorch autograd,backward詳解 - 知乎

Pytorch 模型 查看網(wǎng)絡(luò)參數(shù)的梯度以及參數(shù)更新是否正確,優(yōu)化器學(xué)習(xí)率設(shè)置固定的學(xué)習(xí)率,分層設(shè)置學(xué)習(xí)率_呆呆象呆呆的博客-CSDN博客

總結(jié)

以上是生活随笔為你收集整理的backward理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。