ScalaNLP/Breezeの使い方の第2回です。
ScalaNLP/Breezeが何かとか、インストール方法などについては第1回をご覧下さい。
Breezeを用いた行列とベクトルの復習
簡単な例として、2行2列の例で説明しましょう。
オブジェクトの生成
breezeでは下記のような(密)ベクトル
\( \displaystyle x = \left( \begin{array}{c} 1 \\ 2 \end{array} \right) , \; y = \left( \begin{array}{c} 3 \\ 4 \end{array} \right) \)は
1 2 3 4 5 6 7 |
scala> import breeze.linalg._ scala> val x = DenseVector(1,2) x: breeze.linalg.DenseVector[Int] = DenseVector(1, 2) scala> val y = DenseVector(3,4) x: breeze.linalg.DenseVector[Int] = DenseVector(3, 4) |
と書く事が出来ます。
下記のような(密)行列
\( \displaystyle A = \left(\begin{array}{cc}2 & 3 \\
1 & 2
\end{array}\right), \;
B = \left( \begin{array}{cc} 3 & 4 \\ 2 & 3 \end{array}\right)\)
を定義するには、行ベクトル(横ベクトル)を縦に並べて表現します。
1 2 3 4 5 6 7 8 9 |
scala> val a = DenseMatrix((2,3),(1,2)) a: breeze.linalg.DenseMatrix[Int] = 2 3 1 2 scala> val b = DenseMatrix((3,4),(2,3)) b: breeze.linalg.DenseMatrix[Int] = 3 4 2 3 |
加減算、積など
行列の加減算は通常の +, -
といった演算子が使用出来ます。また行列の積も *
で計算出来ます。
\( \displaystyle
x+y = \left( \begin{array}{c} 4 \\ 6 \end{array}\right), \;
A+B = \left( \begin{array}{cc} 5 & 7 \\ 3 & 5 \end{array}\right), \;
AB = \left( \begin{array}{cc} 12 & 17 \\ 7 & 10 \end{array}\right), \;
Ax = \left( \begin{array}{c} 8 \\ 5 \end{array}\right)
\)
は、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
scala> x+y res2: breeze.linalg.DenseVector[Int] = DenseVector(4, 6) scala> a + b res3: breeze.linalg.DenseMatrix[Int] = 5 7 3 5 scala> a * b res4: breeze.linalg.DenseMatrix[Int] = 12 17 7 10 scala> a*x res5: breeze.linalg.DenseVector[Int] = DenseVector(8, 5) |
となります。
要素の取得、スライス
行列 \(A\) の要素を取り出したり、その部分(slice)を取り出す事も出来ます。行列 \(A\) をa
で表すならば、\(A_{ij}\) は a(i,j)
で表現されます。但し数学と違って添字が1-originではなく0-originであることに注意する必要があります。要素やスライスを取得する例は下記の様になります。(ここだけ判り易い様に3行3列の行列を使ってます)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
scala> val c = DenseMatrix((1,2,3),(4,5,6),(7,8,9)) c: breeze.linalg.DenseMatrix[Int] = 1 2 3 4 5 6 7 8 9 scala> c(0,1) res11: Int = 2 scala> c(0 to 1, 0 to 1) res12: breeze.linalg.DenseMatrix[Int] = 1 2 4 5 scala> c(0 to 2, 0 to 0) res13: breeze.linalg.DenseMatrix[Int] = 1 4 7 scala> c(0 to 0, 0 to 2) res14: breeze.linalg.DenseMatrix[Int] = 1 2 3 |
各行や各列のsliceを作るには別の記法もあります。こちらの方が判り易いかもしれません。
1 2 3 4 5 |
scala> c(::,0) res15: breeze.linalg.DenseVector[Int] = DenseVector(1, 4, 7) scala> c(0,::) res16: breeze.linalg.Transpose[breeze.linalg.DenseVector[Int]] = Transpose(DenseVector(1, 2, 3)) |
mutable object
行列やベクトルは、メモリ使用量や効率を考えmutable objectとして作成されます。従って要素を変更可能です。またsliceは元のobjectを参照しているので下記の様にz
の変更を通じてc
が変更されます。また*=
の様な自分自身を更新する演算子も多数用意されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
scala> val c = DenseMatrix((1,2,3),(4,5,6),(7,8,9)) c: breeze.linalg.DenseMatrix[Int] = 1 2 3 4 5 6 7 8 9 scala> c(0,0) = 10 scala> c res18: breeze.linalg.DenseMatrix[Int] = 10 2 3 4 5 6 7 8 9 scala> val z = c(::,1) z: breeze.linalg.DenseVector[Int] = DenseVector(2, 5, 8) scala> z(1) = 20 scala> z res20: breeze.linalg.DenseVector[Int] = DenseVector(2, 20, 8) scala> c res21: breeze.linalg.DenseMatrix[Int] = 10 2 3 4 20 6 7 8 9 scala> c *= 2 res22: breeze.linalg.DenseMatrix[Int] = 20 4 6 8 40 12 14 16 18 scala> c res25: breeze.linalg.DenseMatrix[Int] = 20 4 6 8 40 12 14 16 18 |
逆行列
逆行列などを計算するにはDouble
型の行列である必要があります。
2 & 3 \\
1 & 2
\end{array}\right), \;
B = \left(\begin{array}{cc}
3 & 4 \\
2 & 3
\end{array}\right),
\;x = \left(\begin{array}{c}
1 \\
2
\end{array}\right)
\)
を下記の様に定義します。
1 2 3 4 5 6 7 8 9 10 11 12 |
scala> val a = DenseMatrix((2.0, 3.0), (1.0, 2.0)) a: breeze.linalg.DenseMatrix[Double] = 2.0 3.0 1.0 2.0 scala> val b = DenseMatrix((3.0, 4.0), (2.0, 3.0)) b: breeze.linalg.DenseMatrix[Double] = 3.0 4.0 2.0 3.0 scala> val x = DenseVector(1.0, 2.0) x: breeze.linalg.DenseVector[Double] = DenseVector(1.0, 2.0) |
\(A\) の逆行列 \(A^{-1}\) はinv(a)
で計算出来ますが、\(A^{-1}B, \; A^{-1}x\) と逆行列を用いて計算したいだけの場合は、a \ b, a \ x
と \
という演算子を用いて逆行列を計算しない事が推奨されています。
\( \displaystyle A^{-1} = \left(\begin{array}{cc}
2 & -3 \\
-1 & 2
\end{array}\right), \;
A^{-1}x = \left(\begin{array}{c}
-4 \\
3 \end{array}\right), \;
A^{-1}B = \left(\begin{array}{cc}
0 & -1 \\
1 & 2
\end{array}\right)
\)
は下記の様になります。
1 2 3 4 5 6 7 8 9 10 11 12 |
scala> inv(a) res35: breeze.linalg.DenseMatrix[Double] = 2.0 -3.0 -1.0 2.0 scala> a \ x res31: breeze.linalg.DenseVector[Double] = DenseVector(-4.0, 3.0) scala> a \ b res32: breeze.linalg.DenseMatrix[Double] = 0.0 -1.0 1.0 2.0 |