最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

08 線性回歸 + 基礎(chǔ)優(yōu)化算法【動手學(xué)深度學(xué)習(xí)v2】

2021-11-16 13:31 作者:如果我是泡橘子  | 我要投稿

線性回歸


房價預(yù)測


線性模型

  • b:標(biāo)量偏差


  • 單層神經(jīng)網(wǎng)絡(luò):帶權(quán)重的層只有一個(輸出層)


真實的神經(jīng)元


衡量預(yù)估質(zhì)量

  • 平方損失:衡量真實值與預(yù)測值之間的誤差
  • 1 / 2:主要是為了求導(dǎo)的時候方便抵消平方的導(dǎo)數(shù)所產(chǎn)生的系數(shù)2


訓(xùn)練數(shù)據(jù)


參數(shù)學(xué)習(xí)

  • 1 / 2:來自損失函數(shù)
  • 1 / n:求平均
  • 最小損失函數(shù)來學(xué)習(xí)參數(shù)


顯示解

  • 因為是線性模型,所以是有顯示解的,并且損失是一個凸函數(shù)
  • 凸函數(shù)的最優(yōu)解滿足梯度等于0



總結(jié)


  • 線性回歸是對n維輸入的加權(quán),外加偏差(對輸出值的預(yù)估)
  • 使用平方損失來衡量預(yù)測值和真實值的差異
  • 線性回歸有顯示解(一般來說,模型都沒有顯示解,有顯示解的模型過于簡單,復(fù)雜度有限,很難衡量復(fù)雜的數(shù)據(jù))
  • 線性回歸可以看做是單層神經(jīng)網(wǎng)絡(luò)(最簡單的神經(jīng)網(wǎng)絡(luò))





基礎(chǔ)優(yōu)化算法


梯度下降

  • η:標(biāo)量,表示學(xué)習(xí)率,代表沿著負(fù)梯度方向一次走多遠(yuǎn),即步長。他是一個超參數(shù)(需要人為的指定值)
  • 學(xué)習(xí)率的選擇不能太小,也不能太大(太小會導(dǎo)致計算量大,求解時間長;太大的話或?qū)е潞瘮?shù)值振蕩,并沒有真正的下降)
  • l:損失函數(shù)
  • 圓圈代表函數(shù)值的等高線,每個圓圈上的點處的函數(shù)值相等
  • 梯度:使得函數(shù)值增加最快的方向,負(fù)梯度就是使函數(shù)下降最快的方向,如圖中黃線所示



小批量隨機(jī)梯度下降

  • 梯度下降時,每次計算梯度,要對整個損失函數(shù)求導(dǎo),損失函數(shù)是對所有樣本的平均損失,所以每求一次梯度,要對整個樣的本的損失函數(shù)進(jìn)行重新計算,計算量大且耗費(fèi)時間長,代價太大
  • 用 b 個樣本的平均損失來近似所有樣本的平均損失,當(dāng) b 足夠大的時候,能夠保證一定的精確度
  • 批量大小的選擇



總結(jié)


  • 梯度下降通過不斷沿著負(fù)梯度方向更新參數(shù)求解(好處是不需要知道顯示解是什么,只需要不斷的求導(dǎo)就可以了)
  • 小批量隨機(jī)梯度下降是深度學(xué)習(xí)默認(rèn)的求解算法(雖然還有更穩(wěn)定的,但是他是最穩(wěn)定、最簡單的)
  • 兩個重要的超參數(shù)是批量大小和學(xué)習(xí)率





線性回歸的實現(xiàn)


1、導(dǎo)入所需要的包


%matplotlib inline

import random

import torch

from d2l import torch as d2l

  • random:導(dǎo)入random包用于隨機(jī)初始化權(quán)重
  • d2l:將用過的或者實現(xiàn)過的算法放在d2l的包里面
  • matplotlib inline:在plot的時候默認(rèn)是嵌入到matplotlib中
  • 報錯 No module named 'matplotlib' :在命令行中使用 pip install matplotlib 安裝 matplotlib 包即可
  • 報錯 No module named 'd2l' :在命令行中使用 pip install d2l 安裝 d2l 包即可,安裝完成之后可能需要重新打開程序才能生效



2、根據(jù)帶有噪聲的線性模型構(gòu)造一個人造的數(shù)據(jù)集


  • 構(gòu)造人造數(shù)據(jù)集的好處是知道真實的 w 和 b
  • X = torch.normal(0,1,(num_examples,len(w))):X 是一個均值為 0 ,方差為 1 的隨機(jī)數(shù),他的行數(shù)等于樣本數(shù),列數(shù)等于 w 的長度
  • y += torch.normal(0,0.01,y.shape):給 y 加上了一個均值為 0 ,方差為 0.01 形狀和 y 相同的噪聲
  • return X,y.reshape((-1,1)):最后把 X 和 y 做成一個列向量返回
  • true_w:真實的 w
  • true_b:真實的 b
  • features,labels = synthetic_data(true_w,true_b,1000),根據(jù)函數(shù)來生成特征和標(biāo)注


def synthetic_data(w,b,num_examples):

? ? """生成 y = Xw + b + 噪聲"""

? ? X = torch.normal(0,1,(num_examples,len(w)))

? ? y = torch.matmul(X,w) + b

? ? y += torch.normal(0,0.01,y.shape)

? ? return X,y.reshape((-1,1))


true_w = torch.tensor([2,-3.4])

true_b = 4.2

features,labels = synthetic_data(true_w,true_b,1000)



3、feature中每一行都包含一個二維數(shù)據(jù)樣本,labels中的每一行都包含一維標(biāo)簽值


print('features:',features[0],'\nlabels',labels[0])

輸出:

features: tensor([0.1605, 0.2305])

labels tensor([3.7450])


d2l.set_figsize()

d2l.plt.scatter(features[:1].detach().numpy(),labels.detach().numpy(),1);

輸出:

  • detach():在pytorch的一些版本中,需要從計算圖中detach出來才能轉(zhuǎn)到numpy中去



4、實現(xiàn)一個函數(shù)讀取小批量


定義一個data_iter函數(shù),該函數(shù)接收批量大小、特征矩陣和標(biāo)簽向量作為輸入,生成大小為batch_size的小批量


def data_iter(batch_size,features,labels):

? ? num_examples = len(features)

? ? indices = list(range(num_examples))

? ? # 這些樣本是隨機(jī)讀取的,沒有特定順序

? ? random.shuffle(indices)

? ? for i in range(0,num_examples,batch_size):

? ? ? ? batch_indices = torch.tensor(indices[i:min(i+batch_size,num_examples)])

? ? ? ? yield features[batch_indices],labels[batch_indices]


batch_size = 10


for X,y in data_iter(batch_size,features,labels):

? ? print(X,'\n',y)

? ? break

  • batch_size:批量大小
  • num_examples:樣本數(shù)
  • random.shuffle(indices):將下標(biāo)打亂,實現(xiàn)對樣本的隨機(jī)訪問
  • for i in range(0,num_examples,batch_size):從 0 開始到樣本數(shù)結(jié)束,每次跳批量大小
  • yield features[batch_indices],labels[batch_indices]:通過indices,每次產(chǎn)生隨機(jī)順序的特征和其對應(yīng)的隨即順序標(biāo)號
  • yield是python中的一個迭代器

輸出:

tensor([[-0.3785, -0.5235],

[ 0.0674, 0.6504],

[-0.9654, 1.3349],

[ 0.6241, -0.1228],

[-1.4924, -1.4087],

[ 0.7791, -0.5478],

[-0.6711, -0.5625],

[-0.0553, -0.1775],

[-0.7085, 0.6464],

[ 2.4625, -1.1113]])

tensor([[ 5.2227],

[ 2.1381],

[-2.2681],

[ 5.8792],

[ 6.0258],

[ 7.6395],

[ 4.7813],

[ 4.6846],

[ 0.5918],

[12.8976]])



5、定義初始化模型參數(shù)


w = torch.normal(0,0.01,size=(2,1),requires_grad=True)

b = torch.zeros(1,requires_grad=True)



6、定義模型


def linreg(X,w,b):

? ? """線性回歸模型"""

? ? return torch.matmul(X,w) + b



7、定義損失函數(shù)


def squared_loss(y_hat,y):

? ? """均方損失"""

? ? return (y_hat - y.reshape(y_hat.shape))**2 / 2

  • y_hat:預(yù)測值
  • y:真實值
  • 雖然 y_hat 和 y 元素個數(shù)是一樣的,但是可能他們一個是行向量一個是列向量,因此需要使用reshape進(jìn)行統(tǒng)一



8、定義優(yōu)化算法


def sgd(params,lr,batch_size):

? ? """小批量梯度下降"""

? ? with torch.no_grad():

? ? ? ? for param in params:

? ? ? ? ? ? param -= lr * param.grad / batch_size

? ? ? ? ? ? param.grad.zero_()

  • params:給定的所有參數(shù),包含 w 和 b ,他是一個list
  • lr:學(xué)習(xí)率
  • param.grad.zero_():手動將梯度設(shè)置成 0 ,在下一次計算梯度的時候就不會和上一次相關(guān)了



9、訓(xùn)練過程


lr = 0.03

num_epochs = 3

net = linreg

loss = squared_loss


for epoch in range(num_epoch):

? ? for X,y in data_iter(batch_size,features,labels):

? ? ? ? l = loss(net(X,w,b),y) # X 和 y 的小批量損失

? ? ? ? # 因為 l 的形狀是(batch_size,1),而不是一個標(biāo)量。l 中的所有元素被加到一起求梯度

? ? ? ? # 并以此計算關(guān)于[w,b]的梯度

? ? ? ? l.sum().backward()

? ? ? ? sgd([w,b],lr,batch_size) # 使用參數(shù)的梯度更新

? ? with torch.no_grad():

? ? ? ? train_l = loss(net(features,w,b),labels)

? ? ? ? print(f'epoch{epoch + 1},loss{float(train_l.):f}')

  • num_epoch=3:將整個數(shù)據(jù)掃描三遍
  • net:之前定義的模型
  • loss:均方損失
  • 每一次對數(shù)據(jù)掃描一遍,掃描的時候拿出一定批量的X和y?

輸出:

epoch1,loss0.034571

epoch2,loss0.000130

epoch3,loss0.000049



10、比較真實參數(shù)和通過訓(xùn)練學(xué)到的參數(shù)來評估訓(xùn)練的成功程度


print(f'w的估計誤差:{true_w - w.reshape(true_w.shape)}')

print(f'b的估計誤差:{true_b - b}')

輸出:

w的估計誤差:tensor([ 0.0003, -0.0004], grad_fn=<SubBackward0>)

b的估計誤差:tensor([-7.7724e-05], grad_fn=<RsubBackward1>)





線性回歸的實現(xiàn)(簡潔版)


使用深度學(xué)習(xí)框架來簡潔的實現(xiàn)線性回歸模型生成數(shù)據(jù)集,使用pytorch的nn的moudule提供的一些數(shù)據(jù)預(yù)處理的模塊來使實現(xiàn)更加簡單


1、導(dǎo)包


import numpy as np

import torch

import torch.utils.data as data

from d2l import torch as d2l


true_w = torch.tensor([2,-3.4])

true_b = 4.2

features,labels = d2l.synthetic_data(true_w,true_b,1000)

  • 這里沐神導(dǎo)包的時候?qū)懙氖?import torch.utils as data ,我在運(yùn)行的時候會報錯 AttributeError: module 'torch.utils' has no attribute 'TensorDataset' ,當(dāng)我改成 import torch.utils.data as data 這種方式來進(jìn)行導(dǎo)包之后就能夠繼續(xù)運(yùn)行了



2、調(diào)用框架中現(xiàn)有的API來讀取數(shù)據(jù)


def load_array(data_arrays,batch_size,is_train=True):

? ? """構(gòu)造一個PyTorch的數(shù)據(jù)迭代器"""

? ? dataset = data.TensorDataset(*data_arrays)

? ? return data.DataLoader(dataset,batch_size,shuffle=is_train)


batch_size = 10

data_iter = load_array((features,labels),batch_size)


next(iter(data_iter))

輸出:

[tensor([[-0.8249, 1.9358],

[-0.9235, -0.2573],

[-1.6639, -1.0040],

[ 0.5258, 1.1980],

[-0.4612, -0.8816],

[ 2.1845, -1.4419],

[-0.0317, 1.7666],

[-0.0510, -0.9682],

[-1.8175, 0.0168],

[ 0.5344, 0.5456]]),

tensor([[-4.0278],

[ 3.2316],

[ 4.2774],

[ 1.1869],

[ 6.2739],

[13.4859],

[-1.8532],

[ 7.3907],

[ 0.5091],

[ 3.4219]])]



3、使用框架的預(yù)定義好的層


from torch import nn

net = nn.Sequential(nn.Linear(2,1))

  • nn 是神經(jīng)網(wǎng)絡(luò)的縮寫
  • nn.Linear(2,1):輸入的維度是2,輸出的維度是1
  • sequential:可以理解成是層的排列,將一層一層的神經(jīng)網(wǎng)絡(luò)進(jìn)行排列在一起



4、初始化模型參數(shù)


net[0].weight.data.normal_(0,0.01)

net[0].bias.data.fill_(0)

  • normal_:使用正態(tài)分布來替換掉data的值(均值為0,方差為0.01)
  • fill_:將偏差直接設(shè)置為0

輸出:

tensor([0.])



5、計算均方誤差使用的是MESLoss類,也稱為L2范數(shù)


loss = nn.MSELoss()



6、實例化SGD實例


trainer = torch.optim.SGD(net.parameters(),lr=0.03)



7、訓(xùn)練過程


和之前的訓(xùn)練過程是一樣的


num_epochs = 3

for epoch in range(num_epochs):

? ? for X,y in data_iter:

? ? ? ? l = loss(net(X),y)

? ? ? ? trainer.zero_grad()

? ? ? ? l.backward()

? ? ? ? trainer.step()

? ? l = loss(net(features),labels)

? ? print(f'epoch {epoch + 1}, loss {l:f}')

  • trainer.step():調(diào)用step函數(shù)來對模型進(jìn)行更新

輸出:

epoch 1, loss 0.000304

epoch 2, loss 0.000100

epoch 3, loss 0.000100





Q&A


1、我想請問可以在Google colab上安裝d2l庫進(jìn)行環(huán)境配置嗎?或者老師推薦一些對學(xué)生黨比較便宜的平臺

?
QA P5 - 00:06
?



2、為啥使用平方損失而不是絕對插值呢?

?
QA P5 - 01:16
?



3、損失為什么要求平均?

?
QA P5 - 02:00
?



4、線性回歸損失函數(shù)是不是通常都是mse?

?
QA P5 - 03:37
?



5、關(guān)于神經(jīng)網(wǎng)絡(luò),我們是通過誤差反饋修改參數(shù),但是神經(jīng)元沒有反饋誤差這一說,請問這一點是人為推導(dǎo)的嗎?

?
QA P5 - 03:50
?



6、物理實驗中經(jīng)常使用 n-1 代替 n 求誤差,請問這里求誤差也能用 n-1 代替n嗎?

?
QA P5 - 04:54
?



7、老師,不管是gd還是sgd怎么找到合適的學(xué)習(xí)率?有什么好的方法嗎?

?
QA P5 - 05:16
?



8、batchsize是否會最終影響模型結(jié)果?batchsize過小是否可能導(dǎo)致最終累積的梯度計算不準(zhǔn)確?

?
QA P5 - 06:26
?



9、在訓(xùn)練過程中,過擬合和欠擬合情況下,學(xué)習(xí)率和批次該如何進(jìn)行調(diào)整呢?有什么常見的策略嗎?

?
QA P5 - 07:45
?



10、針對batchsize大小的數(shù)據(jù)集進(jìn)行網(wǎng)絡(luò)訓(xùn)練的時候,網(wǎng)絡(luò)中每個參數(shù)更新時的減去的梯度是batchsize中每個樣本對應(yīng)參數(shù)梯度求和后取得的平均值嗎?

?
QA P5 - 08:25
?



11、隨機(jī)梯度下降中的“隨機(jī)”是值得批量大小是隨機(jī)的嗎?

?
QA P5 - 08:53
?



12、在深度學(xué)習(xí)上,設(shè)置損失函數(shù)的時候,需要考慮正則嗎?

?
QA P5 - 09:19
?



13、為什么機(jī)器學(xué)習(xí)優(yōu)化算法都采取梯度下降(一階導(dǎo)算法),而不是采用牛頓法(二階導(dǎo)算法),收斂速度更快,一般都能算出一階導(dǎo),二階導(dǎo)也應(yīng)該能算?

?
QA P5 - 09:44
?



14、學(xué)習(xí)率怎么除N,設(shè)置學(xué)習(xí)率的時候嗎?

?
QA P5 - 12:57
?



15、detach()是什么作用?

?
QA P5 - 13:17
?



16、detach和pytorch中的用法一樣嗎?梯度為什么要去掉,這里的梯度是怎么產(chǎn)生的?

?
QA P5 - 13:44
?



17、這樣的data-iter寫法,每次都把所有輸入load進(jìn)去,如果數(shù)據(jù)較多的話,最后內(nèi)存會爆炸吧?有什么好的辦法嗎?

?
QA P5 - 14:06
?



18、這里的indices為什么要轉(zhuǎn)化成tensor,直接用列表不行嗎?

?
QA P5 - 15:42
?



19、每次都是隨機(jī)取出一部分,怎么保證最后所有數(shù)據(jù)都被拿過了?

?
QA P5 - 15:51
?



20、這里使用生成器生成數(shù)據(jù)有什么優(yōu)勢呢,相比return?

?
QA P5 - 16:41
?



21、如果樣本大小不是批量數(shù)的整數(shù)倍,那么需要隨機(jī)剔除多余的樣本嗎?

?
QA P5 - 17:12
?



22、優(yōu)化算法里+batchsize但是最后一個batch里的樣本個數(shù)沒有這么多呀?

?
QA P5 - 18:08
?


?

23、這里學(xué)習(xí)率不做衰減嗎?有什么好的學(xué)習(xí)率衰減方法嗎?

?
QA P5 - 18:56
?



24、老師請問這里面是沒有進(jìn)行收斂判斷嗎?直接人為設(shè)置epoch的大小嗎?

?
QA P5 - 19:42
?



25、本質(zhì)上我們?yōu)槭裁匆肧GD,是因為大部分的實際loss太復(fù)雜,推到不出導(dǎo)數(shù)為0的解嗎?只能逐個batch去逼近?

?
QA P5 - 21:30
?



26、請問 w 為什么要隨機(jī)初始化,不能用相同的值呢?

?
QA P5 - 22:19
?



27、實際中有時候網(wǎng)絡(luò)會輸出nan,nan到底是怎么出現(xiàn)的?為什么不是inf?數(shù)值穩(wěn)定性不是會導(dǎo)致inf嗎?

?
QA P5 - 22:41
?



28、定義網(wǎng)絡(luò)層后一定要手動設(shè)置參數(shù)初始值嗎?

?
QA P5 - 23:03
?



29、l.baxkward()這里是調(diào)用pytorch自定義的back propogation嗎?

?
QA P5 - 23:27
?



30、外層for循環(huán)中最后一行l(wèi)=loss(net(),labels)就是為了print嗎?這里梯度要不要清零呢?會不會有什么影響?

?
QA P5 - 23:31
?



31、每個batch計算的時候,為什么要把梯度先清零?

?
QA P5 - 23:46
?



32、學(xué)習(xí)率設(shè)置過大會不會導(dǎo)致梯度爆炸(數(shù)值為NAN),但從數(shù)學(xué)理解上,如若上一次根據(jù)偏導(dǎo)數(shù)乘以學(xué)習(xí)率調(diào)整參數(shù),就算向相反的方向在調(diào),下一次不是就可以糾正過來嗎?為什么還會爆炸的呢?

?
QA P5 - 24:00
?





----end----

08 線性回歸 + 基礎(chǔ)優(yōu)化算法【動手學(xué)深度學(xué)習(xí)v2】的評論 (共 條)

分享到微博請遵守國家法律
邵阳县| 赫章县| 乐亭县| 扎兰屯市| 兴和县| 柳州市| 秭归县| 星子县| 云浮市| 广汉市| 霍州市| 满洲里市| 商丘市| 苍溪县| 临沧市| 友谊县| 禹城市| 昌平区| 宁国市| 南部县| 长寿区| 涪陵区| 沅江市| 浦城县| 宜兰县| 无锡市| 石阡县| 博乐市| 水富县| 陈巴尔虎旗| 乡宁县| 盘山县| 盘锦市| 神农架林区| 延吉市| 彭山县| 安宁市| 广昌县| 百色市| 东至县| 乐平市|