此系列文章主要为记录作业过程,也为卡在某处提供些许思路,所以还是建议独立完成,这样对知识的理解最为深刻。
warmUpExercise.m
这一部分很简单,主要是熟悉函数的编写,以及了解做题的过程。题目本身没有难度,就是编写一个返回5阶单位矩阵的方法。在warmUpExercise.m编写代码,文件中函数的声明和返回都已经写好了,我们只需要在指定出补充代码即可,在Octave中生成单位矩阵的方法是eye(i)
,其中i为生成的阶数:所以此部分的答案是:
A = eye(5);
Plotting the Data
这部分主要是基础的画图。题目中也给出了答案,只需要理解即可。还是推荐在命令窗口使用help plot
来了解一下Octave的plot命令。答案如下:
data = load("ex1data1.txt");
X = data(:, 1);
y = data(:, 2);
plot(X, y, 'rx', 'MarkerSize', 10);
ylabel('Profit in $10,000s');
xlabel('Population of City in 10,000s');
Computing the cost
这部分主要是计算成本函数。线性回归的成本函数计算很简单,在一开始不熟悉矩阵化运算的情况下,可以使用for循环来计算求和。在1到m的每个循环中,将(h(x) - y)²
累加即可,最后除以2*m
。
for i = 1:m
J = J + (theta(1) * X(i, 1) + theta(2) * X(i, 2) - y(i)) .^ 2;
end
J = J / (2 * m);
Gradient desent
这部分主要计算梯度下降。直接根据公式来即可,但有两点需要注意一下:
- theta的更新必须是同步的,看过课程的应该都知道这一点。而在程序实现上,方法就是使用临时变量。例如在本题中,每轮迭代,先将theta值存到一个临时的变量tmp中,计算的时候使用这个tmp,这样就实现了同步更新theta中的每个值。
- 这里的外层已经有一层for循环了,所以建议使用向量化运算计算求和,对这块如果不熟悉,最好在纸上画一画,多利用维度,例如知道结果是一个实数(也就是
1x1
的矩阵),那么必然是通过1xm
*mx1
得到的,这样就可以推断出具体的乘数了。
综上本题答案如下:
tmp1 = theta(1);
tmp2 = theta(2);
theta(1) = tmp1 - (alpha / m) * (([tmp1 tmp2] * X' - y') * X(:, 1));
theta(2) = tmp2 - (alpha / m) * (([tmp1 tmp2] * X' - y') * X(:, 2));
至此为止,基础的题目已经做完,下面是提高的部分。
Feature Normalization
这部分是基础的特征正规化。首先要计算每一列的平均值和方差,然后在计算每个元素与当前列均值的差值,再除以方差。我这里使用的是逐列计算的方法:
for iter = 1:size(X, 2)
mu(iter) = mean(X(:, iter));
X_norm(:, iter) = X_norm(:, iter) - mu(iter);
sigma(iter) = std(X(:, iter));
X_norm(:, iter) = X_norm(:, iter) / sigma(iter);
endfor
Compute Multi-var Cost and Gradient Desent
这里需要计算多变量的成本函数和梯度下降。如果前面都独立完成了,这里也就比较简单了。而且如果前面用了向量化的方法,这里可以直接用了。计算成本函数如下:
J = (theta' * X' - y') * (theta' * X' - y')' / 2 / m;
计算下降梯度如下:
for iter = 1:num_iters
tmp = theta;
theta = tmp - (alpha / m) * (( tmp' * X' - y') * X)';
J_history(iter) = computeCostMulti(X, y, theta);
end
Normal Equations
这里需要使用标准公式来计算最终的theta,没啥好说的,直接套公式就好了:
theta = pinv( X' * X) * X' * y