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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Pytorch来拟合函数

發(fā)布時間:2024/8/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Pytorch来拟合函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

其實各大深度學習框架背后的原理都可以理解為擬合一個參數(shù)數(shù)量特別龐大的函數(shù),所以各框架都能用來擬合任意函數(shù),Pytorch也能。在這篇博客中,就以擬合y = ax + b為例(a和b為需要擬合的參數(shù)),說明在Pytorch中如何擬合一個函數(shù)。

一、定義擬合網(wǎng)絡

1、觀察普通的神經(jīng)網(wǎng)絡的優(yōu)化流程

# 定義網(wǎng)絡 net = ... # 定義優(yōu)化器 optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005) # 定義損失函數(shù) loss_op = torch.nn.MSELoss(reduction='sum') # 優(yōu)化 for step, (inputs, tag) in enumerate(dataset_loader):# 向前傳播outputs = net(inputs)# 計算損失loss = loss_op(tag, outputs)# 清空梯度optimizer.zero_grad()# 向后傳播loss.backward()# 更新梯度optimizer.step()

上面的代碼就是一般情況下的流程。為了能使用Pytorch內(nèi)置的優(yōu)化器,所以我們需要定義一個一個網(wǎng)絡,實現(xiàn)函數(shù)parameters(返回需要優(yōu)化的參數(shù))和forward(向前傳播);為了能支持GPU優(yōu)化,還需要實現(xiàn)cuda和cpu兩個函數(shù),把參數(shù)從內(nèi)存復制到GPU上和從GPU復制回內(nèi)存。基于以上要求,網(wǎng)絡的定義就類似于:

class Net:def __init__(self):# 在這里定義要求的參數(shù)passdef cuda(self):# 傳輸參數(shù)到GPUpassdef cpu(self):# 把參數(shù)傳輸回內(nèi)存passdef forward(self, inputs):# 實現(xiàn)向前傳播,就是根據(jù)輸入inputs計算一遍輸出passdef parameters(self):# 返回參數(shù)pass

在擬合數(shù)據(jù)量很大時,還可以使用GPU來加速;如果沒有英偉達顯卡,則可以不實現(xiàn)cuda和cpu這兩個函數(shù)。

2、初始化網(wǎng)絡

回顧本文目的,擬合: y = ax + b, 所以在__init__函數(shù)中就需要定義a和b兩個參數(shù),另外為了實現(xiàn)parameters、cpu和cuda,還需要定義屬性__parameters和__gpu:

def __init__(self):# y = a*x + bself.a = torch.rand(1, requires_grad=True) # 參數(shù)aself.b = torch.rand(1, requires_grad=True) # 參數(shù)bself.__parameters = dict(a=self.a, b=self.b) # 參數(shù)字典self.___gpu = False # 是否使用gpu來擬合

要擬合的參數(shù),不能初始化為0! ,一般使用隨機值即可。還需要把requires_grad參數(shù)設置為True,這是為了支持向后傳播。

3、實現(xiàn)向前傳播

def forward(self, inputs):return self.a * inputs + self.b

非常的簡單,就是根據(jù)輸入inputs計算一遍輸出,在本例中,就是計算一下 y = ax + b。計算完了要記得返回計算的結(jié)果。

4、把參數(shù)傳送到GPU

為了支持GPU來加速擬合,需要把參數(shù)傳輸?shù)紾PU,且需要更新參數(shù)字典__parameters:

def cuda(self):if not self.___gpu:self.a = self.a.cuda().detach().requires_grad_(True) # 把a傳輸?shù)絞puself.b = self.b.cuda().detach().requires_grad_(True) # 把b傳輸?shù)絞puself.__parameters = dict(a=self.a, b=self.b) # 更新參數(shù)self.___gpu = True # 更新標志,表示參數(shù)已經(jīng)傳輸?shù)絞pu了# 返回self,以支持鏈式調(diào)用return self

參數(shù)a和b,都是先調(diào)用detach再調(diào)用requires_grad_,是為了避免錯誤raise ValueError("can't optimize a non-leaf Tensor")(參考:ValueError: can’t optimize a non-leaf Tensor?)。

4、把參數(shù)傳輸回內(nèi)存

類似于cuda函數(shù),不做過多解釋。

def cpu(self):if self.___gpu:self.a = self.a.cpu().detach().requires_grad_(True)self.b = self.b.cpu().detach().requires_grad_(True)self.__parameters = dict(a=self.a, b=self.b)self.___gpu = Falsereturn self

5、返回網(wǎng)絡參數(shù)

為了能使用Pytorch內(nèi)置的優(yōu)化器,就要實現(xiàn)parameters函數(shù),觀察Pytorch里面的實現(xiàn):

def parameters(self, recurse=True):r"""..."""for name, param in self.named_parameters(recurse=recurse):yield param

實際上就是使用yield返回網(wǎng)絡的所有參數(shù),因此本例中的實現(xiàn)如下:

def parameters(self):for name, param in self.__parameters.items():yield param

完整的實現(xiàn)將會放在后面。

二、測試

1、生成測試數(shù)據(jù)

def main():# 生成虛假數(shù)據(jù)x = np.linspace(1, 50, 50)# 系數(shù)a、ba = 2b = 1# 生成yy = a * x + b# 轉(zhuǎn)換為Tensorx = torch.from_numpy(x.astype(np.float32))y = torch.from_numpy(y.astype(np.float32))

2、定義網(wǎng)絡

# 定義網(wǎng)絡net = Net()# 定義優(yōu)化器optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)# 定義損失函數(shù)loss_op = torch.nn.MSELoss(reduction='sum')

3、把數(shù)據(jù)傳輸?shù)紾PU(可選)

# 傳輸?shù)紾PUif torch.cuda.is_available():x = x.cuda()y = y.cuda()net = net.cuda()

4、定義優(yōu)化器和損失函數(shù)

如果要使用GPU加速,優(yōu)化器必須要在網(wǎng)絡的參數(shù)傳輸?shù)紾PU之后在定義,否則優(yōu)化器里的參數(shù)還是內(nèi)存里的那些參數(shù),傳到GPU里面的參數(shù)不能被更新。 可以根據(jù)代碼來理解這句話。

# 定義優(yōu)化器optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)# 定義損失函數(shù)loss_op = torch.nn.MSELoss(reduction='sum')

5、擬合(也是優(yōu)化)

# 最多優(yōu)化20001次for i in range(1, 20001, 1):# 向前傳播out = net.forward(x)# 計算損失loss = loss_op(y, out)# 清空梯度(非常重要)optimizer.zero_grad()# 向后傳播,計算梯度loss.backward()# 更新參數(shù)optimizer.step()# 得到損失的numpy值loss_numpy = loss.cpu().detach().numpy()if i % 1000 == 0: # 每1000次打印一下?lián)p失print(i, loss_numpy)if loss_numpy < 0.00001: # 如果損失小于0.00001# 打印參數(shù)a = net.a.cpu().detach().numpy()b = net.b.cpu().detach().numpy()print(a, b)# 退出exit()

6、完整示例代碼

# coding=utf-8 from __future__ import absolute_import, division, print_function import torch import numpy as npclass Net:def __init__(self):# y = a*x + bself.a = torch.rand(1, requires_grad=True) # 參數(shù)aself.b = torch.rand(1, requires_grad=True) # 參數(shù)bself.__parameters = dict(a=self.a, b=self.b) # 參數(shù)字典self.___gpu = False # 是否使用gpu來擬合def cuda(self):if not self.___gpu:self.a = self.a.cuda().detach().requires_grad_(True) # 把a傳輸?shù)絞puself.b = self.b.cuda().detach().requires_grad_(True) # 把b傳輸?shù)絞puself.__parameters = dict(a=self.a, b=self.b) # 更新參數(shù)self.___gpu = True # 更新標志,表示參數(shù)已經(jīng)傳輸?shù)絞pu了# 返回self,以支持鏈式調(diào)用return selfdef cpu(self):if self.___gpu:self.a = self.a.cpu().detach().requires_grad_(True)self.b = self.b.cpu().detach().requires_grad_(True)self.__parameters = dict(a=self.a, b=self.b) # 更新參數(shù)self.___gpu = Falsereturn selfdef forward(self, inputs):return self.a * inputs + self.bdef parameters(self):for name, param in self.__parameters.items():yield paramdef main():# 生成虛假數(shù)據(jù)x = np.linspace(1, 50, 50)# 系數(shù)a、ba = 2b = 1# 生成yy = a * x + b# 轉(zhuǎn)換為Tensorx = torch.from_numpy(x.astype(np.float32))y = torch.from_numpy(y.astype(np.float32))# 定義網(wǎng)絡net = Net()# 傳輸?shù)紾PUif torch.cuda.is_available():x = x.cuda()y = y.cuda()net = net.cuda()# 定義優(yōu)化器optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)# 定義損失函數(shù)loss_op = torch.nn.MSELoss(reduction='sum')# 最多優(yōu)化20001次for i in range(1, 20001, 1):# 向前傳播out = net.forward(x)# 計算損失loss = loss_op(y, out)# 清空梯度(非常重要)optimizer.zero_grad()# 向后傳播,計算梯度loss.backward()# 更新參數(shù)optimizer.step()# 得到損失的numpy值loss_numpy = loss.cpu().detach().numpy()if i % 1000 == 0: # 每1000次打印一下?lián)p失print(i, loss_numpy)if loss_numpy < 0.00001: # 如果損失小于0.00001# 打印參數(shù)a = net.a.cpu().detach().numpy()b = net.b.cpu().detach().numpy()print(a, b)# 退出exit()if __name__ == '__main__':main()

總結(jié)

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

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