X.6 Go语言中用gonum/mat进行其他常见的矩阵操作

在gonum/mat子包中还有许多有用的矩阵处理相关的函数, 我们在安装了该包之后,就可以在godoc文档服务中查看到该包的参考,其位置在包参考中的第三方包列表里。例如,前面用到的矩阵乘法函数Mul,我们可以在gonum/mat文档中查到,

正在上传…重新上传取消

图5.6 gonum/mat包的参考文档

从其中可以看出Mul函数的定义、使用说明与例子。其他函数和数据类型也可以用类似的方法找到。

Gonum包的其他几个子包中还有许多针对其他计算领域有用的数学与科学计算函数以及相关的数据类型。我们也可以用类似的方法来进行文档查阅。

本文将介绍其他几个gonum/mat包中较常用的功能函数,更多的内容可以如前介绍的那样自行查阅该包的文档。

-> 初始化一个全0的矩阵

如果要生成一个新的矩阵并且将矩阵中的数据全都置为0,可以用类似下面的代码来实现:

  matrix1 := mat.NewDense(6, 9, nil)

 fmt.Printf("%v\n",mat.Formatted(matrix1))

-> 生成随机矩阵

科学实验中经常要生成一个随机的矩阵,可以用类似下面的代码来实现:

  data := make([]float64, 25)

  for i := range data {

       data[i] = rand.NormFloat64()

  }

  a = mat.NewDense(5, 5, data)

  t.Printfln("%v", mat.Formatted(a))

* 注:t.Printfln相当于fmt.Printf并多输出一个回车换行符。

注意要引用产生随机数的math/rand包。其中,a是一个5×5的矩阵,用rand.NormFloat64函数来随机生成矩阵上的每个数据。

-> 单独设置行或列的数据

要单独设置矩阵中某一行的数据可以用类似下面的代码实现,主要是应用了mat.Dense类型的成员函数SetRow,其第一个参数为要设置的行的索引,第二个参数是切片类型的一行数据。运行后矩阵a的第2行会被替换成7、8、9三个数字。

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  a.SetRow(1, []float64{7, 8, 9})

  t.Printfln("%v", mat.Formatted(a))

代码 5‑39 单独设置矩阵一行的数据

代码5‑39运行结果为:

⎡1 2  3⎤

⎣7 8  9⎦

同样地,要单独设置矩阵中某一列的数据可以用mat.Dense类型的成员函数SetCol。其参数与SetRow函数类似,唯一的区别是第一个参数代表要设置列的索引。

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  a.SetCol(1, []float64{8, 9})

  t.Printfln("%v", mat.Formatted(a))

代码 5‑40 单独设置矩阵一列的数据

代码5‑40将矩阵a的第二列替换为8和9两个数字,运行结果为:

⎡1 8  3⎤

⎣4 9  6⎦

-> 克隆与复制矩阵

矩阵的克隆是指获得一个与源矩阵完全相同的新矩阵,可以使用mat.Dense类型的成员函数Clone来实现。

package main

import (

  t "tools"

  "gonum.org/v1/gonum/mat"

)

func main() {

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := mat.NewDense(3, 2, []float64{

       8, 8,

       8, 8})

  b.Clone(a)

  t.Printfln("%v", mat.Formatted(b))

}

代码 5‑41 克隆矩阵

代码5‑41的作用是,将矩阵a克隆到矩阵b中,其运行结果是,

⎡1 2  3⎤

⎣4 5  6⎦

可以看出,不管矩阵b的形态,克隆完的新矩阵将同源矩阵(矩阵a)的形态和数据一模一样。

而将一个矩阵中的数据复制到另一个矩阵可以用mat.Dense的成员函数Copy来实现。

package main

import (

  t "tools"

  "gonum.org/v1/gonum/mat"

)

func main() {

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := mat.NewDense(3, 2, []float64{

       8, 8,

       8, 8,

       8, 8})

  b.Copy(a)

  t.Printfln("%v", mat.Formatted(b))

}

代码 5‑42 复制矩阵数据

代码5‑42的作用是将矩阵a中的数据复制到矩阵b中,执行结果是:

⎡1 2⎤

⎢4 5⎥

⎣8 8⎦

可以看出,复制矩阵数据的方式是逐行逐列进行数据复制,当两个矩阵的行数和列数不同时,超出的部分将被丢弃,缺少的部分将不动。由于矩阵a比b多一列,所以a中第3列的数据都被丢弃了;而矩阵b比a多出来的第3行的数据则都没有动。

-> 改变矩阵形态:扩张与切片

如果要扩张矩阵,可以使用mat.Dense类型的Grow成员函数,类似下面的代码,

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := a.Grow(2, 2)

  t.Printfln("%v", mat.Formatted(b))

将得到如下所示的扩展了2行和2列的新矩阵,

⎡1 2  3  0  0⎤

⎢4 5  6  0  0⎥

⎢0 0  0  0  0⎥

⎣0 0  0  0  0⎦

反过来如果要裁剪某个矩阵则要对该矩阵做切片,此时应使用mat.Dense类型的Slice成员函数。例如要将一个2×3的矩阵右侧的2×2的子矩阵切分出来,可以用下面的代码,

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := a.Slice(0, 2, 1, 3)

  t.Printfln("%v", mat.Formatted(b))

代码 5‑43 矩阵切片

代码5‑43中,使用了Slice成员函数,它的4个参数中的第1个和第3个分别对应要截取的行数的起始索引和列数的起始索引,而第2个和第4个参数则是要截取的行数的结尾索引再加上1的值和列数的结尾索引再加上1的值。因此,我们传递的4个参数值就表示从矩阵a中的第1行第2列开始,截取到第2行第3列,注意结尾的索引都应加1,这点容易忘记。本段代码运行后切片出来的矩阵是:

⎡2 3⎤

⎣5 6⎦

-> 矩阵的合并

矩阵的横向合并使用mat.Dense类型的Augment成员函数,两个矩阵只有在行数相同时才能进行横向合并。

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := mat.NewDense(2, 2, []float64{

       8, 8,

       8, 8})

  var c mat.Dense

  c.Augment(a, b)

  t.Printfln("%v", mat.Formatted(&c))

代码 5‑44 矩阵横向合并

代码5‑44的输出结果是,

⎡1 2  3  8  8⎤

⎣4 5  6  8  8⎦

相应地,矩阵的纵向合并是使用mat.Dense类型的Stack成员函数,两个矩阵只有在列数相同时才能进行纵向合并。

  a := mat.NewDense(2, 3, []float64{

       1, 2, 3,

       4, 5, 6})

  b := mat.NewDense(3, 3, []float64{

       8, 8, 8,

       8, 8, 8,

       8, 8, 8})

  var c mat.Dense

  c.Stack(a, b)

  t.Printfln("%v", mat.Formatted(&c))

代码 5‑45 矩阵纵向合并

代码5‑45的运行结果是,

⎡1 2  3⎤

⎢4 5  6⎥

⎢8 8  8⎥

⎢8 8  8⎥

⎣8 8  8⎦

gonum包中还有很多其他有用的数据类型和函数,例如表示向量的VecDense类型;用于矩阵加法、点乘、减法等计算的函数;用于矩阵各种转换的函数等,有兴趣的话可以自行查看文档进行研究。

2人点赞

Go语言极速入门与实例演示



作者:陆满庭
链接:https://www.jianshu.com/p/c3ae215feb04
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值