みらいテックラボ

音声・画像認識や機械学習など, 週末プログラマである管理人が興味のある技術の紹介や実際にトライしてみた様子などメモしていく.

第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(3)

これは, 人工知能技術戦略会議等主催 第1回AIチャレンジコンテスト[1]に引き続き, ユニクロを展開しているファーストリテイリング主催で今年4月~7月に開催された「第1回 FR FRONTIER :ファッション画像における洋服の「色」分類」[2][3]にチャレンジしたときの取組みについて, 数回に分けて紹介するものである.


関連記事:
第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(1)
第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(2)
・第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(3)
第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(4)
第1回FR FRONTIER:ファッション画像における洋服の「色」分類にチャレンジ!!(5)

前回に続き, 今回はモデリングについて試したことの一つを紹介する.

3. モデリング(1)

今回は「色」分類なので画像内に含まれる物体の全体像は必要ない.
そこで, 画像をグリッド分割し, 各領域について「色」識別を行い, 各領域の識別結果を統合して画像全体の結果とする方法を試してみた.

3.1 前処理
画像をN×Nの領域に分割し, 背景色の画素数閾値未満の領域を識別対象とする.
1) 画像を640×640dotにリサイズする.
2) 10×10の領域に分割する.
3) 背景色(255. 255, 255)の画素が25%未満の領域を抽出する.

f:id:moonlight-aska:20170801222402p:plain:w250

コード:

# グリッド分割処理
AREA_WIDTH = 64
AREA_HEIGHT = 64
SHIFT_SIZE = 64

# 背景画素カウント
def calc_whitepixel(img):
    count = 0
    for row in range(img.shape[0]):
        for col in range(img.shape[1]):
            if all(img[row,col] == [255,255,255]):
                count += 1
    return count

# ブロックの抽出
def split_area(img, dest):
    limit = AREA_WIDTH * AREA_HEIGHT * 0.25
    count = 0
    for y in range(0, img.shape[0], SHIFT_SIZE):
        for x in range(0, img.shape[1], SHIFT_SIZE):
            area = img[y:y+AREA_HEIGHT, x:x+AREA_WIDTH]
            pixels = calc_whitepixel(area)
            if limit > pixels:
                file, ext = os.path.splitext(dest)
                fname = '{0}_{1}{2}'.format(file, count, ext)
                cv2.imwrite(fname, area)
                count += 1


3.2 モデルと識別器
領域の「色」識別を行うモデルの構造は, 以下のようなCNNモデルとした.

f:id:moonlight-aska:20170731225127p:plain:w500

コード:

model = Sequential()
model.add(Conv2D(32, (3, 3),
                 padding=='same',
                 input_shape=(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS),
                 activation='relu'))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(24, activation='softmax'))
          
model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.Adam(lr=1e-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.),
              metrics=['accuracy'])


「色」識別器は, 各領域の予測結果を統合するようにした.

f:id:moonlight-aska:20170731231420p:plain:w500
注) 各領域の識別器は, 全領域共通で学習したものを使用.

3.3 評価
以下の2通りの統合方法で評価してみた.
(1) 各領域の予測1位のヒストグラムを取り, 最大のものを最終結果に.
(2) 各領域の各色の予測値(softmaxの出力)の総和を取り, 最大のものを最終結果に.

テストデータ:9801画像

統合方法精度
(1)0.580
(2)0.596

う~ん, 思ったより全然悪い. 残念!!

誤識別の傾向を見るために, エラーしたデータを確認したいところだが, テストデータなのでラベルがない.
そこで, 他の識別実験の結果と今回の結果とが異なるデータの画像をみたが, 明らかにおかしいというものは少なく, 人間でもどちらを選んでもおかしくないというものが多かった.

モデル構造の見直しやハイパーパラメータの調整で少しは改善すると思うが, この方式で10%以上の精度改善は難しいと判断し, 別アイデアを試すことに.

今回は, グリッド分割した領域毎に「色」識別を行い, 予測結果を統合する方法について紹介した.
次回も, モデリングについて試した別の方法について紹介する.

----
参照URL:
[1] 人工知能技術戦略会議等主催 第1回AIチャレンジコンテスト
[2] 第1回 FR FRONTIER :ファッション画像における洋服の「色」分類
[3] 最先端のビジネス課題にチャレンジ!





最強囲碁AI アルファ碁 解体新書 深層学習、モンテカルロ木探索、強化学習から見たその仕組み

最強囲碁AI アルファ碁 解体新書 深層学習、モンテカルロ木探索、強化学習から見たその仕組み


画像認識 (機械学習プロフェッショナルシリーズ)

画像認識 (機械学習プロフェッショナルシリーズ)


深層学習による自然言語処理 (機械学習プロフェッショナルシリーズ)

深層学習による自然言語処理 (機械学習プロフェッショナルシリーズ)


Deep Learning Javaプログラミング 深層学習の理論と実装 (impress top gear)

Deep Learning Javaプログラミング 深層学習の理論と実装 (impress top gear)