A Simple Exhaustive Method for Selecting Optimum Weight of Linear Model
Apr. 03, 2023
对于一组数据:
\[\begin{split} x:1,2,3\\ y:2,4,6 \end{split}\notag\]如何得到$x$和$y$之间所对应的关系呢(尽管这个关系很明显,就是$y=2x$)?一种思路是选取一种模型,并穷举这个模型所有系数的可能取值,之后求解出在相应系数组合下,所有的$x$的预测值$\hat{y}$与真实值$y$之间的误差。最终,可以获得一条误差随权重系数变化的曲线,观察分析曲线,就能够得到最优的(即使得误差最小的)权重系数组合。
如果我们选取的模型是不带有bias的线性模型,并使用MSE(Mean Square Error)来度量误差,则可以编写程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import numpy as np
import matplotlib.pyplot as plt
# Training Set
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
def forward(x): # Define model
return x * w
def loss(x, y): # Define loss function
y_pred = forward(x)
return (y_pred - y) * (y_pred - y)
w_list = [] # For saving weights w
mse_list = [] # For saving MSE
for w in np.arange(0.0, 4.1, 0.1): # Exhaustive method for selecting optimum weight
print('w =', w)
l_sum = 0 # Reset total sum
for x_val, y_val in zip(x_data, y_data):
# Predict value (just for print)
y_pred_val = forward(x_val)
# Calculate loss for each sample
loss_val = loss(x_val, y_val)
# Print information of each sample
print('\t', x_val, y_val, y_pred_val, loss_val)
# Accumulate loss value
l_sum += loss_val
print('MSE =', l_sum / 3)
w_list.append(w)
mse_list.append(l_sum / 3)
# Plot the change of MSE as a function of weights
plt.plot(w_list, mse_list)
# Scatter the ponit corresponding minimum MSE
min_idx = mse_list.index(min(mse_list))
plt.scatter(w_list[min_idx], mse_list[min_idx],c='red')
# Axes settings
plt.ylabel('Loss')
plt.xlabel('w')
plt.show()
虽然这个示例非常得简单,但是其思想是通用的。
进一步地,如果考虑遍历线性模型的bias,则可以得到类似的结果和图像:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Training Set
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
def forward(x): # Define model
return (x * w + b)
def loss(x, y): # Define loss function
y_pred = forward(x)
return (y_pred - y) * (y_pred - y)
mse_list = [] # For saving MSE
ws = np.arange(0.0, 4.1, 0.01)
bs = np.arange(-1.0, 1.1, 0.01)
Ws,Bs = np.meshgrid(ws,bs)
for w,b in zip(Ws.flatten(),Bs.flatten()):
l_sum = 0 # Reset total sum
for x_val, y_val in zip(x_data, y_data):
# Calculate loss for each sample
loss_val = loss(x_val, y_val)
# Accumulate loss value
l_sum += loss_val
print('MSE =', l_sum / 3)
mse_list.append(l_sum / 3)
# Plot the change of MSE as a function of weights and bias
fig = plt.figure()
ax = plt.axes(projection='3d')
surf = ax.plot_surface(Ws,Bs,np.array(mse_list).reshape(Ws.shape),cmap=plt.get_cmap('rainbow'),alpha=0.6)
# Scatter the ponit corresponding minimum MSE
min_idx = mse_list.index(min(mse_list))
ax.scatter(Ws.flatten()[min_idx],Bs.flatten()[min_idx],mse_list[min_idx],s=700,
c='red',marker='*')
# Axes settings
ax.set_xlabel('weight')
ax.set_ylabel('bias')
ax.set_zlabel('MSE error')
ax.set_title('The change of MSE as a function of weights and bias')
fig.colorbar(surf, orientation='vertical')
plt.show()
References
[1] 2. 线性模型 - 刘二大人.