1、基於MXNET框架的線性迴歸從零實現例子
下面部落格是基於MXNET框架下的線性迴歸從零實現,以一個簡單的房屋價格預測作為例子來解釋線性迴歸的基本要素。這個應用的目標是預測一棟房子的售出價格(元)。
為了簡單起見,這裡我們假設價格只取決於房屋狀況的兩個因素,即面積(平方米)和房齡(年)。接下來我們希望探索價格與這兩個因素的具體關係:
設房屋的面積為x1,房齡為x2,售出價格為y。我們需要建立基於輸入x1和x2來計算輸出yy的表示式,也就是模型(model)。顧名思義,線性迴歸假設輸出與各個輸入之間是線性關係:y'=x1w1+x2w2+b
其中w1和w2是權重(weight),b是偏差(bias),且均為標量。它們是線性迴歸模型的引數(parameter)。模型輸出y'是線性迴歸對真實價格y的預測或估計。我們通常允許它們之間有一定誤差。
2、實現部分(各個部分見程式碼註釋)
2.1、生成資料集(隨機生成批量樣本資料與高斯噪聲)
2.2、讀取資料集(遍歷資料集並不斷讀取小批量資料樣本)
2.3、初始化模型引數(均值為0、標準差為0.01的正態隨機數,偏差則初始化成0)
2.4、定義模型
2.5、定義損失函式(平方損失函式)
2.6、定義優化演算法(sgd小批量隨機梯度下降演算法)
2.7、訓練模型(過呼叫反向函式backward
計算小批量隨機梯度,並呼叫優化演算法sgd
迭代模型引數)
3、程式碼實現
1 from IPython import display 2 from matplotlib import pyplot as plt 3 from mxnet import autograd, nd 4 import random 5 6 7 # 生成資料集 8 num_inputs = 2 9 num_examples = 1000 10 11 true_w = [2, -3.4] 12 true_b = 4.2 13 features = nd.random.normal(scale=1, shape=(num_examples, num_inputs)) 14 15 labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b 16 labels += nd.random.normal(scale=0.01, shape=labels.shape) 17 18 print(features[0], labels[0]) 19 20 21 def use_svg_display(): 22 # 用向量圖顯示 23 display.set_matplotlib_formats('svg') 24 25 26 def set_figsize(figsize=(3.5, 2.5)): 27 use_svg_display() 28 # 設定圖的尺寸 29 plt.rcParams['figure.figsize'] = figsize 30 31 32 set_figsize() 33 plt.scatter(features[:, 1].asnumpy(), labels.asnumpy(), 1) 34 35 # plt.scatter(features[:, 0].asnumpy(), labels.asnumpy(), 1) 36 # help(plt.scatter) 37 38 39 # 讀取資料集 40 def data_iter(batch_size, features, labels): 41 num_examples = len(features) 42 indices = list(range(num_examples)) 43 random.shuffle(indices) 44 for i in range(0, num_examples, batch_size): 45 j = nd.array(indices[i: min(i + batch_size, num_examples)]) 46 yield features.take(j), labels.take(j) 47 48 49 batch_size = 10 50 51 for X, y in data_iter(batch_size, features, labels): 52 print(X, y) 53 break 54 55 56 # 初始化模型引數 57 w = nd.random.normal(scale=0.01, shape=(num_inputs, 1)) 58 b = nd.zeros(shape=(1,)) 59 # 之後的模型訓練中,需要對這些引數求梯度來迭代引數的值,因此我們需要建立它們的梯度 60 w.attach_grad() 61 b.attach_grad() 62 63 64 # 定義模型 65 def linreg(X, w, b): 66 return nd.dot(X, w) + b 67 68 69 # 定義平方損失函式 70 def squared_loss(y_hat, y): 71 return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2 72 73 74 #定義優化演算法 75 def sgd(params, lr , batch_size): 76 for param in params: 77 param[:] = param - lr * param.grad / batch_size 78 79 80 #訓練模型 81 lr = 0.03 82 num_epochs = 3 83 net = linreg 84 loss = squared_loss 85 86 for epoch in range(num_epochs): 87 for X, y in data_iter(batch_size, features, labels): 88 with autograd.record(): 89 l = loss(net(X, w, b), y) 90 l.backward() 91 sgd([w, b], lr, batch_size) 92 train_l = loss(net(features, w, b), labels) 93 print('epoch %d, loss %f' % (epoch + 1, train_l.mean().asnumpy())) 94 95 96 97 plt.show()
4、結果
4.1、特徵features[1, :]和[:, 1]與labels之間的散點圖
4.2、迭代結果
4.3、線性迴歸模型真實權重引數與訓練得到的引數比較:print(true_w, w) print(true_b, b)