こんにちは。 Ruby on Rails 、NodeJS、Meteor 等放浪し、現在はデータサイエンティストを目指している五所です。
大学では一応数学を専攻していました。
概要
機械学習への入り口として、よく題材にされるMNISTの手書き数字の分類器を作ってみました。 使ったのはPython3とscikit-learnというライブラリです。
結果としては、
- トレーニングデータは60000字
- テストデータは10000字
- 正答率99.913%
- トレーニングにかかった時間は5分程度
チューニングゼロでこのスコアが出たので、ライブラリは素晴らしいなあと思いました。
画像サイズは28*28ピクセルなので、784次元ベクトルを入力とした10クラス分類問題です。
他クラス分類問題はランダムフォレスト分類器を使いと良いと聞きかじったので、そうしています。
今回作ったファイルはこちらに置いておきました。
※追記 この記事を書いた時点では95%でしたが、ちゃんと測りなおしたら99%超えてました。
環境構築
作ったと言っても、実際にコーディングした時間はほんのわずかで、大部分は環境構築やデータの整形、情報収集でした。
具体的には下記をしました。
- Python3 pip3 virtualenv のインストール
- virtualenv で仮想環境構築
- numpy scipy scikit-learn を構築した仮想環境にインストール
- 手書き数字をダウンロードしてPythonから読み取れる形にする
動作環境はUbuntu 14.04で、Celeron2840N搭載の非力なChromebook上で動いています。 なるべくシステム全体にインストールしたくないので、virtualenvで仮想環境を作成します。
1. Python3 pip3 virtualenv のインストール
sudo apt-get install python3 python-dev python3-pip sudo pip install virtualenv
2. virtualenv で仮想環境構築
# プロジェクト作成 mkdir image-classify cd image-classify virtualenv -p python3 env source env/bin/activate
3. numpy scipy scikit-learn を構築した仮想環境にインストール
# sudoで実行しない pip install numpy pip install scipy # 先にライブラリを入れておく sudo apt-get install gfortran liblapack-dev pip install scikit-learn
4. 手書き数字をダウンロードしてPythonから読み取れる形にする
http://yann.lecun.com/exdb/mnist/から、下記データをダウンロードします。
- train-images-idx3-ubyte.gz: training set images (9912422 bytes)
- train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
- t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
- t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
# データを入れておく場所 mkdir data cd data wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
ダウンロードした教師データを、ダンプファイルからテキストファイルに変換します。
gzip -dc train-images-idx3-ubyte.gz | od -An -v -tu1 -j16 -w784 | sed 's/^ *//' | tr -s ' ' > train-images.txt gzip -dc train-labels-idx1-ubyte.gz | od -An -v -tu1 -j8 -w1 | tr -d ' ' > train-labels.txt gzip -dc train-images-idx3-ubyte.gz | od -An -v -tu1 -j16 -w784 | sed 's/^ *//' | tr -s ' ' > test-images.txt gzip -dc train-labels-idx1-ubyte.gz | od -An -v -tu1 -j8 -w1 | tr -d ' ' > test-labels.txt
これで下準備はおしまいです。
機械学習
#!/usr/bin/env python import numpy as np from sklearn.ensemble import RandomForestClassifier # learninig data data_training = np.loadtxt('data/train-images.txt', delimiter=' ') label_training = np.loadtxt('data/train-labels.txt') # test data data_test = np.loadtxt('data/test-images.txt', delimiter=' ') label_test = np.loadtxt('data/test-labels.txt', delimiter=' ') # learn #estimator = LinearSVC(C=1.0) estimator = RandomForestClassifier() estimator.fit(data_training, label_training) # test print(estimator.score(data_test, label_test))
テストしてみる
python image-classify.py ### 学習に5分程度 ### #=> 0.999133333333
感想
機械学習を使えば、こんな感じのことができるんだなあというのが分かりました。
多次元ベクトルをNクラスに分類する問題に帰結できれば、色々と応用できそうですね。
次回以降、パラメータのチューニングや自然言語処理などをしていきたいと思います。
超絶参考にしたサイト
MNIST 手書き数字データを画像ファイルに変換する http://y-uti.hatenablog.jp/entry/2014/07/23/074845
scikit-learnで機械学習を試す SVM http://qiita.com/yasunori/items/8720c85e75b4679cae47
scikit-learnとgensimでニュース記事を分類する http://qiita.com/yasunori/items/31a23eb259482e4824e2
先人に感謝です。
お知らせ
弊社では、機械学習や統計分析等を使って面白いサービスを生み出すエンジニアを募集しています。
興味がありましたら、ぜひご一読下さい。