Python
Kaggle

Leaf Classificationで良精度を出すまで_1日目

More than 1 year has passed since last update.

データ分析初学者がKaggleのLeaf Classificationをやってみることにしました。
(https://www.kaggle.com/c/leaf-classification/data)

まず問題を把握する

問題

192の特徴量(margin1~64, shape1~64, texture1~64)から99クラス分類を行う。

データセット

  • 1584個の画像+特徴量
  • 正解ラベルは99個
  • 訓練データは990個
  • また、1クラスにつき10個の訓練データが与えられている。
  • テストデータは594個

思ったこと、考えたこと

各データに対して訓練データ10は少ないんじゃないか?

→平行移動などでデータセットを増やしてみるのも良さそうです。
コードを書いて同じラベルのものをどの程度動かしても良さそうかを見てみます。

samelabel_leaf.py
lst = [0,316,905,1001,1124,1158,1269,1319,1449, 1503]#同じラベルの画像のインデックス
for i,j in enumerate(lst):
    plt.subplot(2,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(images[j], "gray")

スクリーンショット 2017-07-07 22.52.22.png

向きがほとんど一緒なので、あまり回転させすぎるのは得策ではないかもしれません。
拡大、縮小も控えめに行った方がむしろ良さそうな気もします。

192個の『特徴量』とはどういうことだろう?

→ margin, shape, textureの意味がよくわからないので、調べてみます。

PLANT_LEAF_CLASSIFICATIONの論文

3.2 Leaves

『この問題は少数の例で幅広いクラスの分類をすることは重要である。』
どうやら、少ないのは意図的なようです。

4.1 Leaf Shape Feature

『二次元領域、または教会を表す一次元のデータである。
CCDCはスケール、平行移動、回転不変のshape descriptorである。
最終的にベクトルを適切なサイズにスケーリングし、同じ要素数を持つようにして計算時間を短縮できるようにしている。』
なにやらよくわからないですが、

shapeの重心$\bar{x}, \bar{y}$を、

$\bar{x}=\frac{\sum_{i=1}^{s}x_i}{s}, \bar{y}=\frac{\sum_{i=1}^{s}y_i}{s}$

として、

$d_i = \sqrt{(x_i-\bar{x})^{2}+(y_i-\bar{y})^{2}}$

$d_i^{'}=\frac{d_i}{\sum_{i=1}^{s}d_i}$

としていると考えると、どうやら重心の平均をとって全体の重心からの離れ具合を表しているようです。

4.2 Leaf Texture Feature

『各画像について、1024個のsmall windowsがランダムに選択される。
それらに対して、回転不変のGaborフィルターをかける。
フィルタの重心の標準偏差を変化させることで5つの異なるスケールフィルタを作る。
各フィルタは各windowと畳み込まれ、そのフィルタの4つの特徴が計算される。
そのあと、1024x20個の特徴ベクトルの各々を64個のベクトルに割り当てる。
その割り当てられた1024個のベクトルからヒストグラムが構築され、64個の特徴ベクトルが与えられる。』
おそらく、small windowsとは画像から切り取った5x5などの小要素のことだと思いますが、どういうことなのかわかりませんでした。

4.3 Leaf Margin Feature

『まず、メディアンフィルタをbinary leaf画像に適用し、画像を平滑化する
これによって輪郭全体をm個の点で表すことができ、この各点について元の輪郭上の対応する点を計算する。
1.大きさ:平滑化されたマージンの点と元の対応する点との符号付き距離
2.勾配:現在の点と次の点との符号付き差
3.曲率:前の点と次の点との間の現在の点での角度
のそれぞれについて正、負の2つのフィーチャがwindowごとに6つの特徴discriptorを生成する。
マージンwindowの特徴ベクトルは4.2と同じ方法で64個の特徴を生成するために使用される。』

つまり
d61e0c76dd87fe4126a47b5dfe250193.jpg
という感じです。

おそらく、どうやら平滑化を行った事で輪郭を認識し、その結果マージンを認識できるという事でしょうか。

縦横比が違っているデータが多くあるが、これはどうしよう。

→2つ考えた。

  • 全て同じサイズに拡大or縮小をしてリサイズをする。
  • 全てが同じサイズになるように正方形を基準として、元の画像の縦横比を保ったまま縦or横方向に0paddingを行う。

前者だと、例えば細長い画像のデータを丸い葉と認識してしまいそうなので後者の方が良さそう。

画像、大きくない?

これは小さくすれば解決すると思う。
Mnistも10クラス分類とはいえ28x28で結構な精度が出るということは、ある程度小さく縮小しても大丈夫そう。
→これについては、色々なサイズで実験して考察することもできそう。

というわけで明日から実装しよう。