はじめに
基本的に機械学習はPython、データクレンジングとかはRでやってるんですけど、Scalaとかで開発してる企業だったらJVM上で機械学習できたら便利なんかなってなって調べたらbreezeってライブラリあるみたいです、ちょっといじってみたのでその備忘録ってことで。
github -> https://github.com/scalanlp/breeze
セットアップ
scalaとsbtは入ってる前提としますね。
scala := 2.10.3
sbt := 0.1.0
一応僕はこんな感じです。
とりあえずテスト用のディレクトリを作ります。そしたら直下にbuild.sbtファイルを作成してください。コードは以下です。
$ mkdir BreezeTest
$ cd BreezeTest
$ touch build.sbt
できたらbuild.sbtに以下を記述してください。(バージョンとか同じだったらコピペで大丈夫なはずです)
name := "scalanlp-usage"
version := "0.1.0"
scalaVersion := "2.10.3"
resolvers ++= Seq(
"maven repo" at "http://zact.googlecode.com/svn/maven/repository",
"Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/",
"sonatype releases" at "http://oss.sonatype.org/content/repositories/releases"
)
libraryDependencies ++= Seq(
"org.scalanlp" % "breeze_2.10" % "0.7",
"org.scalanlp" % "breeze-natives_2.10" % "0.7"
)
scalacOptions ++= Seq("-encoding", "UTF-8")
ここまでできたら動作チェックをします。以下を実行してください。
$ sbt update
実行できて[success]と表示されてたら成功です!
とりあえず動かしてみる
consoleを開いて以下のように実行してみてください。
scala> import breeze.linalg._
import breeze.linalg._mpile / compileIncremental 0s
scala> val m = DenseMatrix((1, 3), (5, 8))
m: breeze.linalg.DenseMatrix[Int] =
1 3
5 8
scala> val v = DenseVector(1, 3)
v: breeze.linalg.DenseVector[Int] = DenseVector(1, 3)
scala> m * v
res0: breeze.linalg.DenseVector[Int] = DenseVector(10, 29)
まあなんとなくわかると思いますけど、行列演算を行なっています。
最初にパッケージをimportして、2×2行列と要素数2の縦ベクトルを生成して行列積を計算してる感じですね。
何してるのか直感的にわかりやすいのはPythonのNumpyと同じくいいですね。
使い方
では具体的にどのように使えばいいのかみてみましょう。
行列の生成
行列は以下のように生成できます。
scala> val m1 = DenseMatrix((1, 2), (3, 4))
m1: breeze.linalg.DenseMatrix[Int] =
1 2
3 4
scala> val m2 = DenseMatrix((1, 2, 3), (4, 5, 6))
m2: breeze.linalg.DenseMatrix[Int] =
1 2 3
4 5 6
breeze.linalg.DenseMatrixの引数にタプルを渡すとそれを列にした行列が生成されます。当然要素数あってなかったらエラー吐きます。
scala> val m3 = DenseMatrix((1, 2, 3), (4, 5, 6, 7))
<console>:10: error: could not find implicit value for parameter rl: breeze.linalg.support.LiteralRow[Product with Serializable,V]
val m3 = DenseMatrix((1, 2, 3), (4, 5, 6, 7))
また、単位行列やゼロ行列、転置行列、乱数行列も生成できます。
scala> val identityMatrix = DenseMatrix.eye[Double](2)
identityMatrix: breeze.linalg.DenseMatrix[Double] =
1.0 0.0
0.0 1.0
scala> val zeroMatrix = DenseMatrix.zeros[Double](2, 2)
zeroMatrix: breeze.linalg.DenseMatrix[Double] =
0.0 0.0
0.0 0.0
scala> val mT = m1.t
mT: breeze.linalg.DenseMatrix[Int] =
1 3
2 4
scala> val randomMatrix = DenseMatrix.rand(2, 2)
randomMatrix: breeze.linalg.DenseMatrix[Double] =
0.9231480299363446 0.24529928109482446
0.3786893726630529 0.7983929038314084
ベクトルの生成にはbreeze.linalg.DenseVectorが使えます。
scala> val v1 = DenseVector(1, 2, 3, 4)
v1: breeze.linalg.DenseVector[Int] = DenseVector(1, 2, 3, 4)
基本的な行列演算
breezeではNumpyのように割と柔軟に行列演算できます。
基本的なやつだけ紹介します。Test.scalaというファイルを作成してコード書いてきます。
import breeze.linalg._
import breeze.numerics._
object Test {
def main(args: Array[String]): Unit = {
// 行列を生成
val m1 = DenseMatrix((1.0, 2.0), (-3.0, 4.0))
val m2 = DenseMatrix((5.0, -6.0), (7.0, 8.0))
// 演算
println("和: " + (m1 + m2))
println("差: " + (m1 - m2))
println("スカラー倍: " + (m1 :*= 2.0))
// 内積
println("内積: " + (m1 * m2))
// 逆行列
println("逆行列: " + (inv(m1)))
// 行列式
println("行列式: " + det(m1))
println("固有値: " + eig(m1)._1)
println("固有ベクトル: " + eig(m1)._3)
}
}
では実行してみましょう。以下を叩いてください。
和: 6.0 -4.0
4.0 12.0
差: -4.0 8.0
-10.0 -4.0
スカラー倍: 2.0 4.0 pile / compileIncremental 0s
-6.0 8.0
10月 29, 2019 4:26:03 午後 com.github.fommil.jni.JniLoader liberalLoad
情報: successfully loaded /var/folders/w_/2q_ddgq51279x8rwrydld_200000gn/T/jniloader1690075005761835753netlib-native_system-osx-x86_64.jnilib
内積: 38.0 20.0
26.0 100.0
10月 29, 2019 4:26:03 午後 com.github.fommil.jni.JniLoader load
情報: already loaded netlib-native_system-osx-x86_64.jnilib
逆行列: 0.2 -0.09999999999999999
0.15000000000000002 0.05
行列式: 40.0
固有値: DenseVector(5.0, 5.0)
固有ベクトル: 0.38729833462074165 -0.5
0.7745966692414834 0.0
ちょっと余計な情報入ってますが悪しからず。ちゃんと計算できているのがわかります。
終わりに
とりあえず行列演算はNumpy的な感じでできるのがわかりました。上でも言いましたけど、割とコードわかりやすいのいいですね。
今度は線形回帰とか実装できたらと思います。(疲れたんで今回はこれで終わり)