Masaponto's Blog

お勉強メモ

機械学習のための実験プログラムについて

Aizu advent calendar 2017 8日目の記事である。

まえがき

本稿では機械学習(または数値解析)における「実験を行うプログラムの作成」から「実験結果資料の作成」までの流れとプログラムの構成を、僕がどのようにやっているかを紹介していく。 僕はPython3を用いて研究を進めているので、いくつかPythonライブラリの紹介もする。 書いているうちに去年書いた記事と似ていて新規性に欠ける気がしてきてけど、今回は過去記事の詳細版ということで。

本題

機械学習アルゴリズムの精度確認のための実験を行う際には、基本的に下記の4つのプログラムに分けて書くようにしている。

  1. 学習アルゴリズムのプログラム
  2. 入力として学習データ及びパラメータを受けとり、それを元に1.のプログラムを動かし、その結果を出力するプログラム
  3. 2.を行うために共通な処理を行うためのプログラム
  4. 入力として2.の結果を受け取り、グラフ画像や表を出力するプログラム

つまり、下の図になる。

f:id:masaponto:20171215095412j:plain
実験用プラグラムの処理の流れ

また、この図を元にしたディレクトリ構成は下記のようになる。

├── 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つである。

  1. 入力するデータセット
  2. 入力するパラメータ
  3. 実験用のプログラム
  4. 実験を助けるユーティリティ関数のプログラム
  5. アルゴリズムのプログラム
  6. グラフ生成用プログラム
  7. 実験資料

これら6つについてそれぞれ書いていく。

入力データセット

僕の研究では、公開データセットを使っている。 基本的には、UCI machine learning repositoryや、LIBSVM Dataで公開されているものである。 データのフォーマットがcsvlibSVM形式などの一般的な形式だと、大抵読み込むライブラリ(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()、なかったらUCILIBSVMから持ってきて、読み込んでBunch objectを返すって流れだと良いと思う。 scikit-learnを使わない場合も同様にデータセットを置いとくディレクトリを作っといて、データセット名を指定すると、データを特定の形式で持ってくるというプログラムを作ればよい。

入力パラメータ

パラメータの入力方法は実験プログラムを実行する際のコマンドライン引数にしている。 僕の場合は標準ライブラリのargparseを使っている。他にもpython-fireClickがあるが僕はまだためしていない。

複数の入力パラメータを用いて、それぞれで実験を試すことはよくあるので、使用したパラメータを実験結果の出力ファイル名にしておくと、わかりやすくて良いと思う。

実験プログラム

上記で紹介したデータセットの読み込み処理と、コマンドライン引数を用いたパラメータ指定は、この実験プログラムに記述する。 つまり、実験を行う際にはこのプログラムを実行し開始することになる。 実験プログラムは、入力にデータセットとパラメータを受けとり、アルゴリズムのプログラムやユーティリティプログラムを適宜呼ぶような構成になる。(アルゴリズムは複数の場合もある)

ユーティリティプログラム

Datasetの読み込みや交差検定、データの前処理など、プログラム中でよく使う関数はutilityとしてまとめたり、ライブラリ化すると便利である。

アルゴリズムのプラグラム

このプログラムは前節の実験プログラムから呼ばれることになる。 scikit-learnに準拠させる場合はBaseEstimatorClassifierMixinを継承させて、学習用の関数fit()と推論用の関数predict()を実装させればよい。 プログラムにおいて(これに限らず)、必要に応じてテストコードを書くとより良い。doctestを用いると関数定義の下に簡単にテストを書くことができるので、おすすめである。 また、ここもアルゴリズムのプラグラムとして独立させておき、ライブラリ化すると便利である。

参考
sklearn準拠モデルの作り方 - Qiita
GitHub - masaponto/Python-ELM
GitHub - masaponto/Python-DBM

実験結果

実験結果はcsvファイル、またはmarkdowntex形式の表にして実験プログラムから出力するようにしている。これは、後のグラフ生成や資料作成を楽にするためである。また、実験結果は、指定ディレクトリに保存すると同時に、ぼっちslackに送るようにしている。簡易的なバックアップやログにもなるし、計算用のサーバで実験を行った最には結果を通知させる役割にもなり非常に便利である。slackに送るにはslackteeを用いると良い。slackteeは標準出力した文字列を任意のslackに投稿する機能を提供する。実験プログラム実行の際に、$ python experiment.py | slacktee.sh -c <chanel-name>とすれば良い。これがなかなか便利で、過去に僕はkamebotを作ったりしたが、全然使わなくなってしまった。ちなみに、kamebotはPythonコードの中の関数にデコレータをつけることで、その関数内の標準出力を指定slackに送るというものである。

一方、表の生成にはpython-tabulateが便利である。markdowntexなどの表形式に対応しているので、何も考えずにそのまま研究資料に貼り付けるだけで済む。

参考: ぼっちsalck

グラフ生成

結果のcsvファイルの読み込みには、Numpynumpy.load_txt()という関数が便利である。ファイルの文字列を引数にとり、Numpy array形式にして返してくれる。また、pandaspandas.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である。 しかし、表紙のついた洒落た資料にしたいときもある。 その場合は、下記のテンプレートと使うと良い。

github.com

これを使ってpandoc on Dockerで資料を作るためのキットを作ってみた。

github.com

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

実際のコード以下のとおり。 f:id:masaponto:20170421231707p:plain 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

tabulate

みなさんも実験結果の資料を作成するのには主にmarkdownを用いると思います。 tabulateを使えば、実験結果をかんたんにmarkdown table にできて良いです。
こんな感じ。
tabulate_sample.py · GitHub

doctest

doctest
さらっと雑なテストをするのに便利です。

slacktee

slacktee

実験スクリプトの実行が終わったら、ぼっちslackの実験チャンネルに結果を通知するようslackteeを使ってます。 以前kamebotなる、slackに投げるやつをを作ったりしてましたが、投げるのにコード書くのがめんどうなので最近はこちらをつかってます。

最後に

この記事を書いている間にJupyter notebookでいいんじゃね?って気持ちになってきました。 使っていた時期もあったのですが、さっとコードを書いて、試して、やり直して、というサイクルがやりにくくて、使わなくなってしまいました。(使い方が悪いのか) で、今は上で列挙したものを使ってやっています。なにか便利なツールがありましたら、教えてください!!

最近は、powerpoint(などのofficeソフト)スライドに実験結果の表を出すのが面倒なので、markdown -> tex -> pdf (or png via texclip)で貼り付けてやってます。 この辺を楽にできたらいいなーと感じています。(なんか作るか)

おまけ

f:id:masaponto:20161207094445j:plain f:id:masaponto:20161208022544p:plain

次の人は @RomTinです。よろしくお願いします。