线性回归算法

线性回归算法是机器学习的入门级别算法 . 算法的基本思想是根据现有的已知数据集 , 试图使用线性模型来对数据进行拟合 , 使用均方误差来衡量拟合的程度 . 假设现有一直数据的输入为 xx , 真实输出为 yy , 采用线性模型对其进行拟合需要两个参数θ0\theta _0θ1\theta_1 , 预测输出表示为 y^=θ0+θ1×x\hat{y} = \theta_0 + \theta_1 \times x . 预测输出与真实输出之间的误差可以使用下面的公式来进行衡量 : J=(y^y)2J = (\hat{y} - y)^2 . 这是一个数据的误差值 , 对于数据集整体来说 , 可以使用每个数据点误差的均值来进行误差大小的衡量 :

J(θ0,θ1,...,θn)=12mi=1m(y^y)2J\left(\theta_{0}, \theta_{1},...,\theta_{n}\right) =\frac{1}{2m} \sum_{i=1}^{m} (\hat{y}-y)^2

由于需要使用梯度下降法来通过不断迭代的方式使得均方误差尽可能的小 , 因此在公式中乘以系数12\frac{1}{2} 以便于后续的求导 . 梯度下降法的参数迭代公式如下 :

θ0:=θ0αθ0J(θ0,θ1,...,θn)\theta_{0} :=\theta_{0}-\alpha \frac{\partial}{\partial \theta_{0}} J\left(\theta_{0}, \theta_{1},...,\theta_{n}\right)

θ1:=θ1αθ1J(θ0,θ1,...,θn)\theta_{1} :=\theta_{1}-\alpha \frac{\partial}{\partial \theta_{1}} J\left(\theta_{0}, \theta_{1},...,\theta_{n}\right)

............

θn:=θnαθnJ(θ0,θ1,...,θn)\theta_{n} :=\theta_{n}-\alpha \frac{\partial}{\partial \theta_{n}} J\left(\theta_{0}, \theta_{1},...,\theta_{n}\right)

其中 , := 为赋值符号 , α\alpha为学习率 , 决定了梯度下降时的步长 , 学习率是机器学习中的超参数 , 也就是说 , 这个参数究竟在何种情况下应该取何值 , 目前还没有一个明确成熟的理论 . 此参数往往由人工指定 , 并且需要不断尝试 , 以寻求一个相对比较好的学习效果 . 一般会选用 0.001 , 0.003 , 0.01 , 0.03 , 0.1 ,0.3 等等数值.

Matlab模型实现

首先需要把上述模型公式抽象成矩阵和向量的形式 , 对于当前比较流行的语言来说 , 都存在这比较成熟的线性代数函数库 , 通过使用矩阵和向量的方式可以批量对数据进行计算 , 并且合理使用已有的线性代数函数库可以很简单且很高效的实现模型 . 以下为上述公式的向量形式 :

  1. 预测输出: y^=θTx\hat{y} = \theta ^ Tx
  2. 均方误差: J=12m(y^y)T(y^y)J = \frac1{2m}(\hat{y}-y)^T(\hat{y}-y)
  3. 参数迭代: θj:=θjα1mi=1m(hθ(x(i))y(i))xj(i)\theta_{j}:=\theta_{j}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)} (for all j)

下面给出模型的简单实现:

1
2
3
4
5
%% 误差函数
function J = wu_cha(X,y,theta)
y_hat = X * theta; % 预测输出
m = size(X , 1); % 样本数
J = sum((y_hat - y).^2) / (2*m); % 均方误差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%% 梯度下降
function [theta ,J_history] = gradD(X,y,k,a,theta)
% 参数列表依次是 : 输入样本(矩阵),真实输出(向量),最大迭代步数(标量),学习率(标量),参数theta(向量)
m = size(y,1); % 样本数
i = 1;
while i <= k && wu_cha(X,y,theta) > 0.5 % 误差小于0.5或者到达迭代步数时终止程序
theta_tmp = theta; % 暂存theta , 因为在迭代过程中需要使用现在的theta值
for j = 1:size(theta,1)
theta_tmp(j) = theta(j) - a * (1/m) * (X*theta - y)' * X(:,j); % 梯度下降的迭代过程
end
theta = theta_tmp;
J_history(i,1) = wu_cha(X,y,theta); % 记录当前误差值
i = i + 1;
end


由于处在初学阶段 ,手里也没什么数据 , 因此采用手动输入无意义数据的方式对模型进行检测 .

输入矩阵为12×512\times5的矩阵 , 这里用列表示特征 , 即此矩阵中包含12个特征数为5的样本 .

image-20200919230825513

真实输出值为 y :

image-20200919230938920

这里取α=0.003\alpha=0.003 , 迭代步数 k=1000k=1000 , θ\theta的初始值为0 .

image-20200919231850236image-20200919231913939image-20200919231937027

观察J_historyJ\_history 变量的前几个数字 , 可以看出 误差在不断的减小 .

image-20200919232155142

随着迭代的不断进行 , 误差减小的差距越来越小 , 直到趋于稳定 .

image-20200919232257601

image-20200919232319668

最终得出的θ\theta值为:

image-20200919232406593

其实对于线性模型来说 , 求最优解可以使用公式直接得出 ,而不必像这样进行数值迭代 , 经过一定的数学推导 , 可以得出最优解公式为:

θ=(XTX)1XTy\theta = (X^TX)^{-1}X^Ty

此公式中涉及矩阵的逆运算等复杂的运算 , 对于数据集在10000以上的实际问题 , 若直接使用公式求解最优解 , 那将是对计算机的很大考验 .

此处 , 我们可以使用此公式来验证我们的梯度下降所得的解与最优解有多大的差距 .

image-20200919233002654

可以看出 , 差距并不大 .