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

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

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

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

GitHub

GitHubは、Gitバージョン管理システムを利用したソフトウェア開発向けの共有ウェブサービスです。GitHub商用プランおよびオープンソースプロジェクト向けの無料アカウントを提供しています。

Q&A

解決済

1回答

1647閲覧

tensorflow+keras 記述コード(Pix2pix)のGPU環境での結果再現性

x_stars

総合スコア10

Keras

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

GitHub

GitHubは、Gitバージョン管理システムを利用したソフトウェア開発向けの共有ウェブサービスです。GitHub商用プランおよびオープンソースプロジェクト向けの無料アカウントを提供しています。

0グッド

0クリップ

投稿2022/01/07 09:31

前提・実現したいこと

以下URLのコード(pix2pix)をベースにして実行。

https://github.com/eriklindernoren/Keras-GAN/tree/master/pix2pix

CPU環境で実行した場合は結果が再現されるが、
GPU環境では再現されない。

下記コードで加筆/修正すべき箇所あれば教えていただきたいです。

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

loss値の初期値は変わらないが、計算過程でずれ始める。
(1Batch目はずれないが、2Batch目からloss値がずれる。)

1回目 <10epochで実施時>
イメージ説明
2回目 <10epochで実施時>
イメージ説明

該当のソースコード

ベースコードからの修正箇所
①冒頭のImport文(tensorflow2.4.0で実施のため)
②乱数固定部分1~6

from __future__ import print_function, division import scipy from tensorflow.keras.datasets import mnist from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout, Concatenate from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D from tensorflow.keras.layers import LeakyReLU from tensorflow.keras.layers import UpSampling2D, Conv2D from tensorflow.keras.models import Sequential, Model from tensorflow.keras.optimizers import Adam import datetime import matplotlib.pyplot as plt import sys from data_loader import DataLoader import numpy as np import os import cv2 from tensorflow.keras.preprocessing.image import load_img, save_img, img_to_array, array_to_img import numpy as np import tensorflow as tf from tensorflow import keras #####乱数固定1####### os.environ['PYTHONHASHSEED'] = '0' os.environ['TF_DETERMINISTIC_OPS'] = 'true' os.environ['TF_CUDNN_DETERMINISTIC'] = 'true' import random as rn def reset_random_seeds(): tf.random.set_seed(SEED) np.random.seed(SEED) rn.seed(SEED) ########## class Pix2Pix(): def __init__(self): # Input shape self.img_rows = 256 self.img_cols = 256 self.channels = 3 self.img_shape = (self.img_rows, self.img_cols, self.channels) # Configure data loader self.dataset_name = 'facades' self.data_loader = DataLoader(dataset_name=self.dataset_name, img_res=(self.img_rows, self.img_cols)) # Calculate output shape of D (PatchGAN) patch = int(self.img_rows / 2**4) self.disc_patch = (patch, patch, 1) # Number of filters in the first layer of G and D self.gf = 64 self.df = 64 optimizer = Adam(0.0002, 0.5) # Build and compile the discriminator self.discriminator = self.build_discriminator() self.discriminator.compile(loss='mse', optimizer=optimizer, metrics=['accuracy']) #------------------------- # Construct Computational # Graph of Generator #------------------------- # Build the generator self.generator = self.build_generator() # Input images and their conditioning images img_A = Input(shape=self.img_shape) img_B = Input(shape=self.img_shape) # By conditioning on B generate a fake version of A fake_A = self.generator(img_B) # For the combined model we will only train the generator self.discriminator.trainable = False # Discriminators determines validity of translated images / condition pairs valid = self.discriminator([fake_A, img_B]) self.combined = Model(inputs=[img_A, img_B], outputs=[valid, fake_A]) self.combined.compile(loss=['mse', 'mae'], loss_weights=[1, 100], optimizer=optimizer) def build_generator(self): """U-Net Generator""" def conv2d(layer_input, filters, f_size=4, bn=True): """Layers used during downsampling""" d = Conv2D(filters, kernel_size=f_size, strides=2, padding='same')(layer_input) d = LeakyReLU(alpha=0.2)(d) if bn: d = BatchNormalization(momentum=0.8)(d) return d def deconv2d(layer_input, skip_input, filters, f_size=4, dropout_rate=0): """Layers used during upsampling""" u = UpSampling2D(size=2)(layer_input) u = Conv2D(filters, kernel_size=f_size, strides=1, padding='same', activation='relu')(u) if dropout_rate: u = Dropout(dropout_rate)(u) u = BatchNormalization(momentum=0.8)(u) u = Concatenate()([u, skip_input]) return u ######乱数固定2######### operation_lebel_seed=0 initializer=tf.keras.initializers.GlorotUniform(seed=operation_lebel_seed) ######## # Image input d0 = Input(shape=self.img_shape) # Downsampling d1 = conv2d(d0, self.gf, bn=False) d2 = conv2d(d1, self.gf*2) d3 = conv2d(d2, self.gf*4) d4 = conv2d(d3, self.gf*8) d5 = conv2d(d4, self.gf*8) d6 = conv2d(d5, self.gf*8) d7 = conv2d(d6, self.gf*8) # Upsampling u1 = deconv2d(d7, d6, self.gf*8) u2 = deconv2d(u1, d5, self.gf*8) u3 = deconv2d(u2, d4, self.gf*8) u4 = deconv2d(u3, d3, self.gf*4) u5 = deconv2d(u4, d2, self.gf*2) u6 = deconv2d(u5, d1, self.gf) u7 = UpSampling2D(size=2)(u6) output_img = Conv2D(self.channels, kernel_size=4, strides=1, padding='same', activation='tanh')(u7) return Model(d0, output_img) def build_discriminator(self): def d_layer(layer_input, filters, f_size=4, bn=True): """Discriminator layer""" d = Conv2D(filters, kernel_size=f_size, strides=2, padding='same')(layer_input) d = LeakyReLU(alpha=0.2)(d) if bn: d = BatchNormalization(momentum=0.8)(d) return d ####乱数固定3###### operation_lebel_seed=0 initializer=tf.keras.initializers.GlorotUniform(seed=operation_lebel_seed) ############# img_A = Input(shape=self.img_shape) img_B = Input(shape=self.img_shape) # Concatenate image and conditioning image by channels to produce input combined_imgs = Concatenate(axis=-1)([img_A, img_B]) d1 = d_layer(combined_imgs, self.df, bn=False) d2 = d_layer(d1, self.df*2) d3 = d_layer(d2, self.df*4) d4 = d_layer(d3, self.df*8) validity = Conv2D(1, kernel_size=4, strides=1, padding='same')(d4) return Model([img_A, img_B], validity) def train(self, epochs, batch_size=1, sample_interval=50): start_time = datetime.datetime.now() # Adversarial loss ground truths valid = np.ones((batch_size,) + self.disc_patch) fake = np.zeros((batch_size,) + self.disc_patch) for epoch in range(epochs): for batch_i, (imgs_A, imgs_B) in enumerate(self.data_loader.load_batch(batch_size)): fake_A = self.generator.predict(imgs_B) d_loss_real = self.discriminator.train_on_batch([imgs_A, imgs_B], valid) d_loss_fake = self.discriminator.train_on_batch([fake_A, imgs_B], fake) d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) g_loss = self.combined.train_on_batch([imgs_A, imgs_B], [valid, imgs_A]) elapsed_time = datetime.datetime.now() - start_time print ("[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %3d%%] [G loss: %f] time: %s" % (epoch, epochs, batch_i, self.data_loader.n_batches, d_loss[0], 100*d_loss[1], g_loss[0], elapsed_time)) if batch_i % sample_interval == 0: self.sample_images(epoch, batch_i) def sample_images(self, epoch, batch_i): os.makedirs('images/%s' % self.dataset_name, exist_ok=True) r, c = 3, 3 imgs_A, imgs_B = self.data_loader.load_data(batch_size=3, is_testing=True) fake_A = self.generator.predict(imgs_B) gen_imgs = np.concatenate([imgs_B, fake_A, imgs_A]) gen_imgs = 0.5 * gen_imgs + 0.5 titles = ['Condition', 'Generated', 'Original'] fig, axs = plt.subplots(r, c) cnt = 0 for i in range(r): for j in range(c): axs[i,j].imshow(gen_imgs[cnt]) axs[i, j].set_title(titles[i]) axs[i,j].axis('off') cnt += 1 fig.savefig("images/%s/%d_%d.png" % (self.dataset_name, epoch, batch_i)) plt.close() if __name__ == '__main__': ########乱数固定部4####### SEED = 123 reset_random_seeds() session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) tf.compat.v1.set_random_seed(SEED) sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf) tf.compat.v1.keras.backend.set_session(sess) ##### gan = Pix2Pix() gan.train(epochs=10, batch_size=1, sample_interval=1) gan.generator.save("saved_model/modelC.h5", include_optimizer=True)

試したこと

以下のURLを参考に乱数/並列計算部分の固定を試みた。
乱数固定部 1~4
参考1
https://webcache.googleusercontent.com/search?q=cache:4kLbH5badwUJ:https://book-read-yoshi.hatenablog.com/entry/2021/03/21/TensorFlow_determinism+&cd=1&hl=ja&ct=clnk&gl=jp
参考2
http://tomo-techblog.com/tensorflowgpu/
参考3
https://github.com/NVIDIA/framework-determinism

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

環境は以下で実施:
GPU NVIDIA RTX2070 SUPER
Keras==2.3.1
numpy==1.19.5
tensorflow==2.4.0

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

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

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

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

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

guest

回答1

0

自己解決

自己解決できました。
2か所修正しました。
Tensorflow2.4.0 では UpSampling2Dの計算順序が固定できていないみたいでした。
repeat_elements を使って書き換えることで計算順序が固定でき、2回コードを回した際の結果が同じになりました。

1か所目 def build_generator(self):   ・・・・ def deconv2d(layer_input, skip_input, filters, f_size=4, dropout_rate=0): """Layers used during upsampling""" #元u = UpSampling2D(size=2)(layer_input)      #新 u = tf.keras.backend.repeat_elements(layer_input,2, axis=1)      #新 u = tf.keras.backend.repeat_elements(u,2, axis=2) 2か所目 def build_generator(self):     ・・・     #元 u7 = UpSampling2D(size=2)(u6)    #新  u7 = tf.keras.backend.repeat_elements(u6, 2, axis=1) u7 = tf.keras.backend.repeat_elements(u7, 2, axis=2)

投稿2022/01/14 08:00

x_stars

総合スコア10

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問