"""
3.3. 線性回歸的簡潔實作
"""
"""
3.3.1. 生成資料集
features是訓練資料特征,labels是标簽
"""
from mxnet import autograd, nd
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = nd.random.normal(scale=1, shape=(num_examples,num_inputs))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += nd.random.normal(scale=0.01, shape=labels.shape)
"""
3.3.2. 讀取資料
"""
from mxnet.gluon import data as gdata
batch_size = 10
# 将訓練資料的特診和标簽組合
dataset = gdata.ArrayDataset(features, labels)
# 随機讀取小批量
data_iter = gdata.DataLoader(dataset, batch_size, shuffle=True)
for X, y in data_iter:
print("X:", X)
print("y:", y)
print("--------------------------------------------------------")
break
"""
3.3.3. 定義模型
首先,導入nn子產品。實際上,“nn”是neural networks(神經網絡)的縮寫。
顧名思義,該子產品定義了大量神經網絡的層。
我們先定義一個模型變量net,它是一個Sequential執行個體。
在Gluon中,Sequential執行個體可以看作是一個串聯各個層的容器。
在構造模型時,我們在該容器中依次添加層。
當給定輸入資料時,容器中的每一層将依次計算并将輸出作為下一層的輸入。
"""
from mxnet.gluon import nn
net = nn.Sequential()
"""
回顧圖3.1中線性回歸在神經網絡圖中的表示。
作為一個單層神經網絡,線性回歸輸出層中的神經元和輸入層中各個輸入完全連接配接。
是以,線性回歸的輸出層又叫全連接配接層。
在Gluon中,全連接配接層是一個Dense執行個體。我們定義該層輸出個數為1。
"""
net.add(nn.Dense(1))
"""
3.3.4. 初始化模型參數
在使用net前,我們需要初始化模型參數,如線性回歸模型中的權重和偏差。
我們從MXNet導入init子產品。
該子產品提供了模型參數初始化的各種方法。
這裡的init是initializer的縮寫形式。
我們通過init.Normal(sigma=0.01)指定權重參數每個元素将在初始化時随機采樣于均值為0、标準差為0.01的正态分布。
偏差參數預設會初始化為零。
"""
from mxnet import init
net.initialize(init.Normal(sigma=0.01))
"""
3.3.5. 定義損失函數
"""
from mxnet.gluon import loss as gloss
loss = gloss.L2Loss() # 平方損失又稱範數損失
"""
3.3.6. 定義優化算法
同樣,我們也無須實作小批量随機梯度下降。
在導入Gluon後,我們建立一個Trainer執行個體,并指定學習率為0.03的小批量随機梯度下降(sgd)為優化算法。
該優化算法将用來疊代net執行個體所有通過add函數嵌套的層所包含的全部參數。
這些參數可以通過collect_params函數擷取。
"""
from mxnet import gluon
trainer = gluon.Trainer(net.collect_params(), "sgd", {"learning_rate":0.03})
"""
3.3.7. 訓練模型
在使用Gluon訓練模型時,
我們通過調用Trainer執行個體的step函數來疊代模型參數。
上一節中我們提到,由于變量l是長度為batch_size的一維NDArray,
執行l.backward()等價于執行l.sum().backward()。
按照小批量随機梯度下降的定義,我們在step函數中指明批量大小,
進而對批量中樣本梯度求平均。
"""
num_epochs = 100
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
with autograd.record():
l = loss(net(X), y)
l.backward()
trainer.step(batch_size)
l = loss(net(features), labels)
print("epoch %d, loss: %f" % (epoch, l.mean().asnumpy()))
"""
下面我們分别比較學到的模型參數和真實的模型參數。
我們從net獲得需要的層,并通路其權重(weight)和偏差(bias)。
學到的參數和真實的參數很接近。
"""
dense = net[0]
print("true_w:", true_w)
print("dense.weight.data():", dense.weight.data())
print("true_b:", true_b)
print("dense.bias.data():", dense.bias.data())