前一节讲线性回归已提过,回归问题的根本目的在于预测。直观上看,线性回归训练与预测的值域都为实数域R,而逻辑回归训练样本值域为{0,1},预测的值域则是(0,1),也就是说逻辑回归用于分类,其结果能给出样本属于某个类的概率。逻辑回归逻辑回归作为机器学习中的一个简单而有效的算法,其应用之广泛已超出我们的想象。
逻辑回归算法推导
首先,确定逻辑回归函数模型,如下:
\(\begin{aligned} h_\theta(x)=\frac{1}{1+e^{-\theta^Tx}} \end{aligned}\)
可以看出该函数定义域为实数域R,值域为(0,1)。这里关于选择该函数的原因暂不讨论,待后面广义线性模型一节再讲。先看看该函数的一个特性,令
\(\begin{aligned} g(z)=\frac{1}{1+e^{-z}} \end{aligned}\)
则
\( \begin{aligned} g^{'}(z)&=\frac{1}{(1+e^{-z})^2}{e^{-z}}\\&={\frac{1}{1+e^{-z}}}{\frac{e^{-z}}{1+e^{-z}}}\\&=g(z)(1-g(z)) \end{aligned} \)
此函数应用甚广,神经网络的激励函数,独立成分分析中源信号分布都是使用该函数的。
假设2个类分别为0和1,回归结果\( h_\theta(x) \)表示样本属于类1的概率,因此样本属于类0的概率则为\( 1- h_\theta(x) \),则有
\( P(y=1|x,\theta)=h_\theta(x) \)
\( P(y=0|x,\theta)=1-h_\theta(x) \)
实际上就是一个两点分布,可写为
\( P(y|x,\theta)=h_\theta(x)^y(1-h_\theta(x))^{1-y} \)
从而给定样本集,其对数似然函数为:
\(\begin{aligned} l(\theta)&=log(L(\theta))\\&=log(\prod_{i=1}^m{h_\theta(x^{(i)})^{y^{(i)}}(1-h_\theta(x^{(i)}))^{1-y^{(i)}}})\\&=\sum_{i=1}^m{(y^{(i)}log(h_\theta(x^{(i)}))+(1-y^{(i)})log(1-h_\theta(x^{(i)})))} \end{aligned}\)
最大化该对数似然函数,也采用梯度下降法,下面对其求导。
首先有
\(\begin{aligned} \frac{\partial logh_\theta(x^{(i)})}{\partial\theta_j}&=\frac{\partial log(g(\theta^T x^{(i)}))}{\partial\theta_j}\\&=\frac{1}{g(\theta^T x^{(i)})}{ g(\theta^T x^{(i)})) (1-g(\theta^T x^{(i)}))x_j^{(i)}}\\&=(1- g(\theta^T x^{(i)}))) x_j^{(i)}\\&=(1-h_\theta(x^{(i)}))x_j^{(i)} \end{aligned}\)
类似可得
\(\begin{aligned} \frac{\partial(1-logh_\theta(x^{(i)}))}{\partial\theta_j}=-h_\theta(x^{(i)})x_j^{(i)} \end{aligned}\)
因此有:
\(\begin{aligned} \frac{\partial l(\theta)}{\partial\theta_j}&=\sum_{i=1}^m{(y^{(i)}(1-h_\theta(x^{(i)}))x_j^{(i)}+(1-y^{(i)})(-h_\theta(x^{(i)})x_j^{(i)}))}\\&=\sum_{i=1}^m{(y^{(i)}-h_\theta(x^{(i)}))x_j^{(i)}} \end{aligned}\)
由于这里是最大化对数似然函数,故迭代规则为:
\(\begin{aligned} \theta_j=\theta_j+\alpha\frac{\partial l(\theta)}{\partial\theta_j} \end{aligned}\)
同样地,这里也有批量梯度下降和随机梯度下降两种实现方法。
算法实现
仔细对比,该迭代公式与线性回归是一样的,但其中的区别在于\(h_\theta(x^{(i)}) \)这个函数是不同的。因此,二者的算法实现可重用代码,只需更改\(h_\theta(x^{(i)}) \)的实现即可。
顺便提一下,在线性回归和逻辑回归的推导中, \(\theta^Tx\)中的常数项为\(\theta_0\),但由于matlab数组下标从1开始,因此程序中常数项\(\theta_{n}\)其中\(x\)为\(n-1\)维的。
具体代码如下,可兼容线性回归与逻辑回归,通过参数传入切换即可:
1 %返回值Theta为回归结果 2 %IterInfo为迭代的中间过程信息,用于调试,查看 3 %Sample为训练样本,每一行为一个样本,每个样本最后一个为Label值 4 %Type为回归算法类型,'Linear'--线性回归, 'Logistic'--逻辑回归 5 %BatchSize为每次批量迭代的样本数 6 function [Theta, IterInfo]=Regression(Sample, Type, BatchSize) 7 if strcmpi(Type, 'Linear') 8 fun = @Linear; 9 elseif strcmpi(Type, 'Logistic') 10 fun = @Sigmod; 11 else 12 return; 13 end 14 [m, n] = size(Sample); %m个样本,每个n维 15 Y = Sample(:, end); %label 16 X = [Sample(:,1:end-1), ones(m,1)]';%x加入常数项1,并转换为每列表示1个样本 17 18 %将样本顺序随机打乱 19 ord = randperm(m); 20 X = X(:, ord); 21 Y = Y(ord); 22 23 BatchSize = min(m, BatchSize); 24 Theta = zeros(n, 1); 25 Theta0= Theta; 26 Alpha = 1e-2 * ones(n, 1); 27 StartID = 1; 28 29 IterInfo.Grad = []; 30 IterInfo.Theta = [Theta]; 31 32 %梯度下降,迭代求解 33 MaxIterTime = 5000; 34 for i = 1:MaxIterTime 35 EndID = StartID + BatchSize; 36 if(EndID > m) 37 TX = [X(:, StartID:m) X(:, 1:EndID-m)]; 38 TY = [Y(StartID:m); Y(1:EndID-m)]; 39 else 40 TX = X(:, StartID:EndID); 41 TY = Y(StartID:EndID); 42 end 43 44 Grad = CalcGrad(TX, TY, Theta, fun); 45 46 Theta = Theta + Alpha .* Grad; 47 48 %记录中间结果 49 IterInfo.Grad = [IterInfo.Grad Grad]; 50 IterInfo.Theta = [IterInfo.Theta Theta]; 51 52 %迭代收敛检验 53 Delta = Theta - Theta0; 54 if(Delta' * Delta < 1e-10) 55 break; 56 end 57 58 Theta0 = Theta; 59 StartID = EndID + 1; 60 StartID = mod(StartID, m) + 1; 61 end 62 63 IterInfo.Time = i; 64 end 65 66 %梯度计算 67 function Grad = CalcGrad(X, Y, Theta, fun) 68 D = 0; 69 for i = 1:size(X,2) 70 h = fun(Theta, X(:,i)); 71 G = (Y(i) - h) * X(:,i); 72 D = D + G; 73 end 74 Grad = D / size(X,2); 75 end 76 77 %线性函数 78 function y = Linear(Theta, x) 79 y = Theta' * x; 80 end 81 82 %逻辑回归函数 83 function y = Sigmod(Theta, x) 84 t = Theta' * x; 85 y = 1 / (1 + exp(-t)); 86 end