読者です 読者をやめる 読者になる 読者になる

Screaming Loud

研究・プログラミングなど気づいたことをメモをしています

早速githubのPRテンプレート機能を使ってみた。

GithubのPRテンプレート機能が出たということで、試しに使ってみた。

何が追加されたか?

GithubのIssueとPRのテンプレートができた。

PRはデフォルトでこんな感じで表示される
f:id:yuutookun:20160218094334p:plain

まあ普通のテンプレートですね。

どうやって使うのか?

プロジェクトのルートディレクトリか.githubフォルダに以下を格納することでできます。

.github
  └ PULL_REQUEST_TEMPLATE.md # PRのテンプレート
 └ ISSUE_TEMPLATE.md # Issueのテンプレート
 └ CONTRIBUTING.md # PR時の注意書き

簡単ですね。

これを利用して、さらにGithubライフを充実させていきましょう。


参考リポジトリはこちら
GitHub - moc-yuto/regression: calculate regression by breeze

Hadoop Spark Conference Japan 2016 に参加したときのメモ

Hadoop Spark Conference Japan 2016に参加したので、その聞いた内容をまとめました。

Spark MLlib Now and Beyond

Spark自体はコントリビュータが多いプロダクト

sparkでは、2つのの機械学習ライブラリがある。

  • spark.mllib: RDDというデータフレームを利用
  • spark.ml: DataFrame, PipelineAPIを利用

spark.mlの利用を推奨
scikit-learnに影響

【データ構造】
  • RDD
  • DataFrameAPI

RDD
numpy.arrayのような配列の形式

【DataFrameAPI】
DataFrameAPI:RDBのように直感的にデータにアクセスできるAPI
pandasに影響を受けて作られている

サポートしているデータソースも豊富
jdbc, mysql, posqresql, hive

ビルトイン関数も豊富
Catalystによる処理最適化によって、生RDDよりDataFrameのほうが速い

【PipelineAPI】

処理をつなげられ、再利用もしやすい

tokenizer:単語のトークン化
hashingTF:単語のベクトル化
logisticRegression:ロジスティック回帰

上の3つの操作をpipelineでまとめることができる

pipelineを再利用することで簡単に使い回すことができる
例えば、入力をtrainDataとtestDataにしたり。

pipelineを使うと
クロスバリデーションも簡単にできる

そしてその作ったpipelineをs3やhdfsに永続化することもできる

pythonで分析して、scalaで読み込む
なんてこともできる

【Mllib2.0】
・GLMの改善
・永続化未対応ライブラリがまだある。それの改善。

SparkによるGISデータを題材として時系列データ

GISデータとは、船の航行データ(緯度、輝度、速度とか)
GISデータ、センサーデータ:多変量時系列データ
データの収集・蓄積はできているが、分析がまだまだ。

【要件】
性能、柔軟性、スケーラビリティが必要

【sparkを用いた時系列データ処理】

時間依存の情報
・時刻
・緯度、経度
時間非依存の情報
・移動体ID

やりたいこと
・移動体ごとにデータをソート
・時刻や座標の差分を計算
・numpyの関数をそのまま使えること

時系列データの評価ポイント

  1. レコード長の違い:長いほうが遅い(普通)
  2. レコードに偏りをもたせるか:ほぼ変わらない
  3. RDDかDataFrameか:DataFrameのほうが速い

RDD [“ships”, “0.0.0"]
DataFrame は表形式
ただ、DataFrameはメモリを使うので、そこら辺のチューニングが必要

flinkとかも出てきている。
pythonでできるところは、pythonで。

行、列指向の片方だけで閉じない

なんでpythonから移行したのか?→データ量が増えてきて、今後に対応できないと感じたから
sparkは1台で実行したのか?→並列で実行させている

sparkUIから確認することで、チューニングを行った。

時系列データにSparkを使うのは現実としてあり。

まだまだ、公式には足りない機能が多いので、spark packagesなどのパッケージ関連を検索してみるのも大事。

Hive on Sparkを活用した高速データ分析

CDHをいれていると、3clickでHive on Sparkが導入可能に。

www.slideshare.net

最短でsbtのコマンドを追加する方法

sbtと打つとREPLが起動し、runしたりtestが走らせられたり色んな挙動をさせられる。

しかし、自分でコマンドを作ろうと調べてみると、案外出てこない。

ということで最短でコマンド作成を紹介します。

最短でHelloという文字を出力させる

Helloという文字列を出力させます。

build.sbtに以下を記載します。

これで以下出力が出せます。

$sbt
>hello
Hello
[success] Total time: 0 s

別ファイルに定義したメソッドを呼ぶ

こちらの方がニーズがあるでしょう。

project/Hello.scalaを作ります。

先ほどと同じようにbuild.sbtに以下を記載します。

このように出力できます。

$sbt
>hello
Hello
[success] Total time: 0 s

sbt REPL上で引数を受け取るタスク

こうやると、引数を受け取れます。

$ sbt
> hello
List()
[success] Total time: 0 s, completed 2016/02/05 19:47:46
> hello a
List(a)
[success] Total time: 0 s, completed 2016/02/05 19:47:49
>

scalaNLPに含まれているライブラリを調べてみる

Scalaにもnumpy, scipyのような数値計算ライブラリがあります。

ScalaNLPというレポジトリで登録されています。
github.com

では、どんなものがあるか調べてみます。

breeze

Breezeは、数値計算ライブラリです。
numpyのようなもので、行列計算などを操作するためのライブラリがメインです。

他のライブラリの基盤ともなっています。

  1. breeze.linalg: breezeで扱う行列など型を定義しています。
  2. breeze.io: CSVからの読み込みなどを行うIOの関数を定義しています。
  3. breeze.numerics: absやsin, cosなど基本的な関数を定義しています。
  4. breeze.signal: デジタル信号の関数を定義しています。
  5. breeze.stats: 乱数生成のライブラリです。

例えば、標準正規分布に基づく乱数であれば、以下の様に出力することができます。

import breeze.stats.distributions._
val mu = 0
val sigma = 1
println(Gaussian(mu, sigma).draw)

nak

Nakは、機械学習のためのライブラリです。

k-meansとロジスティック回帰、SVMがオリジナルで実装されています。
またbreeze-learnからの移植で、ナイーブベイズニューラルネットもあります。

breeze-viz

グラフなどplotして可視化するライブラリです。
いわゆるmatplotlib的なものですね。

このライブラリは、breezeに戻したようです。
他にも以下の様なビジュアライゼーションライブラリもあります。
sameersingh/scalaplot · GitHub

また以下ライブラリは、ScalaNLPには含まれていませんが、wikiにて紹介されているものです。

Epic

Epic形態素解析器です。
PythonのNLTKのようなものです。
日本語はもちろん作られていないので、MeCabを使うのが無難でしょう。

Junto

parthatalukdar/junto · GitHub
Label Propagationのアルゴリズムが実装されています。

ただしこちらは最後のコミットが2014年の3月なので、全然メンテされていないですね。。

やはりRやPythonに比べると、ライブラリの充実度は圧倒的に低いですね。。
Scalaの場合は、Javaの資産をそのまま使えますが、kそれでも劣っているように感じます。

scalaからProcessを使って違うディレクトリでshを叩く

scalaでは他の言語でもできるように、コマンドを叩くことができます。

実際に色んな方が、Processの仕方を紹介をしています。
scala.sys.process | Scalaの標準ライブラリを使ってみる | mwSoft
Scala 2.9.0のscala.sys.processパッケージが便利過ぎる件について - kmizuの日記
scalaで外部コマンドを実行する - Qiita

詰まったところ

実行するjarファイルとは違うディレクトリのファイル操作を行いたかったのですが、cdコマンドがうまく動きませんでした。

解決方法

第2引数にjava.io.Fileのインスタンスを突っ込むとできました。

一つ目は正しく動く方法で、ふたつ目はうまく動かない方法です。

!マークは同期実行です。
非同期実行させたい場合は、!ではなくrunを利用しましょう。

The server quit without updating PID fileが発生して起動できない。

YosemiteからEICapitanにアップデートしたんですが、
その際にMySQLが起動できなくなったので、その解決法を共有します。

【環境】
MacOSX 10.11.2
$ mysql --version
mysql Ver 14.14 Distrib 5.6.26, for osx10.10 (x86_64) using EditLine wrapper
brewで入れたやつです)

事象

MySQLサーバを起動しようとすると以下のエラーが出て、起動出来ませんでした。

$ mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/{PC名}.pid).

解決策

mysqld_safeを打つだけ!

mysqld_safeを打つと、エラー発生時の再起動やエラーのロギングなど安全な起動が行われます。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.3.2 mysqld_safe — MySQL サーバー起動スクリプト

$ mysqld_safe
160106 10:48:15 mysqld_safe Logging to '/var/log/mysql/error.log'.
touch: /var/log/mysql/error.log: No such file or directory
chmod: /var/log/mysql/error.log: No such file or directory
160106 10:48:15 mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
/usr/local/bin/mysqld_safe: line 129: /var/log/mysql/error.log: No such file or directory
/usr/local/bin/mysqld_safe: line 166: /var/log/mysql/error.log: No such file or directory
touch: /var/log/mysql/error.log: No such file or directory
chown: /var/log/mysql/error.log: No such file or directory
chmod: /var/log/mysql/error.log: No such file or directory
160106 10:48:15 mysqld_safe mysqld from pid file /usr/local/var/mysql

mysqlのログディレクトリが無い!と言われたので作ったら動きました。

原因

EICapitanに上げてから、/var/log以下がすっぽり亡くなってました。。
他のScalaから吐き出していたアプリケーションログもお亡くなりに。。

scala(breeze)で重回帰を実装

重回帰とは

重回帰は色んな所に転がっているので今更書かなくてもって感じですが、簡単に。


ある地域の住宅価格を求めたいとなった時に、ランダムで価格を当てるよりも何かの影響を受けて価格が変動すると考えるのが自然です。

 {住宅価格 = \beta_0 + \beta_1 *  犯罪率 + \beta_2 * 宅地の割合 + ...  \beta_n * 低所得者の割合 - (1)}

そこで上のような住宅価格は色んな要素に依存していると考え、各要素がどれくらい住宅価格を求めるのに影響があるのかを求めるのが重回帰です。

住宅価格に犯罪率の寄与が少なければ、{\beta_1}の値は小さくなるでしょうし、大きければその逆になります。

回帰を計算すると、各要素の係数であるβらが求まります。
βらが求まると、上記 (1) の式が埋まるので、新しいデータを各要素に当てはめると、そのデータに対する住宅価格が推定できるようになります。

この住宅価格を目的変数、犯罪率などの要素を説明変数と呼びます。

詳しくは、R - 重回帰モデルの理論と実装 -なぜ正則化が必要か- - Qiitaなどで式の導出は詳しく書かれています。
気になる方は、ぜひ導出も追ってみてください。

実装

Bostonの住宅の価格のCSVです。
Sense · Enterprise Data Science Platform

Python

上述のページで書かれているPythonコードの引用が以下になります。

import pandas as pd
import numpy as np
from numpy import linalg as la

df = pd.read_csv("Boston.csv", index_col=0)
y = df.iloc[:,  13].values
df = (df - df.mean())/df.std() # 基準化
X = df.iloc[:, :13].values
X = np.column_stack((np.ones(len(X)),X)) 
beta = np.dot(np.dot(la.inv(np.dot(X.T, X)),X.T), y)
print beta
R

Rのlm関数で書いたものの引用です

library(MASS)
X <- as.matrix(Boston[, -14])
y <- as.vector(Boston[,  14])
X <- scale(X) #基準化
model <- lm(y ~ X)
print(model)
scala

この式をScalaで書き直します。

def regression(file: File): DenseVector[Double] = {
  val mat = csvread(file, skipLines = 1)
  val y = mat(::, mat.cols - 1) // 目的変数
  val X = DenseMatrix.horzcat(
    DenseMatrix.tabulate(mat.rows, 1) { case _ => 1.0 }, // 要素がない列
    mat(::, 1 to mat.cols - 2) // 要素がある列
  ) // 説明変数の行列
  (inv(X.t * X) * X.t) * y
}

出力

DenseVector(36.45948838509085, -0.10801135783679613, 0.04642045836688007, 0.020558626367099816, 2.6867338193447603, -17.76661122830122, 3.809865206809127, 6.92224640347558E-4, -1.4755668456002482, 0.3060494789851876, -0.012334593916574491, -0.9527472317074077, 0.009311683273793751, -0.5247583778554944)
解説

上の式は

 {住宅価格 = \beta_0 + \beta_1 *  犯罪率 + \beta_2 * 宅地の割合 + ...  \beta_n * 低所得者の割合 - (1)}

Index,犯罪率,宅地の割合,...,低所得者の割合,住宅価格
1,0.5, 0.8, ... , 0.2, 5003,
2,0.53, 0.82, ... , 0.12, 600
3,...

のようなCSVを受け取ります。

まず、1行目で、CSVをロードして行列クラスにぶち込みます。

yは目的変数です。
上のcsvをそのまま行列に突っ込むと、最終列が住宅価格になるので、最終行を目的変数のベクトルとします。

Xは各要素群ですが、そのままだと{\beta_0}の列が作られません。
なので、tabulateで作成して、横で合成しています。
ここは見やすく、fillでVectorを作ってtoDenseMatrixでもよいです。

あとは、最小二乗法の解を求めるだけです。
{\beta = (X^TX)^{-1}X^Ty}
細かい導出式は、今回は求めませんので、他のサイトを見てみるとよいと思います。


今回は基準化を省いていますが、基準化を行うと各要素が同じスケールになるので、上の出力に出た係数を比較するだけでどの要素が目的変数に影響を及ぼすかがわかります。

ただその場合、係数のスケールが変わってしまっているので、目的変数の導出はスケールを戻さないと求められなくなります。


以下に動く実装を置いています。
regression/Regression.scala at master · moc-yuto/regression · GitHub