Scalaで機械学習（１）

# はじめに
基本的に機械学習は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的な感じでできるのがわかりました。上でも言いましたけど、割とコードわかりやすいのいいですね。
今度は線形回帰とか実装できたらと思います。（疲れたんで今回はこれで終わり）