一、自動微分概念
自動微分(Automatic Differentiation,AD)是一種利用計算機程序自動計算函數導數的技術,它是機器學習和優化算法中的核心工具(如神經網絡的梯度下降),通過反向傳播計算并更新梯度。
計算梯度的目的是更新權重w和b,,其中value是梯度值,學習率需要提前指定,求導計算梯度,前面我們學過了手動求導,這次使用自動微分的方法,來簡化我們的工作量。
注意:
1. w和b一定是可自動微分的張量,類型是浮點型,超參數requries_grad=Ture表示允許自動微分。
2. detach():自動微分的張量不能轉換成numpy數組, 通過 張量.detach().numpy() 剝離成不自動微分后可以轉換。detach()返回一個與當前張量共享數據的新張量,該張量是不開啟自動微分的,不參與梯度計算。
? ? clone():返回一個與當前張量數據相同的新張量,默認開啟自動微分,但新張量擁有獨立的存儲。
3. 默認梯度是累加的,所以多輪中每個輪次需要在自動微分之前進行清零!!!
4. 查看張量底層數據地址時推薦使用 張量名.data_ptr()?
import torch# TODO 單輪
#定義權重,并開啟自動微分
w = torch.tensor([10,20],requires_grad=Ture,dtype=torch.float)
#定義損失函數(loss,cost,criterion...)
loss = 2 * w**2
#自動微分求梯度,自動更新梯度
loss.sun().backward()
#手動更新權重
w.data = w.data - 0.01*w.grad# TODO 多輪
#定義權重,并開啟自動微分
w = torch.tensor([10,20],requires_grad=Ture,dtype=torch.float)
#定義遍歷輪次
epochs = 500
for epoch in range(epochs):loss = 2 * w**2# 默認梯度是累加的,所以每輪需要在自動微分之前進行清零if w.grad is not None:w.grad.zero_()loss.sum().backward()# 格式化輸出print(f"當前輪次:{epoch + 1} 當前權重: {w.data},固定學習率:{0.01} 更新后梯度: {w.grad},下一個權重: {w.data - 0.01 * w.grad}")#手動更新權重w.data = w.data - 0.01*w.grad
推導w和b的方法:
import torch
x = torch.ones(2, 5)
y = torch.zeros(2, 3)
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)# 1.首先獲取損失函數
loss_fn = torch.nn.MSELoss()
# 2.然后,計算預測值-> z=wx+b 注意: 這里面的wx是矩陣乘法,需要遵循 (n,m)*(m,p)=(n,p)
z = x.matmul(w) + b
# 3.接著,根據損失函數計算損失值
loss = loss_fn(z, y)
# 4.最后,反向傳播推導更新梯度
loss.sum().backward()# 5.打印結果
print(f'w.grad: {w.grad}')
print(f'b.grad: {b.grad}')
二、 反向傳播及案例
正向傳播:從輸入到輸出,目的是預測結果和損失值;
反向傳播:從輸出到輸入,更新參數做出優化。
案例:使用pytorch構建一個回歸模型
步驟:
1.獲取數據集,提前封裝數據為張量
2.模型訓練預測以及計算損失值
3.繪制損失曲線以及預測和真實值的擬合線
from sklearn.datasets import make_regression
import torch
from torch.utils.data import DataLoader, TensorDataset
from torch.nn import Linear, MSELoss
from torch.optim import SGD
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 1.獲取數據集,提前封裝成張量
def get_data():X,y,coef = make_regressionn(n_samples=100,n_features=1,n_targets=1,noise=10,random_state=1,coef=Ture,bias=14.5)X = torch.tensor(X,dtype=torch.float32)y = torch.tensor(y,dtype=torch.float32)return X,y,coef# 2.模型訓練預測及損失值計算
def get_model_and_loss_list(x, y, epochs):# 2.1 處理數據封裝為數據加載器,為了分批次訓練,避免內存溢出dataloader = DataLoader(TensorDataset(x,y),batch_size = 5,shuffle=Ture)# 2.2 創建模型對象,為了模型預測model = Linear(in_features=1,out_features=1)# 2.3 創建損失函數對象,為了計算損失值loss_fn = MSELoss()# 2.4 創建SGD優化器對象,為了更新模型參數optimizer = SGD(model.parameters(),lr=0.03)# 2.5 模型訓練預測和計算損失# 2.5.1 定義一個空列表,用于保存每輪損失值,再定義累加損失和批次,用于計算每輪的損失值loss_list,total_loss,batch_cnt = [],0.0,0# for循環,外循環輪次,內循環批次for epoch in range(epochs):for batch_x,batch_y in dataloader:# [重點] 正向傳播# 計算預測值y_predict = model(batch_x)# 計算損失值,MSE計算要求形狀必須一致,否則自動廣播會出現無效計算loss = loss_fn(y_predict,batch_y.reshape(-1,1))# 累加損失和批次total_loss += loss.item()batch_cnt += 1# [重點] 反向傳播# 梯度清零optimizer.zero_grad()# 梯度計算loss.backward()# 參數更新 step()底層是w1 = w0-lr*梯度optimizer.step()# TODO 內層循環結束,即一輪結束,可以計算每輪損失值,并保存到列表中epoch_loss = total_loss / batch_cntloss_list.append(epoch_loss)print(f"第{epoch + 1}輪,損失值為:{epoch_loss:.2f}")# TODO 外層循環結束,即所有輪次結束,可以返回模型和損失值列表# 打印模型參數字典print(f"模型參數:{model.state_dict()}")# print(f"模型權重:{model.weight}, 偏置:{model.bias}")# 返回結果return model, loss_list# 3.繪制損失曲線及預測和真實值擬合線
def plot_show(epochs, model, loss_list, x, y, coef):# todo 1.繪制每輪損失曲線plt.plot(range(epochs), loss_list)plt.xlabel('訓練的輪數')plt.ylabel('該輪的平均損失')plt.title('損失變化曲線圖')plt.grid()plt.show()# todo 2.繪制預測和真實值擬合線plt.scatter(x, y)# 使用x的最小值,最大值生成1000個x值等差張量X = torch.linspace(x.min(), x.max(), 1000)# 細節: numpy * 張量 -> 不可以 張量 * numpy -> 可以, 要么把v放到前面位置要么把coef轉為張量y_pred = torch.tensor([v * model.weight + model.bias for v in X])y_true = torch.tensor([v * coef + 14.5 for v in X])plt.plot(X, y_pred, label='訓練', color='red')plt.plot(X, y_true, label='真實', color='green')plt.legend()plt.grid()plt.show()if __name__ =='__main__':# 1.獲取數據集,提前封裝數據為張量x, y, coef = get_data()# 2.模型訓練預測以及計算損失值epochs = 4000model, loss_list = get_model_and_loss_list(x, y, epochs)# 3.繪制損失曲線以及預測和真實值擬合線plot_show(epochs, model, loss_list, x, y, coef)