音声信号をスペクトログラム化してみる

テクスチャの識別に関する以下の読み物を読んでいたら, 加速度信号をCNNへ入力する前にフーリエ変換してスペクトログラムにしていたので、自分でも真似てみる.

今回はLMT Haptic Texture Databaseの音声信号(.wav)を可視化する.
この音声信号はテクスチャをスタイラスでなぞった際に集音したデータセット
http://www.lmt.ei.tum.de/downloads/texture/

STFTでspectrogramを作った。 窓関数はハミング窓。
spectrogramからiSTFTで元の信号への変換も行ってみた.

サンプル1

f:id:yusuke_ujitoko:20170930230803p:plain

サンプル2

f:id:yusuke_ujitoko:20171001000809p:plain

音声信号にSTFTかけるのは一般的なようだが、 今回のように加速度や音声に対してもSTFT掛けてCNNに入力するのも常套手段のよう。 これでテクスチャ識別器を作れる。

Adversarial Examplesに興味がある

adversarial exampleを勉強したくて読んだ。
メモ。

  • 本文ではDNNの直観的でない以下の2つの性質について触れている
    • 個別ユニットを観察するのも、複数ユニットの組合せを観察するのも違いはない
    • 入力と出力のマッピングが非連続なので、
      ちょっと入力に摂動を加えると誤識別を起こせる

性質1. 個々のユニットの値に特に意味はない。層全体で意味を持っている

  • 従来、CVでは特徴量抽出に対して焦点を当ててきた.
    この考え方の延長で、ある座標空間における各座標に対して意味を付与でき、
    これを調べると入力画像との対応が取れるものと扱ってきた。
  • あるユニットを活性化させた入力画像群(natural basis)を抽出(下図)
    するとユニットごとに意味の割当があるように感じる

f:id:yusuke_ujitoko:20170928233642p:plain

  • でも適当にとった基底(random basis)を活性化させた入力画像群をみても意味がある気がする(下図)

f:id:yusuke_ujitoko:20170928233715p:plain

→結局NNは座標系をdisentangleしていない

性質2. adversarial exampleを作れる

  • 汎化能力の高いニューラルネットワークは、摂動にはロバストであってほしい。
    つまり,訓練データ内で距離が非常に近いもの同士は同クラスに分類されてほしい.
  • でも非線形関数が積み重なると、入力空間に対して重要性が低いスポットが発生し,
    滑らかさは保たれない
  • 実際 adversarial examplesを作れば誤りを発生できる。
    (以下はalexnetで作成) f:id:yusuke_ujitoko:20170929000252p:plain

    • 層の数が変わっても、活性化関数が変わっても、訓練データの異なるサブセットを使っても、同じ摂動を加えると誤る

Adversarial training

「このadversarial exampleを学習に活用すれば,より汎用的でロバストにできるかも」
という発想で実験が行われている.

MNISTの識別では,もとのデータセットにadversarial exampleを少し加えたものを学習に用いることで,少しテストエラーを低くできた.
どうやら前方の層を参照して作成したadversarial examplesよりも後方の層によるadversarial examplesの方が効果的のよう.

DRAGAN + SRResNetでいらすとや画像生成する

MakeGirlsMoeは 驚異的な生成画像の質で、お盆休み中の世間を驚かせた。
このMakeGirlsMoeの

  • ネットワーク構造(SRResNet)
  • 目的関数(DRAGAN)

を使っていらすとや画像を生成してみる。

DRAGANについては、以前に記事を書いている。 当時あまり注目されていないながらも、私の手元のデータセットに関してはCramerGANやWGAN-gpよりも当時性能が出ていてビックリした。

SRResNetに関しては、https://arxiv.org/abs/1609.04802のネットワークをそのまま利用した。

f:id:yusuke_ujitoko:20170926224811p:plain

通常のGANだと、アップサンプリングはdeconvolutionで行うが、SRResNetではPixelCNNを使う。
ResNetが深いので、メモリが4~8GしかないGPUだとあまりバッチサイズを大きく出来ず学習は厳しかった。

画像生成:ブロンド外国人による支配

これまでにない、とても鮮明な画像を生成できている。
しかしながら、生成画像に多様性はない。
何度か試したものの、いずれも 途中でブロンド外国人にmode collapseしてしまった。

conditional GANにしないとそもそも多様性は保てない?のかもしれない。 cGANにすればコントロールは少なくともできるかも。 論文ではAC-GANを使っていたので次はそちらを試す予定。

パターン1

完全にブロンド少年しか生成しなくなった。
(↓に行くほど学習が進んだ時の生成画像)

f:id:yusuke_ujitoko:20170926223713p:plain

f:id:yusuke_ujitoko:20170926001234p:plain

f:id:yusuke_ujitoko:20170926001142p:plain

f:id:yusuke_ujitoko:20170926001153p:plain

パターン2

パラメータを少し変えた別の学習では、女性率高めになった f:id:yusuke_ujitoko:20170926224105p:plain

パターン3

目がチカチカする。 f:id:yusuke_ujitoko:20170926224044p:plain

pix2pixで車載画像の昼夜の変換を試す

最近、業務の忙しさと、
別件で進行しているモデルのパラメータチューニングの収束しなさから、
ブログ更新をしばらく行っていなかった。

一旦、更新が途絶えてしまうと、なかなかモチベーション的に再開しづらいので、
以前も試したことのあってお手軽なpix2pixを再び試してみようと思う。
(お手軽と言っても学習に数日は掛けた)

さて、pix2pixの変換事例はいろいろ紹介されているが、
Image-to-Image Demo - Affine Layer

論文の中の昼と夜の画像変換については、datasetが公開されておらず、
ネットを探しても先行事例は見つからなかった。
more datasets available? · Issue #8 · phillipi/pix2pix · GitHub
↑のように昼夜画像データセット難民は多いようだ。

pix2pixにはペアの訓練画像が必要なのだが、
これがなかなか見つからない。
色々探しているうちに車載動画のdatasetを見つけた。
Alderley Day/Night Dataset - Robotics@QUT - Confluence f:id:yusuke_ujitoko:20170925231115p:plain

昼夜の訓練ペア画像は1.5万弱。
これらに対して学習を行った。
学習後の訓練ペア画像への変換結果は以下のようになった。

昼→夜

f:id:yusuke_ujitoko:20170925232215j:plain

夜→昼

f:id:yusuke_ujitoko:20170925232218j:plain

別の車載画像を試す

KITTI Vision Benchmark Suiteへ、上記で学習済みのpix2pixを掛けてみた。

f:id:yusuke_ujitoko:20170925232859j:plain

不自然な煙?のようなものがいずれの画像にも見えて、失敗している。
上のデータセットの影響を大きく受けているのがわかる。
より汎化を目指すためには巨大なペア画像データセットが必要なのだが、
現状公開されていないために難しい。

こうなるとペア画像でなくてもよいcycleGANが使いやすくて、こちらの発展を期待してしまう。

pix2pixの枠組みを利用した動画の異常検知

  • 異常検知の難しさ
    • 既存の異常データセットのサンプルサイズが小さいこと
    • 異常の定義がはっきりしていないこと

  • これらの課題に対して、正常なパターンのみ学習させた生成モデルで対処
    • 学習時には(集めやすい)正常データのみ用意
    • 正常データとの距離により異常を判定

  • 生成モデルとしてGANを利用
  • GANを使った異常検知としては, https://arxiv.org/abs/1703.05921 もあったが,こちらとは異なる利用方法をしている

動画内の正常パターンを学習

時刻tにおけるフレーム{F_{t}}とそのときのオプティカルフロー{O_{t}}をデータとし,
pix2pixと同じ枠組みのネットワークを構築し正常パターンを学習させる.

2つのネットワークを組み,以下の変換をそれぞれ学習させる

  • {G^{F \rightarrow O}} ({F_{t} \rightarrow O_{t}})
  • {G^{O \rightarrow F}} ({O_{t} \rightarrow F_{t}})

正常の場合のみのデータで学習させておけば、
異常データとして{F}{O}を入力したときには、変換が上手く行かないはず。

f:id:yusuke_ujitoko:20170907002839p:plain

上の画像がその例になっている。
上部では{G^{F \rightarrow O}}によって、車を含むフレーム {F} (異常パターン)からオプティカルフロー {O} を再構成しようとしているが、 車の部分のオプティカルフローがうまく再構成できていない。
下部では{G^{O \rightarrow F}}によって、車を含むオプティカルフロー{O}からフレーム{F}を再構成しようとしているが,こちらも変な塊ができてしまっている。

テスト動画の判定はどのように行うかというと,テスト動画の各フレームからオプティカルフローを計算し, フレームとオプティカルフローの組を作る.
そして,2つのネットワークでそれぞれ変換し,変換後のフレームとオプティカルフローと変換前の両者の差分から判定する.

具体的には,以下の2つを組み合わせて行う.

f:id:yusuke_ujitoko:20170907003343p:plain