ScalaNLPのbreezeで線形代数の演算をしてみる
Scalaで数値演算処理を行う場合、ScalaNLPのbreezeを利用することが出来ます。
このエントリでは、
線形代数で扱う行列演算の中から、
基本的なものを実際に試してみたので、以下にまとめておきます。
以下のチートシートに従っています。
Linear Algebra Cheat Sheet
https://github.com/scalanlp/breeze/wiki/Linear-Algebra-Cheat-Sheet
以下のようにbuild.sbtにライブラリを指定し、
サンプルコードを書いて、sbt runで実行すれば試すことが出来ます。
build.sbt
scalaVersion := "2.12.8"
libraryDependencies ++= Seq(
"org.scalanlp" %% "breeze" % "0.13.2",
)
mainClass in (Compile, run) := Some("LinearAlgebra")
src/main/scala/LinearAlgebra.scala
import breeze.linalg._
import breeze.numerics._
object LinearAlgebra {
def main(args: Array[String]): Unit = {
// 行列の定義
println("**** 行列の定義")
val matrix1 = DenseMatrix((1.0, 0.0, -4.0),(2.0, -3.0, -1.0))
println("行列A: \n" + matrix1)
println("Aの転置行列: \n" + matrix1.t)
val zeroMatrix = DenseMatrix.zeros[Double](2,2)
println("ゼロ行列: \n" + zeroMatrix)
val identityMatrix = DenseMatrix.eye[Double](2)
println("単位行列: \n" + identityMatrix)
// 行列の和とスカラー倍
println("\n**** 行列の和とスカラー倍")
val matrixA = DenseMatrix((1.0, 0.0, -4.0),(2.0, -3.0, -1.0))
val matrixB = DenseMatrix((-3.0, 4.0, 8.0),(1.0, 5.0, -2.0))
println("行列A: \n" + matrixA)
println("行列B: \n" + matrixB)
println("A+B: \n" + (matrixA + matrixB))
println("A-B: \n" + (matrixA - matrixB))
println("3A: \n" + (matrixA *:* 3.0))
println("A-2B: \n" + (matrixA - matrixB *:* 2.0))
// 行列の内積
println("\n**** 行列の内積")
val matrix2A = DenseMatrix((3.0, -3.0, 1.0), (0.0, -2.0, 4.0))
val matrix2B = DenseMatrix((-1.0, 0.0), (5.0, 1.0), (0.0, -3.0))
println("行列A: \n" + matrix2A)
println("行列B: \n" + matrix2B)
println("AB: " + (matrix2A * matrix2B))
// 逆行列
println("\n**** 逆行列")
val matrix3A = DenseMatrix((1.0, 2.0),(3.0, 4.0))
println("行列A: \n" + matrix3A)
println("Aの逆行列: \n" + inv(matrixA))
// 行列式、固有値と固有ベクトル
println("\n**** 行列式、固有値と固有ベクトル")
val matrix4A = DenseMatrix((1.0, -2.0),(3.0, -4.0))
println("行列A: \n" + matrix4A)
println("行列式: \n" + det(matrix4A))
println("固有値: \n" + eig(matrix4A).eigenvalues)
println("固有ベクトル: \n" + eig(matrix4A).eigenvectors)
}
}
実行結果:
$ sbt run
※途中省略※
[info] Running LinearAlgebra
**** 行列の定義
行列A:
1.0 0.0 -4.0
2.0 -3.0 -1.0
Aの転置行列:
1.0 2.0
0.0 -3.0
-4.0 -1.0
ゼロ行列:
0.0 0.0
0.0 0.0
単位行列:
1.0 0.0
0.0 1.0
**** 行列の和とスカラー倍
行列A:
1.0 0.0 -4.0
2.0 -3.0 -1.0
行列B:
-3.0 4.0 8.0
1.0 5.0 -2.0
A+B:
-2.0 4.0 4.0
3.0 2.0 -3.0
A-B:
4.0 -4.0 -12.0
1.0 -8.0 1.0
3A:
3.0 0.0 -12.0
6.0 -9.0 -3.0
A-2B:
7.0 -8.0 -20.0
0.0 -13.0 3.0
**** 行列の内積
行列A:
3.0 -3.0 1.0
0.0 -2.0 4.0
行列B:
-1.0 0.0
5.0 1.0
0.0 -3.0
AB: -18.0 -6.0
-10.0 -14.0
**** 逆行列
行列A:
1.0 2.0
3.0 4.0
Aの逆行列:
1.0 0.0 -1.0
0.6666666666666666 -0.3333333333333333 -3.5
**** 行列式、固有値と固有ベクトル
行列A:
1.0 -2.0
3.0 -4.0
行列式:
2.0
固有値:
DenseVector(-0.9999999999999996, -2.0)
固有ベクトル:
0.7071067811865476 0.5547001962252291
0.7071067811865475 0.8320502943378437
[success] Total time: 8 s, completed 2019/01/19 19:55:27
行列計算については見ればわかるので、特に説明しませんでした。
上記の例に無い演算は、やりたいことを英訳して、
チートシート内を検索すればだいたい見つけられます。
# 例えば、対角成分
# →(英訳)→ diagonal element
# →(検索)→ Create view of matrix diagonal: diag(a) とか。
また、Spark MLlibを使っている場合は、
SparkMLlibがbreezeに依存しているので、
ライブラリの設定はしなくても、spark-shellなどから利用できます。