TensorFlowはディープラーニングに基づく画像補完を実装する

TensorFlowはディープラーニングに基づく画像補完を実装する

[[191845]]

目次

■ はじめに

■ ステップ1: 画像を確率分布のサンプルとして理解する

不足している情報をどのように入力すればよいですか?

しかし、どうやって数え始めればいいのでしょうか?これらはすべて画像です。

では、どうやって画像を完成させるのでしょうか?

■ ステップ2: 偽画像を素早く生成する

未知の確率分布の下で新しいサンプルを生成するための学習

[ML-Heavy] 生成的敵対的ネット (GAN) のアーキテクチャ

G(z)を使用して偽の画像を生成する

[ML-Heavy] DCGANのトレーニング

既存のGANおよびDCGANの実装

[ML-Heavy] Tensorflow で DCGAN を構築する

画像セットでDCGANを実行する

■ステップ3: 画像補完に最適な疑似画像を見つける

DCGANを使用した画像補完

[ML-Heavy] pgpgへの投影のための損失関数

[ML-Heavy] DCGAN 画像の補完に TensorFlow を使用する

画像を完成させる

■ 結論


導入

コンテンツに応じた塗りつぶしは、デザイナーや写真家が画像の不要な部分や欠けている部分を塗りつぶすために使用できる強力なツールです。画像の補完と修復は、画像の欠落部分や破損部分を補うための 2 つの密接に関連した手法です。コンテンツに応じた塗りつぶし、画像の補完、およびインペインティングを実装する方法は多数あります。このブログでは、RaymondYeh、Chen Chen らによる論文「Semantic Image Inpainting with Perceptual and ContextualLosses」を紹介します。この論文は2016年7月26日にarXivで公開され、画像補完にDCGANネットワークを使用する方法が紹介されました。このブログ投稿は、一般的な技術的背景を持つ読者を対象としており、一部のコンテンツでは機械学習の背景が必要になります。関連するセクションには [ML-Heavy] のタグを付けましたので、あまり詳細を読みたくない場合は、そのセクションをスキップできます。ここでは、顔画像の欠落部分を埋めるケースのみを取り上げます。ブログ投稿に関連する Tensorflow コードは、GitHub で公開されています: bamos/dcgan-completion.tensorflow。

画像の完成は3つのステップに分かれています。

  • まず、画像を確率分布のサンプルとして理解します。

  • この理解に基づいて、偽の画像を生成する方法を学びます。

  • 次に、埋め戻すのに最適な疑似画像を見つけます。

Photoshop を使用して画像の欠けている部分を補完し、Photoshop を使用して不要な部分を自動的に削除します。

画像の補完については後ほど紹介します。画像の中心は自動的に生成されます。ソースコードはここからダウンロードできます。

これらの画像は、LFW データセットからランダムに取得したサンプルです。

ステップ1: 画像を確率分布のサンプルとして理解する

1. 不足している情報をどのように入力しますか?

上記の例では、不足している部分を補うことができるシステムを構築していると想像してください。あなたならどうしますか?人間の脳はどうやってこれを実現すると思いますか?どのような情報を利用しましたか?

このブログ投稿では、次の 2 種類の情報に焦点を当てます。

コンテキスト情報: 周囲のピクセルから、欠落しているピクセルに関する情報を推測できます。

知覚情報: 実際の生活や他の写真で見たものなどの「通常の」情報を空欄に入力します。

どちらも重要です。文脈情報がなければ、どれを記入すればよいのかどうやってわかるのでしょうか?知覚情報がなければ、同じコンテキストを通じて無数の可能性が生み出される可能性があります。機械学習システムにとって「正常」に見える画像でも、人間にとっては正常に見えない場合があります。

前述の画像完成手順で述べた両方の特性を捉えることができる、正確で直感的なアルゴリズムがあれば素晴らしいでしょう。特定の状況では、そのようなアルゴリズムを構築することが可能です。しかし、一般的な方法はありません。現時点での最善の解決策は、統計と機械学習を使用して近似手法を得ることです。

2. しかし、統計の収集はどのように始めればよいのでしょうか?これらはすべて画像です。

思考を刺激するために、よく理解されていて簡潔な形式で記述できる確率分布、つまり正規分布から始めます。これは正規分布の確率密度関数 (PDF) です。 PDF は入力空間内で水平方向に移動しており、垂直軸は特定の値が発生する確率を表していると考えることができます。 (興味があれば、このグラフを生成したコードは bamos/dcgan-completion.tensorflow:simple-distributions.py からダウンロードできます。)

この分布からサンプリングすることで、いくつかのデータを取得できます。明確にする必要があるのは、PDF とサンプルの関係です。

正規分布からのサンプリング

PDF と 2D 画像のサンプル。 PDF は、サンプル ポイントが上部にプロットされた等高線プロットとして表示されます。

入力は 1 つの次元に沿ってのみ可能であるため、これは 1D 分布です。同じことは 2 次元でも実行できます。

画像と統計の間の重要なつながりは、画像を高次元の確率分布からのサンプルとして見ることができることです。確率分布は画像のピクセルに対応します。カメラで写真を撮っているところを想像してください。結果の画像は有限の数のピクセルで構成されます。カメラで写真を撮るときは、この複雑な確率分布からサンプリングしていることになります。この確率分布によって、画像が正常であるか異常であるかが判断されます。画像の場合、正規分布とは異なり、真の確率分布を知ることはできず、サンプルを収集することしかできません。

この記事では、RGB カラーで表されるカラー画像を使用します。画像の幅は 64 ピクセル、高さは 64 ピクセルなので、確率分布は 64⋅64⋅3≈12k 次元になります。

3. では、画像を完成させるにはどうすればよいでしょうか?

まず、インスピレーションを得るために多変量正規分布を考えてみましょう。 x=1 の場合、y の最も可能性の高い値は何でしょうか? x の値を固定し、PDF を最大化する y を見つけることができます。

多次元正規分布において、xが与えられたとき、yの最大値を求める

この概念は、画像の確率分布に自然に拡張できます。いくつかの値はわかっており、欠落している値を入力したいと考えています。これは単純に最大化問題として理解できます。可能性のあるすべての欠損値を検索し、最も確率の高い画像が補完に使用されます。

正規分布のサンプルからは、サンプリングするだけで PDF を取得できます。好きな統計モデルを選択して、データに適合させるだけです。

ただし、実際にはこのアプローチは使用しません。シンプルな配布の場合、PDF は簡単に見つかります。しかし、より複雑な画像分布の場合、処理が非常に困難になります。この複雑さの理由の一部は、複雑な条件依存関係です。つまり、1 つのピクセルの値は、画像内の他のピクセルの値に依存します。さらに、一般的な PDF を最大化することは、非常に困難で解決困難な非凸最適化問題です。

ステップ2: 偽の画像を素早く生成する

1. 未知の確率分布の下で新しいサンプルを生成することを学ぶ

PDF を計算する方法を学ぶことに加え、統計学で確立されたもう 1 つの考え方は、生成モデルを使用して新しい (ランダムな) サンプルを生成する方法を学ぶことです。生成モデルのトレーニングと処理は一般的に困難ですが、ディープラーニング コミュニティはこの分野で驚くべき進歩を遂げました。 Yann LeCun 氏は、この Quora の回答で、生成モデルのトレーニング方法について興味深い議論を展開し、これを過去 10 年間の機械学習における最も興味深いアイデアと呼んでいます。

ヤン・ルカンによる生成的敵対ネットワークの紹介

[[191848]]

生成的敵対ネットワークをアーケード ゲームと比較します。 2つのネットワークは互いに競争しながら、共に進歩していきます。まるでゲームで戦う二人の人間のように

変分オートエンコーダ (VAE) などの他のディープラーニング手法も、生成モデルのトレーニングに使用できます。このブログ投稿では、Generative Adversarial Nets (GAN) を使用します。

2. [ML重視] 生成的敵対的ネット (GAN) アーキテクチャ

このアイデアは、2014 年の Neural Information Processing Systems (NIPS) ワークショップで発表された画期的な論文「Generative Adversarial Nets (GANs)」で Ian Goodfellow らによって提案されました。主なアイデアは、pzpz で表される、単純で一般的に使用される分布を定義することです。以下では、pzpz を使用して、-1 から 1 までの閉区間上の均一分布を表します。分布からのサンプルをz∼pzz∼pzと表します。 pzpz が 5 次元の場合、1 行の Python NumPy コードでサンプリングできます。

  1. z = np.random.uniform(- 1 , 1 , 5 )
  2. 配列([ 0.77356483 , 0.95258473 , - 0.18345086 , 0.69224724 , - 0.34718733 ])

サンプルを採取するための単純な分布ができたので、元の確率分布からサンプルを採取するための関数 G(z) を定義します。

  1. G(z)の定義:
  2. ...
  3. 画像サンプルを返す
  4. z = np.random.uniform(- 1 , 1 , 5 )
  5. 画像サンプル =G(z)

では、ベクトルを入力して画像を出力するように G(z) をどのように定義するのでしょうか?ディープニューラルネットワークを使用します。ニューラル ネットワークの基礎に関するチュートリアルはたくさんあるので、ここでは説明しません。優れた参考資料としては、スタンフォード大学の CS231n コース、Ian Goodfellow らのディープラーニング ブック、「Image Kernels Explained Visually」、畳み込み演算ガイドなどがあります。

ディープラーニングベースの G(z) を構築する方法は多数あります。オリジナルの GAN 論文では、アイデア、トレーニング手順、およびいくつかの予備的な実験結果が提示されました。このアイデアは大幅に拡張され、その 1 つのアイデアは、2016 年の国際表現学習会議 (ICLR、「アイクリア」と発音) で発表された、Alec Radford、Luke Metz、および Soumith Chintala による論文「Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks」で提案されました。この論文では、マイクロストライド畳み込みを使用して画像をアップサンプリングする Deep Convolutional GAN (DCGAN と呼ばれる) を提案しています。

では、マイクロストライド畳み込みとは何でしょうか。また、どのようにして画像をアップサンプリングするのでしょうか。 VincentDumoulin と Francesco Visin の論文「ディープラーニングのための畳み込み演算ガイド」と畳み込み演算プロジェクトは、ディープラーニングにおける畳み込み演算の非常に優れた入門書です。イラストは素晴らしく、マイクロストライド畳み込みがどのように機能するかを直感的に理解できます。まず、一般的な畳み込みがカーネルを入力空間 (青) にスライドさせ、出力空間 (緑) を生成する仕組みを理解していることを確認してください。ここでは、出力は入力よりも小さくなります。 (理解できない場合は、CS231n CNN セクションまたは畳み込み演算ガイドを参照してください。)

畳み込み演算の図。青が入力、緑が出力です。

次に、3X3 入力があるとします。私たちの目標は、より大きな出力が得られるようにアップサンプリングすることです。マイクロストライド畳み込みは、入力画像を拡大し、ピクセル間にゼロを挿入するものと考えることができます。次に、この拡大された画像に対して畳み込み演算を実行し、より大きな出力を取得します。ここで、出力は 5X5 です。

マイクロステップ畳み込み演算の図。青が入力、緑が出力です。

補足: アップサンプリングを実行する畳み込み層には、フル畳み込み、ネットワーク内アップサンプリング、分数ストライド畳み込み、後方畳み込み、逆畳み込み、アップ畳み込み、転置畳み込みなど、さまざまな名前があります。 「デコンボリューション」という用語はすでに他の文脈で使用されているため、使用しないことを強くお勧めします。特定の数学演算やコンピューター ビジョンの他のアプリケーションでは、この用語はまったく異なる意味を持ちます。

マイクロストライド畳み込み構造ができたので、ベクトルz∼pzz∼pzを入力として受け取り、64x64x3のRGB画像を出力するG(z)の表現を得ることができます。

DCGAN を使用したジェネレーターの構築方法。 DCGAN論文からの画像

DCGAN の論文では、バッチ正規化やリーキー RELU など、DCGAN をトレーニングする際の他の手法や調整も提案されています。

3. G(z)を使用して偽の画像を生成する

ちょっと立ち止まって、G(z) がいかに強力であるかを実感してみましょう。 DCGAN の論文では、寝室のデータセットでトレーニングした後の DCGAN の様子が示されています。すると、G(z) は次の疑似画像を生成します。これは、ジェネレータが寝室がどのように見えると考えているかを示しています。以下の写真は元のデータセットには含まれていません。

あるいは、入力空間 z に対して代数演算を実行することもできます。以下は顔を生成するネットワークです

DCGAN に基づく顔代数演算に関する DCGAN 論文

4. [ML-Heavy] DCGANのトレーニング

これで、G(z) を定義し、それがいかに強力であるかを確認しました。それで、どうやって訓練するのでしょうか?見つける必要のある未知の変数 (パラメータ) が多数あります。この時点で、敵対的ネットワークを使用する必要があります。

まず、いくつかのシンボルを定義する必要があります。データ (未知) の確率分布は pdatapdata で表されます。するとG(z)(ただしz∼pzz∼pz)は確率分布からのサンプリングとして理解できる。この確率分布をpgpgと表記します。

シンボル pzpdatapg は、単純で既知の z の確率分布を意味します。画像 (未知) の確率分布は、画像データ サンプルのソースです。ジェネレータ G は、確率分布をサンプリングするために使用されます。pg==pdata であることを期待します。シンボル pzz は、単純で既知の pzz の確率分布を意味します。画像 (未知) の確率分布は、画像データ サンプルのソースです。ジェネレータ G は、確率分布をサンプリングするために使用されます。pg==pdata であることを期待します。

識別器ネットワークD(x)は画像xを入力として受け取り、画像xがpdatapdataの分布からサンプリングされる確率を返します。理論的には、入力画像が pdatapdata からサンプリングされた場合、識別器は 1 に近い値を出力し、入力画像が pgpg からサンプリングされた画像などの疑似画像の場合、識別器は 0 に近い値を出力します。 DCGAN では、D(x) は従来の畳み込みニューラル ネットワークです。

識別器畳み込みニューラルネットワーク、画像復元論文からの画像

識別器をトレーニングする目標は次のとおりです。

1. 真のデータ分布x∼pdatax∼pdataの各画像について、D(x)を最大化します。

2. 真のデータ分布x≁pdatax≁pdataに含まれない各画像について、D(x)を最小化します。

ジェネレータG(z)のトレーニング目標は、Dを混乱させる可能性のあるサンプルを生成することです。出力は、識別器への入力として使用できる画像です。したがって、ジェネレーターは D(G(z)) を最大化すること、つまり (1-D(G(z))) を最小化することを目指します。これは、D が 0 から 1 までの値を持つ確率であるためです。

この論文では、敵対的ネットワークを以下の最小および最大戦略を通じて実装することを提案しています。最初の項の数学的期待値は真のデータ分布を横断し、2番目の項の数学的期待値はpzpz内のサンプルを横断します。つまり、G(z)∼pgG(z)∼pgを横断します。

  1. 最小GmaxDEx∼pdatalog(D(x)+Ez∼pz[log( 1 −D(G(z)))]最小GmaxDEx∼pdatalog(D(x)+Ez∼pz[log( 1 −D(G(z)))]

この式の勾配を D と G のパラメータに関して取ることで、それらをトレーニングすることができます。この式の各部分を素早く評価する方法がわかっています。数学的期待値はサイズ m の小さなデータ バッチによって推定でき、内部最大化は k ステップの勾配によって推定できます。トレーニングには k=1 がより適した値であることが示されています。

識別器のパラメータを表すためにθdθdを使用し、生成器のパラメータを表すためにθgθgを使用します。 D と G は両方とも本格的なニューラル ネットワーク モジュールで構成されているため、θdθd と θgθg に関する損失の勾配はバックプロパゲーションによって計算できます。以下は、GAN 論文のトレーニング戦略です。理論的には、トレーニング後、pg==pdatapg==pdata になります。したがって、G(z)はpdatapdata分布に従うサンプルを生成できます。

GAN 論文からのトレーニング アルゴリズム。

5. 既存のGANとDCGANの実装

  • Github では、素晴らしい GAN および DCGAN の実装を多数見ることができます。
  • goodfeli/adversarial: GAN 論文の著者によって書かれた Theano GAN 実装。
  • tqchen/mxnet-gan: 非公式の MXNet GAN 実装。
  • Newmu/dcgan_code: DCGAN 論文の著者によって書かれた Theano GAN 実装。
  • soumith/dcgan.torch: DCGAN 論文著者の 1 人 (Soumith Chintala) による Torch DCGAN 実装。
  • carpedm20/DCGAN-tensorflow: 非公式の TensorFlow DCGAN 実装。
  • openai/improved-gan: OpenAI の最初の論文の背後にあるコード。 carpedm20/DCGAN-tensorflow をベースに多くの変更が加えられました。
  • mattya/chainer-DCGAN: 非公式の Chainer DCGAN 実装。
  • jacobgil/keras-dcgan: 非公式 (未完成) KerasDCGAN 実装。

carpedm20/DCGAN-tensorflow をベースにモデルを構築します。

6.[ML-Heavy] Tensorflow 上での DCGAN の構築

この部分の実装は、私の bamos/dcgan-completion.tensorflow Github リポジトリにあります。この部分のコードは Taehoon Kim による carpedm20/DCGAN-tensorflow からのものであることを強調する必要があります。これを自分のライブラリで使用して、画像完成の次の部分で使用できるようにします。

実装コードのほとんどは、model.py の Python クラス DCGAN にあります。すべてを 1 つのクラスにまとめると、トレーニング後に中間プロセスを保存し、後で使用するために読み込むことができるため、多くの利点があります。

まず、ジェネレータとディスクリミネータの構造を定義します。 linear、conv2d_transpose、conv2d、および lrelu 関数は ops.py で定義されています。

  1. defgenerator(自己, z):
  2. self .z_、 self .h0_w、 self .h0_b = linear(z、 self .gf_dim* 8 * 4 * 4'g_h0_lin' 、with_w= True )
  3. self .h0 = tf.reshape( self .z_, [- 1 , 4 , 4 , self .gf_dim * 8 ])
  4. h0 = tf.nn.relu(自己.g_bn0(自己.h0))
  5. 自己.h1、自己.h1_w、自己.h1_b =conv2d_transpose(h0、
  6. [ self .batch_size, 8 , 8 , self .gf_dim* 4 ],name= 'g_h1' , with_w= True )
  7. h1 = tf.nn.relu(自己.g_bn1(自己.h1))
  8. h2,自己.h2_w,自己.h2_b =conv2d_transpose(h1,
  9. [ self .batch_size, 16 , 16 , self .gf_dim* 2 ], name= 'g_h2' , with_w= True )
  10. h2 = tf.nn.relu(自己.g_bn2(h2))
  11. h3,自己.h3_w,自己.h3_b =conv2d_transpose(h2,
  12. [ self .batch_size, 32 , 32 , self .gf_dim* 1 ], name= 'g_h3' , with_w= True )
  13. h3 = tf.nn.relu(自己.g_bn3(h3))
  14. h4,自己.h4_w,自己.h4_b =conv2d_transpose(h3,
  15. [ self .batch_size, 64 , 64 , 3 ],name= 'g_h4' , with_w= True )
  16. tf.nn.tanh(h4)を返す
  17. defdiscriminator(自己、 イメージ 、 再利用 = False ):
  18. 再利用する場合:
  19. tf.get_variable_scope().reuse_variables()
  20. h0 = lrelu(conv2d(画像、 self .df_dim、名前 = 'd_h0_conv' ))
  21. h1 = lrelu( self .d_bn1(conv2d(h0, self .df_dim* 2 , 名前 = 'd_h1_conv' )))
  22. h2 = lrelu( self .d_bn2(conv2d(h1, self .df_dim* 4 , 名前 = 'd_h2_conv' )))
  23. h3 = lrelu( self .d_bn3(conv2d(h2, self .df_dim* 8 , 名前 = 'd_h3_conv' )))
  24. h4 = linear(tf.reshape(h3, [- 1 , 8192 ]), 1 , 'd_h3_lin' )
  25. tf.nn.sigmoid(h4)、h4を返す

このクラスを初期化するときに、これら 2 つの関数を使用してモデルを構築します。パラメータを共有(再利用)する 2 つの識別子が必要です。 1 つはデータ分布からの画像のミニバッチ用で、もう 1 つはジェネレータによって生成された画像のミニバッチ用です。

  1. 自己.G =自己.ジェネレータ(自己.z)
  2. self .D、 self .D_logits = self .discriminator( self .images)
  3. self .D_、 self .D_logits_ = self .discriminator( self .G、reuse= True )

次に、損失関数を定義します。合計する代わりに、より実用的なため、D の予測値と実際の値の間のクロスエントロピーを使用します。識別器は、すべての「実際の」データに対して 1 を予測し、ジェネレータによって生成されたすべての「偽の」データに対して 0 を予測します。ジェネレーターは、識別器が両方に対して 1 を予測することを望んでいます。

  1. 自己.d_loss_real = tf.reduce_mean(
  2. tf.nn.sigmoid_cross_entropy_with_logits(自己.D_logits,
  3. tf.ones_like(自分.D)))
  4. 自己.d_loss_fake = tf.reduce_mean(
  5. tf.nn.sigmoid_cross_entropy_with_logits(自己.D_logits_,
  6. tf.zeros_like(自分.D_)))
  7. 自己.g_loss = tf.reduce_mean(
  8. tf.nn.sigmoid_cross_entropy_with_logits(自己.D_logits_,
  9. tf.ones_like(自分.D_)))
  10. 自己.d_loss =自己.d_loss_real +自己.d_loss_fake

各モデルの変数を集約して、個別にトレーニングできるようにします。

  1. t_vars = tf.trainable_variables()
  2. self .d_vars = [var for var in t_vars if 'd_' in var.name]
  3. self .g_vars = [var for var in t_vars if 'g_' in var.name]

ここで、ADAM 最適化を使用してパラメータの最適化を開始します。これは、SGD と非常に競争力のある適応型非凸最適化手法であり、通常、学習率、運動量、およびその他のハイパーパラメータの手動調整を必要としません。

  1. d_optim = tf.train.AdamOptimizer(config.learning_rate, beta1=config.beta1) \
  2. .minimize(自己.d_loss, var_list=自己.d_vars)
  3. g_optim = tf.train.AdamOptimizer(config.learning_rate, beta1=config.beta1) \
  4. .minimize(自己.g_loss, var_list=自己.g_vars)

次に、データを反復処理します。各反復で、データのミニバッチをサンプリングし、オプティマイザーを使用してネットワークを更新します。興味深いことに、G が 1 回だけ更新された場合、識別器の損失は 0 になりません。また、これらの値はすでに d_optim と g_optim で計算されているため、d_loss_fake と d_loss_real への最後の呼び出しでは不要な計算が実行されると思います。 Tensorflow の連絡先として、この部分を最適化し、元のリポジトリに PR を送信してみてください。

  1. エポック inxrange(config.epoch)の場合:
  2. ...
  3. xrange( 0 , batch_idxs )内のidxの場合:
  4. batch_images = ...
  5. batch_z = np.random.uniform(- 1 , 1 ,[config.batch_size, self .z_dim]) \
  6. .astype(np.float32)
  7. # Dネットワークを更新
  8. _, summary_str = self .sess.run([d_optim, self .d_sum],
  9. feed_dict={ self .images:batch_images, self .z:batch_z })
  10. # Gネットワ​​ークを更新
  11. _, summary_str = self .sess.run([g_optim, self .g_sum],
  12. feed_dict={ self .z: batch_z })
  13. # g_optim を 2 回実行して、d_loss がゼロにならないことを確認します (論文とは異なります)
  14. _, summary_str = self .sess.run([g_optim, self .g_sum],
  15. feed_dict={ self .z: batch_z })
  16. errD_fake = self .d_loss_fake.eval({ self .z: batch_z})
  17. errD_real = self .d_loss_real.eval({ self .images: batch_images})
  18. errG = self .g_loss.eval({ self .z:batch_z})

終わり!もちろん、完全なコードにはさらに多くのコメントが含まれ、model.py で表示できます。

7. 画像セットに対してDCGANを実行する

前のセクションをスキップしたが、コードを試してみたい場合は、bamos/dcgan-completion.tensorflow Github リポジトリで入手できます。このコードは Taehoon Kim による carpedm20/DCGAN-tensorflow からのものであることを再度強調しておきます。次のステップに進む方が便利なので、ここでは私のライブラリを使用します。警告: CUDA 対応の GPU がない場合、ネットワークのこの部分のトレーニングは非常に遅くなります。

まず、私の bamos/dcgan-completion.tensorflow Github リポジトリをクローンし、OpenFace をローカルにクローンします。 OpenFace の Python のみの部分を使用して、画像の前処理を実行します。心配しないでください。OpenFace の Torch 依存関係をインストールする必要はありません。新しいディレクトリを作成し、次のリポジトリをクローンします。

  1. git クローンhttps://github.com/cmusatyalab/openface.git
  2. git クローンhttps://github.com/bamos/dcgan-completion.tensorflow.git

次に、Python2 をサポートする OpenCV と dlib をインストールします。興味があれば、python3 の dlib サポートを実装してみてください。インストールにはいくつかヒントがあり、OpenFace セットアップ ガイドに、インストールしたバージョンやインストール方法などのメモをいくつか書きました。次に、画像を前処理できるように OpenFace Python ライブラリをインストールします。仮想環境を使用していない場合は、setup.py を実行してグローバルにインストールするときに sudo を使用する必要があります。 (この部分が難しい場合は、OpenFace の Docker インストールを使用することもできます。)

顔画像データセットをダウンロードしましょう。データセットに注釈があるかどうかは関係なく、削除されます。網羅的ではないリストは次のとおりです: MS-Celeb-1M、CelebA、CASIA-WebFace、FaceScrub、LFW、MegaFace。データセットの生データであることを示すために、画像を dcgan-completion.tensorflow/data/your-dataset/raw ディレクトリに配置します。

ここで、OpenFace の位置合わせツールを使用して、画像を 64X64 データに前処理します。

  1. ./openface/util/align-dlib.pydata/dcgan-completion.tensorflow/data/your-dataset/raw aligninnerEyesAndBottomLipdata/dcgan-completion.tensorflow/data/your-dataset/aligned --size 64

最後に、処理された画像のディレクトリをフラット化して、サブフォルダのないディレクトリ内に画像のみが含まれるようにします。

  1. cddcgan-completion.tensorflow/data/your-dataset/aligned
  2. find . -name '*.png' - exec mv {} . \;
  3. 検索 . -type d-empty -delete
  4. CD ../../..

これで DCGAN をトレーニングできます。 Tensorflow をインストールしてトレーニングを開始します。

  1. ./train-dcgan.py --dataset ./data/your-dataset/aligned --epoch 20

ジェネレータからランダムにサンプリングされたサンプル画像がサンプル フォルダーでどのように見えるかを確認できます。手元にあった CASIA-WebFace データセットと FaceScrub データセットでトレーニングしました。 14 ラウンドのトレーニング後、サンプルは次のようになりました。

CASIA-WebFace と FaceScrub で 14 エポックのトレーニングを行った後の DCGAN のサンプル

TensorBoard で Tensorflow グラフと損失関数を表示することもできます。

  1. テンソルボード --logdir ./logs

TensorBoard 損失の視覚化。トレーニング中にリアルタイムで更新されます。

DCGAN ネットワークの TensorBoard 可視化

ステップ3: 画像補完に最適な疑似画像を見つける

1. 画像補完にDCGANを使用する

判別器 D(x) と生成器 G(z) ができたので、これを画像完成にどのように使用すればよいでしょうか?この章では、RaymondYeh、Chen Chen らによる論文「知覚的損失と文脈的損失によるセマンティック画像インペインティング」を紹介します。この論文は2016年7月26日にarXivに掲載されました。

特定の画像 y の場合、欠落しているピクセルの D(y) を最大化することが合理的だが実現不可能な解決策です。結果は、データ分布 (pdatapdata) でも生成された分布 (pgpg) でもありません。私たちが望むのは、y を生成分布に投影することです。

(a): 生成された分布(青い表面)からの y の理想的な再構築。 (b): D(y)を最大化してyを再構築しようとして失敗した例。イメージ修復紙からの画像

2.[ML-Heavy] pgpgへの投影の損失関数

投影の適切な定義を与えるために、まず画像補完のためのいくつかの表記法を定義します。 0 と 1 の 2 つの値のみを持つバイナリ マスク M (マスク) を使用します。値が 1 の場合、画像のこの部分を保持することを示し、値が 0 の場合、この部分を完了することを示します。ここで、バイナリマスク M が与えられた場合に y を完了する方法を定義できます。 y の要素を M の要素で乗算します。 2 つの行列の対応する要素の乗算は、アダマール積とも呼ばれ、M⊙yM⊙y で表されます。 M⊙yM⊙yは画像の元部分を表します。

バイナリマスクの凡例

次に、欠損値を再構築する適切な G(z^)G(z^) を生成できる z^z^ を見つけたと仮定します。補完されたピクセル(1−M)⊙G(z^)(1−M)⊙G(z^)を元のピクセルに追加して再構成された画像を得ることができます。

  1. x再構成=M⊙y+( 1 −M)⊙G(z^)x再構成=M⊙y+( 1 −M)⊙G(z^)

ここで私たちがしなければならないことは、画像を完成させるのに適した G(z^)G(z^) を見つけることです。 z^z^ を見つけるために、この記事の冒頭で述べたコンテキストと認識を思い出し、それらを DCGAN のコンテキストとして使用します。この目的のために、任意のz∼pzz∼pzに対して損失関数を定義します。損失関数が小さいほど、z^z^ は適切になります。

コンテキスト損失: 入力画像と同じコンテキストを取得するには、既知のピクセル位置 y に対応する G(z)G(z) が可能な限り類似していることを確認する必要があります。したがって、G(z) の出力が y の既知の位置の画像と類似していない場合、G(z) にペナルティを課す必要があります。これを行うには、y の対応する位置にあるピクセルを G(z) から減算し、非類似度を取得します。

  1. L文脈(z)=||M⊙G(z)−M⊙y||L文脈(z)=||M⊙G(z)−M⊙y||

ここで、||x||1=∑i|xi|||x||1=∑i|xi| はベクトル x の l1l1 ノルムです。 l2l2 規範も望ましいですが、この論文では、実践では l1l1 規範の方が効果的であることが示されていると指摘しています。

理想的には、既知の部分 y と G(z) のピクセルは等しくなります。つまり、既知の位置にあるピクセルiに対して、||M⊙G(z)i−M⊙yi||=0||M⊙G(z)i−M⊙yi||=0 、Lcontextual(z)=0Lcontextual(z)=0 となります。

知覚損失: 本物に見える画像を再構築するには、識別器が画像が本物に見えると判断できるようにする必要があります。これを行うには、DCGAN のトレーニングと同じ手順に従います。

  1. L知覚的(z)=log( 1 −D(G(z)))L知覚的(z)=log( 1 −D(G(z)))

最後に、文脈的損失と知覚的損失を組み合わせることで、z^z^; を見つけることができます。

  1. L(z)=L文脈(z)+λL知覚(z)z^=argminzL(z)L(z)=L文脈(z)+λL知覚(z)z^=arg⁡minzL(z)

ここで、λλ は、知覚損失と比較して文脈損失がどの程度重要であるかを制御するハイパーパラメータです。 (私はデフォルトの λ=0.1λ=0.1 を使用し、この値を詳細に調整しませんでした。) 次に、G(z) を使用して、以前と同じように y の欠落部分を再構築します。

  1. L文脈(z)=||M⊙G(z)−M⊙y||L文脈(z)=||M⊙G(z)−M⊙y||

この画像では、ポアソンブレンディングを使用して画像を滑らかにしています。

3.[ML-Heavy] TensorFlow を使った DCGAN 画像補完

この章では、画像補完のための Taehoon Kim の carpedm20/DCGAN-tensorflow コードに対する私の変更点について説明します。

  1. self .mask = tf.placeholder(tf.float32, [ None ] + self .image_shape, name= 'mask' )

勾配∇zL(z)∇zL(z)に対して勾配降下法を実行することで、argminzL(z)arg⁡minzL(z)を反復的に見つけることができます。損失関数を定義したので、Tensorflow の自動微分によってこの値が自動的に計算されます。したがって、既存の DCGAN 実装に 4 行の Tensorflow コードを追加することで、完全な DCGAN ベースの実装を実現できます。 (もちろん、これを実装するには Tensorflow 以外のコードも必要です。)

  1. 自己.contextual_loss = tf.reduce_sum(
  2. tf.contrib.layers.flatten() は、
  3. tf.abs(tf.mul( self .mask, self .G) -tf.mul( self .mask, self .images))), 1 )
  4. 自己.知覚損失 =自己.g_loss
  5. 自己.完全損失 =自己.文脈損失 +自己.lam *自己.知覚損失
  6. 自己.grad_complete_loss = tf.gradients(自己.complete_loss,自己.z)

次に、マスクを定義します。画像の中央領域に 1 つ追加しましたが、ランダム マスクなど、他のものを追加して、プル リクエストを送信することもできます。

  1. ifconfig.maskType == 'center' :
  2. スケール = 0.25
  3. アサート(スケール <= 0.5
  4. マスク = np.ones(自己.image_shape)
  5. l = int(自己.image_size*scale)
  6. u = int(自己.image_size * ( 1.0 -scale ))
  7. マスク[l:u, l:u, :] = 0.0

勾配降下法では、zを[-1, 1]に投影するために、運動量を使用したミニバッチ投影勾配降下法を使用します。

  1. idx inxrange( 0 , batch_idxs )の場合:
  2. batch_images = ...
  3. batch_mask = np.resize(mask,[ self .batch_size] + self .image_shape)
  4. zhats = np.random.uniform(- 1 , 1 ,size=( self .batch_size, self .z_dim))
  5. 0 = 0です
  6. xrange(config.nIter)内のiの場合:
  7. fd = {
  8. 自己.z: zhats、
  9. 自己.mask: batch_mask,
  10. 自己.images: batch_images、
  11. }
  12. 実行 = [ self .complete_loss, self .grad_complete_loss, self .G]
  13. 損失、g、G_imgs = self .sess.run(run、feed_dict=fd)
  14. v_prev = np.copy(v)
  15. v = config.momentum*v - config.lr*g[ 0 ]
  16. zhats += -config.momentum * v_prev +( 1 +config.momentum)*v
  17. zhats = np.clip(zhats, - 1 , 1 )

4. 画像を完成させる

画像補完用にいくつかの画像を選択し、 dcgan-completion.tensorflow/your-test-data/raw に配置します。次に、dcgan-completion.tensorflow/your-test-data/aligned で前と同じように整列させます。ここではLFWからランダムにいくつかの画像を選びました。私の DCGAN は LFW 画像を使用してトレーニングされていません。

次のようにして画像を完成させることができます。

  1. ./complete.py ./data/your-test-data/aligned/* --outDir 出力画像

このコードは画像を生成し、定期的に --outDir フォルダーに出力します。 ImageMagick を使用して gif を生成できます。

  1. cd 出力画像
  2. 変換 -delay10 -loop 0完了/*.png 完了.gif

最終イメージ完成。画像の中心は自動的に生成されます。ソースコードはここからダウンロードできます。これはLFWからランダムに選んだサンプルです

結論は

読んでくれてありがとう、これで終わりです!この記事では、画像補完の方法について説明しました。

1. 画像を確率の分布として理解する。

2. 偽の画像を生成します。

3. 完成に最適な疑似画像を見つけます。

私の例は顔でしたが、DCGAN は他の種類の画像にも使用できます。一般的に、GAN のトレーニングは難しく、特定のクラスのオブジェクトでどのようにトレーニングするか、または大きな画像でどのようにトレーニングするかは明確ではありません。しかし、これは大きな可能性を秘めたモデルであり、将来 GAN が何を生み出してくれるのか楽しみです。

<<:  大規模機械学習のためのプログラミング手法、計算モデル、Xgboost および MXNet の事例

>>:  AWS 上でディープラーニングホストを構築する (Windows 版)

ブログ    
ブログ    

推薦する

...

...

...

ドローンによる空中撮影は野生の人々に迷惑をかけている、問題解決の鍵はここにある

[[416193]]近年、民間ドローンの急速な発展に伴い、航空写真撮影市場におけるドローンの応用はま...

word2vecの作者はイリヤらとの10年間の恨みを明かした。seq2seqも私のアイデアだった

画期的な論文word2vec は、当然の NeurIPS Test of Time Award を受...

Google の AI 覇権を解決する別の方法は?開発プラットフォームのエコシステム包囲

編集者注:この記事はWeChatパブリックアカウント「脑极体」(ID:unity007)からのもので...

機械学習の次元削減手法で「次元の呪い」を打破する

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

クラウド、持続可能性、デジタル導入 - 2022 年のアジア太平洋地域の技術予測

フォレスターのアジア太平洋地域における 2022 年の予測によると、地域特有の圧力により、どこからで...

人工知能の台頭によりプログラマーは消滅するのでしょうか?

ローコードおよびノー​​コード プラットフォームの爆発的な成長により、個人でも組織でも、従来はコード...

...

...

スマートテクノロジーは高齢化問題の解決に役立つでしょうか?

世界保健機関によれば、2050年までに世界中で約20億人が60歳以上になると予想されています。これら...

マスク氏はOpenAIを訴えた。彼らはAGIを作成し、それをマイクロソフトにライセンス供与したが、これは設立協定に対する露骨な裏切りである。

つい先日、「劇的な対立に耽溺する」マスク氏は新たな行動を起こした。共同設立者の一人であるOpenAI...

GPT-4の予測の新たな波は、大きすぎず密度も高くないテキストのみのモデルに向けて到来している。

2020年5月、GPT-3はGPT-2の1年後に正式にリリースされました。GPT-2も、オリジナル...