我們現(xiàn)在準(zhǔn)備好通過(guò)線性回歸的全功能實(shí)現(xiàn)來(lái)工作。在本節(jié)中,我們將從頭開(kāi)始實(shí)現(xiàn)整個(gè)方法,包括(i)模型;(ii) 損失函數(shù);(iii) 小批量隨機(jī)梯度下降優(yōu)化器;(iv) 將所有這些部分拼接在一起的訓(xùn)練功能。最后,我們將運(yùn)行3.3 節(jié)中的合成數(shù)據(jù)生成器 并將我們的模型應(yīng)用于生成的數(shù)據(jù)集。雖然現(xiàn)代深度學(xué)習(xí)框架幾乎可以自動(dòng)執(zhí)行所有這些工作,但從頭開(kāi)始實(shí)施是確保您真正了解自己在做什么的唯一方法。此外,當(dāng)需要自定義模型、定義我們自己的層或損失函數(shù)時(shí),了解引擎蓋下的工作原理將很方便。在本節(jié)中,我們將僅依賴張量和自動(dòng)微分。稍后,我們將介紹一個(gè)更簡(jiǎn)潔的實(shí)現(xiàn),利用深度學(xué)習(xí)框架的花哨功能,同時(shí)保留以下結(jié)構(gòu)。
%matplotlib inline
import tensorflow as tf
from d2l import tensorflow as d2l
3.4.1. 定義模型
在我們開(kāi)始通過(guò)小批量 SGD 優(yōu)化模型參數(shù)之前,我們首先需要有一些參數(shù)。在下文中,我們通過(guò)從均值為 0 且標(biāo)準(zhǔn)差為 0.01 的正態(tài)分布中抽取隨機(jī)數(shù)來(lái)初始化權(quán)重。幻數(shù) 0.01 在實(shí)踐中通常效果很好,但您可以通過(guò)參數(shù)指定不同的值sigma
。此外,我們將偏差設(shè)置為 0。注意,對(duì)于面向?qū)ο蟮脑O(shè)計(jì),我們將代碼添加到__init__
子類的方法中(在3.2.2 節(jié)d2l.Module
中介紹 )。
class LinearRegressionScratch(d2l.Module): #@save
"""The linear regression model implemented from scratch."""
def __init__(self, num_inputs, lr, sigma=0.01):
super().__init__()
self.save_hyperparameters()
self.w = torch.normal(0, sigma, (num_inputs, 1), requires_grad=True)
self.b = torch.zeros(1, requires_grad=True)
class LinearRegressionScratch(d2l.Module): #@save
"""The linear regression model implemented from scratch."""
def __init__(self, num_inputs, lr, sigma=0.01):
super().__init__()
self.save_hyperparameters()
self.w = np.random.normal(0, sigma, (num_inputs, 1))
self.b = np.zeros(1)
self.w.attach_grad()
self.b.attach_grad()
class LinearRegressionScratch(d2l.Module): #@save
"""The linear regression model implemented from scratch."""
num_inputs: int
lr: float
sigma: float = 0.01
def setup(self):
self.w = self.param('w', nn.initializers.normal(self.sigma),
(self.num_inputs, 1))
self.b = self.param('b', nn.initializers.zeros, (1))
class LinearRegressionScratch(d2l.Module): #@save
"""The linear regression model implemented from scratch."""
def __init__(self, num_inputs, lr, sigma=0.01):
super().__init__()
self.save_hyperparameters()
w = tf.random.normal((num_inputs, 1), mean=0, stddev=0.01)
b = tf.zeros(1)
self.w = tf.Variable(w, trainable=True)
self.b = tf.Variable(b, trainable=True)
接下來(lái),我們必須定義我們的模型,將其輸入和參數(shù)與其輸出相關(guān)聯(lián)。在(3.1.4)中使用相同的符號(hào),對(duì)于我們的線性模型,我們簡(jiǎn)單地采用輸入特征的矩陣向量乘積X和模型權(quán)重w,并加上偏移量b每個(gè)例子。Xw是一個(gè)向量并且b是一個(gè)標(biāo)量。由于廣播機(jī)制(參見(jiàn) 第 2.1.4 節(jié)),當(dāng)我們添加一個(gè)向量和一個(gè)標(biāo)量時(shí),標(biāo)量將添加到向量的每個(gè)分量。生成的 方法 通過(guò)(在第 3.2.1 節(jié)中介紹 )forward
在類中注冊(cè)。LinearRegressionScratch
add_to_class
3.4.2. 定義損失函數(shù)
由于更新我們的模型需要采用損失函數(shù)的梯度,因此我們應(yīng)該首先定義損失函數(shù)。這里我們使用(3.1.5)中的平方損失函數(shù)。在實(shí)現(xiàn)中,我們需要將真實(shí)值轉(zhuǎn)換y
為預(yù)測(cè)值的形狀 y_hat
。以下方法返回的結(jié)果也將具有與y_hat
. 我們還返回小批量中所有示例的平均損失值。
3.4.3. 定義優(yōu)化算法
正如第 3.1 節(jié)中所討論的,線性回歸有一個(gè)封閉形式的解決方案。然而,我們這里的目標(biāo)是說(shuō)明如何訓(xùn)練更通用的神經(jīng)網(wǎng)絡(luò),這需要我們教您如何使用小批量 SGD。因此,我們將借此機(jī)會(huì)介紹您的第一個(gè) SGD 工作示例。在每一步,使用從我們的數(shù)據(jù)集中隨機(jī)抽取的小批量,我們估計(jì)損失相對(duì)于參數(shù)的梯度。接下來(lái),我們朝著可能減少損失的方向更新參數(shù)。
以下代碼應(yīng)用更新,給定一組參數(shù),一個(gè)學(xué)習(xí)率lr
。由于我們的損失是按小批量的平均值計(jì)算的,因此我們不需要根據(jù)批量大小調(diào)整學(xué)習(xí)率。在后面的章節(jié)中,我們將研究如何為分布式大規(guī)模學(xué)習(xí)中出現(xiàn)的非常大的小批量調(diào)整學(xué)習(xí)率。現(xiàn)在,我們可以忽略這種依賴性。
評(píng)論
查看更多