用矩阵运算实现,不使用循环
最近学习了逻辑回归,然后用MATLAB实现了。中间遇到点小问题,上网查了一些资料。本文中前面的部分介绍以及实验中用到的数据,是直接引用的这篇博文
损失函数
更新公式及停止准则
更新方式:
g
=
∂
J
(
θ
)
∂
θ
=
1
m
∑
i
=
1
m
[
(
h
(
x
i
)
−
y
i
)
x
i
]
θ
=
θ
−
α
⋅
g
g=\frac{\partial J(\theta)}{\partial \theta}=\frac{1}{m}\sum \limits_{i=1}^{m}[(h(x_{i})-y_{i})x_{i}] \\ \theta = \theta -\alpha \cdot g
g=∂θ∂J(θ)=m1i=1∑m[(h(xi)−yi)xi]θ=θ−α⋅g
停止准则:满足下列条件或者达到最大迭代次数
∥
J
k
(
θ
)
−
J
k
−
1
(
θ
)
∥
2
<
ϵ
\| J^{k}(\theta)-J^{k-1}(\theta) \|_{2} < \epsilon
∥Jk(θ)−Jk−1(θ)∥2<ϵ
本文中,
ϵ
=
1
e
−
5
\epsilon=1e^{-5}
ϵ=1e−5
实现
主函数
%% 数据准备
% x_{i} \in {1 \times d} 一个样本
% y_{i} \in {0,1}
% 二分类 随机生成数据。 200个数据 每个数据2个特征
% 在我们的数据中,一行表示一个样本
data=1*rand(300,2);
label=zeros(300,1);
label((data(:,2)+data(:,1)>1))=1;
%在data上加常数特征项;
data=[data,ones(size(data,1),1)];
%打乱顺序
randIndex = randperm(size(data,1));
data_new=data(randIndex,:);
label_new=label(randIndex,:);
%80%训练 20%测试
k=0.8*size(data,1);
X=data_new(1:k,:);
Y=label_new(1:k,:);
tstX=data_new(k+1:end,:);
tstY=label_new(k+1:end,:);
max_iter = 300;
%% 调用函数
[loss,acc,pre_Y] = logistic_regression(X,Y,tstX,tstY,max_iter);
acc
% 画出迭代过程损失函数值的变化
plot(loss)
logistic_regression()
function [loss,acc,pre_Y] = logistic_regression(X,Y,tstX,tstY,max_iter)
%% 梯度下降法
iter = 1;
epsilon = 1e-5;
loss = zeros(max_iter,1);
alpha = 1; % 学习率为1
[m,d] = size(X);
theta = rand(d,1); % 初始化
while iter < max_iter
% 计算梯度
% 将求和写成矩阵的形式
h = 1./(1+exp(-X*theta)); % h(\theta)
item1 = repmat(h,1,d);
item2 = repmat(Y,1,d);
g = sum(X.*(item1-item2))/m;
g = g'; % 梯度
theta = theta-alpha*g;
iter = iter+1;
loss(iter) = -(Y'*log(h)+(1-Y')*log(1-h))/m; % 计算交叉熵损失
if norm(loss(iter)-loss(iter-1)) < epsilon
break;
end
end
%% 预测
tmp = tstX*theta;
p1 = 1./(1+exp(-tmp));
% 预测值
pre_Y = p1>0.5; % 大于0.5表示正类
% 精度
acc = sum(pre_Y==tstY)/length(tstY)*100;
精度能达到 95% 及以上