假设对于数据集\(D=\{(x_{1},y_{1}),\cdots,(x_{N},y_{N})\}\),然后定义矩阵\(X\)如下
\[\mathbf{X} = \left[ \begin{matrix}x_{11}&\cdots&x_{1p}\\\vdots & \cdots & \vdots\\x_{N1} & \cdots & x_{Np}\end{matrix}\right ]=[\mathbf{x}_{1},\cdots,\mathbf{x}_{N}]^T
\]
以及输出矩阵\(Y\)
\[\mathbf{Y}=\left [ \begin{matrix}y_{1}\\y_{2}\\\vdots\\y_{N}\end{matrix}\right ]
\]
那么对于模型\(f(w)=\mathbf{w}^Tx\)而言,基于上面的数据集,结合最小二乘法可以得到加权系数\(\mathbf{w}\)的值。首先定义损失函数
\[\ell({\mathbf{w}})=\sum_{n=1}^{N}\lvert \lvert \mathbf{w}^Tx_i-y_{i}\rvert\rvert^2\\=\sum_{n=1}^{N}({\mathbf{w}^Tx_i-y_{i})}^2
\]
进而可以将\(\ell({\mathbf{w}})\)表示成
\[\ell(\mathbf{w})=(\,\mathbf{w}^T\mathbf{x}_{1}-y_{1},\cdots,\mathbf{w}^T\mathbf{x}_{N}-y_{N})\left (\begin{matrix} \mathbf{w}^T\mathbf{x}_{1}-y_{1}\\\mathbf{w}^T\mathbf{x}_{2}-y_{2} \\\vdots\\ \mathbf{w}^T\mathbf{x}_{N}-y_{N} \end{matrix}\right )\\
\]
对上式进行化简整理得到
\[\ell(\mathbf{w})=(\mathbf{w}^T\mathbf{X}^T-\mathbf{Y}^T)(\mathbf{Xw-Y})\\=\mathbf{w^TX^TXw-2w^TX^TY+Y^TY}\\
\]
让\(\ell({\mathbf{w}})\)对\(\mathbf{w}\)求导,可以得到
\[\frac{\partial{\ell({\mathbf{w}})}}{\partial\mathbf{w}}=\mathbf{2X^T Xw-2X^TY}=0
\]
从而可以得到
\[\mathbf{w}=\mathbf{(X^TX)^{-1}X^TY}
\]
另外从概率角度分析,假设噪声\(\epsilon\)服从均值为0,方差为\(\sigma^2\)的高斯分布,定义
\[y=f(\mathbf{w})+\epsilon
\]
那么\(y\)将服从均值为\(\mathbf{w}^Tx\),方差为\(\sigma^2\)的高斯分布。另外定义损失函数
\[\ell_{p}(\mathbf{w})=log\Pi_{n=1}^{N}p(y_{i}|x_{i};\mathbf{w})=\sum_{n=1}^{N}log p(y_{i}|x_i;\mathbf{w})\\=\sum_{n=1}^{N}(log(\frac{1}{\sqrt{2\pi}})+log\frac{1}{\sigma}-\frac{(y_i-\mathbf{w}^Tx_{i})^2}{2\sigma^2})
\]
那么参数\(\hat{\mathbf{w}}\)可以用如下的公式进行估计
\[\hat{\mathbf{w}}=argmax\ell_{p}(\mathbf{w})\\=argmin(y_i-\mathbf{w}^Tx_{i})^2
\]
接下来求取\(\hat{\mathbf{w}}\)的步骤就和上面的最小二乘法一样。结合推导过程可以得到,利用最小二乘法计算权重使用了噪声服从高斯分布这个前提。
可以看到\(\hat{\mathbf{w}}\)的求取涉及到了逆矩阵求解,为了保证逆存在,因此引入正则化是有必要的。正则化主要有两种正则化:\(\ell_{1}\)正则化和\(\ell_{2}\)正则化。两者的区别在于加入的正则项不一样。引入\(\ell_{2}\)正则化,此时可以得到损失函数为
\[\ell({\mathbf{w}})=\sum_{n=1}^{N}\lvert\lvert\mathbf{w}^Tx_{i}-y_{i}\rvert\rvert^2+\alpha\lvert\lvert\mathbf{w}\rvert\rvert^2
\]
可以得到此时的权重为
\[\hat{\mathbf{w}}_{r}=\mathbf{(X^TX+\alpha I)^{-1}X^TY}
\]
从而保证矩阵的求逆能够正确进行。
import torch
from matplotlib import pyplot as plt
import numpy as np
import torch.nn
from torch.nn import init
import torch.optim as optim
num_inputs = 2
num_examples = 1000
true_w = [2, -4.3]
true_b = 3.5
features = torch.randn(num_examples, num_inputs, dtype=torch.float32)
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float32)
# plt.plot(x_data, y_data, 'ro', label='Origin Data')
# plt.show()
batch_size = 10
dataset = torch.utils.data.TensorDataset(features, labels)
# 随机读取小批量
data_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True)
# 定义模型参数
num_inputs = 2
# 第一种定义网络结构
# net = torch.nn.Sequential()
# net.add_module('linear', torch.nn.Linear(num_inputs, 1))
# 第二种定义网络结构
class LinearNet(torch.nn.Module):
def __init__(self, n_feature):
super(LinearNet, self).__init__()
self.linear = torch.nn.Linear(n_feature, 1)
def forward(self, x):
out = self.linear(x)
return out
net = LinearNet(num_inputs)
# print(net)
# 初始化模型参数
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)
# 损失函数
loss = torch.nn.MSELoss()
# 定义优化算法
optimizer = optim.SGD(net.parameters(), lr = 0.03)
# 训练模型
num_epochs = 3
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
output = net(X)
l = loss(output, y.view(-1, 1))
optimizer.zero_grad()
l.backward()
optimizer.step()
print('epoch %d, loss: %f' % (epoch, l.item()))
print(true_w, net.linear.weight)
print(true_b, net.linear.bias)
结果如下
epoch 1, loss: 0.000542
epoch 2, loss: 0.000167
epoch 3, loss: 0.000069
[2, -4.3] Parameter containing:
tensor([[ 1.9995, -4.3000]], requires_grad=True)
3.5 Parameter containing:
tensor([3.5006], requires_grad=True)