使用最小二乘法和梯度下降法进行线性回归分析

线性回归问题

线性回归问题即已知一系列样本的自变量和因变量的值,求解以下方程中的各θj

$$h_θ(x) = θ_0 + θ_1x_1 + θ_2x_2 + \cdots + θ_nx_n$$

设样本数量为m,评估拟合的直线与实际样本之间差异的代价函数(Cost Function)为:

$$J(θ_0,θ_1,\cdots,θ_n) = \frac{1}{2m}\sum_{i=1}^{m}(h_θ(x^{(i)})-y^{(i)})^2$$

因此,寻找最佳拟合的线性回归模型则转化为求解该代价函数的最小值,常用方法为最小二乘法(Least Squares Method)和梯度下降法(Gradient Descent Method)。

这里以一元线性回归为例,分别使用最小二乘法和梯度下降法进行线性回归,使用的语言为Octave/MATLAB。首先准备样品的数据集:

X = [ones(100, 1), [1:100]']; % 构建一个100×2的因变量x的矩阵,第一列都为1(x_0=1)
randn("seed", 123); % 设定randn的seed为123,方便后面重现随机过程
% 按照方程y = 2x + 200(即θ_0=200, θ_1=2)生成因变量,并加上随机抖动:
y = ([1:100]'+10*(randn(100, 1)))*2+200;
plot(X(:,2), y, 'rx'); % 绘制点图
xlabel('X');
ylabel('y');
hold on;

其中X为自变量组成的设计矩阵,行对应各样本,列对应各特征;y为因变量组成的矢量:

$$ X = \begin{bmatrix} {1}&{(x_{1}^{(1)})}&{\cdots}&{(x_{n}^{(1)})}\\ {\vdots}&{\vdots}&{\ddots}&{\vdots}\\ {1}&{(x_{1}^{(m)})}&{\cdots}&{(x_{n}^{(m)})}\\ \end{bmatrix} ;\ y = \begin{bmatrix} {y^{(1)}}\\ {\vdots}\\ {y^{(m)}}\\ \end{bmatrix} $$

得到点图如下所示:

自变量-因变量散点图

使用最小二乘法求解线性回归问题

最小二乘法是将代价函数的每个θ的偏导数设为0(一元线性回归时即为全导数),通过得到的正规方程求解各θ的值:

$$set:\ \frac{∂}{∂θ_j}J(θ) = 0$$

可得到求解θ的正规方程组为:

$$θ = (X^TX)^{-1}X^Ty$$

因为是直接计算不需要迭代,因此代码很简单,一行就搞定:

theta = pinv(X'*X)*X'*y; % pinv函数为求解伪逆矩阵,在这个简单的例子里用inv也可以
plot(X(:,2), X*theta, 'g'); % 用绿色的直线绘制拟合的函数

可得到θ的计算结果为[203.6221; 1.9871],即拟合的公式为y = 1.9871x + 203.6221,如下图:

最小二乘法线性回归拟合的直线

需要注意的是:

  • XTX通常情况下是可逆的。如果遇到不可逆的情况,检查是否有冗余的特征,或者特征数量太多。
  • 因为公式中进行了3次X矩阵(或其转置、逆矩阵)相乘,因此最小二乘法的复杂度大体可表示为:O(n3)。虽然最小二乘法可以直接计算代价函数的最小值,但是当样本数n非常大时,速度就会变得很慢。这时候我们可以使用梯度下降法来解决线性回归的问题。

使用梯度下降法求解线性回归问题

梯度下降法将线性回归问题形象化为一个“下山问题”。从一组设定的θ开始,通过调整θ的值逐步减小代价函数的值,最终得到代价函数的局部最小解(即回归模型的局部最优解)。因为线性回归的代价函数总是凸函数,所以局部最优解即为全局最优解。调整θ的方法为每次迭代时每个特征所对应的θ同时减去学习率α乘以代价函数的偏导数:

$$ \begin{align} repeat &\{ \\ & θ_j := θ_j - α\frac{∂}{∂θ}J(θ) = θ_j - α\frac{1}{m}\sum_{i=1}^{m}(h_θ(x^{(i)}-y^{(i)}))x_j^{(i)} \\ & \} \ (同时更新:j = 0,\cdots,n)\\ \end{align} $$

代码实现如下:

% 定义函数gd,用于计算每轮迭代用于更新θ的矢量
function r = gd(m, X, y, alpha, theta)
  predictions = X * theta;
  r = alpha*(1/m)*(X'*(predictions-y));
endfunction

theta = [0; 0]; % 初始化theta,这里设定为[0; 0]
alpha = 0.0005; % 设定学习率为0.0005
m = size(X, 1); % m为训练样本数,在这里即100

% 进行100000次迭代
for n = 1:100000,
  r = gd(m, X, y, alpha, theta);
  theta = theta - r; % 更新θ
  disp(theta');
end;
plot([1:100], [1:100]*theta(2)+theta(1), 'b'); % 用蓝色的直线绘制拟合的函数

经过100000轮迭代后最终得到θ的计算结果为[203.6212; 1.9871],与上面最小二乘法计算出来的[203.6221; 1.9871]非常接近。从图中也可以看出,梯度下降法拟合的直线基本上遮住了最小二乘法求解的直线:

梯度下降法线性回归拟合的直线

附录

代价函数的计算:

function J = calCostFunction(X, y, theta)
  predictions = X * theta;
  m = size(X, 1);
  J = 1/(2*m)*sum((predictions-y).^2);
endfunction

参考资料:

吴恩达机器学习课程:https://study.163.com/course/courseLearn.htm?courseId=1004570029

标签: 算法

知识共享许可协议 作者: 链接:https://byteofbio.com/archives/13.html
本文采用“署名-非商业性使用-相同方式分享 4.0 国际许可协议”进行许可

暂无评论

添加新评论