最近在学习机器学习,课后作业很重要,贴上来记录一下,使用Octave实现,上干货!
warmup,代价函数和特征缩放比较简单,就不赘述了,直接看梯度下降核心部分:
gradientDescent.m
% 使用梯度下降公式,固定写死为单变量线性回归(theta是一个2元素列向量)
% 用(X*theta-y)点积X(:,1)的原因:(X*theta-y)是97*1维向量,按公式应该是(hθ(x(i)) − y(i))矩阵
% 和xj(i)矩阵的乘积来表示求和,这种表现形式等价于两个97*1的矩阵点积之后再求和,如:
% a=[1 2],b=[3;4],ab=sum(a.*b')
% 以下方法任选一种,只是一个小trick,完全等价
% 使用点积计算的方式:两个97*1的向量点积求和
% new_theta0 = theta(1) - (alpha / m) * sum((X * theta - y) .* X(:,1));
% new_theta1 = theta(2) - (alpha / m) * sum((X * theta - y) .* X(:,2));
% 使用矩阵乘法的方式1*97和97*1的矩阵乘法,不用单独求和
% new_theta0 = theta(1) - (alpha / m) * ((X * theta - y)' * X(:,1));
% new_theta1 = theta(2) - (alpha / m) * ((X * theta - y)' * X(:,2));
theta(1) = new_theta0;
theta(2) = new_theta1;
gradientDescentMulti.m
% 统一单变量和多变量线性回归,利用矩阵运算(各种补向量,乘法,转置等)
% 公式:new_theta = theta - (alpha / m) * ((X * theta - y)' * X(:,1));
% 在theta右边补一列-1,转换为n*2矩阵,目的是为了用矩阵运算代替theta - (alpha/m) * ((X * theta - y)' * X(:,1))
theta_mat = [theta ones(size(X, 2), 1) * (-1)];
% 计算theta_mat的行数,即theta参数的个数
theta_num = size(theta_mat, 1);
% 计算整个alpha/m整个这一块
s = (alpha / m) * ((X * theta - y)' * X)
% 在s上方补一行1
s = [ones(1, theta_num); s];
% 用theta_mat乘以s,再点乘单位矩阵,截取对角线的值即为每一个new theta值,求和是为了压缩为一维行向量
res = sum(theta_mat * s .* eye(theta_num));
% 转置为列向量,同时更新所有theta
theta = res'
以上算法满足任意维度的线性回归,同时计算、更新了theta的所有维度,虽然稍显复杂(截取对角线前,有很多冗余运算,最终只取了一部分值) ,和网上其它资料相比可能不够简洁,但是我自己思考的结果,以此记录
PS:完整代码请见附件
欢迎交流,wx:vinceall,备注机器学习