本文是吴恩达《机器学习》视频笔记第29篇,对应第2周第11个视频。
“Octave Tutorial——Computing on data”
01
—
笔记
上一个视频学习了如何将数据装入矩阵中,本次视频讲解Octave对数据的基本运算方法。
定义3个矩阵,3×2的A和B、2×2的C
octave:1> A = [1 2; 3 4; 5 6]
A =
1 2
3 4
5 6
octave:2> B = [11 12; 13 14; 15 16]
B =
11 12
13 14
15 16
octave:3> C = [1 1; 2 2]
C =
1 1
2 2
矩阵乘法,m*n的矩阵和一个n*n的矩阵相乘。A*C
octave:4> A * C
ans =
5 5
11 11
17 17
还有一种比较有意思的运算,将一个矩阵中的所有元素与另一个和它形状相同的矩阵的每个元素对应相乘。用到的运算符号是“.*“,翻一番前面A和B的初识值,就知道这个是什么意思了。
octave:5> A .* B
ans =
11 24
39 56
75 96
需要注意的是:上面的这些计算其实都没有改变运算符两边的矩阵的值,它们仅仅是进行了一个运算得到了一个结果,仅此而已,运算完之后A还是原来那个A、B还是原来的那个B。下面的运算也类似,当然你可以把这个结果赋给一个变量,把它保存到内存中。
类似的,还可以使用“.^”运算将矩阵中的每个元素都求平方,如:
octave:7> A .^ 2
ans =
1 4
9 16
25 36
再定义一个列向量,
octave:8> v= [1; 2; 3]
v =
1
2
3
如果想要得到一个矩阵或向量中所有元素的倒数组成的新的矩阵或者向量,方法类似。
octave:5> 1 ./ v
ans =
1.00000
0.50000
0.33333
octave:6> 1 ./ A
ans =
1.00000 0.50000
0.33333 0.25000
0.20000 0.16667
同样的,像log()、exp()、abs()都可以往上招呼,都是对矩阵或向量的每个元素进行运算的。
还可以这样:
octave:9> v + ones(length(v),1)
ans =
2
3
4
转置,就是加个单引号就行了:
octave:10> A'
ans =
1 3 5
2 4 6
octave:11> A''
ans =
1 2
3 4
5 6
如果转置两次,就又转回来了。
好,再定义一个行向量,带小数点的:
octave:12> a=[1 15 2 0.5]
a =
1.00000 15.00000 2.00000 0.50000
可以使用max函数获取a的最大值、及最大值所在的位置。
octave:14> [val,in]=max(a)
val = 15
in = 2
如果把max函数作用在矩阵上,就会得到每一列上的最大值,及所在的位置。
octave:17> X = [1 3; 1 5; 2 2]
X =
1 3
1 5
2 2
octave:18> [val in]=max(X)
val =
2 5
in =
3 2
然后,看一下逻辑运算也比较好玩。
octave:19> a
a =
1.00000 15.00000 2.00000 0.50000
octave:20> a>3
ans =
0 1 0 0
如果用“a>3"这样的表达式,会把a的每一个元素和3比较,返回一个和a形状一样的行向量,对应的每个元素是逻辑表达式的结果。
还可以用这样的逻辑表达式加上find函数,巧妙地查找一些元素。
octave:23> a
a =
1.00000 15.00000 2.00000 0.50000
octave:24> find(a < 3)
ans =
1 3 4
find(a<3)这行命令,找到了a中所有小于3的元素的标号。
magic函数比较有意思,它会生成一个每行、每列、两个对角线上的元素的和都一样的一个方阵。如:
octave:25> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
magic看着挺炫,实际上好像也没啥用。
如果想求向量所有元素的和就可以用sum函数,如果想求所有元素的乘积呢?就可以用prod函数。
octave:26> a
a =
1.00000 15.00000 2.00000 0.50000
octave:27> sum(a)
ans = 18.500
octave:28> prod(a)
ans = 15
还有地板求整和天花板求整:
octave:29> floor(a)
ans =
1 15 2 0
octave:30> ceil(a)
ans =
1 15 2 1
值得注意的是,向下(地板)取整、向上(天花板)取整并不是四舍五入。
生成随机数(矩阵)的函数
octave:33> rand(3)
ans =
0.161875 0.332942 0.717015
0.518125 0.629254 0.128823
0.512882 0.966183 0.093146
一个矩阵,可以按列找出每一列的最大值组成一个行、也可以按行找出每行的最大值组成一个列。
octave:37> max(A,[],1)
ans =
8 9 7
octave:38> max(A,[],2)
ans =
8
7
9
如果要想找整个矩阵的最大值怎么办呢?可以这样:
octave:39> max(max(A))
ans = 9
octave:40> max(A(:))
ans = 9
上面两种方法都可行。
我们再来定义一个9*9的magic矩阵。
octave:41> A = magic(9)
A =
47 58 69 80 1 12 23 34 45
57 68 79 9 11 22 33 44 46
67 78 8 10 21 32 43 54 56
77 7 18 20 31 42 53 55 66
6 17 19 30 41 52 63 65 76
16 27 29 40 51 62 64 75 5
26 28 39 50 61 72 74 4 15
36 38 49 60 71 73 3 14 25
37 48 59 70 81 2 13 24 35
那我们怎样验证magic的行、列、正负对角线的和都相同呢?
按列求和、按行求和比较简单,分别用sum(A,1)、sum(A,2)
octave:42> sum(A,1)
ans =
369 369 369 369 369 369 369 369 369
octave:43> sum(A,2)
ans =
369
369
369
369
369
369
369
369
369
那对角线求和该怎么办呢?
需要想办法把矩阵的两个对角线给提出来,需要先构造一个单位阵,然后想法把它点乘到A上,就可以把A的对角线拿出来。然后单位阵转个90°,就可以把斜对角线也拿出来了,如:
我把过程拆细一点:
octave:44> eye(9)
ans =
Diagonal Matrix
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1
octave:45> A .* eye(9)
ans =
47 0 0 0 0 0 0 0 0
0 68 0 0 0 0 0 0 0
0 0 8 0 0 0 0 0 0
0 0 0 20 0 0 0 0 0
0 0 0 0 41 0 0 0 0
0 0 0 0 0 62 0 0 0
0 0 0 0 0 0 74 0 0
0 0 0 0 0 0 0 14 0
0 0 0 0 0 0 0 0 35
octave:46> sum(A .* eye(9))
ans =
47 68 8 20 41 62 74 14 35
octave:47> sum(sum(A .* eye(9)))
ans = 369
类似的,把eye矩阵纵向翻转之后再来计算A的斜对角线的和。
octave:48> flipud(eye(9))
ans =
Permutation Matrix
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
octave:49> sum(sum(A .* flipud(eye(9))))
ans = 369
octave:50>
这个比较简单,用函数pinv即可,
octave:50> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
octave:51> temp = pinv(A)
temp =
0.147222 -0.144444 0.063889
-0.061111 0.022222 0.105556
-0.019444 0.188889 -0.102778
octave:52> A * temp
ans =
1.00000 -0.00000 0.00000
0.00000 1.00000 -0.00000
-0.00000 0.00000 1.00000
关于数据运算就到这里,下一个视频讲解数据可视化。