一、線性回歸---單層神經網絡


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
'''

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM