此系列文章主要为记录作业过程,也为卡在某处提供些许思路,所以还是建议独立完成,这样对知识的理解最为深刻。
plotData
这部分练习的关键在于从数据集中筛选出正例和反例。使用的是Octave中的find
方法。筛选完成后,直接调用plot
方法绘图即可。参考答案如下:
pos_index = find(y==1);
neg_index = find(y==0);
plot(X(pos_index,1), X(pos_index,2), "k+", "MarkerSize", 10, "LineWidth", 2);
plot(X(neg_index,1), X(neg_index,2), "yo", "MarkerFaceColor", "y", "MarkerSize", 10);
sigmoid
sigmoid方法的实现为此道上机题的热身题目。难度不大,套公式即可。但注意黑体文字说明了需要适应实数、列向量和矩阵等。这里为了适配,有个简单的做法,就是利用元素的绝对序列。在Octave中,无论是实数,还是列向量或者矩阵,都可以看做矩阵,例如实数就是1x1
的矩阵,列向量就是mx1
的矩阵,当然矩阵就是mxn
的矩阵。而对于矩阵来说,每个元素都有一个绝对序号,对于列向量和矩阵来说,这个序号是由上而下、由左而右递增的。例如对于实数a = 2
来说,a(1) = 2
;对于列向量v = [2;3;4]
来说,v(1) = 2
;对于数组m = [2 3; 4 5]
来说,m(1) = 2; m(3) = 4
。所以这部分的参考答案如下:
for i = 1:numel(z)
g(i) = 1 / (1 + e ^ (-z(i)));
endfor
costFuntion
costFunction和gradient的计算太多好说的,公式大家都知道,使用向量化的写法写出来即可,如果遇到问题,多使用维度分析的方法。参考答案如下:
J = -1 / m * (y' * log(sigmoid(X * theta)) + (1 - y') * log(1 - sigmoid(X * theta)));
grad = 1 / m * (X' * (sigmoid(X * theta) -y));
fminunc
这里得到了costFunction和gradient之后,就需要用进阶函数fminunc来训练参数了。这部分的代码在练习中已经给出,但是还是有必要学习一下的。在调用fminunc的时候,使用了内联函数@(t) ( costFunction(t, X, y) )
,这部分内容我们在后续的作业中还会见到。
predict
上面一步使用fminunc训练出了theta之后,在预测这一步,直接带入即可。但要注意,需要对最后的结果进行sigmoid,而且最终的结果是通过与0.5比较大小得来的,大于等于0.5的预测为1,小于0.5的预测为0。参考答案如下:
hx = sigmoid(X * theta);
pos = find(hx >= 0.5);
neg = find(hx < 0.5);
p(pos) = 1;
p(neg) = 0;
costFunctionReg
这部分正规化的costFunction和gradient的求解。需要注意的是对于第一个参数是不需要正规化的,如果没考虑到这一点,你的答案可能有些许的偏差。参考答案如下:
tmp = theta;
tmp(1) = 0;
J = costFunction(theta, X, y)(1) + lambda / 2 / m * (tmp' * tmp);
grad = 1 / m * (X' * (sigmoid(X * theta) -y)) + (lambda / m) * tmp;