1、簡單介紹
線性回歸模型為,其中w1和w2為對應特征x1、x2的權重,b為偏差。
用神經網絡圖表現線性回歸模型如下,圖中未展示權重和偏差:
輸入層為x1、x2,輸入層個數為2,在神經網絡中輸入層個數即為特征數。輸出為o,輸出層個數為1.,即為線性回歸模型中的輸出。由於輸入層不參與計算,計算層僅有輸出層一層,故神經網絡層數為1,即線性回歸是一個單層神經網絡。神經網絡中負責計算的單元叫神經元,在該模型中o即為神經元。在線性回歸中,o的輸出依賴於x1、x2,即輸出層中的神經元和輸入層中各個輸入完全連接,故,此處輸出層又叫全連接層。
2、線性回歸的實現
(1)一些概念
(1.1)np.random.normal(size,loc,scale)
loc:此概率分布的均值(對應着整個分布的中心centre),不寫默認為0
scale:此概率分布的標准差(對應於分布的寬度,scale越大越矮胖,scale越小,越瘦高),方差=標准差的平方
size:輸出的shape,默認為None,只輸出一個值
(1.2)矩陣乘法
X*XT表示如下
nd.dot(X, X.T)
(1.3)自動求梯度
函數:y = 2xTX求列向量x的梯度
(a)求變量x的梯度,需要先調用attach_grad函數來申請存儲梯度所需要的內存
x.attach_grad()
(b)mxnet需要調用record函數來記錄與梯度有關的計算
with autograd.record():
y = 2 * nd.dot(x.T, x)
(c)調用backward函數自動求梯度,如果y不是一個標量,mxnet將會先對y中元素求和得到新的變量,再求該變量有關x的梯度
y.backward()
(d)獲取變量x的梯度結果
x.grad
(1.4)小批量隨機梯度下降迭代模型參數
線性回歸中模型參數迭代過程如下:
w1是迭代的參數,η是學習率取正數,是小批量中的樣本個數
(2)實現過程
(2.1)生成數據集
構造一個訓練數據集,樣本數為1000,特征數為2。隨機批量生成樣本1000*2,使用線性回歸模型真實權重W=[2,-3.4]T和偏差b=4.2,以及一個隨機噪聲e來生成標簽,數據之間的關系為y=XW+b+e,其中噪聲e服從均值為0,標准差為0.01的正態分布。
from IPython import display from matplotlib import pyplot as plt from mxnet import autograd,nd import random 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)
(2.2)生成小批量
在多次迭代模型參數時,每次迭代中,根據當前讀取的小批量數據樣本,通過調用反向函數backward計算小批量隨機梯度,並調用優化算法sgd迭代模型參數。小批量函數每次返回一個batch_size大小的隨機樣本及標簽
# 讀取小批量,每次返回一個batch_size大小的隨機樣本及其標簽 def data_iter(batch_size, features, labels): num_examples = len(features) indices = list(range(num_examples)) random.shuffle(indices)#樣本讀取順序隨機 for i in range(0, num_examples, batch_size): j = nd.array(indices[i:min(i + batch_size, num_examples)]) yield features.take(j),labels.take(j)
(2.3)線性回歸矢量計算
矢量計算公式y=X*w+b,dot函數可以用來做矩陣乘法
# 線性回歸矢量計算表達式,用dot函數做矩陣乘法 def linreg(X, w, b): return nd.dot(X,w) + b
(2.4)定義損失函數
線性回歸采用平方損失函數來計算損失,輸入為值為模型預測出來的標簽和真實標簽,在計算過程中其中兩個標簽的形狀不一樣,需要進行轉換
# 定義損失函數 # 將真實值y變成預測值y_hat的形狀,以便進行平方損失的計算 def squared_loss(y_hat,y): return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
(2.5)迭代模型參數,優化損失函數
params是傳入的需要迭代的參數,此處為w和b,lr為學習率此處自定義為0.03,batch_size為自定義小批量樣本大小,采用迭代公式為下圖
此處,對於一個迭代周期中,小批量樣本迭代選擇參數過程中,直接取的一個迭代周期中最后一個小批量對應的參數
def sgd(params, lr, batch_size): for param in params: param[:] = param - lr * param.grad / batch_size
(2.6)完整代碼
部分說明:在每一個迭代周期中,將會完整遍歷一遍所有數據,迭代小批量求出最佳模型參數,然后根據最佳參數得出訓練數據集的損失值
from matplotlib import pyplot as plt from mxnet import autograd, nd import random from IPython import display import d2lzh as dlz 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) # 權重初始化為均值為0,標准差為0.01的正態隨機數,偏差初始化為0 w = nd.random.normal(scale=0.01, shape=(num_inputs, 1)) b = nd.zeros(shape=(1,)) # 在模型訓練中迭代w和b,因此要創建它們的梯度 w.attach_grad() b.attach_grad() # 在每次迭代中 lr = 0.03 num_epochs = 3 net = dlz.linreg batch_size = 10 # 迭代周期 for epoch in range(num_epochs): # 在每個迭代周期中會使用訓練數據集中所有的樣本 # 小批量迭代尋找每次迭代周期中最佳參數 for X, y in dlz.data_iter(batch_size, features, labels): with autograd.record(): l = dlz.squared_loss(net(X, w, b), y) # l是有關小批量X和y的損失 l.backward() # 小批量的損失對模型參數求梯度 dlz.sgd([w, b], lr, batch_size) # 使用小批量隨機梯度下降迭代模型參數 train_l = dlz.squared_loss(net(features, w, b), labels) print('epoch %d, loss %f' % (epoch + 1, train_l.mean().asnumpy())) ''' 輸出結果: epoch 1, loss 0.035021 epoch 2, loss 0.000126 epoch 3, loss 0.000048 '''