做完前面的线性回归练习后,这里继续练习逻辑斯谛回归模型http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&doc=exercises/ex4/ex4.html。
给出的数据是40个被大学接收的学生和40个被拒绝的学生的数据,输入是一个二维向量,表示2门科目成绩,输出是一个分类结果(接收、拒绝),用0和1表示。
首先,我们要知道logistic regression的假设函数为:
这个假设函数是估计在参数为theta下,输入x被预测为1的概率。这个函数是sigmoid函数,是神经网络中的常用的一种激活函数。
模型的损失函数是:
这个形式是适用于类别y的值为0、1的,如果是1或-1就要变成另一种形式了。为什么要最小化这个函数呢?这个损失函数是怎么来的呢?它是通过最大化数据出现的概率推出来的,就是MLE(最大似然估计)。当样本类别为1时,我们的模型要使数据出现1的可能性最大,当样本类别为0时,我们要使它出现0的可能性最大。对于整个样本集,我们希望它们一起出现的概率最大,假设样本之间是独立的,则把每个样本出现的概率作累积就是样本集的似然估计。
要最大化L(theta), 即要最大化l(theta),即最小化损失函数J(theta)。
使这个损失函数最小的算法可以用梯度下降法,也可以用牛顿法,梯度下降法要求出J对theta的一阶导数,然后逐步更新theta达到局部最优,而牛顿方法要用到一阶导和二阶导也就是海森矩阵,牛顿法其实是求解函数f(x)=0的x值,对于初始值点x0,求出函数在这点的切线,然后求出切线与x轴的交点作为新的x值,一直重复这样的步骤直到到达f(x)=0的点x。
还记得我们是要最小化损失函数J, 我们就要找到使得J达到局部最优的theta,即极小点,在这一点上,J对theta的导数为0, 所以我们要求使得J的一阶导为0的theta。这样,就可以使用牛顿方法来求出这样的theta,而牛顿方法也要算出一阶导来,所以就要对J进行二阶求导,也就是海森矩阵。
J对theta的一阶导为:
这个看起来跟之前做过的线性回归的求导方程是一样的!但是是要根据J的表达式一步一步推出来的。
海森矩阵的方程式如下:
牛顿方法的更新规则:
实现如下:
%% Exercise 4: Logistic Regression and Newton's Method % 逻辑斯蒂回归和牛顿方法 % 这里是采用logistic regression模型和newton算法对数据进行二类分类(0和1)的 % 数据是40个被大学接收的学生和40个被拒绝的学生的两门成绩 % 从中学到分类模型然后给出一名学生的两门成绩,预测被大学接收的概率 %% %% 初始化数据 x = load('ex4x.dat'); y = load('ex4y.dat'); m = length(x); %m训练样本数 x = [ones(m,1), x]; %加入偏置项1到第一列 n = size(x, 2); % n为特征数,这里是3 % find找出满足条件的行号索引 pos = find(y == 1); neg = find(y == 0); % 画图显示 plot(x(pos, 2), x(pos, 3), '+'); hold on plot(x(neg, 2), x(neg, 3), 'o'); hold on xlabel('Exam 1 score') ylabel('Exam 2 score') %% %% 定义sigmod 函数 g = inline('1.0 ./ (1.0 + exp(-z))', 'z'); % 用法: 要找出2的sigmod值,调用g(2) % 如果传入矩阵或向量,则计算矩阵或向量中每个元素的sigmod %% %% 牛顿法 MAX_ITR = 20; % 最大迭代次数 J = zeros(MAX_ITR, 1); % 保存每次迭代后损失 theta = zeros(n, 1); % 初始化训练参数 for i = 1:MAX_ITR h = g(x*theta); % 计算假设函数,得到一个列向量,每行为那个样本属于1的概率 J(i) = (1/m) * sum(-y.*log(h) - (1-y).*log(1-h)); % 计算损失函数 % 计算梯度和海森矩阵 grad = (1/m) .* x' * (h - y); %计算J对theta的一阶导 % 自己想到的实现 H = (1/m) .* x' * (repmat(h .* (1-h), 1, n) .* x); %计算海森矩阵,即J对theta的二阶导 theta = theta - inv(H)*grad; % Solution中的实现 % H = (1/m).*x'*diag(h)*diag(1-h)*x; % theta = theta - H\grad; % 左除跟inv(H)*grad一样 end % Display theta theta %% %% prediction fprintf(['Probability that a student with a escore of exam 1 20 and 80 on exam 2 \n' ... 'will not be admitted to college is %f\n'], 1 - g([1 20 80]*theta)); %% %% 画出牛顿方法结果 % 决策边界:theta(1)*1+theta(2)*x2 + theta(3)*x3=0 % 两点确定一点直线,这里选择x2维度上的两点, plot_x = [min(x(:,2))-2, max(x(:,2))+2]; % 算出对应的x3值 plot_y = (-1./theta(3)).*(theta(2).*plot_x+theta(1)); % 画直线 plot(plot_x, plot_y) legend('Admitted', 'Not admitted', 'Decision Boundary') hold off %% %% 画出J figure plot(0:MAX_ITR-1, J, 'o--', 'MarkerFaceColor', 'r', 'MarkerSize', 8) xlabel('Iteration'); ylabel('J') J %% %% 跟梯度下降法对比 MAX_ITR = 20; % 最大迭代次数 J = zeros(MAX_ITR, 1); % 保存每次迭代后损失 theta = zeros(n, 1); % 初始化训练参数 alpha = 0.01; for i = 1:MAX_ITR h = g(x*theta); % 计算假设函数,得到一个列向量,每行为那个样本属于1的概率 J(i) = (1/m) * sum(-y.*log(h) - (1-y).*log(1-h)); % 计算损失函数 % 计算梯度 grad = (1/m) .* x' * (h - y); %计算J对theta的一阶导 theta = theta - alpha*grad; end % Display theta theta hold on plot(0:MAX_ITR-1, J, '*--', 'MarkerFaceColor', 'r', 'MarkerSize', 8) legend('newton', 'gradient descent')
从图中梯度下降与牛顿法的比较可以看出,梯度下降要经过至少10次才靠近局部最优,而牛顿法不到5次就收敛了,而且梯度下降法如果步长选得不好可能不会收敛,但是牛顿法的计算代价比较大,要算出海森矩阵的逆来,不过有一些优化方法比如拟牛顿法,这些以后再慢慢研究。