基於MXNET框架的線性迴歸從零實現(房價預測為例)

流星斬月發表於2021-05-10

1、基於MXNET框架的線性迴歸從零實現例子 

  下面部落格是基於MXNET框架下的線性迴歸從零實現,以一個簡單的房屋價格預測作為例子來解釋線性迴歸的基本要素。這個應用的目標是預測一棟房子的售出價格(元)。

  為了簡單起見,這裡我們假設價格只取決於房屋狀況的兩個因素,即面積(平方米)和房齡(年)。接下來我們希望探索價格與這兩個因素的具體關係:

  設房屋的面積為x1,房齡為x2,售出價格為y。我們需要建立基於輸入x1和x2來計算輸出yy的表示式,也就是模型(model)。顧名思義,線性迴歸假設輸出與各個輸入之間是線性關係:y'=x1w1+x2w2+b

  其中w1w2是權重(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)

 

相關文章