1. 程式人生 > >Scala 的矩陣運算

Scala 的矩陣運算

本文講解 Scala 中進行矩陣運算的包 breeze 的一些基礎操作。

Breeze 是 Scala 中用於線性代數相關數值運算的開源庫。

安裝

首先我們使用 SBT 匯入:

libraryDependencies  ++= Seq(
  // Last stable release
  "org.scalanlp" %% "breeze" % "0.13.2",

  // Native libraries are not included by default. add this if you want them (as of 0.7)
  // Native libraries greatly improve performance, but increase jar sizes.
  // It also packages various blas implementations, which have licenses that may or
may not // be compatible with the Apache License. No GPL code, as best I know. "org.scalanlp" %% "breeze-natives" % "0.13.2", // The visualization library is distributed separately as well. // It depends on LGPL code "org.scalanlp" %% "breeze-viz" % "0.13.2" )

這裡其官方 Github 的文件還有這樣一句:

resolvers += "Sonatype Releases"
at "https://oss.sonatype.org/content/repositories/releases/"

但是我加上以後就會報錯,去掉以後就 build 好了,很奇怪。

快速開始

首先引入下面內容:

import breeze.linalg._

新建一個向量:

// Dense vector will allocate memory for zeros, where sparse won't.
val x = DenseVector.zeros[Double](5)
val y = SparseVector.zeros[Double](5)

println(x) // DenseVector(0.0, 0.0, 0.0, 0.0, 0.0)
println(y) // SparseVector(5)()

與 Scala 不同,breeze 建立的所有向量都是列向量

可以通過下標獲取或者更改向量中的元素,而且支援負數下標。

// Access and update data elements by their index
// and negative indices are supported, x(i) == x(x.length + i)
println(x(0)) // 0.0
x(4) = 4
println(x(-1)) // 4.0

Breeze 也支援切片,並且範圍切片比任意切片快得多。切片賦值時使用的時 :=,可以給切片賦一個相同的值,也可以給其賦一個相同長度的向量。

x(3 to 4) := .5
x(0 to 1) := DenseVector(.1, .2)
println(x) // DenseVector(0.1, 0.2, 0.0, 0.5, 0.5)

接下來我們再新建一個全為 0 的 5x5 矩陣:

val m = DenseMatrix.zeros[Int](5, 5)
println(m)

結果:

0  0  0  0  0  
0  0  0  0  0  
0  0  0  0  0  
0  0  0  0  0  
0  0  0  0  0

然後我們可以訪問其行或者列,列就是 DenseVectors 的型別,行是 DenseVectors 的轉置。

// The columns of m can be accessed as DenseVectors, and the rows as DenseMatrices.
val size = (m.rows, m.cols)
println(size) // (5,5)

val column = m(::, 1)
println(column) // DenseVector(0, 0, 0, 0, 0)

// Transpose to match row shape
m(4, ::) := DenseVector(1, 2, 3, 4, 5).t
println(m)

結果:

0  0  0  0  0  
0  0  0  0  0  
0  0  0  0  0  
0  0  0  0  0  
1  2  3  4  5

同樣可以切割出一個子矩陣:

m(0 to 1, 0 to 1) := DenseMatrix((3, 1), (-1, -2))
println(m)

結果:

3   1   0  0  0  
-1  -2  0  0  0  
0   0   0  0  0  
0   0   0  0  0  
1   2   3  4  5