現(xiàn)線性回歸)
目錄第一步 準(zhǔn)備數(shù)據(jù)第二步 設(shè)計(jì)模型第三步 構(gòu)造損失函數(shù)和優(yōu)化器1、損失函數(shù)2、優(yōu)化器第四步 訓(xùn)練過程第五步 測試模型代碼作業(yè)Adagrad優(yōu)化器1、介紹2、代碼y_hat w * x b第一步 準(zhǔn)備數(shù)據(jù)采用minibatch風(fēng)格的梯度下降的算法利用pytorch的廣播機(jī)制因此X,Y必須是矩陣3×1的向量w矩陣的維度要根據(jù) X 和 Y 的維度來確定第二步 設(shè)計(jì)模型重點(diǎn)是構(gòu)造計(jì)算圖想要構(gòu)造w和b的維度形狀需要知道輸入x和輸出y_hat的維度因?yàn)閄,Y都以張量的形式計(jì)算所以計(jì)算出的loss也是張量的形式因此需要對 loss_i 求和再根據(jù)需要決定是不是要求均值所有模型類一定要繼承于Module必須要實(shí)現(xiàn)__init__構(gòu)造函數(shù)和forward前饋網(wǎng)絡(luò)兩個(gè)函數(shù)繼承于Module類會自動(dòng)實(shí)現(xiàn) backward() 的過程class torch.nn.Linear(in_features, out_features, biasTure)超參數(shù)不可訓(xùn)練但可配置1in_features --每一個(gè)輸入的特征樣本x的維度2out_features --每一個(gè)輸出的特征樣本y的維度3bias --指定是否需要偏置值b可訓(xùn)練的參數(shù)1weight --學(xué)習(xí)權(quán)重矩陣形狀是out_features×in_features2bias --偏置向量形狀是out_featuresself.linear torch.nn.Linear(11) 是一個(gè)對象其中包含權(quán)重w和偏置值b兩個(gè)張量因此可以使用linear來自動(dòng)實(shí)現(xiàn)這樣一個(gè)計(jì)算linear也繼承自Module因此也可以自動(dòng)進(jìn)行反向傳播注意in_features 和out_features是指每一個(gè)特征樣本x或y的維度例如在一元線性回歸中輸入為x輸出為y所以值為in_features 1out_features1,此時(shí)輸入X的形狀為[batchsizein_features][n1]Y的形狀為[n1]W的形狀為1×1b的形狀為1×1在多元線性回歸中輸入為x1,x2,x3輸出為y所以值為in_features 3out_features1此時(shí)輸入X的形狀為[batchsizein_features][n3]Y的形狀為[n1]W的形狀為1×3b的形狀為1×1。self.linear(x)是一個(gè)可以調(diào)用的對象其作用是完成線性函數(shù)的計(jì)算得到y(tǒng)_predmodel LinearModel()中 model也是一個(gè)可以調(diào)用的對象第三步 構(gòu)造損失函數(shù)和優(yōu)化器1、損失函數(shù)類classtorch.nn.MSELoss(size_averageTrue, reduceTrue)MSELoss也是繼承于nn.Modulesize_average -- 是不是要對所有樣本的Loss求均值一般設(shè)置為Falsereduce -- 最后是不是要把得到的Loss向量降維也就是求和一般不管對象criterion是這個(gè)類的一個(gè)可調(diào)用對象核心方法就是__call__需要的參數(shù)是y_hat和y用于求Loss2、優(yōu)化器類classtorch.optim.SGD(params, lrobject object, momentum0, dampening0, weight_decay0, nesterovFalse)params就是指權(quán)重Model里面沒有定義權(quán)重只有一個(gè)Linear成員這個(gè)成員包含兩個(gè)權(quán)重model.parameters()會檢查model中的所有成員取得Linear的權(quán)重是通過調(diào)用linear.parameters如果成員里面有相應(yīng)的權(quán)重它就把這些都加入到要訓(xùn)練的參數(shù)集合里面lr是學(xué)習(xí)率對象optimizer就是一個(gè)優(yōu)化器對象它知道自己要優(yōu)化哪些參數(shù)也知道學(xué)習(xí)率optimizer對象的核心方法方法作用是否需要參數(shù)optimizer.zero_grad()清零所有參數(shù)的梯度? 不需要optimizer.step()用梯度更新所有參數(shù)? 不需要optimizer.param_groups查看參數(shù)組調(diào)試用? 不需要注意雖然這里的優(yōu)化器是SGD但這段代碼算法實(shí)際是BGD。這是因?yàn)?PyTorch偷懶。torch.optim.SGD這個(gè)類名它具體執(zhí)行的是 SGD、BGD 還是 Mini-batch SGD完全不取決于優(yōu)化器本身而是取決于傳給它的 數(shù)據(jù)批次大小Batch Size如果把所有數(shù)據(jù)一次性喂進(jìn)去如你的代碼 →就是 BGD。如果把1個(gè)樣本喂進(jìn)去 →就是純 SGD。如果把32個(gè)樣本喂進(jìn)去Mini-batch →就是 Mini-batch SGD工業(yè)界最常用大家平時(shí)口頭說的“SGD”通常指這個(gè)。第四步 訓(xùn)練過程print(loss)時(shí)會自動(dòng)調(diào)用loss.__str__()不會產(chǎn)生計(jì)算圖.step()會根據(jù)每個(gè)參數(shù)的梯度和更新每次backward求梯度之前要把之前的梯度清零第五步 測試模型前面的步驟已經(jīng)將模型訓(xùn)練好了重新創(chuàng)建一個(gè)tensor張量x_test輸入給模型得到輸出y_test model(x_test)—— 執(zhí)行預(yù)測前向傳播model(x_test)實(shí)際上會調(diào)用model.__call__()方法而__call__()方法內(nèi)部會自動(dòng)調(diào)用forward()所以model的參數(shù)應(yīng)該與forward()傳入的參數(shù)一樣也就是x代碼import torch import matplotlib.pyplot as plt x_data torch.Tensor([[1.0], [2.0], [3.0]]) y_data torch.Tensor([[2.0], [4.0], [6.0]]) 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() criterion torch.nn.MSELoss(size_averageFalse) optimizer torch.optim.SGD(model.parameters(), lr0.01) for epoch in range(100): y_pred model(x_data) loss criterion(y_pred, y_data) print(epoch, loss.item()) optimizer.zero_grad() loss.backward() optimizer.step() print(w , model.linear.weight.item()) print(b ,model.linear.bias.item()) x_test torch.Tensor([[4.0]]) y_test model(x_test) plt.plot(range(1, 101, 1), loss_list) plt.xlabel(epoch) plt.ylabel(Loss) plt.show() print(y_pred , y_test.data)運(yùn)行結(jié)果w 1.7945618629455566 b 0.4670093357563019y_pred tensor([[7.6134]])作業(yè)Adagrad優(yōu)化器1、介紹傳統(tǒng) SGD優(yōu)化器所有參數(shù)用同一個(gè)學(xué)習(xí)率但是有些參數(shù)更新頻繁有些很少用同一個(gè)學(xué)習(xí)率不合理。Adagrad中每個(gè)參數(shù)有自己的學(xué)習(xí)率。更新頻繁的參數(shù)學(xué)習(xí)率自動(dòng)變小更新稀少的參數(shù)學(xué)習(xí)率自動(dòng)變大數(shù)學(xué)公式為# 累計(jì)梯度平方和歷史信息G G (梯度)2# 參數(shù)更新公式w w - (lr / (√G ε)) * 梯度torch.optim.Adagrad(params, # 要優(yōu)化的參數(shù)必需lr0.01, # 學(xué)習(xí)率默認(rèn) 0.01lr_decay0, # 學(xué)習(xí)率衰減默認(rèn) 0weight_decay0, # L2 正則化默認(rèn) 0eps1e-10, # 防止除零默認(rèn) 1e-10initial_accumulator_value0 # G 的初始值默認(rèn) 0)2、代碼只需將optimizer torch.optim.SGD(model.parameters(), lr0.01)改為optimizer torch.optim.Adagrad( model.parameters(), lr0.01, # 學(xué)習(xí)率 weight_decay0.001 # 可以加 L2 正則化 )運(yùn)行結(jié)果w 0.6798529624938965 b 1.0155056715011597 y_pred tensor([[3.7349]])