以前からDCGANで生成した画像でデータセットを作ろうと思い、画像生成をしていたが、ようやくそれっぽい画像ができた。
今回はDCGANで作成した画像を「訓練画像」に、DCGANに食わせた元画像を「テスト画像」にして、CNNで分類してみることにした。CNNは以前、VGGNetモデルのCNNで画像分類したやつを使用。
「DCGANで作成した画像は、データセットに使えるのか」という試みで、その結果を書いていきたい。
目次
・全体の行程
・DCGANで訓練画像生成
・CNNでテスト画像分類
全体の行程
まず全体の作業行程のポイントは次の通り・生成画像の中から、よさげな画像7040枚を訓練画像に採用
・DCGANに読み込ませた元画像523枚をテスト画像にする
・DCGANで生成した訓練画像をCNNで学習、テスト画像を分類できるか試す
これが全体の行程だ。CNNは以前、VGGNetを参考にマンション画像分類をしたものを使用し、それに今回新しく作った「マンションの外観」の訓練画像とテスト画像をプラスして、新たに正解率を評価する。
上手くいけばDCGANはCNNのデータセットも作れることの証明になる。
けど、結論から書くと上手くいかなかった。今回はそれをまとめていこうと思う。
DCGANで訓練画像生成
画像の用意
今回、生成するのは「マンションの外観」画像。元画像はGoogle画像から収集し、それを増幅。増幅させるやり方は前の記事で書いてるので、それをそのまま使用し、523枚から31360枚に増幅。特に”角度変換”を何回も使った。
あとはDCGANにかけるだけ。最初、jupyter用のDCGANコードを書いたんだけど、broken pipeが出てカーネルが死ぬとまた最初からやり直しになるので、全くメリットがなかった。
なので普通にローカルで作成するものを作った。
作成画像
48エポック(だいたい34800ステップ)ほど回してできた画像がこちら。だいたい100ステップごとに冒頭に貼ったような1枚64pxの8×8=64枚、512pxの塊がフォルダに保存されていく。ほぼ外観とそっくりなのでいいできだと思う。ただアップで見るとクレヨンで描いたような画質なので、元画像と比べてドット感がないのが少し気になる。
生成画像の中から、よさげな画像を別のファルダに入れていった。だいたい60枚くらいたまったら、この512pxの塊を単一の64pxの画像にバラす。
DCGANの訓練が終わってから画像を生成してもいいんだけど、訓練後に生成すると全て同じ画像になってしまうので、訓練途中にできた中から、出来のいいのを採用。
64枚、512pxの塊は下のコードで一気に分解できる。
64枚の塊画像をまとめて保存したファルダパスと、分解した画像を保存するファルダパスを指定して実行すれば、勝手に保存されていく。
import os import sys import scipy.misc import cv2, matplotlib import numpy as np path_restore="DCGAN生成画像のフォルダパス" path_save='分解画像保存先のフォルダパス' images = os.listdir(path_restore) # 画像の読み込み rows = [] # 横に分解 for i in images[1:]: rows.append(np.hsplit(cv2.imread(path1+'/'+i),8)) tin=[] # 縦に分解 for idx in range(len(rows)): for sec in rows[idx]: tin.append(np.vsplit(sec,8)) count=0 for idx in range(len(tin)): count+=1 for sec in tin[idx]: count+=1 scipy.misc.imsave(path_save+'/split{:04d}_{:02d}.jpg'.format(idx, count), sec)
こうして、CNNに読み込ませる訓練画像、約3520枚ができたので、”左右反転”をかけ、増幅して7040枚に。あとはDCGANに読み込ませた画像(増幅前)の元画像523枚をテスト画像にして、CNNで上手く判別できるかを試す。
CNNでテスト画像分類
訓練画像とテスト画像
さっきも書いたけど、
テスト画像 → DCGANに読み込ませた訓練画像(増幅前)の元画像523枚
訓練画像 → DCGANからできた画像の中から、出来のいいやつを分解した7040枚
にした。
CNNは前にマンション関連の画像を判別するために、あらかじめ作ってあるやつを使う。そのときのラベル0〜3の訓練画像とテスト画像に、今回の画像をプラスする。
今回プラスする分は新しくラベル4にした。CNNのコードは数カ所の数値を書き換えただけ。
前のサイトで書いてるけど、訓練画像とテスト画像の内訳は改めて書くと、こんな感じ。
Label 0 玄関 50, 廊下 50, リビング 150, 寝室 100, クローゼット 100 (増幅して6300枚)
Label 1 キッチン 300 (増幅して6000枚)
Label 2 トイレ 400, 風呂 150, 洗面化粧室 150 (増幅して7000枚)
Label 3 眺望 300枚 (増幅して6000枚)
Label 4 外観 3520枚 (増幅して7040枚)
テスト画像→ 合計 1063枚
Label 0 玄関 30, 廊下 30, リビング 30, 寝室 30, クローゼット 30 (150枚)
Label 1 キッチン 115(115枚)
Label 2 トイレ 80, 風呂 40, 洗面化粧室 40 (160枚)
Label 3 眺望 115 (115枚)
Label 4 外観 523枚(523枚)
新しくプラスした訓練画像も十分な枚数。DCGANから生成された画像でも、別に読み込ませた元画像に似てるわけではないので、元画像をテスト画像にしてみた。
仮にこれが上手くいけば500枚くらい画像を集めれば、訓練画像とテスト画像ができることになるので、ある意味画期的な手法ってことになる。
正解率
結果、正解率は48%。
メッチャ低い。以前のCNNでは87.8%だったので、理由が知りたい、というわけでラベルごとの正解率をまとめてみた。
Label 1 83.9%
Label 2 91.5%
Label 3 94.5%
Label 4 3%
結果は見ての通り、ラベル0〜3は普通に高いのに、DCGANで作成した画像のラベル4が「3%」だった。
原因を考察してみる
外観画像は、ラベル3の眺望と結構似てるから
ラベル3の訓練画像に数枚ほど、外観とかなり似ている画像が含まれていたため、ラベル3に分類されたかもしれない。けど、数枚なのでその可能性は低い。
それよりもラベル3の眺望自体、他の建物も写ってるので、ラベル4の外観と似てる。そのため、ラベル4がラベル3に分類されてしまった可能性もある。
ちなみに純粋にラベル4の外観画像を、訓練画像、テスト画像ともにGoogle検索で収集したもので判別したときは、正解率は高かった。
DCGANで作成した画像は、元画像とは特徴抽出が違くて、まったく別物だから
生成された外観画像を画面上で見ると、人間には「外観」に充分見えるんだけど、CNNには全く別物に見えるらしい。多分、特徴量が本物の外観と全然違うのが一番の原因と考えられる。
スギャーンメモのサイトでも人間の顔と全く違う特徴抽出をしていたらしい。もう少し精巧に作れば、本物と同じように特徴抽出されるのかわからない。
とはいえ3%は低すぎるので、DCGANは本物の元画像とは似ても似つかないもののようだ
結論
外観の本物の画像を訓練画像に使った時は、ふつうに正解率が高かったことを考えると、やっぱりDCGANで作った画像は本物と違うらしく、データセットにはできないようだ。
今回はDCGANで生成した画像を使って、読み込ませた元画像を分類することができるか試したが、見事にコケた。CNN自体はかなり精度の高いものを使っているので、やっぱりDCGANの作成画像は本物も全く違うところに問題がある。
アイドル画像分類とかも、DCGAN生成画像を訓練画像にするなんてことは絶対できないだろうから、画像分類のデータセットはやっぱりキチンと集める必要がありそうだ。