线性回归推理与Matlab实现
1 线性回归
线性回归是最简单的机器学习模型,其形式简单,易于实现,同时也是很多机器学习模型的基础。对于给定的数据集,线性回归的目标是找到一个与这些数据最为吻合的线性函数。
1.1 一元线性回归
(1) 模型假设
其中,\(x\), \(y\)是标量。
(2) 评价标准-均方差损失
求导:
令(1)和(2)分别为0
1.2 多元线性回归
(1) 模型假设
其中,\(w \in R^n\)与\(b \in R\)为模型参数,也称为回归系数。为了方便,通常将\(b\)纳入权向量\(\vec{w}\),作为\(w_0\),同时为输入向量\(\vec{x}\)添加一个常数1作为\(x_0\),模型可以简化为:
(2) 评价标准
如果利用一元线性回归的思想求解是比较困难的,利用矩阵的方法可以省时省力。
设
矩阵求导:
如果\(X^TX\)存在逆矩阵,则
注:矩阵求导:参考《矩阵分析与应用》--张贤达
(3) 求解
很多时候,机器学习模型是不能通过闭式方程直接求解,此时需要求助于迭代优化的方法。迭代优化就是每次根据当前情况做出一点点微调,反复迭代调整,直到最优时停止。在迭代优化方法中,应用最为广泛的是梯度下降法(Gradient Descent)。梯度下降法可描述为:
(a) 根据当前参数\(\vec{w}\)计算损失函数梯度\(\nabla{L(\vec{w})}\);
(b) 沿着负梯度方向\(-\nabla{L(\vec{w})}\),调整\(\vec{w}\),调整步长的大小为\(\eta\),使用公式表述为:
(c) 反复执行上述过程,直到梯度为0或者损失函数降低小于阈值,此时称算法已收敛。
要证明上面的解是全局最优解,需要证明\(L(\vec{w})\)是凸函数。
【证明方法参考】
https://blog.csdn.net/AIHUBEI/article/details/104347195
1.3 项目实战
本文使用的数据集下载地址:https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/
普通方法:
clc;
clear;
close all;
%% 导入数据集
data = readtable("winequality-red.csv","VariableNamingRule","preserve");
data = table2array(data);
%% 划分数据集
num_data = size(data, 1); % 样本数目
idx = randperm(num_data);
rate = 0.7; % 划分比例
num_train = ceil(num_data*rate); % 训练集样本数目
train_data = data(idx(1:num_train),:); % 训练数据集
x_train = train_data(:, 1:end-1);
x_train = [x_train, ones(num_train,1)];
y_train = train_data(:, end);
test_data = data(idx(num_train+1:end),:); % 测试数据集
x_test = test_data(:, 1:end-1);
x_test = [x_test, ones(num_data-num_train, 1);];
y_test = test_data(:, end);
% 求解
w = (x_train'*x_train)^(-1)*x_train'*y_train;
loss = sum((x_test*w - y_test));
梯度下降方法:
clc;
clear;
close all;
%% 导入数据集
data = readtable("winequality-red.csv","VariableNamingRule","preserve");
data = table2array(data);
%% 划分数据集
num_data = size(data, 1); % 样本数目
idx = randperm(num_data);
rate = 0.7; % 划分比例
num_train = ceil(num_data*rate); % 训练集样本数目
train_data = data(idx(1:num_train),:); % 训练数据集
x_train = train_data(:, 1:end-1);
x_train = [x_train, ones(num_train,1)];
y_train = train_data(:, end);
test_data = data(idx(num_train+1:end),:); % 测试数据集
x_test = test_data(:, 1:end-1);
x_test = [x_test, ones(num_data-num_train, 1);];
y_test = test_data(:, end);
max_iter = 3000; % 最大迭代次数
w = zeros(size(x_train,2), 1);
eta = 0.0001; % 学习率
tol = 0.00001; % 损失降低阈值
%% 训练
for iter=1:max_iter
y_pred = x_train*w;
loss = 1/(2*num_train)*sum((y_train - y_pred).^2);
if iter>2
error = loss_old - loss;
if error<tol
break;
end
end
loss_old = loss;
w = w - eta*(1/num_train)*x_train'*(y_pred- y_train);
end
%% 测试
y_ = x_test*w;
loss_ = 1/(2*(num_data-num_train))*sum((y_test - y_).^2);