質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

1485閲覧

DCGANによる半教師あり学習の実装

kentaro189

総合スコア0

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/12/25 06:13

編集2020/12/26 05:31

前提・実現したいこと

GANを使用した半教師あり学習により、MNITSの教師あり画像を100枚使用しただけで精度90%の汎化性能を達成するべく、コード作成に取り組んでおります。

発生している問題・エラーメッセージ

一方、実際の精度は60-70%程度で向上せず、何が原因なのか頭を悩ませております。
過学習が発生している可能性があるため、とりあえず画像の水増しなども実装してみたのですが、やはり汎化精度が向上しません。
もし何かわかる方がいらっしゃいましたらアドバイス頂けると大変助かります。

該当のソースコード

Python

1import matplotlib.pyplot as plt 2%matplotlib inline 3import numpy as np 4 5from keras import backend as K 6from keras.datasets import mnist 7from keras.layers import Activation, BatchNormalization, Concatenate, Dense, Dropout, Flatten, Input, Lambda, Reshape 8from keras.layers.advanced_activations import LeakyReLU 9from keras.layers.convolutional import Conv2D, Conv2DTranspose 10from keras.models import Model, Sequential 11from keras.optimizers import Adam 12from keras.utils import to_categorical 13from keras.preprocessing.image import ImageDataGenerator 14 15## モデルの入力次元の定義 16img_rows = 28 17img_cols = 28 18channels = 1 19 20#入力画像の解像度 21img_shape = (img_rows, img_cols, channels) 22 23#Generatorに入力するノイズベクトルzのサイズ 24z_dim = 100 25 26#データセット内のクラスの数 27num_classes = 10 28 29##訓練と検証のためのデータの設定 num_labeledで指定された枚数の画像のみを使用(残りはラベルなしとして使用) 30class Dataset: 31 def __init__(self, num_labeled): 32 33 # 訓練用に使用するラベル付き画像の数 34 self.num_labeled = num_labeled 35 36 # MNISTデータのDL 37 (self.x_train, self.y_train), (self.x_test, self.y_test) = mnist.load_data() 38 39 def preprocess_imgs(x): 40 # [0, 255] のグレースケール画素値を [-1, 1]の値に変換する 41 x = (x.astype(np.float32) - 127.5) / 127.5 42 # xの画像の次元を横幅×縦幅×チャンネル数に拡張する 43 x = np.expand_dims(x, axis=3) 44 return x 45 46 def preprocess_labels(y): 47 return y.reshape(-1, 1) 48 49 # 訓練データ 50 self.x_train = preprocess_imgs(self.x_train) 51 self.y_train = preprocess_labels(self.y_train) 52 53 # テストデータ 54 self.x_test = preprocess_imgs(self.x_test) 55 self.y_test = preprocess_labels(self.y_test) 56 57 def batch_labeled(self, batch_size): 58 # ラベル付き画像とそのラベルをランダムに取り出してバッチをつくる 59 idx = np.random.randint(0, self.num_labeled, batch_size) 60 imgs = self.x_train[idx] 61 labels = self.y_train[idx] 62 63  datagen = ImageDataGenerator(rotation_range = 50) 64 g = datagen.flow(imgs, labels, batch_size, shuffle=False) 65 imgs, labels = g.next() 66 67 return imgs, labels 68 69 def batch_unlabeled(self, batch_size): 70 # ラベルなし画像をランダムに取り出してバッチをつくる 71 idx = np.random.randint(self.num_labeled, self.x_train.shape[0],batch_size) 72 imgs = self.x_train[idx] 73 return imgs 74 75 def training_set(self): 76 x_train = self.x_train[range(self.num_labeled)] 77 y_train = self.y_train[range(self.num_labeled)] 78 return x_train, y_train 79 80 def test_set(self): 81 return self.x_test, self.y_test 82 83## ラベル付き訓練データの数の指定 84 85num_labeled = 100 86 87dataset = Dataset(num_labeled) 88 89## 生成器(Generator)の実装 90 91def build_generator(z_dim): 92 93 model = Sequential() 94 95 # 入力を全結合により7×7×256のテンソルに変形する 96 model.add(Dense(256 * 7 * 7, input_dim=z_dim)) 97 model.add(Reshape((7, 7, 256))) 98 99 # 転置畳み込み層により14x14x128のテンソルに変形する(転置畳み込みにより、幅と高さを拡大する代わりに深さを小さくできる⇔普通の畳み込みと逆) 100 model.add(Conv2DTranspose(128, kernel_size=3, strides=2, padding='same')) 101 102 # Batch normalization(バッチ正規化) 103 model.add(BatchNormalization()) 104 105 # Leaky ReLU による活性化 106 model.add(LeakyReLU(alpha=0.01)) 107 108 # 転置畳み込み層により14x14x64のテンソルに変形する 109 model.add(Conv2DTranspose(64, kernel_size=3, strides=1, padding='same')) 110 111 # Batch normalization (バッチ正規化) 112 model.add(BatchNormalization()) 113 114 # Leaky ReLU による活性化 115 model.add(LeakyReLU(alpha=0.01)) 116 117 # 転置畳み込み層により28x28x1のテンソルに変形する 118 model.add(Conv2DTranspose(1, kernel_size=3, strides=2, padding='same')) 119 120 # tanhによる活性化を行った出力層(tanhにすることでよりはっきりした画像になる) 121 model.add(Activation('tanh')) 122 123 return model 124 125## 識別機(Discriminator)の実装 126 127def build_discriminator_net(img_shape): 128 129 model = Sequential() 130 131 # 畳み込み層により14x14x32のテンソルに変形する 132 model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) 133 134 # Leaky ReLU による活性化 135 model.add(LeakyReLU(alpha=0.01)) 136 137 # 畳み込み層により7x7x64のテンソルに変形する 138 model.add(Conv2D(64, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) 139 140 # Batch normalization (バッチ正規化) 141 model.add(BatchNormalization()) 142 143 # Leaky ReLU による活性化 144 model.add(LeakyReLU(alpha=0.01)) 145 146 # 畳み込み層により3x3x128のテンソルに変形する 147 model.add(Conv2D(128, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) 148 149 # Batch normalization (バッチ正規化) 150 model.add(BatchNormalization()) 151 152 # Leaky ReLU による活性化 153 model.add(LeakyReLU(alpha=0.01)) 154 155 # ドロップアウト 156 model.add(Dropout(0.5)) 157 158 # テンソルを一列に変形する 159 model.add(Flatten()) 160 161 # num_classesニューロンへの全結合層 162 model.add(Dense(num_classes)) 163 164 return model 165 166## 教師あり部分のSGAN識別機の実装 167 168def build_discriminator_supervised(discriminator_net): 169 170 model = Sequential() 171 172 model.add(discriminator_net) 173 174 # ソフトマックスによる活性化により、本物のクラスの中のどれに該当するのか推定確率を出力 175 model.add(Activation('softmax')) 176 177 return model 178 179## 教師なし部分のSGAN識別機の実装 180 181def build_discriminator_unsupervised(discriminator_net): 182 183 model = Sequential() 184 185 model.add(discriminator_net) 186 187 def predict(x): 188 # 本物のクラスごとの確率分布を、本物か偽物かの2値の確率に変換する 189 prediction = 1.0 - (1.0 /(K.sum(K.exp(x), axis=-1, keepdims=True) + 1.0)) 190 return prediction 191 192 # 本物か偽物かを出力する 193 model.add(Lambda(predict)) 194 195 return model 196 197## モデル構築 198 199def build_gan(generator, discriminator): 200 201 model = Sequential() 202 203 # 生成器と識別器を結合する 204 model.add(generator) 205 model.add(discriminator) 206 207 return model 208 209# 教師ありと教師なしで共有される層 210discriminator_net = build_discriminator_net(img_shape) 211 212# 教師あり学習のための識別機をコンパイルする 213discriminator_supervised = build_discriminator_supervised(discriminator_net) 214discriminator_supervised.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer=Adam()) 215 216# 教師なし学習のための識別機をコンパイルする 217discriminator_unsupervised = build_discriminator_unsupervised(discriminator_net) 218discriminator_unsupervised.compile(loss='binary_crossentropy', optimizer=Adam()) 219 220# 生成器の作成 221generator = build_generator(z_dim) 222 223# 生成器の訓練中は識別機のパラメータは定数 224discriminator_unsupervised.trainable = False 225 226# 生成器の訓練を行うため、識別機のパラメータを固定したGANモデルを構築し、コンパイルする 227gan = build_gan(generator, discriminator_unsupervised) 228gan.compile(loss='binary_crossentropy', optimizer=Adam()) 229 230'''''''''''''''''''''' 231SGAN訓練アルゴリズムの実装 232 233①教師あり識別機の訓練 234 235ラベリングされた本物のデータからランダムにサンプルを取り出し、ミニバッチを作成 236このミニバッチからロスを計算し、誤差逆伝播によってパラメータθを更新 237②生成器の訓練 238 239ラベルのない本物データからランダムにミニバッチを作成 240ここからロスを計算し、2値分類の誤差逆伝播によってθを更新 241ノイズベクトルzから偽サンプルのミニバッチを作成 242このミニバッチからもロスを計算し、2値分類の誤差逆伝播によってθを更新 243③生成器の訓練 244 245ノイズベクトルzから偽の生成サンプルからなるミニバッチを作成 246このミニバッチからロスを計算し、2値分類の誤差逆伝播によってθを更新 247''''''''''''''''''''''' 248 249supervised_losses = [] 250iteration_checkpoints = [] 251 252 253def train(iterations, batch_size, sample_interval): 254 255 # 本物の画像のラベル: すべて1 256 real = np.ones((batch_size, 1)) 257 258 # 偽物の画像のラベル: すべて0 259 fake = np.zeros((batch_size, 1)) 260 261 #識別機の訓練 262 for iteration in range(iterations): 263 264 # ラベル付きデータの取得 265 imgs, labels = dataset.batch_labeled(batch_size) 266 267 # ワンホットエンコードされたラベル 268 labels = to_categorical(labels, num_classes=num_classes) 269 270 # ラベルなしデータの取得 271 imgs_unlabeled = dataset.batch_unlabeled(batch_size) 272 273 # 偽画像のバッチ作成 274 z = np.random.normal(0, 1, (batch_size, z_dim)) 275 gen_imgs = generator.predict(z) 276 277 # ラベル付き本物データによる訓練 278 d_loss_supervised, accuracy = discriminator_supervised.train_on_batch(imgs, labels) 279 280 # ラベルなしの本物サンプルによる訓練 281 d_loss_real = discriminator_unsupervised.train_on_batch(imgs_unlabeled, real) 282 283 # 偽のサンプルによる訓練 284 d_loss_fake = discriminator_unsupervised.train_on_batch(gen_imgs, fake) 285 286 d_loss_unsupervised = 0.5 * np.add(d_loss_real, d_loss_fake) 287 288 # 生成器の訓練 289 290 # 偽画像のバッチ作成 291 z = np.random.normal(0, 1, (batch_size, z_dim)) 292 gen_imgs = generator.predict(z) 293 294 # 生成器の訓練 295 g_loss = gan.train_on_batch(z, np.ones((batch_size, 1))) 296 297 if (iteration + 1) % sample_interval == 0: 298 299 # 生成器の教師ありの分類損失を、訓練後にプロットするために保存しておく 300 supervised_losses.append(d_loss_supervised) 301 iteration_checkpoints.append(iteration + 1) 302 303 # 訓練の進捗を出力 304 print("%d [D loss supervised: %.4f, acc.: %.2f%%] [D loss unsupervised: %.4f] [G loss: %f]" % (iteration + 1, d_loss_supervised, 100 * accuracy, d_loss_unsupervised, g_loss)) 305 306# ハイパーパラメータの設定 307iterations = 8000 308batch_size = 32 309sample_interval = 800 310 311# SGANを指定した回数だけ反復訓練させる 312train(iterations, batch_size, sample_interval) 313 314x, y = dataset.test_set() 315y = to_categorical(y, num_classes=num_classes) 316 317# テストデータの分類データの測定 318_, accuracy = discriminator_supervised.evaluate(x, y) 319print("Test Accuracy: %.2f%%" % (100 * accuracy)) 320

試したこと

補足情報に記載したGitHubコード(とあるDCGANに関する書籍のサンプルコードです)の単純なコピペではうまくいかなかったため、kerasのImageDataGeneratorを使用して、(Class:Dataset内に)以下のコードを追加してみたのですが、汎化精度が向上しませんでした。

datagen = ImageDataGenerator(rotation_range = 50) g = datagen.flow(imgs, labels, batch_size, shuffle=False) imgs, labels = g.next()

補足情報(FW/ツールのバージョンなど)

GitHubソースコード
https://github.com/GANs-in-Action/gans-in-action/tree/master/chapter-7

その他参考情報
https://sinyblog.com/deaplearning/gansemi-supervised-gan-001/

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2020/12/25 07:44

> 精度90%の汎化性能を達成するコードを作成 > 一方、精度は60-70%程度で向上せず 文言が矛盾していますがどういう状況でしょうか?
kentaro189

2020/12/25 11:18

ご質問ありがとうございます。当方、日本語がいまいちでお手数おかけしました。 記載を修正いたしました。 状況としましては、90%以上の汎化精度を目指しているものの、実際には60-70%程度にしか達していないというものです。 また、日本語の修正のほか、ImageDataGeneratorを使用し、見よう見まねでコードを追記してみております。やはり精度は変わらなかったので、コードがおかしいのか、ほかに原因があるのか、もし何かわかればご指摘頂き度く、宜しくお願い致します。
guest

回答1

0

引数なしのadamを指定するとlr=0.001が適用されると思います。
うまくいく保証はありませんが、これを2桁~4桁くらい落として試してはいかがでしょうか?
少なくとも、別のDCGANではlr=0.0002が使われていますので、これくらいを目安に下げた方がよさそうな気がします。

投稿2021/01/01 07:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問