Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

多维特征(Multiple Features)

多元线性回归,即包含多个变量,比如房子的房龄、面积、房间数等,标记如下:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
假设函数就变成了:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
可以理解为:
θ0表示基础价格
θ1为每平方价格,X1为平米数
θ2为每层价格,X2为层数

假设函数简写为:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
梯度下降就变成了:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
左图是之前单变量时的梯度下降,右图是多变量的梯度下降,二者对比如下:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

特征值预处理

当几个特征的量级相差过大时,会出现左图的情况,收敛路径复杂且缓慢;

最好将特征都缩放到接近[-1, 1],就能像右图一样收敛形成圆润的等高线,加快收敛,减少迭代次数。
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

可以使用以下两个技术。

特征缩放(Feature Scaling)

将特征值除以 Xmax - Xmin,得到新的取值范围在1以内的特征。

均值归一(mean normalization)

将xi 替换为xi - ui 来使均值接近0。

两个技术同时应用,即采用以下公式:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
ui = mean(x)
si = xmax - xmin

学习速率——α

debug梯度学习

为了确保梯度下降正常工作,可以观察 迭代次数 - 代价函数 的图像:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
当J(θ)减少量少于 10-3 时可视为收敛。

学习速率 α 的选取

如果α 太大,可能会出现左侧两图的情况,要么J持续变大,要么上下波动。

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
但若α 太小,会造成收敛速度过慢。所以可按照以下序列尝试:

α = 0.001,0.003,0.01, 0.03, 0.1, 0.3,1 …

一边画出如上J与iter的函数图,观察效果。

多项式回归

观察面积和价格的关系,假设函数不一定是线性的,也可以是多项式的:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
如果选用上面的多项式函数,那么假设函数在x继续增大时会下降,这是不合理的。

此时可选用下面蓝框中的平方根函数(或者三次函数)。

注意,此时特征缩放就很重要了。x x2 x3的量级可能相差巨大。

正态方程(Normal Equation)

不同于梯度下降法,正态方程能用代数方法直接求解最佳的θ值

即分别令各个偏导为0,求解出θ值:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
例如以下例子,可以构造出X和Y后,直接用下面红框里的公式计算出θ的值(具体为啥先不深究):
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
对比梯度下降法。

梯度下降:

  • 需要选择α
  • 需要多次迭代
  • 当n很大时效果良好,复杂度O(kn2

正态方程:

  • 无需选择α
  • 无需多次迭代
  • 当n很大时,XT X是一个n * n的矩阵,计算n * n矩阵转置复杂度为O(n3
  • 无法解决逻辑回归和分类等问题

当 n < 1000时(1000个特征以内),会优先使用正态方程。
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

正态方程中XTX不可逆的情况

  • 有多余特征,比如若x1 和 x2是线性相关的,那么XTX不可逆。
  • 过多特征,比如 m <= n,样本数小于特征数时,需要删除一些特征,或做正则化(regularization)

Matlab / Octave 常用操作

参考:https://codeantenna.com/a/mVcQGKR7LB#1_3

基础操作

计算数值

>> 5 + 6
ans = 11
>> 3 * 4
ans = 12
>> 1/3
ans = 0.3333
>> 2^6
ans = 64

计算逻辑值

>> 1 == 2
ans = 0
>> 1 ~= 2 
ans = 1
>> 1 && 0
ans = 0
>> 1 || 0
ans = 1

变量

>> a = 6
a = 6
>> a = 6;  %加上分号可以使变量不打印输出
>>

打印变量

>> a = pi;
>> a       
a = 3.1416
>> disp(a)       %仅输出a的值
    3.1416
>> disp(sprintf("2 decimals : %0.2f",a))  %打印字符串(用c语言的格式)
2 decimals : 3.14
>> 

建立矩阵和向量

>> A = [1 2;3 4;5 6]  %分号代表矩阵的换行
A =
     1     2
     3     4
     5     6
>> v = [1 2 3]     %表示行向量(1*3的矩阵)
v =
     1     2     3
>> v = [1;2;3]     %表示列向量(3*1的矩阵)
v =
     1
     2
     3
>> v = 1:0.1:2   %表示从1~2每隔0.1取数,得到的是一个行向量
v =
  1 至 8 列
    1.0000    1.1000    1.2000    1.3000    1.4000    1.5000    1.6000    1.7000
  9 至 11 列
    1.8000    1.9000    2.0000
>> v = 1:6       %当然也可以不取间隔
v =
     1     2     3     4     5     6

用特殊方法建立矩阵

>> ones(2,3)   %建立2*3的矩阵,元素全部为1
ans =
     1     1     1
     1     1     1
>> 2*ones(2,3)    %用2*矩阵,元素全部为2
ans =
     2     2     2
     2     2     2
>> zeros(2,2)    %生成零矩阵
ans =
     0     0
     0     0
>> rand(1,3)    %生成0~1的随机矩阵
ans =
    0.8147    0.9058    0.1270
>> randn(1,3)   %生成高斯分布矩阵(正态分布)均值为0,标准差为1
ans =
    0.8622    0.3188   -1.3077
>> >> w = -6 + sqrt(10)*(randn(1,10000)); % 生成均值为-6,方差为10的10000个数据的矩阵
>> hist(w)     %将这个矩阵用直方图的形式画出来
>> hist(w,50)  %用50个竖条的直方图显示

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

>> eye(4)   %生成单位矩阵
ans =
     1     0     0     0
     0     1     0     0
     0     0     1     0
     0     0     0     1
>> eye(3)
ans =
     1     0     0
     0     1     0
     0     0     1

移动数据

矩阵的大小

>> A = [1 2;3 4;5 6]
A =
     1     2
     3     4
     5     6
>> size(A)      %size()可以查看矩阵的大小
ans =
     3     2
>> s = size(A)   
s =
     3     2
>> size(s)        %size()本身返回的就是一个矩阵
ans =
     1     2
>> size(A,1)     %将返回A矩阵第一维度的大小(行数)
ans =
     3
>> size(A,2)     %将返回A矩阵第二维度的大小(列数)
ans =
     2
>> v = [1 2 3 4]
v =
     1     2     3     4
>> length(v)      %返回行向量的长度
ans =
     4
>> length(A)   %返回较大的维度长度3
ans =
     3

加载文件

>> load('ex1data1.txt')   %使用load直接可以将文件中的数据读出来
>> who           %显示当前工作区的变量

Your variables are:

A         ans       ex1data1  s         v         

>> size(ex1data1)       %刚刚读的矩阵,查看长度
ans =
    97     2
>> whos   %查看当前工作区变量的详细信息
  Name           Size            Bytes  Class     Attributes

  A              3x2                48  double              
  ans            1x1                 8  double              
  ex1data1      97x2              1552  double              
  s              1x2                16  double              
  v              1x4                32  double              
>> clear(v)   %删除变量,不加指定则删除全部变量
>> v = ex1data1(1:10)  %取前10个元素
v =
  1 至 8 列
    6.1101    5.5277    8.5186    7.0032    5.8598    8.3829    7.4764    8.5781
  9 至 10 列
    6.4862    5.0546
>> save v.mat v    %将v矩阵中的数据存到文件v.mat中去

以上是以二进制格式存储的,进行了压缩。如果想变得易读,可以用以下参数:

>> save v.txt v -ascii

操作矩阵数据

>> A
A =
     1     2
     3     4
     5     6
>> A(3,2)  %取A矩阵中第三行第二列的元素
ans =
     6
>> A(2,:)   %取A矩阵中第二行的所有元素
ans =
     3     4
>> A(:,2)   %取第二列的所有元素
ans =
     2
     4
     6
>> A([1 3],:)    %取A矩阵第一行和第三行的所有元素
ans =
     1     2
     5     6
>> A(:,2) = [10 15 20]  %取出元素之后其实可以对其进行赋值
A =
     1    10
     3    15
     5    20
>> A = [A,[100;150;200]] %在A矩阵后面追加一列
A =
     1    10   100
     3    15   150
     5    20   200
>> A(:)    %把A矩阵的所有元素放到一个列向量中
ans =
     1
     3
     5
    10
    15
    20
   100
   150
   200
>> A = [1 2;3 4;5 6];
>> B = [11 12;13 14;15 16];
>> C = [A,B]     %将两个矩阵拼接到一起
C =
     1     2    11    12
     3     4    13    14
     5     6    15    16
>> C = [A;B]      %分号表示换行,B矩阵放在A矩阵的下面
C =
     1     2
     3     4
     5     6
    11    12
    13    14
    15    16

计算数据

矩阵间运算

>> A = [1 2;3 4;5 6];
>> B = [11 12;13 14;15 16];
>> C = [1 1;2 2]
C =
     1     1
     2     2
>> A * C     %A与C进行矩阵相乘
ans =
     5     5
    11    11
    17    17 
>> A .* B      %'.*'代表矩阵中对应元素相乘
ans =
    11    24
    39    56
    75    96
>> A .^ 2     %'.'代表对矩阵中的所有元素,乘方
ans =
     1     4
     9    16
    25    36
>> v = [1 2 3] 
>> v = 1 ./ v    %取v矩阵的倒数
v =
    1.0000    0.5000    0.3333
>> log(v)     %对v取log运算
ans =
         0   -0.6931   -1.0986
>> exp(v)      %对v取e^v次方运算
ans =
    2.7183    1.6487    1.3956
>> abs([-1;-2;3])  %对矩阵取绝对值运算
ans =
     1
     2
     3
>> -v          %对矩阵取相反数
ans =
   -1.0000   -0.5000   -0.3333
>> v = [1;2;3];
>> v = v + ones(length(v),1) %将v中所有元素+1,先构造一个和v维度相同的矩阵(元素全为1),再把他们相加
v =
     2
     3
     4
>> v = v +1     %实际上用+号就可以实现
v =
     3
     4
     5
>> A'      %一个撇号是求矩阵的转置
ans =
     1     3     5
     2     4     6

函数

>> a = [-0.2 9.8 4.5 8 2.0]
a =
   -0.2000    9.8000    4.5000    8.0000    2.0000
>> val = max(a)   %求矩阵的最大值
val =
    9.8000 
>> [val index] = max(a)    %求矩阵的最大值并返回他的下标索引
val =
    9.8000
index =
     2
>> a < 3     %拿a中的所有元素和3比较返回结果
ans =
  1×5 logical 数组
   1   0   0   0   1
>> find(a<3)   %返回满足条件的元素在a中的索引
ans =
     1     5
>>A = magic(3)  %幻方矩阵,每一行每一列包括对角线元素之和相等
 A =
     8     1     6
     3     5     7
     4     9     2
>> [r,c] = find(A>=7)  %寻找A中大于等于7的元素索引,行和列
r =
     1
     3
     2
c =
     1
     2
     3
>> sum(a)    %对矩阵中的元素求和
ans =
   24.1000
>> prod(a)    %对矩阵中的元素相乘
ans =
 -141.1200
>> floor(a)    %向下取整
ans =
    -1     9     4     8     2
>> ceil(a)      %向上取整
ans =
     0    10     5     8     2
>> A
A =
     8     1     6
     3     5     7
     4     9     2
>> max(A) %默认取每一列的最大值
ans =
     8     9     7
>> max(A,[],1)   %取每一列的最大值,1代表是第一维度
ans =
     8     9     7
>> max(A,[],2)   %取每一行的最大值
ans =
     8
     7
     9
>> max(max(A))  %取A矩阵所有元素的最大值
ans =
     9
>> max(A(:))  %或者先将矩阵A转化为列向量,在取最大值
ans =
     9
>> sum(A,1)  %求A每一列的和
ans =
    15    15    15
>> sum(A,2) %求A每一行的和
ans =
    15
    15
    15
>> A .* eye(3)   %将单位矩阵与A中的元素相乘得到对角线的元素
ans =
     8     0     0
     0     5     0
     0     0     2
>> sum(sum(A .* eye(3)))  %求对角线元素的和
ans =
    15
>> pinv(A)    %求逆矩阵
ans =
    0.1472   -0.1444    0.0639
   -0.0611    0.0222    0.1056
   -0.0194    0.1889   -0.1028
>> temp = pinv(A);
>> A*temp     %发现这就是单位矩阵
ans =
    1.0000   -0.0000    0.0000
    0.0000    1.0000   -0.0000
   -0.0000    0.0000    1.0000

绘制数据

>> t = [0:0.01:0.98]; 
>> y1 = sin(2*pi*4*t);
>> plot(t,y1);   %用plot就可以画出对应的sin函数图像
>> y2 = cos(2*pi*4*t);
>> hold on;     %在同一界面上画图像
>> plot(t,y2,'r');   %画出cos的函数图像,用red
>> xlabel('time');    %设置x轴坐标
>> ylabel('value');   %设置y轴坐标
>> legend('sin','cos');  %设置标识
>> title('my plot');   %设置标题
>> print -dpng 'myplot.PNG';  %将图像保存为PNG格式

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

>> figure(1); plot(t,y1);  %对图像进行标号这样每个图象一个界面
>> figure(2); plot(t,y2);

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

>> subplot(1,2,1);    %将界面分为1*2的区域,用第一块区域
>> plot(t,y1);     %第一块区域画y1的图像
>> subplot(1,2,2);    %用第二块区域
>> plot(t,y2);      %第二块区域画y2的图像
>> axis([0.5 1 -1 1]);   %设置图像的横纵坐标范围

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

>> A = magic(5)  %5*5的幻方矩阵
A =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9
>> imagesc(A);   %矩阵也可以可视化

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

流程控制

>> v = zeros(10,1)
>> for i = 1:10,  %i = 1:10,之后把v(i)的值变为2的i次方
     v(i) = 2^i;
   end            %注意结束的时候加上end
>> v
v =
           2
           4
           8
          16
          32
          64
         128
         256
         512
        1024
>> i = 1;
>> while true,    %while循环
     v(i) = 999;  %设置v(i)的值为999
     i = i + 1;
     if i == 6,  %当i=6时跳出循环
        break;
     end
  end
>> v
v =
         999
         999
         999
         999
         999
          64
         128
         256
         512
        1024

函数

将下面代码存储为squareThisNumber.m:

function y = squareThisNumber(x) %y是返回值,x为传入的参数
    y = x^2
end

在该目录下执行下面语句,即可调用该函数:

>> squareThisNumber(5);
y =
    25

多返回值的函数:

function [a,b] = squareTwoNumber(x)
    a = x^2
    b = x^3
end
>> squareTwoNumber(5) %y是返回值,x为传入的参数

a =

    25


b =

   125


ans =

    25

定义代价函数如下:

function J = costFunctionJ(X,y,theta)
    m = size(X,1);       %数据集的个数
    predictions = X*theta;    %假设函数预测的结果矩阵
    sqrErrors = (predictions - y) .^ 2;   %与实际值得误差
    J = 1/(2*m) * sum(sqrErrors);     %计算代价函数
end

调用函数:

>> X = [1 1;1 2;1 3];
>> Y = [1;2;3];
>> X
X =
     1     1
     1     2
     1     3
>> Y
Y =
     1
     2
     3
>> theta = [0;1]
theta =
     0
     1
>> costFunctionJ(X,Y,theta)  %theta0=0,theta0=1刚好拟合,故代价函数为0
ans =
     0
>> theta = [0;0]
theta =
     0
     0
>> costFunctionJ(X,Y,theta)
ans =
    2.3333

向量化

向量化的代码会更加简单明了。

假设函数

左侧的假设函数公式,可用右侧的向量化方式计算:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
假设函数:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

matlab函数:

function pre = prediction(X,theta)
   pre = theta' * X;  % ' 代表矩阵的转置
end

梯度下降

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
梯度下降更新公式:
Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

matlab代码:

function Theta = UpdateTheta(X,Y,theta,alpha)
    m = size(X,1);
    Error = X * theta - Y;
    delta = alpha/m * (X' * Error);
    Theta = theta - delta;
end

作业

warmUpExercise.m

function A = warmUpExercise()
%WARMUPEXERCISE Example function in octave
%   A = WARMUPEXERCISE() is an example function that returns the 5x5 identity matrix
% ============= YOUR CODE HERE ==============
% Instructions: Return the 5x5 identity matrix 
%               In octave, we return values by defining which variables
%               represent the return values (at the top of the file)
%               and then set them accordingly. 

A = eye(5);
% ===========================================
end

plotData.m

function plotData(x, y)
%PLOTDATA Plots the data points x and y into a new figure 
%   PLOTDATA(x,y) plots the data points and gives the figure axes labels of
%   population and profit.

figure; % open a new figure window

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the training data into a figure using the 
%               "figure" and "plot" commands. Set the axes labels using
%               the "xlabel" and "ylabel" commands. Assume the 
%               population and revenue data have been passed in
%               as the x and y arguments of this function.
%
% Hint: You can use the 'rx' option with plot to have the markers
%       appear as red crosses. Furthermore, you can make the
%       markers larger by using plot(..., 'rx', 'MarkerSize', 10);

plot(x, y, 'rx', 'MarkerSize', 10); % Plot the data 
ylabel('Profit in $10,000s'); % Set the y−axis label 
xlabel('Population of City in 10,000s'); % Set the x−axis label

% ============================================================

end

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记

computeCost.m

function J = computeCost(X, y, theta)
%COMPUTECOST Compute cost for linear regression
%   J = COMPUTECOST(X, y, theta) computes the cost of using theta as the
%   parameter for linear regression to fit the data points in X and y

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly 
% J = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta
%               You should set J to the cost.

h = X * theta;
sqrErrors = (h - y) .^ 2;
J = 1 / (2 * m) * sum(sqrErrors);


% =========================================================================

end

gradientDescent.m

function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%GRADIENTDESCENT Performs gradient descent to learn theta
%   theta = GRADIENTDESCENT(X, y, theta, alpha, num_iters) updates theta by 
%   taking num_iters gradient steps with learning rate alpha

% Initialize some useful values
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);

for iter = 1:num_iters

    % ====================== YOUR CODE HERE ======================
    % Instructions: Perform a single gradient step on the parameter vector
    %               theta. 
    %
    % Hint: While debugging, it can be useful to print out the values
    %       of the cost function (computeCost) and gradient here.
    %
    theta = theta - alpha / m * (X' * (X * theta - y))


    % ============================================================

    % Save the cost J in every iteration    
    J_history(iter) = computeCost(X, y, theta);

end

end

梯度下降公式:

theta = theta - alpha / m * (X' * (X * theta - y))

其中 X * theta - y 是 m * 1矩阵,

X'是 (n+1) * m 矩阵,

(X' * (X * theta - y)) 就是(n+1) * 1矩阵,

alpha / m是标量,

结果得到theta仍然是(n+1) * 1矩阵。

Machine Learning - Coursera 吴恩达机器学习教程 Week2 学习笔记
最后面的 xj(i) ,当j=0时,就是x0(i) ,用到的是X的第0列。

更新每个θ,只用到对应X的一个维度的值。

所以每次更新的矩阵是 alpha / m * (X' * (X * theta - y))X'将X转置,每次相乘就用到了一列的值。

上一篇:MySQL出现1030-Got error 28 from storage engine错误


下一篇:实现鼠标双击(OnGUI)