本文为机器学习的学习总结,讲解机器学习编程入门。
我们常将 Octave 称为 Matlab 的开源版本,因为 Octave 和 Matlab 语法基本相同,功能很类似。
运行环境
- Windows 10
- MATLAB R2019b
基本操作
变量
用 disp()
和 sprintf()
语句结合打印小数变量:
>> a = pi; % 赋值为pi
>> a
a = 3.1416
>> disp(sprintf('2 decimals: %0.2f', a)) %格式化输出a
2 decimals: 3.14
>> format long %格式化为小数点后很多位数字
>> a
a = 3.141592653589793
>> format short %格式化为小数点后较少位数字
>> a
a = 3.1416
矩阵
>> w = randn(1,3) % 高斯分布的1×3行向量,均值=0,标准差=1
w = 0.5377 1.8339 -2.2588
>> w = -6 + sqrt(10)*(randn(1,10000)); %设置一个复杂一点的函数
>> hist(w) %绘制直方图
>> hist(w,50) %更多竖线的直方图
得到的高斯直方图为:
更多竖线:
>> eye(3) %生成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返回的是一个1×2的矩阵
ans = 3 2
>> sz
sz = 3 2
>> size(sz)
ans = 1 2
>> size(A,1) % sz向量的第一个数字,表示A的行数
ans = 3
>> v = [1, 2, 3, 4]
v = 1 2 3 4
>> length(v) % 返回矩阵的最大维度,向量则直接返回大小
ans = 4
>> length(A) % 返回矩阵的最大维度,一般只对向量使用
ans = 3
读入数据
桌面上有数据文件 featuresX.dat 和 pricesY.dat 分别存放房屋训练集的特征和房屋价格。
>> cd 'C:\Users\22808\Desktop' % 使用cd切换当前工作目录
>> pwd % 显示当前工作目录
ans = 'C:\Users\22808\Desktop'
>> load featuresX.dat %load读取文件中的数据,数据以矩阵形式存入,变量名为文件名
>> load pricesY.dat
>> load('featuresX.dat')
>> who % 显示当前所有的变量
您的变量为:
A ans pricesY v
a featuresX sz w
>> whos % 显示每个变量的详情,这里featuresX文件中数据为空
Name Size Bytes Class Attributes
A 3x2 48 double
a 1x1 8 double
ans 1x22 44 char
featuresX 0x0 0 double
pricesY 10x1 80 double
sz 1x2 16 double
v 1x4 32 double
w 1x10000 80000 double
>> clear featuresX % 使用clear 变量名 来删除变量
>> who % featuresX已经被删除
您的变量为:
A a ans pricesY sz v w
>> v = pricesY(1:10)
v = 3999
3299
3690
2320
5399
2999
3149
1989
2120
2425
>> save hello.mat v; % 将变量v保存在hello.mat文件中,存储为二进制格式,数据越大压缩程度越大
此时桌面上出现 hello.mat 文件:
![hello-txt](img/hello-txt.png)>> clear % 清除所有数据
>> load hello.mat % 从文件中加载变量v
>> v
v = 3999
3299
3690
2320
5399
2999
3149
1989
2120
2425
>> save hello.txt v -ascii %把文件存成人类能看懂的ascii形式
hello.txt 文件内容为:
矩阵索引
>> A = [1 2; 3 4; 5 6]
A = 1 2
3 4
5 6
>> A(3,2) % 矩阵第 3 行第 2 列的元素
ans = 6
>> A(2,:) %:表示该行或该列的所有元素
ans = 3 4
>> A([1,3],:) % 获取第1,3行的所有元素
ans =
1 2
5 6
>> A(:,2) = [10;11;12] % 用向量代替了矩阵的第二列
A = 1 10
3 11
5 12
>> A = [A, [100; 101; 102]]; % 在A右边新加一列
A = 1 10 100
3 11 101
5 12 102
>> A(:) % 将A放入一个列向量中
ans =
1
3
5
10
11
12
100
101
102
>> A = [1 2; 3 4; 5 6];
>> B = [11 12; 13 14; 15 16]
>> C = [A B] % 将AB在水平方向连在一起
C = 1 2 11 12
3 4 13 14
5 6 15 16
>> C = [A; B] % 将AB在垂直方向连在一起,可将;理解为换行
C = 1 2
3 4
5 6
11 12
13 14
15 16
计算数据
>> v = [1; 2; 3];
>> v + ones(length(v), 1) % 给v的每个元素都+1
ans =
2
3
4
>> v + 1 % % 给v的每个元素都+1
ans =
2
3
4
>> a = [1 15 2 0.5];
>> val = max(a) %max返回a中的最大值
val = 15
>> [val, ind] = max(a) %返回两个值。val为最大值,ind为最大值的索引
val = 15
ind = 2
>> max(A) % max对矩阵返回每列最大值
ans = 5 6
>> A = magic(3) % 生成幻方矩阵,每行每列及对角线的元素和相等
A = 8 1 6
3 5 7
4 9 2
>> [r,c] = find(A >= 7) % r,c分别表示元素所在行列
r = 1
3
2
c = 1
2
3
>> prod(a) % prod对a的所有元素乘积
ans = 15
>> max(A,[],1) % 每一行的最大值,1表示第一维
ans = 8 9 7
>> max(A,[],2) % 每一列的最大值,2表示第二维
ans =
8
7
9
>> max(max(A)) % 求A中的最大值
ans = 9
>> max(A(:)) % 求A中的最大值
ans = 9
>> sum(sum(A .*eye(3))) % 求对角线元素和:先用单位矩阵取出对角线元素后对矩阵求和
ans = 15
>> sum(sum(A .* flipud(eye(3)))) % 求逆对角线元素和,flipud为取逆
ans = 15
>> temp = pinv(A) % 求矩阵A的伪逆
temp =
0.1472 -0.1444 0.0639
-0.0611 0.0222 0.1056
-0.0194 0.1889 -0.1028
>> temp * A % 验证结果
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)
得到图像:
输入以下代码绘制余弦函数,会直接覆盖正弦函数图像。
>> y2 = cos(2*pi*4*t);
>> plot(t,y2);
使用以下代码可以同时保留两个图像而不被覆盖:
>> plot(t,y1);
>> hold on; % 保留第一张图
>> plot(t,y2,'r');
>> xlabel('time') % 设置横坐标标签
>> ylabel('value')
>> legend('sin', 'cos') % 设置图例
>> title('my plot') % 设置图片标题
>> cd 'C:\Users\22808\Desktop'; print -dpng 'myPlot.png' % 切换路径并将图片以png形式把保存
>> close % 使用close关闭图像
得到结果:
还可以对图像进行编号:
>> figure(1); plot(t,y1);
>> figure(2); plot(t,y2);
可以对显示框进行分割从而显示多个子图:
>> subplot(1,2,1); % 将显示框分割为1×2(前2个参数)的格子,在第1个格子画图
>> plot(t,y1);
>> subplot(1,2,2); % 在第2个格子画图
>> plot(t,y2);
>> axis([0.5 1 -1 1]) % 设置横纵坐标范围
>> clf; % 清除图像
得到结果:
还可以对矩阵进行可视化:
>> A = magic(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) % 彩色方块代表不同的值
>> imagesc(A), colorbar, colormap gray; % 逗号连续函数,一个接一个执行并打印结果
得到的彩色图:
得到的灰色图及 color bar:
可视化 15 维的矩阵:
>> imagesc(magic(15)), colorbar, colormap gray;
图像为:
控制语句:for, while, if 语句
首先介绍 for 语句:
v = zeros(10,1)
for i=1:10
v(i)=2^i;
end;
v = 2
4
8
16
32
64
128
256
512
1024
也可以使用 indices:
indices = 1:10
indices =
1 2 3 4 5 6 7 8 9 10
for i=indices
disp(i);
end;
1
2
3
4
5
6
7
8
9
10
接下来是 while 循环和 if 语句,可见 v 已被更新:
i = 1;
while i<=5
v(i)=100;
i=i+1;
end;
v
v = 100
100
100
100
100
64
128
256
512
1024
i=1;
while true
v(i)=999;
i=i+1;
if 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; # 函数主体
切换到文件路径下,调用函数:
>> pwd
ans = 'C:\Users\xxx\Desktop'
>> squareThisNumber(5)
ans = 25
还可以使用 addpath 添加路径,将该目录添加到搜索路径。这样以后,我们在别的目录下也可以搜索此目录下的函数了:
>> cd 'C:\'
>> addpath('C:\Users\22808\Desktop\')
>> squareThisNumber(5)
ans = 25
一个函数还可以返回多个值,例如在 SquareAndCubeThisNumber.m 文件中定义函数:
function [y1,y2] = squareAndCubeThisNumber(x)
y1 = x^2;
y2 = x^3;
得到结果:
>> [a,b] = squareAndCubeThisNumber(5);
>> a
a = 25
>> b
b = 125
最后再展示一个计算代价函数的例子。首先我们有一个样本集:
定义计算代价的函数:
function J = costFunctionJ(X,y,theta)
% X 是 "design matrix" 包含了训练样本
% y 是类标签
m = size(X,1); %训练样本个数
predictions = X*theta; %计算预测值
sqrErrors = (predictions-y).^2;% 计算平方误差
J = 1/(2*m) * sum(sqrErrors); % 计算代价函数
传入参数:
>> X = [1 1; 1 2; 1 3];
>> X
X = 1 1
1 2
1 3
>> y = [1; 2; 3];
>> y
y = 1
2
3
>> theta = [0;1]; %theta为[0;1]可以很好的拟合出我们的数据
>> j = costFunctionJ(X,y,theta);
>> j
j = 0
>> theta = [0;0];
>> j = costFunctionJ(X,y,theta); %不能很好的拟合
>> j
j = 2.3333
矢量
Octave、Matlab 和 C++ 等都有内置或易获取的线性代数库,通常经过高度优化,可以充分利用计算机的硬件性能,并且还能简化我们的代码。
例如我们对下面的式子进行计算:
对于非向量化的实现:
prediction = 0.0;
for j = 1:n+1,
prediction = prediction + theta(j) * x(j)
end;
对于向量化的实现:
prediction = theta' * x;
再例如 C++ 的例子:
// 非向量化的实现
double prediction = 0.0;
for (int j = 0; j <= n; j++)
prediction += theta[j] * x[j];
// 向量化实现
double prediction = theta.transpose() * x;
我们再来看梯度下降算法的例子。其中更新公式为:
当
共 3 项时有:
这些应该是同步更新的。向量化的实现为:
其中
,是一个
维的向量,因为其中的
是一个向量。