SVM(サポート・ベクタ・マシン)とpythonで空の写真から天気を判定させてみる

f:id:karaage:20170831173544p:plain:w640

SVM(サポート・ベクタ・マシン)

 SVMとは、機械学習の分野で、多数のデータを複数のクラスに分類する問題によく使われるアルゴリズムです。他にも2つのクラスの分類問題に有効なロジスティック回帰というものもあるらしいですが、3つ以上のクラスに分類するときにはSVMが効率がよいのでよく使われる(らしいです)。

 SVMに関しての概要は、以下の記事がわかりやすそうです。

 あと、ちょっとクセは強いですが、以下の記事も面白く、分かりやすいかもしれません

 SVMを含む機械学習手法と、ディープラーニングとの関係を知りたい方は、以前書いた以下記事を参考にしてみて下さい。

 今は、認識や判別というと、とにかくディープラーニングという印象がありますが、一昔前は認識・判別といえばSVMでした(らしいです)。ディープラーニングより多くの場合、結果がわかりやすい、少ないデータでうまくいく、計算量が少ないといった特徴ががあるため、今でも好んでSVMを使う人は多いようです。というわけで一度やってみることにしました。参考にした書籍などは、本記事の最後に紹介しますので、よろしければ参考にしてみて下さい。

 本記事では、参考書籍をもとにscikit-learnというpythonのパッケージを用いて、MacとRaspberry Piで動かしました。

SVMを使ったお天気の判定

 今回は例題として、空の写真から天気の判定をしてみようと思います。空の画像をもとに、青空、曇り空、夜空を判定させるだけです。ちなみに、今回そんなにうまくいってないので、結果には期待しないでくださいw あくまでSVMの使い方がメインです。

データ準備

 空の写真のデータ取得。最初は、涼風真世さんのブログからダウンロードしていこうと思ったのですが、途中で精神を病みそうになったので、技術の力に頼ることにしました。

 そうして、生まれたのが以下の闇のスクリプトです。

 以下のようなコマンドを実行すると、青空写真がどんどんネットから集まってきます。我に力を…

$ python get_images_yahoo.py "青空"

pythonでSVMを実行するためのセットアップ方法

 SVMはpython上で行います。SVMを使えるライブラリは複数あります。SVM専用のライブラリであるLIBSVMと機械学習の総合ライブラリであるscikit-learnの両方試したのですが、ネット上での説明例が豊富で、データセットのダウンロードができる、他の機械学習にも応用ききそうという理由で、自分はscikit-learnが良さそうだなと感じました。

 よって、ここからはMac(iMac Retina 4K, 21.5-inch,2017)とRaspberry Piでのセットアップ方法を説明していきます。

Macでのセットアップ方法

 Macで使用するパッケージとバージョンは以下です。

  • python 3.6.2
  • sklearn 0.19.0
  • numpy 1.13.1
  • scipy 0.19.1
  • matplotlib 2.0.2
  • OpenCV2 3.3.0

 Macでは、pyenvを使ってpython環境を構築しました。pyenvに関しては下記記事参照下さい。

 上記記事のpyenvのインストールまで完了したら、具体的には以下コマンドで必要なパッケージをインストールしたpython環境を構築します。

$ pyenv install anaconda3-4.4.0 
$ pyenv global anaconda3-4.4.0
$ conda create -n svm python
$ pyenv global anaconda3-4.4.0/envs/svm
$ pip install numpy
$ pip install sklearn
$ pip install scipy
$ pip install matplotlib
$ pip install opencv-python

 condaでパッケージインストールすると、バージョン関係でうまくいかなかったので全てpipでインストールしています(pythonの闇を見てしまった気がします…今回は見ないふりしました)。

 matplotlib関係でエラーが出た場合は、以下記事参照して設定ください。

 これで環境は構築できました。

Raspberry Piでのセットアップ

 Raspberry Piでは、色々な事情によりPython2を使っています。使用するパッケージとバージョンは以下です。

  • python 2.7.13
  • sklearn 0.18
  • numpy 1.12.1
  • scipy 0.18.1
  • matplotlib 2.0.0
  • OpenCV2 2.4.9.1

 Raspberry Piの基本的なセットアップに関しては、以下記事参照ください。 karaage.hatenadiary.jp

 上記記事を参考に、基本的なセットアップを完了させましょう。

 あとは、ターミナルで以下コマンドを実行して必要なパッケージをインストールします。

$ sudo apt-get update
$ sudo apt-get install python-pip
$ sudo apt-get install python-numpy
$ sudo apt-get install python-sklearn
$ sudo apt-get install python-scipy
$ sudo apt-get install python-matplotlib
$ sudo apt-get install python-opencv

 pipを使っていないのは、インストールの時間短縮のためです。

SVMテスト

 ここからは、Mac, Raspberry Pi共通の手順となります。例によって、pythonでSVMをテストするための簡単なプログラムを作ってみました。

 以下コマンドを実行すると、irisという機械学習で分類問題に使われるデータセット(scikit-learnに含まれています)を使って、SVMで分類をします。ちなみにirisは花(アヤメ)の種類と特徴の変数がセットになったデータらしいです。

$ git clone https://github.com/karaage0703/svm-pi
$ cd svm-pi
$ python svm.py

 以下がscikit-learnでチューニングした分類の様子です。

f:id:karaage:20170831173544p:plain:w640

 赤、白、青の丸が、iris(花)の種類を表しています。なんかうまいこと分類してくれるのがわかると思います。分かりやすく可視化するために、2次元の変数としていますが、多次元変数も、もちろん扱えます。

空の写真から天気の判定

 いよいよ、天気の判定です。ディープラーニングだと、とりあえず画像を入れれば良い感じに判別してくれるのですが、SVMの場合は判別するための特徴量を画像から抽出する必要があります。このとき、どういう特徴量を使うかで判別できるかできないかが決まってきます。

 今回は、簡単に色を使ってみることにしましょう。事前に軽くフィルタリングをかけてから(空以外の建物などを除くため)、画像の色の平均値(RGB値)を計算します。

 以下のような構成でフォルダを構成します。

svm-pi
 |- data/
       |--- 01/sky_01.jpg, sky_02.jpg, ...
       |--- 02/sky_01.jpg, sky_02.jpg, ...
       |--- 03/sky_01.jpg, sky_02.jpg, ...
$ python make_svm_data.py data

 すると、 /tmp/svm/svm.tsv という特徴量を抽出したテキストファイルが生成されます。念のため、ファイルの中身を見て変なデータ(nanなど)がある行は取り除いておきましょう。

 あとは、以下コマンド実行すると、SVMで分類できます。

$ python test_svm.py /tmp/svm/svm.tsv

 以下のようなグラフbest_tuned.pngが生成されます。

f:id:karaage:20170901231501p:plain:w640

 割とそれっぽく分類できたように見えますが、うまく分離できず、混じってしまっているところも多いですね。この結果から、特徴量の抽出をもう少し工夫した方が良さそうだなとわかります。前処理のフィルタのパラメータや、単純に平均をとる以外も考えた方が良さそうですね。

 この学習結果を使って、空の写真を撮って、天気を判別させる。といったことももちろん可能です。が、今回は省略します。興味ある人はやってみてください。

まとめ

 SVMを使って簡単な分類問題に挑戦してみました。教師ありデータを簡単にクラス分けするなら、SVMが最適かなと思います。ディープラーニングは、流行りではありますが、SVMで解けるような問題にディープラーニングを使って、貴重な計算資源や時間を無駄に使わないようにしたいですね。

 また、画像認識ではディープラーニングとSVMを組み合わせることで、計算コストを削減するということにも使われるらしいです。具体的には、学習済みのディープなニューラルネットワークを特徴量抽出器として使ってSVMで判定するようです(いわゆる転移学習の一種になるのかなと思います)。機会があればそういった組み合わせにもチャレンジしてみたいですね。

参考書籍

Interface(インターフェース) 2016年07月号

Interface(インターフェース) 2016年07月号

 Interface誌。Raspberry Piでの例が書かれていますが、SVMの説明が非常に分かりやすかったです。この号は全体的に結構面白くためになりました。

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

  • 作者: 比戸将平,馬場雪乃,里洋平,戸嶋龍哉,得居誠也,福島真太朗,加藤公一,関喜史,阿部厳,熊崎宏樹
  • 出版社/メーカー: 技術評論社
  • 発売日: 2015/09/10
  • メディア: 大型本
  • この商品を含むブログ (7件) を見る
 この本は、全体的にさらっとしか書いていないです。ちょっと興味があって概要が知りたいなという人向けでしょうか

Pythonではじめる機械学習 ―scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎

Pythonではじめる機械学習 ―scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎

  • 作者: Andreas C. Muller,Sarah Guido,中田秀基
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/05/25
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る
 最近買った本です。がっつり機械学習の基礎とscikit-learnの使い方が書かれています。実はこの記事を書き終えてから買ったのですが、もっと早く買っても良かったかもしれません。良書の予感がビンビンしてますのでこれから読み進めていきます。

 ちなみにこの本は、下記記事を読んだその日に本屋で立ち読みして購入しました(笑)

📚最近弊社で買ったデータ分析入門書📚 - Misoca開発ブログ

関連記事

参考リンク

sklearn.metrics.accuracy_score — scikit-learn 0.19.0 documentation

Scikit learnより グリッドサーチによるパラメータ最適化 - Qiita