CycleGAN が敵対的ネットワーク画像処理ツールを生成

CycleGAN が敵対的ネットワーク画像処理ツールを生成

1. GANの紹介

「食べるために一生懸命働く人、食べるために一生懸命働く人こそが人々の中で最も優れている。」

このGAANのライスイーターは、そんなパサパサしたライスイーターではありません。この記事で説明する GAN は、Goodfellow2014 によって提案された生成的敵対モデル、つまり Generative Adversarial Nets です。では、GAN の何がそんなに不思議なのでしょうか?

画像分類、オブジェクト検出、セマンティックセグメンテーション、インスタンスセグメンテーションなどの従来のディープラーニングタスクでは、これらのタスクの結果は予測に帰属します。画像分類では単一のカテゴリが予測され、オブジェクト検出では bbox とカテゴリが予測され、セマンティック セグメンテーションまたはインスタンス セグメンテーションでは各ピクセルのカテゴリが予測されます。 GANは画像などの新しいものを生成します。

GAN の原理は一文で説明できます。

  • 敵対的アプローチを通じて、データ分布の生成モデルを学習します。 GAN は、データセットの分布をキャプチャして、ランダムノイズから同じ分布を持つデータを生成できる教師なしプロセ​​スです。

GANの構成: 識別モデルと生成モデル間の左手ゲーム

  • D 判別モデル: 真偽の境界を学習し、データが真か偽かを判断する
  • GGenerative Model: データ分布を学習し、データを生成する

GANの典型的な損失は次のとおりです(minmaxは対立を反映します)

2. 実践的なCycleGANスタイル転送

GANの役割がわかったところで、GANの魔法のような効果を体験してみましょう。ここでは、画像のスタイル変換を実現するために、cycleGAN を例に挙げます。いわゆるスタイル転送とは、元の画像のスタイルを変更することです。下の図に示すように、左側が元の画像、真ん中がスタイル画像(ゴッホの絵画)、生成された画像は右側がゴッホのスタイルを加えた元の画像です。生成された画像は全体として元の画像の内容をほとんど保持していることがわかります。

2.1 サイクルGANの紹介

CycleGAN は本質的に GAN と同じであり、データセット内の基礎となるデータ分布を学習します。 GAN はランダムノイズから同じ分布の画像を生成し、cycleGAN は学習した分布を意味のある画像に追加して別のフィールドから画像を生成します。 CycleGAN は、画像間の 2 つの領域の間に潜在的な接続があると想定します。

周知のとおり、GAN のマッピング機能では、生成された画像の有効性を保証することは困難です。 CycleGAN は、サイクルの一貫性を使用して、生成された画像と入力画像の構造の一貫性を確保します。 cycleGANの構造を見てみましょう。

特徴は以下のようにまとめられます。

  • 双方向 GAN: 2 つのジェネレーター [G:X->Y、F:Y->X] と 2 つの識別器 [Dx、Dy]。G と Dy はオブジェクトを生成することを目的としていますが、Dy (正のクラスは Y ドメイン) は識別できません。 F と Dx についても同様です。
  • 循環一貫性: G は Y を生成するジェネレータであり、F は X を生成するジェネレータです。循環一貫性とは、G と F によって生成されるオブジェクトの範囲を制約し、G によって生成されたオブジェクトをジェネレータ F を介して元のドメインに戻すことができるようにすることです。例: x->G(x)->F(G(x))=x

敵対的損失は次のとおりです。

2.2 サイクルGANの実装

2.2.1 ジェネレータ

上記の紹介から、ジェネレータには 2 つのジェネレータがあり、1 つは前進用、もう 1 つは後進用であることがわかります。この構造は、論文「リアルタイム スタイル転送と超解像度における知覚的損失: 補足資料」に基づいています。これは、次の図(論文より)に示すように、大まかに、ダウンサンプリング + 残差ブロック + アップサンプリングに分けられます。

アップサンプリングとダウンサンプリングの実装は、ストライド = 2 の畳み込みであり、アップサンプリングでは nn.Upsample を使用します。

  1. # 残余ブロック 
  2. クラス ResidualBlock(nn.Module):  
  3. def __init__(self, in_features):  
  4. super(ResidualBlock, self).__init__()  
  5. 自己ブロック= nn.シーケンシャル(  
  6. nn.ReflectionPad2d(1)、  
  7. nn.Conv2d(in_features, in_features, 3),  
  8. nn.InstanceNorm2d(in_features)、  
  9. nn.ReLU(インプレース= True )、  
  10. nn.ReflectionPad2d(1)、  
  11. nn.Conv2d(in_features, in_features, 3),  
  12. nn.InstanceNorm2d(in_features)、  
  13.  
  14. def forward(self, x):  
  15. x + self.block(x) を返す
  16. クラス GeneratorResNet(nn.Module):  
  17. def __init__(self, input_shape, num_residual_blocks):  
  18. super(GeneratorResNet、self).__init__()  
  19. チャンネル= input_shape [0]  
  20. # 初期畳み込みブロック 
  21. アウトフィーチャー= 64    
  22. モデル= [  
  23. nn.ReflectionPad2d(チャンネル)、  
  24. nn.Conv2d(チャンネル、out_features、7)、  
  25. nn.InstanceNorm2d(out_features)、  
  26. nn.ReLU(インプレース= True )、  
  27. ]  
  28. in_features = out_features    
  29. # ダウンサンプリング 
  30. _ が範囲内(2)の場合:  
  31. アウトフィーチャ *= 2  
  32. モデル += [  
  33. nn.Conv2d(in_features, out_features, 3,ストライド= 2 ,パディング= 1 ),  
  34. nn.InstanceNorm2d(out_features)、  
  35. nn.ReLU(インプレース= True )、  
  36. ]  
  37. in_features = out_features  
  38. # 残余ブロック 
  39. _ が範囲内(num_residual_blocks)の場合:  
  40. モデル += [ResidualBlock(out_features)]  
  41. # アップサンプリング 
  42. _ が範囲内(2)の場合:  
  43. 出力フィーチャ //= 2  
  44. モデル += [  
  45. nn.アップサンプル(スケール係数= 2 )、  
  46. nn.Conv2d(in_features, out_features, 3,ストライド= 1 ,パディング= 1 ),  
  47. nn.InstanceNorm2d(out_features)、  
  48. nn.ReLU(インプレース= True )、  
  49. ]  
  50. in_features = out_features    
  51. # 出力層 
  52. モデル += [nn.ReflectionPad2d(チャネル), nn.Conv2d(out_features, チャネル, 7), nn.Tanh()]  
  53. self.model = nn.Sequential (*モデル)  
  54. def forward(self, x):  
  55. self.model(x) を返す

2.2.2 識別器

従来のGAN識別子は、真偽の度合いを判定する値を出力します。 patchGAN の出力は N*N 値で、それぞれが元の画像上の特定のサイズの受容野を表します。直感的に言えば、元の画像上の切り抜きの下の繰り返し可能な領域の真正性を判定します。これは、pix2pix (条件付き敵対的ネットワークによる画像から画像への変換) で最初に提案された完全な畳み込みネットワークと考えることができます。利点はパラメータが少ないことであり、もう 1 つの利点は高周波情報をローカルでより適切にキャプチャできることです。

  1. クラス Discriminator(nn.Module):  
  2. def __init__(self, input_shape):  
  3. super(ディスクリミネータ、self).__init__()  
  4. チャンネル、高さ、= input_shape    
  5. # 画像識別器(PatchGAN)の出力形状を計算する 
  6. self.output_shape = (1, 高さ // 2 ** 4, 幅 // 2 ** 4)  
  7. def discriminator_block(in_filters, out_filters, normalize = True ):  
  8. """各識別ブロックのダウンサンプリング レイヤーを返します"""  
  9. レイヤー= [nn.Conv2d(in_filters, out_filters, 4,ストライド= 2 ,パディング= 1 )]  
  10. 正規化する場合:  
  11. レイヤーを追加します(nn.InstanceNorm2d(out_filters))  
  12. レイヤーを追加します(nn.LeakyReLU(0.2, inplace = True ))  
  13. リターンレイヤー 
  14. 自己.モデル= nn.シーケンシャル(  
  15. * discriminator_block(チャネル、64、正規化= False )、  
  16. *識別子ブロック(64, 128)、  
  17. *識別子ブロック(128, 256)、  
  18. *識別子ブロック(256, 512)、  
  19. nn.ZeroPad2d((1, 0, 1, 0))、
  20.   nn.Conv2d(512, 1, 4,パディング= 1 )  
  21.  
  22. def forward(self, img):  
  23. self.model(img) を返します。

2.2.3 トレーニング

損失とモデルの初期化

  1. # 損失 
  2. criterion_GAN = torch.nn.MSELoss ()  
  3. criterion_cycle = torch.nn.L1Loss () の 
  4. 基準_identity = torch.nn.L1Loss ()  
  5. cuda = torch.cuda.is_available () です 
  6. input_shape = (opt.channels、opt.img_height、opt.img_width) です。  
  7. # ジェネレータとディスクリミネータを初期化する 
  8. G_AB =ジェネレーターResNet (入力シェイプ、opt.n_residual_blocks)  
  9. G_BA =ジェネレーターResNet (入力シェイプ、opt.n_residual_blocks)  
  10. D_A =判別器(input_shape)  
  11. D_B =判別器(input_shape)

最適化とトレーニング戦略

  1. # オプティマイザー 
  2. オプティマイザー_G = torch.optim.Adam (  
  3. itertools.chain(G_AB.parameters(), G_BA.parameters()), lr = opt .lr, betas =(opt.b1, opt.b2)  
  4.  
  5. optimizer_D_A = torch.optim.Adam (D_A.parameters(), lr = opt.lr ベータ=(opt.b1, opt.b2))  
  6. optimizer_D_B = torch.optim.Adam (D_B.parameters(), lr = opt.lr ベータ=(opt.b1, opt.b2))  
  7. # 学習率更新スケジューラ 
  8. lr_scheduler_G = torch.optim.lr_scheduler.LambdaLR (  
  9. optimizer_G、 lr_lambda = LambdaLR (opt.n_epochs、opt.epoch、opt.decay_epoch).step  
  10.  
  11. lr_scheduler_D_A = torch.optim.lr_scheduler.LambdaLR (  
  12. optimizer_D_A、 lr_lambda = LambdaLR (opt.n_epochs、opt.epoch、opt.decay_epoch).step  
  13.  
  14. lr_scheduler_D_B = torch.optim.lr_scheduler.LambdaLR (  
  15. optimizer_D_B、 lr_lambda = LambdaLR (opt.n_epochs、opt.epoch、opt.decay_epoch).step  

トレーニングの反復

  • トレーニング データはペア データですが、ペアではないデータです。つまり、A と B には直接的な接続がありません。 Aはオリジナル画像、Bはスタイル画像
  • 発電機のトレーニング
    • GAN損失: 識別器は、AとBによって生成されたfake_A、fake_B、およびGTの損失を区別します。
    • サイクル損失: 逆に、fake_A と fake_B によって生成された画像は、A と B のピクセルとは異なります。
  • 識別器のトレーニング:
    • loss_real: A/B と GT を区別するための MSELoss
    • loss_fake: 生成された fake_A/fake_B を GT と区別するための MSELoss
  1. 範囲内のエポックの場合(opt.epoch、opt.n_epochs):  
  2. i の場合、enumerate(dataloader) でバッチ処理します。  
  3. # データはペアデータですが、ペアではないデータです。つまり、AとBは直接接続されていません。  
  4. real_A =変数(batch["A"].type(Tensor))  
  5. real_B =変数(batch["B"].type(Tensor))  
  6. # 敵対的グラウンドトゥルース 
  7. 有効=変数(Tensor(np.ones((real_A.size(0), *D_A.output_shape)))、 requires_grad = False )  
  8. fake =変数(Tensor(np.zeros((real_A.size(0), *D_A.output_shape))), requires_grad = False )  
  9. # ------------------  
  10. # 列車発電機 
  11. # ------------------  
  12. G_AB.train()  
  13. G_BA.train()  
  14. オプティマイザー_G.ゼロ_grad()  
  15. # アイデンティティの喪失 
  16. loss_id_A =基準の同一性(G_BA(real_A), real_A)  
  17. loss_id_B =基準の同一性(G_AB(real_B), real_B)  
  18. 損失ID = (損失ID_A + 損失ID_B) / 2  
  19. # GAN損失 
  20. 偽のB = G_AB (本物のA)  
  21. loss_GAN_AB = criterion_GAN (D_B(fake_B)、有効)  
  22. 偽のA = G_BA (本物のB)  
  23. loss_GAN_BA = criterion_GAN (D_A(fake_A)、有効)  
  24. 損失GAN = (損失GAN_AB + 損失GAN_BA) / 2
  25. # サイクル損失 
  26. recov_A = G_BA (偽のB)  
  27. 損失サイクルA =基準サイクル(回復A、実数A)  
  28. recov_B = G_AB (偽のA)  
  29. 損失サイクルB =基準サイクル(回復B、実数B)  
  30. 損失サイクル= (損失サイクルA + 損失サイクルB) / 2  
  31. # 全損 
  32. loss_G = loss_GAN + opt.lambda_cyc * loss_cycle + opt.lambda_id * loss_identity
  33. loss_G.後方()  
  34. オプティマイザ_G.ステップ()  
  35. # -----------------------  
  36. # 列車識別器 A  
  37. # -----------------------   
  38. オプティマイザー_D_A.ゼロ_勾配()  
  39. # 本当の損失 
  40. loss_real = criterion_GAN (D_A(real_A), 有効)  
  41. # 偽の損失(以前に生成されたサンプルのバッチ)  
  42. # fake_A_ = fake_A_buffer .push_and_pop(fake_A)  
  43. loss_fake = criterion_GAN (D_A(fake_A_.detach()), フェイク)  
  44. # 全損
  45. 損失_D_A = (損失_実数 + 損失_偽数) / 2
  46. loss_D_A.後方()  
  47. オプティマイザー_D_A.ステップ()  
  48. # -----------------------  
  49. # 列車識別器 B  
  50. # -----------------------  
  51. オプティマイザーD_B.ゼロ勾配()
  52. # 本当の損失 
  53. loss_real = criterion_GAN (D_B(real_B)、有効)  
  54. # 偽の損失(以前に生成されたサンプルのバッチ)  
  55. # fake_B_ = fake_B_buffer .push_and_pop(fake_B)  
  56. loss_fake = criterion_GAN (D_B(fake_B_.detach()), フェイク)  
  57. # 全損 
  58. 損失_D_B = (損失_実数 + 損失_偽数) / 2  
  59. loss_D_B.後方()
  60. オプティマイザー_D_B.ステップ()  
  61. 損失_D = (損失_D_A + 損失_D_B) / 2  
  62. # --------------  
  63. # ログの進行状況 
  64. # --------------  
  65. # 残り時間の目安を決定する 
  66. batches_done =エポック* len(データローダー) + i  
  67. batches_left = opt .n_epochs * len(データローダー) - batches_done  
  68. time_left = datetime.timedelta (= batches_left * (time.time() - prev_time))  
  69. prev_time = 時間.時間()  
  70. # 学習率を更新する 
  71. lr_scheduler_G.ステップ()  
  72. lr_scheduler_D_A.ステップ()  
  73. lr_scheduler_D_B.ステップ()

2.2.4 結果の表示

この記事では、次の図に示すように、モネスタイルの変換をトレーニングします。1行目と2行目はモネスタイルの絵画を通常の写真に変換したもので、3行目と4行目は通常の写真からモネスタイルの絵画に変換したものです。

実際の携帯電話の写真を見てみましょう:

2.2.5 cycleGANのその他の用途

3. 結論

この記事では、GAN の応用例の 1 つである cycleGAN を詳しく紹介し、それを画像のスタイル転送に適用します。要約すると:

  • GAN はデータ内の分布を学習し、同じ分布を持つ新しいデータを生成します。
  • CycleGAN は、2 つのジェネレーターと 2 つの識別器を備えた双方向 GAN です。ジェネレーターによって生成された画像が入力画像と特定の関係を持ち、ランダムに生成された画像ではないことを確認するために、サイクル一貫性が導入され、A->fake_B->recove_A と A の違いが判断されます。
  • ジェネレーター: ダウンサンプリング + 残差ブロック + アップサンプリング
  • 識別器:グラフから判定値を生成する代わりに、patchGAN方式ではN*Nの値を生成し、平均をとります。

<<:  機械学習のテストセットをスケールアップする方法

>>:  AIによる顔の変形がトレンドになり、人工知能の世界があなたの探索を待っています

ブログ    
ブログ    
ブログ    

推薦する

NTUは、3枚の画像のみを使用して高品質の3Dシーンを合成するSparseNeRFを提案しています。

ディープラーニングと 3D テクノロジーの発展により、Neural Radiance Fields ...

詳細 | ビッグデータアルゴリズムアプリケーションのテストの開発

[[389157]]この記事では、アリババ AI ミドルプラットフォームの技術品質システム、つまり検...

今後数年間の AI テクノロジーの分野で最も注目される新しい方向性は何でしょうか?

近年、AI の分野を調査しているうちに、世界中の研究者の視野の中に敵対的攻撃という概念が徐々に現れて...

...

人工知能を搭載したロボットは私たちの生活からどれくらい離れているのでしょうか?

産業用ロボットは幅広い用途でますます利用されるようになっているわが国は世界最大かつ最も活発な産業用ロ...

顔認識システムはすごいですね!チケット転売業者が体調を崩して入院、警戒を呼び起こす

最近、北京同仁病院の警報システムが作動し、職員は北京天壇病院で活動していたチケット転売業者が北京同仁...

ビッグデータに責任を負わせないでください。スモールデータをうまく活用する方が効果的かもしれません。

誰もがビッグ データについて語っていますが、大規模なデータ セットを処理するにはより多くのストレージ...

リアルタイムの犯罪警報: ディープラーニングで安全を守る方法

この記事は、公開アカウント「Reading the Core」(ID: AI_Discovery)か...

武器化されたAIとIoT攻撃は最大の技術的脅威となる

1. 「企業が人工知能やモノのインターネットなどの新しいテクノロジーの導入を検討するにつれ、攻撃対象...

信じられない! XiaoIceのデジタルツイン仮想人物は70日間ライブ放送されましたが、誰もそれが本物の人間ではないことに気づきませんでした

[[441368]]中国ビジネスニュースは70日間生放送されましたが、アンカーがデジタルツインの仮想...

人工知能の時代において、結核を根絶するまでにどれくらい時間がかかるのでしょうか?

結核は古代の呼吸器感染症として人類の歴史を通じて存在し、何億人もの命を奪い、「白ペスト」として知られ...

DeepMind、ロボットの物体積み重ね能力を向上させるための新たなベンチマークを提案

ほとんどの人にとって、あるオブジェクトを別のオブジェクトの上に重ねることは簡単な作業です。しかし、最...

機械学習を予知保全に適用するにはどうすればよいでしょうか?

機械学習と産業用 IoT (IIoT) デバイスから収集されたデータを組み合わせることで、プロセスの...

データセンターにおけるロボットの使用はどのように増加するのでしょうか?

[[407824]]調査によると、ロボットがデータセンターに導入されつつありますが、データセンター...

...