博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Octave来学习Machine Learning(二)
阅读量:7219 次
发布时间:2019-06-29

本文共 5096 字,大约阅读时间需要 16 分钟。

小之的公众号 : WeaponZhi

前言

上一篇我们介绍了 Octave 的一些基本情况,大家对 Octave 应该已经有了一个基本的了解,我相信看这篇文章的朋友已经在自己的电脑中安装好 Ocatve 了。矩阵的操作是 Octave 的一大特色。这一节,我将讲述 Octave 对于矩阵的一些操作,希望大家在看文章的过程中可以跟着一起敲一下代码,加深一下印象。

矩阵的生成

Octave 中,我们用一个中括号来表示一个矩阵,用分号来分隔每一行,即使在输入的时候不在同一行就像下面这样:

>> A = [1 2; 3 4; 5 6]A =   1  2  3  4  5  6>> A = [1 2;> 3 4;> 5 6]A =   1  2  3  4  5  6>> A = [1,2; 3,4; 5,6]A =   1  2  3  4  5  6复制代码

注意到,你可以通过逗号来区分每行中的每一个元素,但我们一般不这样用,这样看起来不太清晰。那么如果要表示向量该怎么做呢?我们知道,行向量和列向量分别是一行三列和三行一列的矩阵,那举一反三的你一定知道该怎么定义了吧?

>> A = [1 2 3]A =    1  2  3>> A = [1; 2; 3]A =    1   2   3复制代码

可以通过冒号来实现具有递进规则的行向量,两个冒号之间的数代表递进的 step 大小,很容易理解,和 Python 的操作有点像。

>> A = 1:0.1:1.5A =   1.0000 1.1000 1.2000 1.3000 1.4000 1.5000>> A = 1:5A =   1 2 3 4 5复制代码

通过一些函数可以快速生成一些特殊矩阵

>> ones(2,3)ans =    1 1 1   1 1 1>> 2*ones(2,3)ans =    2 2 2   2 2 2>> zeros(2,3)ans =    0 0 0   0 0 0>> eye(3)ans = Diagonal Matrix   1 0 0   0 1 0   0 0 1>> rand(2,3)ans =    0.480397 0.505024 0.056767   0.336853 0.774152 0.535887>> magic(3)ans =    8 1 6   3 5 7   4 9 2复制代码

ones() 生成全是 1 的矩阵,你可以使用数字和 ones() 生成的矩阵相乘,它和 zeros() 还有 rand() 一样,第一个参数代表行数,第二个参数代表列数。zeros() 生成元素全是 0 的矩阵,而 rand() 可以生成元素是 0-1 之间随机数的矩阵。eye()可以生成单位矩阵,熟悉线性代数的朋友可能会对单位矩阵比较熟悉,它很有用,但线性代数的知识不是本文的重点。形式上可以理解为正斜对角线都是 1 的矩阵。

magic(n) 生成一个 n 阶矩阵,这个矩阵的特点就是不论横线,竖线还是对角线,加起来的值都是一样的,数字还不能重复,必须是从 1 到 n 的平方,很有趣吧。

矩阵的操作

讲述矩阵的操作之前,让我们先来定义一个 3x2 的矩阵 A,方便我们理解代码

>> A = [1 2; 3 4; 5 6]A =   1 2  3 4  5 6复制代码

我们可以通过 size 和 length 函数来获取矩阵维度的相关信息

>> size(A)ans =     3 2>> size(A,1)ans = 3>> size(A,2)ans = 2>> length(A)ans = 3复制代码

size(A) 返回一个行向量,这个行向量代表了 A 的维度,这里输出的 3 2 代表 A 是一个 3 行 2 列的矩阵。size()还可以添加第二个参数,size(A,1) 输出 A 的第一个维度的数量,也就是行数,2 代表的是列数。length(A) 返回的是 A 矩阵中最大维度的大小,所以这里返回的是 A 的行数 3,一般我们都是对向量使用 length() 来直接返回向量的长度。

我们来看看对于矩阵的各种读取操作吧。

>> A(3,2)ans = 6>> A(:)ans =    1    2    3    4    5    6>> A(1:6)ans =    1 3 5 2 4 6复制代码

A(3,2) 代表取 A 矩阵第三行第二列的元素,这个比较好理解。A(:) 会将矩阵转化为一个列向量,A(1:6) 将按列顺序输出 A 矩阵第 1 到 第 6 个元素。这些都还是比较简单的,后两个往往在求和的时候用的比较多,我们后面会说到。

我们来看一波天秀操作

>> A(:,2)ans =      2     4     6>> A(2,:)ans =      3 4>> A([2,3],:)ans =      3 4     5 6>> A(:,2) = [1; 3; 5]A =     1 1    3 3    5 5>> A = [A,[1; 2; 3]]A =     1 1 1     3 3 2    5 5 3 >> B = 5*ones(3)B =     5 5 5    5 5 5     5 5 5>> [A B] % [A,B] % 号是注释ans =      1 1 1 5 5 5      3 3 2 5 5 5     5 5 3 5 5 5>> [A; B]ans =      1 1 1     3 3 2     5 5 3     5 5 5      5 5 5复制代码

来,我们一点点看。A(:,2) 输出 A 的第二列,A(2,:) 输出 A 的第二行,A([2,3],:) 输出第二行和第三行,你可以把冒号换成数字这样就可以输出这几行的第几个元素了。A(:,2) = [1; 3; 5] 将 A 的第二列替换成 [1; 3; 5] 这个列向量。[A B] 和 [A, B] 的含义一样,将 B 并到 A 的右边。[A; B] 则是把 B 并到 A 的下面。

矩阵的运算

这节将讲一些矩阵运算的操作,涉及到一些线代的知识,如果有疑惑,可以自己去重温下,你大概只要知道矩阵相乘和逆矩阵是怎么一回事就行了。先来看一段代码

>> A = [1 2; 3 4; 5 6];>> B = [1 1 1;2 2 2;];>> C = [11 12; 13 14; 15 16];>> A * Bans =      5  5  5      11 11 11      17 17 17>> A .* Cans =       11 24      39 56      75 96复制代码

我们先定义了三个矩阵,还记得吗,末尾加分号将不会打印出来。A * B 代表矩阵 A 和 B 的乘积,这是数学上的乘积方式,所以一个三行两列的矩阵乘以两行三列的矩阵,将得到一个三行三列的矩阵,这里就不具体说乘积运算的规则了。A .* C 会将 A 和 C 的同位置元素相乘,这就代表了 A 和 C 的维度必须要一样。

我们来看下矩阵和数字的操作

>> A + 1ans =     2   3     4   5     5   6>> A * 2ans =      2   4     6   8     10 12>> A .^ 2ans =       1  4      9 16     25 36>> A / 2ans =      0.50000 1.00000     1.50000 2.00000     2.50000 3.00000>> 1 ./ Aans =      1.00000 0.50000     0.33333 0.25000     0.20000 0.16667复制代码

A+1 将每个元素作加法,A * 2 把 A 中每个元素都乘以 2,当然 2 * A 也可以,结果一致,我们在上面曾经使用 5 * ones(3) 来快速生成三阶全是 5 的矩阵。A .^ 2 代表对 A 每个元素进行次方操作。A / 和 ./ 含义是一样的,但 1 / A 将会报错

>> 1 / Aerror:operator /:nonconformat arguments>> 1 / [2]ans = 0.50000>> 1 / 2ans = 0.50000复制代码

除数必须得是 1x1 的矩阵或者是个数,总而言之它这是真正的算数除法运算了。

当然还有一些对元素做操作的运算,比如 log(A) 是每个元素求对数,exp(A) 是对每个元素求 e 的指数,abs(A) 是求绝对值,当然还有很多,就不一一列举了。大家可以通过 help 指令直接进行文档查阅。

下面看看转置矩阵和逆矩阵如何表示

>> A'ans =      1 3 5    2 4 6>> (A')'ans =    1 2    3 4    5 6>> flipud(A)ans =     5 6    3 4    1 2>> B = pinv(A)B =    -1.33333 -0.33333  0.66667     1.08333  0.33333 -0.41667>> A * B   % B * Aans =     1.00000 0.00000   -0.00000 1.00000复制代码

用单引号 ' 来表示矩阵的转置矩阵。flipud(A) 将矩阵翻转,这个函数一般用在翻转范围矩阵 flipud(eye(n)) ,这样就可以获得一个反对角线单位矩阵了。

pinv(A) 表示 A 的逆矩阵,逆矩阵和原矩阵相乘是单位矩阵,值得注意的是,不是每一个矩阵都有逆矩阵,但 pinv() 始终都能得到结果,实际上 pinv() 获取的是一个伪逆矩阵,但这不重要,你可以把 pinv() 当作对矩阵的求逆,这里就不具体深究了。

到目前为止,矩阵的运算还是比较简单的,相比起来,下面的运算就有点蒂花之秀了。

>> max(A)ans =      5 6>> max(A,[],1)ans =       5 6    >> max(A,[],2)ans =      2      4      6>> [val, ind] = max(A)val =       5 6ind =       3 3>> max(A,[3 3; 3 3; 3 3])ans =     3 3     3 4     5 6>> A > 3ans =      0 0      0 1      1 1>> find([1 2 3] > 1)ans =       2 3>> [r,c] = find(A > 3)r =     3    2     3c =     1    2    2复制代码

max(A) 将求每列的最大值,并以行向量形式输出,默认形式等同于 max(A,[],1),如果求每列最大值,则把第三个参数改为2。用 [val, ind] 接收的话,val 的值为最大值,ind 为这个值在该列的索引位置。max(A,B) 将取每个位置中 A 与 B 较大的元素。min 和 max 操作是一样的。

A > 3 输出一个同维度的矩阵,符合条件的为 1 ,不符合条件的为 0。find() 函数中如果是一个向量,则返回符合条件的索引位置,如果是一个矩阵,则用 [r,c] 返回元素的索引,r 代表行号,c 代表列号,比如例子中第一个匹配值 A(3,1) 是 5 ,的确大于 3。

最后看下求和

>> sum(A,1)ans =      9 12>> sum(A,2)ans =       3      7     11>> sum(sum(A))ans = 21复制代码

sum 和 max 一样,默认情况下是列运算,行向量输出,但参数设置为 2 的时候,则是行求和,列向量输出。所以就像例子中一样,如果我们要求一个矩阵所有元素的和,只需要做两次 sum(sum(A)) 即可。

总结

Octave 矩阵方面的介绍就这么多了,写的很多,权当一个笔记吧,实际上还有很多操作,大家可以使用 help 指令或者观看官方文档来进行学习。


欢迎关注我的公众号

转载地址:http://ivxym.baihongyu.com/

你可能感兴趣的文章
java主函数的含义
查看>>
中国大学MOOC —— 学习笔记(四)
查看>>
访问,ringbtn,
查看>>
致橡树
查看>>
一段测试代码,哦哦哦,
查看>>
uiimagepickercontroller,中文,--》摘
查看>>
第四次作业
查看>>
在python中调用js或者nodejs
查看>>
【年终总结】2年计划还是要有的,万一实现了呢?(转自叶小钗)
查看>>
数字图像处理学习笔记(1.1)---位图的读写、几何变换、傅里叶变换、直方图均衡...
查看>>
javascript数组顺序-----1冒泡的另一种比较好理解的写法
查看>>
数据结构-栈的实现之行编译器核心实现
查看>>
C++ Project 积累(2)
查看>>
(1)用VisualSvn Server,Tortoise Svn,AnkhSvn搭建Svn版本控制
查看>>
Mysql索引
查看>>
格式化输出
查看>>
hdu 3804 Query on a tree (树链剖分+线段树)
查看>>
定位、指南针、地理编码
查看>>
Kafka 简介
查看>>
MySQL 用户连接与用户线程
查看>>