octave - 为什么我为吴恩达写的课程不被接受?
问题描述
Andrew Ng 在 Coursera 中的课程,这是斯坦福的机器学习课程,其特点是编程作业,处理实施课堂教授的算法。这个任务的目标是通过梯度下降来实现线性回归,输入集为X, y, theta, alpha (learning rate), and number of iterations
.
我在课程中规定的语言 Octave 中实现了这个解决方案。
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
m = length(y);
J_history = zeros(num_iters, 1);
numJ = size(theta, 1);
for iter = 1:num_iters
for i = 1:m
for j = 1:numJ
temp = theta(j) - alpha /m * X(i, j) * (((X * theta)(i, 1)) - y(i, 1));
theta(j) = temp
end
prediction = X * theta;
J_history(iter, 1) = computeCost(X,y,theta)
end
end
另一方面,这是成本函数:
function J = computeCost(X, y, theta)
m = length(y);
J = 0;
prediction = X * theta;
error = (prediction - y).^2;
J = 1/(2 * m) .* sum(error);
end
这不通过submit()
函数。该submit()
函数只是通过传递一个未知的测试用例来验证数据。
我已经检查了 StackOverflow 上的其他问题,但我真的不明白。:)
非常感谢你!
解决方案
您的渐变似乎是正确的,正如@Kasinath P 给出的答案中已经指出的那样,问题很可能是代码太慢了。你只需要矢量化它。在 Matlab/Octave 中,您通常需要避免for
循环(请注意,虽然您parfor
在 Matlab 中有,但在 octave 中尚不可用)。因此,在性能方面,编写类似的东西总是更好,而不是用A*x
循环遍历每一行。您可以在此处阅读有关矢量化的信息。A
for
如果我理解正确,X
是一个大小矩阵,m*numJ
其中m
是示例numJ
数,是特征数(或每个点所在空间的维度。在这种情况下,您可以将成本函数重写为
(1/(2*m)) * (X*theta-y)'*(X*theta-y);%since ||v||_2^2=v'*v for any vector v in Euclidean space
现在,我们从基本矩阵演算中知道,对于任何两个向量s
,并且v
是函数 fromR^{num_J}
到R^m
,Jacobian 由s^{t}v
下式给出
s^{t}Jacobian(v)+v^{t}*Jacobian(s) %this Jacobian will have size 1*num_J.
将其应用于您的成本函数,我们得到
jacobian=(1/m)*(theta'*X'-y')*X;
所以如果你只是更换
for i = 1:m
for j = 1:numJ
%%% theta(j) updates
end
end
和
%note that the gradient is the transpose of the Jacobian we've computed
theta-=alpha*(1/m)*X'*(X*theta-y)
您应该会看到性能有了很大的提高。
推荐阅读
- python - 我们如何将字符串转换为浮点数?
- java - JTable更改选择而不闪烁ui
- python - 如何使 ProcessPoolExecutor 中的任务表现得像守护进程?
- javascript - 抽象中间件函数
- laravel - 找不到类 '\Laravel\Socialite\Two\TwitterProvider' 错误
- video - ffmpeg 质量很差的 mp4 转换
- javascript - @hapi/joi 依赖的模块解析失败
- python - 如何保存终端中显示的所有旧值
- c++ - 使用 static_assert 确保模板参数只使用*最多*一次
- xml - 从 PowerShell 脚本创建 XML 输出文件