機械学習のための実験プログラムについて
Aizu advent calendar 2017 8日目の記事である。
まえがき
本稿では機械学習(または数値解析)における「実験を行うプログラムの作成」から「実験結果資料の作成」までの流れとプログラムの構成を、僕がどのようにやっているかを紹介していく。 僕はPython3を用いて研究を進めているので、いくつかPythonライブラリの紹介もする。 書いているうちに去年書いた記事と似ていて新規性に欠ける気がしてきてけど、今回は過去記事の詳細版ということで。
本題
機械学習アルゴリズムの精度確認のための実験を行う際には、基本的に下記の4つのプログラムに分けて書くようにしている。
- 学習アルゴリズムのプログラム
- 入力として学習データ及びパラメータを受けとり、それを元に1.のプログラムを動かし、その結果を出力するプログラム
- 2.を行うために共通な処理を行うためのプログラム
- 入力として2.の結果を受け取り、グラフ画像や表を出力するプログラム
つまり、下の図になる。
また、この図を元にしたディレクトリ構成は下記のようになる。
├── docs │ ├── experiment_01.md │ └── experiment_02.md ├── experiment_01 │ ├── algorithm.py │ ├── experiment.py │ ├── graph_generator.py │ ├── utils.py │ ├── graphs/ │ │ ├── {dataset_name}_{prameters}.png │ │ └── {dataset_name}_{prameters}.eps │ └── results │ ├── {dataset_name}_{prameters}.csv │ └── summary.md └─── experiment_02 ├── hogehoge.py ├── fugafuga.py .......
このようにプログラムを分割しておくと、追加実験による仕様変更に比較的少ないプログラム変更で対応できるかなと思う。
登場するものは、以下の6つである。
これら6つについてそれぞれ書いていく。
入力データセット
僕の研究では、公開データセットを使っている。 基本的には、UCI machine learning repositoryや、LIBSVM Dataで公開されているものである。 データのフォーマットがcsvやlibSVM形式などの一般的な形式だと、大抵読み込むライブラリ(scikit-learnなど)が存在している。 しかし、たまに独自フォーマット(僕が知らないだけかもしれないが)のデータががあったりする。(あるいは2クラス分類問題の教師信号が{-1, 1}でない場合がある)その場合は、それ用のプログラムを書かねばならないので、非常にめんどうだったりする。これに限っては頑張るしかないかなと思っている。
Pythonでscikit-learnを使用している場合は、sklearn.datasets.fetch_mldata()
という便利な関数がある。
fetch_mldata
これはデータセットの名前の文字列を引数に与えるとmldata.orgから、ダウンロードしてきて、データセットのオブジェクト(Bunch object, sklearn.datasets.base.Bunch)で返してくれる。デフォルトでは、自身のホームディレクトリに~/scikit_learn_data
というディレクトリが生成され、その中にデータセットのファイルが入る。
まとめると、とりあえずmldata.orgを探して、あったらfetch_mldata()
、なかったらUCIやLIBSVMから持ってきて、読み込んでBunch objectを返すって流れだと良いと思う。
scikit-learnを使わない場合も同様にデータセットを置いとくディレクトリを作っといて、データセット名を指定すると、データを特定の形式で持ってくるというプログラムを作ればよい。
入力パラメータ
パラメータの入力方法は実験プログラムを実行する際のコマンドライン引数にしている。 僕の場合は標準ライブラリのargparseを使っている。他にもpython-fireやClickがあるが僕はまだためしていない。
複数の入力パラメータを用いて、それぞれで実験を試すことはよくあるので、使用したパラメータを実験結果の出力ファイル名にしておくと、わかりやすくて良いと思う。
実験プログラム
上記で紹介したデータセットの読み込み処理と、コマンドライン引数を用いたパラメータ指定は、この実験プログラムに記述する。 つまり、実験を行う際にはこのプログラムを実行し開始することになる。 実験プログラムは、入力にデータセットとパラメータを受けとり、アルゴリズムのプログラムやユーティリティプログラムを適宜呼ぶような構成になる。(アルゴリズムは複数の場合もある)
ユーティリティプログラム
Datasetの読み込みや交差検定、データの前処理など、プログラム中でよく使う関数はutilityとしてまとめたり、ライブラリ化すると便利である。
アルゴリズムのプラグラム
このプログラムは前節の実験プログラムから呼ばれることになる。
scikit-learnに準拠させる場合はBaseEstimator
とClassifierMixin
を継承させて、学習用の関数fit()
と推論用の関数predict()
を実装させればよい。
プログラムにおいて(これに限らず)、必要に応じてテストコードを書くとより良い。doctestを用いると関数定義の下に簡単にテストを書くことができるので、おすすめである。
また、ここもアルゴリズムのプラグラムとして独立させておき、ライブラリ化すると便利である。
参考
sklearn準拠モデルの作り方 - Qiita
GitHub - masaponto/Python-ELM
GitHub - masaponto/Python-DBM
実験結果
実験結果はcsvファイル、またはmarkdownやtex形式の表にして実験プログラムから出力するようにしている。これは、後のグラフ生成や資料作成を楽にするためである。また、実験結果は、指定ディレクトリに保存すると同時に、ぼっちslackに送るようにしている。簡易的なバックアップやログにもなるし、計算用のサーバで実験を行った最には結果を通知させる役割にもなり非常に便利である。slackに送るにはslackteeを用いると良い。slackteeは標準出力した文字列を任意のslackに投稿する機能を提供する。実験プログラム実行の際に、$ python experiment.py | slacktee.sh -c <chanel-name>
とすれば良い。これがなかなか便利で、過去に僕はkamebotを作ったりしたが、全然使わなくなってしまった。ちなみに、kamebotはPythonコードの中の関数にデコレータをつけることで、その関数内の標準出力を指定slackに送るというものである。
一方、表の生成にはpython-tabulateが便利である。markdownやtexなどの表形式に対応しているので、何も考えずにそのまま研究資料に貼り付けるだけで済む。
参考: ぼっちsalck
グラフ生成
結果のcsvファイルの読み込みには、Numpyのnumpy.load_txt()
という関数が便利である。ファイルの文字列を引数にとり、Numpy array形式にして返してくれる。また、pandasのpandas.read_csv()
で読み込むと、csvにヘッダとして文字列が入っていても問題なく読み込むことができる。
グラフの生成にはmatplotlibを使う。この際、epsファイル(などのベクター画像)とpngファイルを生成するようにしている。epsファイルは論文用、pngファイルはmarkdownドキュメントとスライド用である。
グラフを生成する際に注意することは2つある。グラフの軸のラベルを必ずつけることと、グラフのタイトルはつけないことである。 前者、後者ともに読者にわかりやすくするためである。後者の方は、グラフ画像にタイトルをつけると、論文に画像として読み込んだ際に、latexのfigureのcaptionとでグラフの名前の記述が重複してしまい読みにくくなるからである。
実験資料
実験結果として他人に伝えるためには、得られたものを資料にまとめなければならない。
僕はmarkdwonで資料を書いて、pandocを使って、pdfを生成するようにしている。
pandocとはドキュメント向けのファイルを様々な形式で変換できるツールである。また、pdfへの変換にはlatexを経由するので、数式も対応する。(latexの形式で数式を記述する)
適当な資料なら$ pandoc document.md -o document.pdf
でpdfが生成されてOKである。
しかし、表紙のついた洒落た資料にしたいときもある。
その場合は、下記のテンプレートと使うと良い。
これを使ってpandoc on Dockerで資料を作るためのキットを作ってみた。
Docker環境さえあればどこでも$ make
で動く。
おわりに
3年生のときに研究をはじめて、実験プログラムを作りはじめたとき、よく考えずにファイルを作っていたため、ディレクトリの構成がごちゃごちゃになっていた。 そういう過去があったので、本稿のような記事があれば少し役立つかなと思い、書くことにした。 今でも、追加実験が複数続いたりすると、構成がわかりにくくなってきてしまうことがあり、難しいなと感じている。 Pythonのようにゴリゴリ書けてしまう言語だと余計そうなりやすいのかもしれない。 大切なのは、できるだけ共通部分とそうでない部分に分割し、前者をライブラリ化していくことだと思う。
本稿が機械学習や数値解析を用いた研究を進めていく際の参考の一つになるとよいと思う。
そんな感じで修論がんばるぞい!
おまけに修論用Dockerを置いておく。
修論用 · GitHub
MESHでラズパイにお天気情報をしゃべらせた話
MESHのボタンを押すとRaspberry Pi 3 model Bがその日の天気をしゃべるようにした。本稿はその作業メモである。
構成
<MESH>--<iPad>--<ラズパイ>--<スピーカ>
Rasberry Pi 3
OSはRASPBIAN JESSIE LITEにした。
ローカルサーバにしようと思ったのでGUI環境はいらないからである。
ddコマンドでmicroSDに焼いて終わり。
また、ラズパイの電源確保のためAnkerのUSB充電器を買った。
Open Jtalk
ラズパイに日本語をしゃべらすのにOpen Jtalkを使った。
Open Jtalkで日本語の文字列をしゃべる音声ファイルを生成し、aplayで再生する。
「Raspberry pi Open Jtalk」でググると多くの記事が見つかる。
以下のページを参考にした。
クラゲのIoTテクノロジー
メイちゃんの声にした。
Python2で天気情報をしゃべらせる
以下のページを参考にした。
Raspberry Piにしゃべらせてみた(OpenJTalk 1.08、.htsvoiceファイル対応): Raspberry Piでやってみた
Raspberry Piに現在時刻と、天気をしゃべらせてみた(Python): Raspberry Piでやってみた
天気情報にはWeather Hacksを用いた。
Python bottle, BottleDaemonでサーバを立ててリクエストがきたら天気情報を取得してしゃべるようにした。
実際のコードは以下のとおり。
MESHボタン押すとラズパイが天気喋るよ · GitHub
BottleDaemonにより
$ python app.py start
これでデーモンとして動く。
MESHとの連携
MESHを使用するにはMESH用iOS/Androidアプリと連携させる必要がある。
MESHとiOS/Android端末はBluetoothで接続する。
筆者はiPad 4thを使うことにした。
MESH用iOS/AndroidアプリではMESHからのイベントを取得し、音声再生やメール送信、Javascriptの実行等をGUIプログラミングすることができる。ただし、Javascriptのコードは、別途に書いてMESH SDKに登録する必要がある。なお、アプリはバックグラウンドにしていても動作する。
以下のページを参考にした。
KB_1506/developLog_Software_MESH_Tag.md at master · jphacks/KB_1506 · GitHub
実際のコード以下のとおり。 MESHボタン押すとラズパイが天気喋るよ · GitHub
作業は以上である。
おわり
このページの動画を見て作りたくなった。偶然MESHのボタンタグを入手できたので、今回のことをやろうと思った。これで毎朝、画面を見ることなく天気情報が得られる。今後アイデアがあれば機能を増やしていきたい。
Python3による機械学習(数値解析)の実験を助けるツール -- Aizu AdC 2016
この記事はAizu advent calendar 2016 9日目の記事です。
前の人 @innocent_mame
次の人 @RomTin
ギリシャ-アテネからの投稿です!!! masapontoです。
今年は主に何をやっていたかって振り返ると、アニメを見てた 研究(機械学習)のためのPython3コードを書いてた気がします。
今回はその研究での実験を行うのために使っているツールやライブラリを紹介しようと思います。
なにか便利ツールやより良い使い方があれば教えてください。
Numpy、scipy、scikit-learn
Pythonで機械学習といえば、こいつらなしには語れないでしょう。(深層学習だとTensorflow, Keras, Chainerもありますね)
自分で学習器を実装する場合はNumpy, scipyをを使ってます。scikit-learnの分類器にしたがって実装する(fit(X, y)に学習、predict(X)に分類を行う関数を実装する)と、scikit-learnで実装されている交差検定が使えて便利です。
こんな感じです。(こういう使い方するもんなのか、不安なのだが)
https://github.com/masaponto/Python-ELM
https://github.com/masaponto/Python-MLP
Anaconda3 on pyenv-virtualenv
pyenv-virtualenv
anaconda
これも有名ですね。anaconda3の環境だと数値解析に必要なライブラリ(僕がほしいNumpy、scipy、scikit-learn, pandas)は大体そろってます。
pandas
pandas
pandasは今のところ、あまりつかってません。
実験スクリプトで吐いたcsv形式の結果を、グラフにするのに使ってます。(with matplotlib)
pandas.read_csvして、dataflame.plotすると楽です。
こんな感じ
graph.py · GitHub
参考
numpy/scipy/pandas/matplotlibメモ | mwSoft
Tabulate
みなさんも実験結果の資料を作成するのには主にmarkdownを用いると思います。
tabulateを使えば、実験結果をかんたんにmarkdown table にできて良いです。
こんな感じ。
tabulate_sample.py · GitHub
doctest
slacktee
実験スクリプトの実行が終わったら、ぼっちslackの実験チャンネルに結果を通知するようslackteeを使ってます。
以前kamebotなる、slackに投げるやつをを作ったりしてましたが、投げるのにコード書くのがめんどうなので最近はこちらをつかってます。
最後に
この記事を書いている間にJupyter notebookでいいんじゃね?って気持ちになってきました。 使っていた時期もあったのですが、さっとコードを書いて、試して、やり直して、というサイクルがやりにくくて、使わなくなってしまいました。(使い方が悪いのか) で、今は上で列挙したものを使ってやっています。なにか便利なツールがありましたら、教えてください!!
最近は、powerpoint(などのofficeソフト)スライドに実験結果の表を出すのが面倒なので、markdown -> tex -> pdf (or png via texclip)で貼り付けてやってます。 この辺を楽にできたらいいなーと感じています。(なんか作るか)
おまけ
次の人は @RomTinです。よろしくお願いします。