用pytorch實(shí)現(xiàn)線性回歸
B站學(xué)習(xí)的視頻鏈接 用pytorch實(shí)現(xiàn)線性回歸
1 復(fù)習(xí)引入

和上一次一樣采用的是這個(gè)比較基本的模型進(jìn)行講解,并且采用隨機(jī)下降模型梯度
在上一講中已經(jīng)使用了一定的pytorch的模型

tensor:數(shù)據(jù)backward()自動(dòng)反饋求解處理。
2 模型建立
1 訓(xùn)練數(shù)據(jù)
給定一定的樣本數(shù)據(jù)
這次咱們應(yīng)當(dāng)使用的是具體的pytorch的數(shù)據(jù)結(jié)構(gòu)進(jìn)行輸入,采用的是\(mini\ batch\)。
也就是說將\(x\)和\(y\)放在一起即可。
例如:\((x_{1},y_{1}),(x_{2},y_{2}),(x_{3},y_{3})\)
import torch
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])
注意:x和y必須是矩陣。
2 設(shè)計(jì)模型
用來計(jì)算咱們的\(\hat{y}\)
根據(jù)比較基本的模型也就是線性模型而言:\(\hat{y}=w\times x + b\)
如果輸入的數(shù)據(jù)是上面那個(gè)樣子的話,那么咱們的\(\hat{y}\)就可以變成,\(\begin{cases}\hat{y}_{1}=w\cdot x_{1}+b\\\hat{y}_{2}=w\cdot x_{2}+b\\\hat{y}_{3}=w\cdot x_{3}+b&\end{cases}\)
這個(gè)時(shí)候就可以采用向量的寫法了:\(\left.\left[\begin{array}{c}{\hat{y}_{1}}\\{\hat{y}_{2}}\\{\hat{y}_{3}}\end{array}\right.\right]=w\cdot\begin{bmatrix}{x_{1}}\\{x_{2}}\\{x_{3}}\end{bmatrix}+b\)
之前咱們是人工求導(dǎo)數(shù)的,現(xiàn)在咱們最重要的事情是構(gòu)造計(jì)算圖,求導(dǎo)是\(pytorch\)的事情。

這個(gè)時(shí)需要要確定權(quán)重的性轉(zhuǎn)和\(b\)的大小。
如果想要知道權(quán)重的形狀那么就需要知道輸入的一個(gè)維度形狀。
注意輸出的\(loss\)必須是一個(gè)標(biāo)量。
在
pytorch中首先先將模型定義成一個(gè)類。每一個(gè)類一定要繼承咱們的
Module模塊

注意:必須要這兩個(gè)函數(shù),一個(gè)是
__init__()另一個(gè)是forward()名字都不可以錯(cuò)。

class LinearModel(torch.nn.Module):
def __init__(self):
super(LinearModel, self).__init__() # 調(diào)用副類,直接這么寫就完了。
self.linear = torch.nn.Linear(1, 1) #nn.linear()是pytorch的一個(gè)類,這兩個(gè)分別是權(quán)重和偏置。也在構(gòu)造一個(gè)對(duì)象。 Neural network nn.Linear(輸入維度,輸出維度)。
def forward(self, x): # forward的函數(shù)名是固定的。
y_pred = self.linear(x) #實(shí)現(xiàn)了一個(gè)可以調(diào)用的對(duì)象。
return y_pred
model = LinearModel() # 實(shí)例化
nn.Linear(in_features,out_features,bias=True)
- in_features : size of each input sample
- out_features : size of each output sample
- bias : If set to False, the layer will not learn an additive bias. Default: True
class LinearModel(torch.nn.Module):
def __init__(self):
super(LinearModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)
def forward(self, x):
y_pred = self.linear(x)
return y_pred
model = LinearModel()
3 構(gòu)造損失函數(shù)和優(yōu)化器
使用pytorch的應(yīng)用接口進(jìn)行構(gòu)造。
咱們?cè)镜哪P蜑椋?span id="w0obha2h00" class="math inline">\(loss = (\hat{y}-y)^2\)
那么對(duì)于這么一堆數(shù)據(jù)就有:\(loss_{1}=(\hat{y}_{1}-y_{1})^{2} \\loss_{2}=(\hat{y}_{2}-y_{2})^{2} \\loss_{3}=(\hat{y}_{3}-y_{3})^{2}\)。
這時(shí)候用向量的形式可以表示為:\(\begin{bmatrix}\log_2\\\log_2\\\log_3\end{bmatrix}=\begin{pmatrix}\begin{bmatrix}\hat{y}_1\\\hat{y}_2\\\hat{y}_3\end{bmatrix}-\begin{bmatrix}y_1\\\hat{y}_2\\\hat{y}_3\end{bmatrix}\end{pmatrix}^{2}\)
由于要求咱么輸出的loss是一個(gè)標(biāo)量,因此需要將這個(gè)\(loss\)進(jìn)行求和操作。
用
MSE的方式求loss這個(gè)MSEloss也是繼承nn下的module,計(jì)算圖

torch.nn.MSELoss(size_average = True , reduce=Ture)
- 是否需要求均值
- 是否需要計(jì)算聚合的標(biāo)量損失值,所謂聚合就是求和罷了。
注意這個(gè)里面的東西已經(jīng)被棄用了現(xiàn)在合成了一個(gè)
reduction
reduction='mean': 等價(jià)于reduce=True且size_average=True。計(jì)算批次的平均損失。reduction='sum': 等價(jià)于reduce=True且size_average=False。計(jì)算批次的總和損失。reduction='none': 等價(jià)于reduce=False。不進(jìn)行聚合,返回每個(gè)樣本的損失。
優(yōu)化器

這個(gè)
parameter會(huì)檢查這里面的所有成員,如果有相應(yīng)的權(quán)重,那么直接就加到咱們的訓(xùn)練結(jié)果上面。
criterion = torch.nn.MSELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
4 做好訓(xùn)練的過程
forward, backward, update,
將這個(gè)訓(xùn)練數(shù)據(jù)送進(jìn)去

一定要注意梯度的歸零操作。

然后進(jìn)行反向傳播

- \(\hat{y}\)
- \(loss\)
- \(backward\)
- \(upade\)
最后打印這個(gè)運(yùn)行的日志。

for epoch in range(100):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
3 代碼綜合
import numpy as np
import matplotlib.pyplot as plt
import torch
# 1 訓(xùn)練數(shù)據(jù)準(zhǔn)備
x_data = torch.tensor([[1.0] , [2.0] , [3.0]])
y_data = torch.tensor([[2.0] , [4.0] , [6.0]])
# 2 設(shè)計(jì)模型 線性模型 y=x*w+b loss 求和平方函數(shù)
class LinearModel(torch.nn.Module):
def __init__(self):
super(LinearModel , self).__init__()
self.linear = torch.nn.Linear(1,1) # 定義線性模型 y = w*x + b
def forward(self , x):
y_pred = self.linear(x) # 直節(jié)調(diào)用self.linear()這個(gè)方法
return y_pred
Model = LinearModel() # 模型進(jìn)行實(shí)例化
# 3 定義損失函數(shù)并確定優(yōu)化器
criterion = torch.nn.MSELoss(size_average=False) # sum
optimizer = torch.optim.SGD(Model.parameters(),lr =0.05)
# 4 開始進(jìn)行學(xué)習(xí)
loss_list = []
epoch_list = []
w_list = []
b_list = []
for epoch in range(0 , 51 , 1):
epoch_list.append(epoch)
y_pred = Model(x_data)
loss = criterion(y_pred , y_data)
loss_list.append(loss.item()) # 轉(zhuǎn)換成標(biāo)量
optimizer.zero_grad()
loss.backward()
optimizer.step()
w_list.append(Model.linear.weight.item())
b_list.append(Model.linear.bias.item())
# 日志打印
for e,l,w ,b in zip(epoch_list , loss_list , w_list , b_list):
print(f'第{e}輪的時(shí)候,損失為{l:.6f},權(quán)重為{w:.6f} , 偏置為{b:.6f} \n')
fig , axes = plt.subplots(3,1 , figsize =(5, 6))
axes[0].plot(epoch_list , loss_list , 'b-' , linewidth = 2 , label = 'Loss curve')
axes[0].set_xlabel('Number of training rounds')
axes[0].set_ylabel('Size of loss')
axes[0].set_title('Loss curve')
axes[0].legend()
axes[1].plot(epoch_list,w_list,'b-',linewidth=2 , label = 'Weight curve')
axes[1].set_xlabel('Number of training rounds')
axes[1].set_ylabel('Size of Weight')
axes[1].legend()
axes[2].plot(epoch_list,b_list,'r-',linewidth=2 , label = 'Bias curves')
axes[2].set_xlabel('Number of training rounds')
axes[2].set_ylabel('Size of Bias')
axes[2].legend()
plt.tight_layout()
plt.show()

注意
pytorch有很多優(yōu)化器:
- torch.optim.Adagrad
- torch.optim.Adam
- torch.optim.Adamax
- torch.optim.ASGD
- torch.optim.LBFGS
- torch.optim.RMSprop
- torch.optim.Rprop
- torch.optim.SGD
總結(jié)
這一次咱們主要使用了pytorch進(jìn)行線性模型的學(xué)習(xí)操作,讓我們?cè)僖淮位仡櫼幌赂黝惒僮鳎约吧疃葘W(xué)習(xí)的流程。
1 深度學(xué)習(xí)的流程
實(shí)際上深度學(xué)習(xí)的流程就那么四個(gè)
- 確定并導(dǎo)入訓(xùn)練數(shù)據(jù)。
- 確定并設(shè)計(jì)訓(xùn)練模型。
- 給定損失函數(shù)以及優(yōu)化器。
- 進(jìn)行訓(xùn)練,打印日志,繪制圖表。
2. 代碼處理
根據(jù)上面四部,我們?cè)僖淮伪容^清晰粗略的以線性模型為例子,進(jìn)行說明。
1 確定并導(dǎo)入訓(xùn)練模型。

2 確定并設(shè)計(jì)訓(xùn)練模型。

3 給定損失函數(shù)以及優(yōu)化器。

4 進(jìn)行訓(xùn)練

打印日志

繪制圖表

可見其實(shí)使用pytorch進(jìn)行深度學(xué)習(xí)是非常的清晰的。我們最終要的就是對(duì)其中的第二步和第三步進(jìn)行琢磨和處理。
3 函數(shù)總結(jié)
最后的最后讓我把這一次使用到的函數(shù)進(jìn)行一個(gè)總結(jié)
torch.tensor()
創(chuàng)建一個(gè)PyTorch張量(Tensor),這是PyTorch中最基本的數(shù)據(jù)結(jié)構(gòu)。
- 類似于NumPy的ndarray,但可以在GPU上運(yùn)行
- 支持自動(dòng)求導(dǎo)(Autograd)
- 是深度學(xué)習(xí)計(jì)算的基礎(chǔ)單元
torch.nn.Linear()
創(chuàng)建一個(gè)全連接層(線性層),執(zhí)行線性變換:y = xA^T + b
參數(shù):
-
in_features:輸入特征數(shù) -
out_features:輸出特征數(shù) -
bias:是否使用偏置項(xiàng)(默認(rèn)為True)
內(nèi)部參數(shù):
.weight:權(quán)重矩陣,形狀為(out_features, in_features).bias:偏置向量,形狀為(out_features,)
torch.nn.MSELoss()
算均方誤差損失\((Mean Squared Error Loss)\),用于回歸問題。
公式:\(\mathrm{MSE}=\frac{1}{N}\sum_{i=1}^N(y_i-\hat{y}_i)^2\)
參數(shù):
reduction:指定縮減方式'mean':返回?fù)p失的均值(默認(rèn))'sum':返回?fù)p失的總和'none':不縮減,返回每個(gè)元素的損失
torch.optim.SGD()
實(shí)現(xiàn)隨機(jī)梯度下降優(yōu)化算法。
參數(shù):
params:需要優(yōu)化的參數(shù)(通常來自model.parameters())lr:學(xué)習(xí)率(learning rate)momentum:動(dòng)量系數(shù)(可選,默認(rèn)為0)weight_decay:權(quán)重衰減(L2正則化,可選)
.zero_grad()
將模型參數(shù)的梯度清零。
.backward()
自動(dòng)計(jì)算梯度(反向傳播)
Model.linear.weight.item()
從權(quán)重張量中提取標(biāo)量值。
分解:
Model.linear:訪問模型中的linear層.weight:獲取該層的權(quán)重參數(shù)(是一個(gè)張量).item():將單元素張量轉(zhuǎn)換為Python標(biāo)量
Model.linear.bias.item()
從偏置張量中提取標(biāo)量值。
分解:
Model.linear:訪問模型中的linear層.bias:獲取該層的偏置參數(shù)(是一個(gè)張量).item():將單元素張量轉(zhuǎn)換為Python標(biāo)量


浙公網(wǎng)安備 33010602011771號(hào)