Skip to content

Instantly share code, notes, and snippets.

@mami-t
Created February 1, 2018 05:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mami-t/f3eff836a62a0f9d14e2016261d490b0 to your computer and use it in GitHub Desktop.
Save mami-t/f3eff836a62a0f9d14e2016261d490b0 to your computer and use it in GitHub Desktop.
GAN
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
" from ._conv import register_converters as _register_converters\n",
"Using TensorFlow backend.\n",
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/importlib/_bootstrap.py:205: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6\n",
" return f(*args, **kwds)\n"
]
}
],
"source": [
"from keras.models import Sequential\n",
"from keras.layers import Dense, Activation, Reshape\n",
"from keras.layers.normalization import BatchNormalization\n",
"from keras.layers.convolutional import UpSampling2D, Convolution2D,MaxPooling2D\n",
"from keras.layers.advanced_activations import LeakyReLU\n",
"from keras.layers import Flatten, Dropout"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def generator_model():\n",
" model = Sequential()\n",
" model.add(Dense(input_dim=100, output_dim=1024))\n",
" model.add(BatchNormalization())\n",
" model.add(Activation('relu'))\n",
" model.add(Dense(128*7*7))\n",
" model.add(BatchNormalization())\n",
" model.add(Activation('relu'))\n",
" model.add(Reshape((7, 7, 128), input_shape=(128*7*7,)))\n",
" model.add(UpSampling2D((2, 2)))\n",
" model.add(Convolution2D(64, (5, 5), border_mode='same'))\n",
" model.add(BatchNormalization())\n",
" model.add(Activation('relu'))\n",
" model.add(UpSampling2D((2, 2)))\n",
" model.add(Convolution2D(1, (5, 5), border_mode='same'))\n",
" model.add(Activation('tanh'))\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def discriminator_model():\n",
" model = Sequential()\n",
" model.add(Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same',\n",
" input_shape=(28, 28,1)))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Convolution2D(128, (5, 5), subsample=(2, 2)))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Flatten())\n",
" model.add(Dense(256))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Dropout(0.5))\n",
" model.add(Dense(1))\n",
" model.add(Activation('sigmoid'))\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from keras.datasets import mnist\n",
"from keras.optimizers import Adam\n",
"from PIL import Image\n",
"import matplotlib.pyplot as plt\n",
"from keras.datasets import fashion_mnist"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(28, 28)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(X_train, y_train), (_, _) = fashion_mnist.load_data()\n",
"X_train[0].shape"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"BATCH_SIZE = 32\n",
"NUM_EPOCH = 20"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def show_images(images):\n",
" fig = plt.figure(figsize=(10,21))\n",
" for i, image in enumerate(images):\n",
" plt.subplot(int(BATCH_SIZE/5)+(BATCH_SIZE%5>0),5,i+1)\n",
" plt.imshow(image[:,:,0])\n",
" plt.gray()\n",
" plt.show() "
]
},
{
"cell_type": "code",
"execution_count": 146,
"metadata": {},
"outputs": [],
"source": [
"def train(X_train, y_train):\n",
" #(X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
"\n",
" discriminator = discriminator_model()\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = generator_model()\n",
" dcgan = Sequential([generator, discriminator])\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
"\n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" generated_images = generator.predict(noise, verbose=0)\n",
"\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images)\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" X = np.concatenate((image_batch, generated_images))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch(X, np.array(y))\n",
" disc_pred=discriminator.predict(X)\n",
" print(disc_pred[0][0])\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" g_loss = dcgan.train_on_batch(noise, np.array([1]*BATCH_SIZE))\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('generator.h5')\n",
" discriminator.save_weights('discriminator.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"(X_train, y_train), (_, _) = mnist.load_data()\n",
"generator=train(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"(X_train, y_train), (_, _) = fashion_mnist.load_data()\n",
"generator_fashion=train(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": 148,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'generator_fashion' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-148-544d71371806>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mnoise\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0muniform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m100\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mBATCH_SIZE\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mgenerated_images\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgenerator_fashion\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnoise\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mshow_images\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerated_images\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'generator_fashion' is not defined"
]
}
],
"source": [
"noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
"generated_images = generator_fashion.predict(noise, verbose=0)\n",
"show_images(generated_images)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## CGAN"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"import keras\n",
"from keras.layers import Input\n",
"from keras.models import Model"
]
},
{
"cell_type": "code",
"execution_count": 164,
"metadata": {},
"outputs": [],
"source": [
"def cgenerator_model():\n",
" z_input = Input(shape=(100,), dtype='float32', name='z_input')\n",
" x = Dense(200)(z_input)\n",
" x=BatchNormalization()(x)\n",
" z_output=Activation('relu')(x)\n",
" y_input = Input(shape=(10,), dtype='float32', name='y_input')\n",
" x = Dense(200)(y_input)\n",
" x=BatchNormalization()(x)\n",
" y_output = Activation('relu')(x)\n",
" x = keras.layers.concatenate([z_output, y_output])\n",
" x = Dense(1200)(x)\n",
" x=BatchNormalization()(x)\n",
" x = Activation('relu')(x)\n",
" x=Dense(128*7*7)(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,))(x)\n",
" x=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(64, (5, 5), border_mode='same')(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same')(x)\n",
" output=Activation('tanh')(x)\n",
" model = Model(inputs=[z_input, y_input], outputs=[output, y_input])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 165,
"metadata": {},
"outputs": [],
"source": [
"def cdiscriminator_model():\n",
" x_input=Input(shape=(28, 28,1), dtype='float32', name='x_input')\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(x_input)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x_input)\n",
" x_output=Flatten()(x)\n",
" y_input = Input(shape=(10,), dtype='float32', name='y_input')\n",
" x = Dense(50)(y_input)\n",
" y_output = Activation('relu')(x)\n",
" x = keras.layers.concatenate([x_output, y_output])\n",
" x=Dense(256)(x)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Dropout(0.5)(x)\n",
" x=Dense(1)(x)\n",
" output=Activation('sigmoid')(x)\n",
" model = Model(inputs=[x_input, y_input], outputs=[output])\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {},
"outputs": [],
"source": [
"def ctrain():\n",
" (X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" discriminator = cdiscriminator_model()\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = cgenerator_model()\n",
" y_dcgan = discriminator(generator(generator.inputs))\n",
" dcgan=Model(inputs=generator.inputs, outputs=y_dcgan)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
"\n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict({'z_input': noise, 'y_input': y_noise}, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images[0])\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" X = np.concatenate((image_batch, generated_images[0]))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch({'x_input': X, 'y_input': Y}, y)\n",
"\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch({'z_input': noise, 'y_input': y_noise}, [1]*BATCH_SIZE)\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('cgenerator.h5')\n",
" discriminator.save_weights('cdiscriminator.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cgenerator=ctrain()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LAPGAN"
]
},
{
"cell_type": "code",
"execution_count": 195,
"metadata": {},
"outputs": [],
"source": [
"def lap_generator28(size=28):\n",
" z_input = Input(shape=(100,), dtype='float32', name='z_input')\n",
" x = Dense(200)(z_input)\n",
" x=BatchNormalization()(x)\n",
" z_output=Activation('relu')(x)\n",
" I_input = Input(shape=(size,size,1), dtype='float32', name='I_input')\n",
" x = MaxPooling2D(pool_size=(2, 2))(I_input)\n",
" y_output=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(y_output)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Flatten()(x)\n",
" x = Dense(200)(x)\n",
" x=BatchNormalization()(x)\n",
" I_output = Activation('relu')(x)\n",
" x = keras.layers.concatenate([z_output, I_output])\n",
" x = Dense(1024)(x)\n",
" x=BatchNormalization()(x)\n",
" x = Activation('relu')(x)\n",
" x=Dense(128*7*7)(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,))(x)\n",
" x=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(64, (5, 5), border_mode='same')(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same')(x)\n",
" output=Activation('tanh')(x)\n",
" model = Model(inputs=[z_input, I_input], outputs=[output, y_output])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 196,
"metadata": {},
"outputs": [],
"source": [
"def lap_generator14(size=14):\n",
" z_input = Input(shape=(100,), dtype='float32', name='z_input')\n",
" x = Dense(200)(z_input)\n",
" x=BatchNormalization()(x)\n",
" z_output=Activation('relu')(x)\n",
" I_input = Input(shape=(size,size,1), dtype='float32', name='I_input')\n",
" x = MaxPooling2D(pool_size=(2, 2))(I_input)\n",
" y_output=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(y_output)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Flatten()(x)\n",
" x = Dense(200)(x)\n",
" x=BatchNormalization()(x)\n",
" I_output = Activation('relu')(x)\n",
" x = keras.layers.concatenate([z_output, I_output])\n",
" x = Dense(1024)(x)\n",
" x=BatchNormalization()(x)\n",
" x = Activation('relu')(x)\n",
" x=Dense(128*7*7)(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,))(x)\n",
" x=UpSampling2D((2, 2))(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same')(x)\n",
"\n",
" output=Activation('tanh')(x)\n",
" model = Model(inputs=[z_input, I_input], outputs=[output, y_output])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 192,
"metadata": {},
"outputs": [],
"source": [
"def lap_generator7(size=14):\n",
" z_input = Input(shape=(100,), dtype='float32', name='z_input')\n",
" x = Dense(200)(z_input)\n",
" x=BatchNormalization()(x)\n",
" x = Activation('relu')(x)\n",
" x = Dense(1024)(x)\n",
" x=BatchNormalization()(x)\n",
" x = Activation('relu')(x)\n",
" x=Dense(128*7*7)(x)\n",
" x=BatchNormalization()(x)\n",
" x=Activation('relu')(x)\n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,))(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same')(x)\n",
"\n",
" output=Activation('tanh')(x)\n",
" model = Model(inputs=[z_input], outputs=[output])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 199,
"metadata": {},
"outputs": [],
"source": [
"def lap_discriminator(size=7):\n",
" x_input=Input(shape=(size, size,1), dtype='float32', name='x_input')\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(x_input)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x_input)\n",
" x_output=Flatten()(x)\n",
" y_input=Input(shape=(size, size,1), dtype='float32', name='x_input')\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(y_input)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x_input)\n",
" y_output=Flatten()(x)\n",
" x = keras.layers.concatenate([x_output, y_output])\n",
" x=Dense(256)(x)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Dropout(0.5)(x)\n",
" x=Dense(1)(x)\n",
" output=Activation('sigmoid')(x)\n",
" model = Model(inputs=[x_input, y_input], outputs=[output])\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 202,
"metadata": {},
"outputs": [],
"source": [
"def produce_image28(size=28):\n",
" model = Sequential()\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" model.add(UpSampling2D((2, 2)))\n",
" \n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 201,
"metadata": {},
"outputs": [],
"source": [
"def produce_image7(size=28):\n",
" model = Sequential()\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" model.add(UpSampling2D((2, 2)))\n",
" \n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 204,
"metadata": {},
"outputs": [],
"source": [
"def down_image14(size=28):\n",
" model = Sequential()\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" \n",
" \n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 213,
"metadata": {},
"outputs": [],
"source": [
"def down_image7(size=28):\n",
" model = Sequential()\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" model.add(MaxPooling2D((2, 2),input_shape=(size, size,1)))\n",
" \n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 221,
"metadata": {},
"outputs": [],
"source": [
"def train28():\n",
" (X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" #y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" discriminator = lap_discriminator(28)\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = lap_generator28()\n",
" y_dcgan = discriminator(generator(generator.inputs))\n",
" dcgan=Model(inputs=generator.inputs, outputs=y_dcgan)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
" image_model=produce_image28()\n",
" \n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict({'z_input': noise, 'I_input': image_batch}, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images[0])\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" X_original = np.concatenate((image_batch, generated_images[0]))\n",
" X=image_model.predict(X_original)\n",
" X_diff=X_original-X\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" #Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch({'x_input': X, 'y_input': X_diff}, y)\n",
"\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch({'z_input': noise, 'I_input': image_batch}, [1]*BATCH_SIZE)\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('lap_generator28.h5')\n",
" discriminator.save_weights('lap_discriminator28.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": 222,
"metadata": {},
"outputs": [],
"source": [
"def train14():\n",
" (X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" #y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" discriminator = lap_discriminator(14)\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = lap_generator14()\n",
" y_dcgan = discriminator(generator(generator.inputs))\n",
" dcgan=Model(inputs=generator.inputs, outputs=y_dcgan)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
" image_model=produce_image28(size=14)\n",
" down_image_model=down_image14()\n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = down_image_model.predict(X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE])\n",
" #y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict({'z_input': noise, 'I_input': image_batch}, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images[0])\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" X_original = image_model.predict(image_batch)\n",
" X=(np.concatenate((X_original, X_original)))\n",
" X_diff=np.concatenate((image_batch-X_original, generated_images[0]))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" #Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch({'x_input': X, 'y_input': X_diff}, y)\n",
"\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch({'z_input': noise, 'I_input': image_batch}, [1]*BATCH_SIZE)\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('lap_generator14.h5')\n",
" discriminator.save_weights('lap_cdiscriminator14.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": 211,
"metadata": {},
"outputs": [],
"source": [
"def lap_generator7():\n",
" model = Sequential()\n",
" model.add(Dense(input_dim=100, output_dim=1024))\n",
" model.add(BatchNormalization())\n",
" model.add(Activation('relu'))\n",
" model.add(Dense(128*7*7))\n",
" model.add(BatchNormalization())\n",
" model.add(Activation('relu'))\n",
" model.add(Reshape((7, 7, 128), input_shape=(128*7*7,)))\n",
" model.add(Convolution2D(1, (5, 5), border_mode='same'))\n",
" model.add(Activation('tanh'))\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 218,
"metadata": {},
"outputs": [],
"source": [
"def lap_discriminator7():\n",
" model = Sequential()\n",
" model.add(Convolution2D(32, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same',\n",
" input_shape=(7, 7,1)))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Convolution2D(64, (3, 3), subsample=(2, 2)))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Flatten())\n",
" model.add(Dense(256))\n",
" model.add(LeakyReLU(0.2))\n",
" model.add(Dropout(0.5))\n",
" model.add(Dense(1))\n",
" model.add(Activation('sigmoid'))\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 223,
"metadata": {},
"outputs": [],
"source": [
"def train7():\n",
" (X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" #y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" discriminator = lap_discriminator7()\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = lap_generator7()\n",
" dcgan=Sequential([generator, discriminator])\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
" image_model=produce_image28(size=14)\n",
" down_image_model=down_image7()\n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = down_image_model.predict(X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE])\n",
" #y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict(noise, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images)\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" \n",
" X=np.concatenate((image_batch,generated_images))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" #Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch(X, y)\n",
"\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch(noise, [1]*BATCH_SIZE)\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('lap_generator7.h5')\n",
" discriminator.save_weights('lap_discriminator7.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"lap_generator28=train28()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"lap_generator14=train14()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"lap_generator7=train7()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Dropout"
]
},
{
"cell_type": "code",
"execution_count": 115,
"metadata": {},
"outputs": [],
"source": [
"def cgenerator_dropout():\n",
" y_input = Input(shape=(10,), dtype='float32', name='y_input')\n",
" x = Dense(200, name='dense_1')(y_input)\n",
" x=BatchNormalization(name='batch_norm_1')(x)\n",
" x = Activation('relu', name='activation_1')(x)\n",
" x=Dropout(0.5, name='dropout_1')(x)\n",
" x = Dense(1200, name='dense_2')(x)\n",
" x=BatchNormalization(name='batch_norm_2')(x)\n",
" x = Activation('relu', name='activation_2')(x)\n",
" x=Dropout(0.5, name='dropout_2')(x)\n",
" x=Dense(128*7*7, name='dense_3')(x)\n",
" x=BatchNormalization(name='batch_norm_3')(x)\n",
" x=Activation('relu', name='activation_3')(x)\n",
" x=Dropout(0.5, name='dropout_3')(x)\n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,), name='reshape_1')(x)\n",
" x=UpSampling2D((2, 2), name='upsampling_1')(x)\n",
" x=Convolution2D(64, (5, 5), border_mode='same', name='conv2d_1')(x)\n",
" x=BatchNormalization(name='batch_norm_4')(x)\n",
" x=Activation('relu', name='activation_4')(x)\n",
" x=UpSampling2D((2, 2), name='upsampling_2')(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same', name='conv2d_2')(x)\n",
" output=Activation('tanh', name='output')(x)\n",
" model = Model(inputs=[y_input], outputs=[output, y_input])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"def cdiscriminator_model():\n",
" x_input=Input(shape=(28, 28,1), dtype='float32', name='x_input')\n",
" x=Convolution2D(64, (5, 5),\n",
" subsample=(2, 2),\n",
" border_mode='same')(x_input)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Convolution2D(128, (5, 5), subsample=(2, 2))(x)\n",
" x=LeakyReLU(0.2)(x_input)\n",
" x_output=Flatten()(x)\n",
" y_input = Input(shape=(10,), dtype='float32', name='y_input')\n",
" x = Dense(50)(y_input)\n",
" y_output = Activation('relu')(x)\n",
" x = keras.layers.concatenate([x_output, y_output])\n",
" x=Dense(256)(x)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Dropout(0.5)(x)\n",
" x=Dense(1)(x)\n",
" output=Activation('sigmoid')(x)\n",
" model = Model(inputs=[x_input, y_input], outputs=[output])\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"def ctrain_dropout():\n",
" (X_train, y_train), (_, _) = mnist.load_data()\n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" discriminator = cdiscriminator_model()\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = cgenerator_dropout()\n",
" y_dcgan=discriminator(generator(generator.inputs))\n",
" dcgan=Model(inputs=generator.inputs, outputs=y_dcgan)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" dcgan.compile(loss='binary_crossentropy', optimizer=g_opt)\n",
" \n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" #noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict(y_noise, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images[0])\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" \n",
" X=np.concatenate((image_batch,generated_images[0]))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" d_loss = discriminator.train_on_batch({'x_input':X, 'y_input':Y}, y)\n",
"\n",
" # generatorを更新\n",
" #noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch(y_noise, [1]*BATCH_SIZE)\n",
" print(\"epoch: %d, batch: %d, g_loss: %f, d_loss: %f\" % (epoch, index, g_loss, d_loss))\n",
"\n",
" generator.save_weights('cgenerator_dropout.h5')\n",
" discriminator.save_weights('cdiscriminator_dropout.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cgenerator_dropout=ctrain_dropout()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## patch GAN"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"import keras.backend as K\n",
"from keras.layers import Lambda"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"def cdiscriminator_patch(img_dim, nb_patch, model_name=\"DCGAN_discriminator\", use_mbd=False):\n",
" \"\"\"\n",
" Discriminator model of the DCGAN\n",
" args : img_dim (tuple of int) num_chan, height, width\n",
" pretr_weights_file (str) file holding pre trained weights\n",
" returns : model (keras NN) the Neural Net model\n",
" \"\"\"\n",
" \n",
" list_input = [Input(shape=(7,7,1), name=\"disc_input_%s\" % i) for i in range(nb_patch)]\n",
"\n",
" if K.image_dim_ordering() == \"th\":\n",
" bn_axis = 1\n",
" else:\n",
" bn_axis = -1\n",
"\n",
" nb_filters = 64\n",
" nb_conv = 1#int(np.floor(np.log(img_dim[1]) / np.log(2)))\n",
" list_filters = [nb_filters * min(8, (2 ** i)) for i in range(nb_conv)]\n",
"\n",
" # First conv\n",
" x_input = Input(shape=(7,7,1), name=\"discriminator_input\")\n",
" \n",
" x = Convolution2D(list_filters[0], (5, 5), subsample=(2, 2), name=\"disc_conv2d_1\")(x_input)\n",
" x = BatchNormalization()(x)\n",
" x = LeakyReLU(0.2)(x)\n",
"\n",
" # Next convs\n",
" for i, f in enumerate(list_filters[1:]):\n",
" name = \"disc_conv2d_%s\" % (i + 2)\n",
" x = Convolution2D(f, (5, 5), subsample=(2, 2), name=name)(x)\n",
" x = BatchNormalization()(x)\n",
" x = LeakyReLU(0.2)(x)\n",
" x_flat = Flatten()(x)\n",
" \n",
" x=Dense(256)(x_flat)\n",
" x=LeakyReLU(0.2)(x)\n",
" x=Dropout(0.5)(x)\n",
" \n",
" \n",
" #y_input = Input(shape=(10,), dtype='float32', name='y_input')\n",
" #x = Dense(50)(y_input)\n",
" #y_output = Activation('relu')(x)\n",
" #x_flat = keras.layers.concatenate([x_flat, y_output])\n",
" x = Dense(1, activation='softmax', name=\"disc_dense\")(x)\n",
" PatchGAN = Model(input=[x_input], output=[x, x_flat], name=\"PatchGAN\")\n",
" print(\"PatchGAN summary\")\n",
" PatchGAN.summary()\n",
"\n",
" x = [PatchGAN(patch)[0] for patch in list_input]\n",
" x_mbd = [PatchGAN(patch)[1] for patch in list_input]\n",
"\n",
" if len(x) > 1:\n",
" x = keras.layers.concatenate(x)\n",
" else:\n",
" x = x[0]\n",
" # use flat x\n",
" if use_mbd:\n",
" if len(x_mbd) > 1:\n",
" x_mbd = keras.layers.concatenate(x_mbd)\n",
" else:\n",
" x_mbd = x_mbd[0]\n",
"\n",
" num_kernels = 100\n",
" dim_per_kernel = 5\n",
"\n",
" M = Dense(num_kernels * dim_per_kernel, bias=False, activation=None)\n",
" #MBD = Lambda(minb_disc, output_shape=lambda_output)\n",
"\n",
" x_mbd = M(x_mbd)\n",
" #x_mbd = Reshape((num_kernels, dim_per_kernel))(x_mbd)\n",
" #x_mbd = MBD(x_mbd)\n",
" x = keras.layers.concatenate([x,x_mbd])\n",
"\n",
" x_out = Dense(1, activation=\"softmax\", name=\"disc_output\")(x)\n",
"\n",
" discriminator_model = Model(input=list_input, output=[x_out], name=model_name)\n",
"\n",
" return discriminator_model"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"def DCGAN_patch(generator, discriminator_model, img_dim, patch_size):#, image_dim_ordering):\n",
"\n",
" gen_input = Input(shape=(10,), name=\"DCGAN_input\")\n",
"\n",
" generated_image = generator(gen_input)[0]\n",
"\n",
" #if image_dim_ordering == \"th\":\n",
" # h, w = img_dim[1:]\n",
" #else:\n",
" h, w = img_dim[:-1]\n",
" ph, pw = patch_size\n",
"\n",
" list_row_idx = [(i * ph, (i + 1) * ph) for i in range(int(h / ph))]\n",
" list_col_idx = [(i * pw, (i + 1) * pw) for i in range(int(w / pw))]\n",
"\n",
" list_gen_patch = []\n",
" for row_idx in list_row_idx:\n",
" for col_idx in list_col_idx:\n",
" #if image_dim_ordering == \"tf\":\n",
" # x_patch = Lambda(lambda z: z[:, row_idx[0]:row_idx[1], col_idx[0]:col_idx[1], :])(generated_image)\n",
" #else:\n",
" x_patch = Lambda(lambda z: z[ :, row_idx[0]:row_idx[1], col_idx[0]:col_idx[1],:])(generated_image)\n",
" list_gen_patch.append(x_patch)\n",
"\n",
" DCGAN_output = discriminator_model(list_gen_patch)\n",
" DCGAN = Model(input=[gen_input],\n",
" output=[generated_image, DCGAN_output],\n",
" name=\"DCGAN\")\n",
"\n",
" return DCGAN"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"def l1_loss(y_true, y_pred):\n",
" return K.sum(K.abs(y_pred - y_true), axis=-1)"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {},
"outputs": [],
"source": [
"def ctrain_patch(X_train, y_train):\n",
" \n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" img_dim=[28,28,1]\n",
" nb_patch=16\n",
" \n",
" discriminator = cdiscriminator_patch(img_dim, nb_patch, model_name=\"DCGAN_discriminator\", use_mbd=True)\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = cgenerator_dropout()\n",
" generator.summary()\n",
" patch_size=[7,7]\n",
" dcgan=DCGAN_patch(generator, discriminator, img_dim, patch_size)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" loss = [l1_loss, 'binary_crossentropy']\n",
" loss_weights = [1E1, 1]\n",
" dcgan.compile(loss=loss, loss_weights=loss_weights, optimizer=g_opt)\n",
" \n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" #noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict(y_noise, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images[0])\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" \n",
" X=np.concatenate((image_batch,generated_images[0]))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" h, w = img_dim[:-1]\n",
" ph, pw = patch_size\n",
"\n",
" list_row_idx = [(i * ph, (i + 1) * ph) for i in range(int(h / ph))]\n",
" list_col_idx = [(i * pw, (i + 1) * pw) for i in range(int(w / pw))]\n",
" list_gen_patch = []\n",
" list_gen_func=lambda z: z[:,row_idx[0]:row_idx[1], col_idx[0]:col_idx[1],:]\n",
" \n",
" for row_idx in list_row_idx:\n",
" for col_idx in list_col_idx:\n",
"\n",
" x_patch = list_gen_func(X)\n",
" \n",
" list_gen_patch.append(np.array(x_patch))\n",
" d_loss = discriminator.train_on_batch(list_gen_patch, np.array(y))\n",
"\n",
" # generatorを更新\n",
" #noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch(y_batch, [image_batch,np.array([1]*BATCH_SIZE)])\n",
" print(\"epoch: %d, batch: %d, g_loss: , d_loss: %f\" % (epoch, index, d_loss))\n",
" print(g_loss)\n",
"\n",
" generator.save_weights('cgenerator_patch.h5')\n",
" discriminator.save_weights('cdiscriminator_patch.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(X_train, y_train), (_, _) = mnist.load_data()\n",
"cgenerator_patch=ctrain_patch(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(X_train, y_train), (_, _) = fashion_mnist.load_data()\n",
"cgenerator_patch_fashion=ctrain_patch(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": 121,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/site-packages/ipykernel_launcher.py:17: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(64, (5, 5), name=\"conv2d_1\", padding=\"same\")`\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"y_input (InputLayer) (None, 10) 0 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 200) 2200 \n",
"_________________________________________________________________\n",
"batch_norm_1 (BatchNormaliza (None, 200) 800 \n",
"_________________________________________________________________\n",
"activation_1 (Activation) (None, 200) 0 \n",
"_________________________________________________________________\n",
"dropout_1 (Dropout) (None, 200) 0 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 1200) 241200 \n",
"_________________________________________________________________\n",
"batch_norm_2 (BatchNormaliza (None, 1200) 4800 \n",
"_________________________________________________________________\n",
"activation_2 (Activation) (None, 1200) 0 \n",
"_________________________________________________________________\n",
"dropout_2 (Dropout) (None, 1200) 0 \n",
"_________________________________________________________________\n",
"dense_3 (Dense) (None, 6272) 7532672 \n",
"_________________________________________________________________\n",
"batch_norm_3 (BatchNormaliza (None, 6272) 25088 \n",
"_________________________________________________________________\n",
"activation_3 (Activation) (None, 6272) 0 \n",
"_________________________________________________________________\n",
"dropout_3 (Dropout) (None, 6272) 0 \n",
"_________________________________________________________________\n",
"reshape_1 (Reshape) (None, 7, 7, 128) 0 \n",
"_________________________________________________________________\n",
"upsampling_1 (UpSampling2D) (None, 14, 14, 128) 0 \n",
"_________________________________________________________________\n",
"conv2d_1 (Conv2D) (None, 14, 14, 64) 204864 \n",
"_________________________________________________________________\n",
"batch_norm_4 (BatchNormaliza (None, 14, 14, 64) 256 \n",
"_________________________________________________________________\n",
"activation_4 (Activation) (None, 14, 14, 64) 0 \n",
"_________________________________________________________________\n",
"upsampling_2 (UpSampling2D) (None, 28, 28, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_2 (Conv2D) (None, 28, 28, 1) 1601 \n",
"_________________________________________________________________\n",
"output (Activation) (None, 28, 28, 1) 0 \n",
"=================================================================\n",
"Total params: 8,013,481\n",
"Trainable params: 7,998,009\n",
"Non-trainable params: 15,472\n",
"_________________________________________________________________\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/site-packages/ipykernel_launcher.py:21: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(1, (5, 5), name=\"conv2d_2\", padding=\"same\")`\n"
]
}
],
"source": [
"cgenerator_patch_fashion=cgenerator_dropout()\n",
"cgenerator_patch_fashion.summary()"
]
},
{
"cell_type": "code",
"execution_count": 122,
"metadata": {},
"outputs": [],
"source": [
"cgenerator_patch_fashion.load_weights('cgenerator_patch.h5', by_name=True)"
]
},
{
"cell_type": "code",
"execution_count": 123,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAARtCAYAAABx4cAPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAIABJREFUeJzs3Xus3VWd///XskC5tPRCS+m9UEoF\nuYjKRbnoCAgyQgejE4gDfE0z+AdmNDEZ0Jl/Zkwm6iRmJv7GSZrogI5RZwKTMioQRFFwGGxFBtpC\nL9xKoTdoaUtLoYXP74+zu3ivN92r++y1zz57f/bzkRDWPmtfPufz/qx9Vj/vdQlVVQkAAADtec9o\nHwAAAEA/ozMFAABQgM4UAABAATpTAAAABehMAQAAFKAzBQAAUIDOFAAAQIGizlQI4YoQwuoQwroQ\nwq2dOiiMDuJZH8SyXohnfRDLegrtLtoZQhgjaY2kyyRtkLRM0nVVVa3q3OGhW4hnfRDLeiGe9UEs\n6+uwgteeK2ldVVXPSFII4SeSFklqelGEEHpyufUjjjgieTxlypRYfs97Wrt599prryWPX3311fID\nGwFVVYUmVcOKZy/F8qijjorlY445Jql76623Dlr2xowZE8uHH354Uvfmm2/G8o4dO5K60dxBoFOx\nbDynZ+J55JFHxrKNrZTGwpbffvvt5HmHHfbOV5u/Juxz6xjPXorloKpr2xxUmXhGJZ2pmZJeMI83\nSDqv4P26KoR3zs2MGTOSus9//vOxfPTRR8ey/YPr3+O3v/1tUnfXXXfFcu6PeA/pm3j6OCxcuDCW\nzznnnKTO/rHctWtXLPuYHHvssbE8e/bspO65556L5V/84hdJ3RtvvNHiUXdV38RSevc/WObNmxfL\nZ511VlL3wgsvHLTs/zFz3HHHxfL555+f1Nnn3nvvvUnd3r17Y7mHttrqq3gii1jWVElnqiUhhJsk\n3TTSn9PCcSSPL7/88lhesmRJUmf/mNp/xfovV/tH/a/+6q+Suh/84Aex/Jd/+ZdJ3f79+1s97J7S\nzVjazo0kXXXVVbFsYydJ5557bixPnjy56fvk7jLau1G+g2TvMq5alf4D8r777ovlpUuXJnVPPfVU\nLPs7J71gpOOZ+wfLZz/72Vj+6Ec/mtSdeuqpsWw7RZI0ceLEWN63b18s206QJE2aNCmWfXvbunVr\nLNuOsiQ99thjsXz33XcndbbjZe+K9YJe+Z5FZxDP/lPSmXpRkv0n/KzGzxJVVS2RtETidmWPO2Q8\niWXfoG3WC22zPmibNVUym2+ZpAUhhBNDCEdIulbSXYd4DXoX8awPYlkvxLM+iGVNtX1nqqqq/SGE\nL0q6V9IYSd+vqmplx44MXUU864NY1gvxrA9iWV9tL43Q1od1+XalHSPjxzTdcMMNsTx16tSkzs7+\n8YOdLTsmxI/Z2LNnTyz//ve/T+r++q//Opb9mI2R1sqshFaMRCwvvPDCWLZjpCRp1qxZsWxnW0pp\n/PxMPBtLez3451k7d+5MHttY2nE6krR58+ZYtmNxJOnBBx+M5R/+8IdJXSfGUHUqllJn4ulnxS5e\nvDiWzzsvHWNrx1CNGzcuqbMx87P57GM7icCPh7Pt1sZPknbv3n3Q95DSwen+devXr4/l73znO0nd\nihUrVKqX2yaGp9faJsq0Ek9WQAcAAChAZwoAAKBArdJ8Y8eOTR5/+ctfjuVPf/rTSZ1NFdlFAqU0\nXWHTBz6VYFM1Pv1j036vv/56Urdy5Tsp8n/8x39M6mxKcCRi00uphPHjxyePv/a1r8Xy3Llzkzo7\nJd6WpTRN5JfAsHKpPRs/P5XexsHHZNu2bbHsF2rdsmVLLH/3u99N6uw10K5eSyVce+21yeOrr746\nlv3CmTaGdi03KW2PufRdLi42fefjaa8Rn261KUC//IFNAT799NNJnb12fcq/Vb3UNlGm19omypDm\nAwAAGGF0pgAAAArQmQIAACgw4tvJjDQ7Dubv//7vkzo71d5vT2LHYvhxE3aMRW7ckq3z72Ef+7E6\nJ554YizbsRaS9Hd/93ex/Oijjzb97Dqw28BI0vz582P5hBNOSOrsOfRj3Gwc/FR3W5fbxse+rtWY\nS+m4L39cdgzfxRdfnNR1YsxUL7AbCl9wwQVJnd0Kxo9ntPH059SOVfJj4Oxzc+PjWm2b/rPt94Jf\n6sEuy2D3D5Skj33sY7F8zz33ND0uAPXEnSkAAIACdKYAAAAK9H2a7y/+4i9i+ZxzzknqbGovNy3e\np4asTqT5PJsOmjlzZlL3+c9/Ppb/+Mc/tnws/ejMM89MHtvlKnxa1v7uflV6e65zqTz7vNwyF55N\nJ/lrJZd+tCkwnxbKpZn7yfnnnx/L06ZNS+rs+fDtz/7+Pl3Xaso1J/e6Vs+3v85sPCdPnpzUnX32\n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\nJF0maYOkZZKuq6pqVecOD91CPOuDWNYL8awPYllfhxW89lxJ66qqekaSQgg/kbRIUtOLIoTQXs9t\nBBx11FGxfMwxxyR1b7311kHL3pgxY2L58MMPT+refPPNWN6xY0dS124HthOqqgpNqoYVz16K5WGH\nvXMZ27hK0htvvBHL+/fvj2UiM8lQAAAgAElEQVQfgxDeOS1HH310Umefu3v37rKD7aBOxbLxnJ6J\nJ23zXfq2bVq2jUnSscceG8v2vPsY2Pbt25+NZS+hbQ5M24xKOlMzJb1gHm+QdF7B+40oG0BJWrhw\nYSyfc845SZ0N4q5du2LZXyD2y2D27NlJ3XPPPRfLv/jFL5I6+we+h/RVPK0pU6bE8hlnnJHUrVmz\nJpa3bt0ay/v27Uued+SRR8by2WefndTZBr58+fKkznbQekhfxZK2eUh9Fc9m/B/Oiy66KJZtG/Nt\nc+rUqbHs29+zzz4by6P5x3YY+iqWtM3WlXSmWhJCuEnSTSP9ORh5xLJeiGd9EMt6IZ79p6Qz9aIk\n262c1fhZoqqqJZKWSCN/u9L2eCXpqquuiuXLL788qTv33HNjefLkyU3f5z3vaT5G3/5Ly/eaX331\n1VhetSq9g3vffffF8tKlS5O6p556Kpbffvvtpp89Ag4Zz27GMueGG25IHn/uc5+L5eOOOy6ps3et\ndu7cGcuvv/568rwJEybE8p49e5K61157LZb/7//+L6m75ZZbmr5uFNE2aZujwqbkJGnOnDmx/M1v\nfjOpW7RoUSzbtpNLBz799NNJnW1/P/vZz5I6e7erh+5a0Tbr1Tajktl8yyQtCCGcGEI4QtK1ku7q\nzGFhFBDP+iCW9UI864NY1lTbd6aqqtofQviipHsljZH0/aqqVnbsyNBVxLM+iGW9EM/6IJb1VTRm\nqqqqX0j6xSGfiL5APOuDWNYL8awPYllPba8z1daHjUDu98ILL4xlm+uVpFmzZsWyHTsjpTNE/CwT\nO+XT5n798yw7HkdKxwD42SmbN2+OZTvDTJIefPDBWP7hD3+Y1HUiF9zKFM9WdHtcxhFHHBHLf/u3\nf5vUXXzxxbHsl0awr7OzSvx1b8+tn25tX/f8888ndT/5yU9i+e67727+C4yATsVSom0eQNs8ND8l\n/pprronl885LJ6adfPLJsXzSSScldXacoh1v49uwHbNo4yNJ27dvj+UnnngiqVu2bFks+7a5fv36\nWB6JMTa0zcFrm2wnAwAAUIDOFAAAQIERX2eq08aPH588/tM//dNY9guATZw4senr/BRey66ya29R\n7t27N3mevQ3pF2+003v9bU67wra91S2lU0/9AnUrVw7uOEWbLvBTee35za1e3srPpXenMez0XZs2\nlNJrbNDRNuvr9NNPj+Wbb745qVuwYEEstxo7KW2DuTZmUz8+LWTjbheUlKT58+fH8sc//vGk7qc/\n/Wks33HHHU2Pqy5omyOPO1MAAAAF6EwBAAAUoDMFAABQoO/GTNncqJTmxU844YSkzuZc7Ua2UpoX\n9xsx2rrcRra5qfbN3k9K89D+uMaOHRvLdsq/VP9xGTk2j+/Pmc3j+3Ntc/D23Prn2Tj768HW+TED\ndnyV3wajjmMvcmib9eGXJ1i8eHEs+7FJ9lz7ZUXsOfRbONlxUrmtmOzUdn892Mf+/e3Yq0mTJiV1\nn/nMZ2LZbtArpduW1AVtc+RxZwoAAKAAnSkAAIACfZfmO/PMM5PHdoVWP2Xe3iYcM2ZMUmdvHedu\nSdrn+Z2wcyur2pSPvx2au41q00jz5s1L6uznj9bO2KPF/u5+6rQ9Z77OsjHx56/VXc5z03UHPc1H\n2zz0Z/eLD3zgA8ljuzRJ7px5/rmWTQnaOOdi6c+tff/cdeTZlJFPC/3yl7+M5bq0YdrmoT+7FHem\nAAAACtCZAgAAKEBnCgAAoEDfjZmaOXNm8tjmfv02IHZ5e59/tUva+7y4fWzLPt9qH/vccrP38M/1\nr7O/w9y5c5M6O13Zb81Qd5s2bYplHwcby9x2B5Y/77nxVHbKtd2lXpK2bdsWy3UZX9Eu2uaQOrRN\nu0WMlC5N4ttYbrq8HVfjx9g0G6eYG2fl49Vqe/djbOz4m+OPP77pc/1yC/2KtjlkJNsmd6YAAAAK\n0JkCAAAo0HdpvmnTpiWP7S28cePGJXX2lqRfmdfecva3E5tNn/RT3+3zfJ29he1vZ9vn+l257THb\nW+tSemu2DqmE4XjhhRdi+emnn07q7FRYf8u+Weott1K6j5e9djZu3JjUrVix4pCfNShom0Pq0Db9\niuF2hWkfS7t6eS6WXqsrYVvDabc2BWiP37+PTwFOmDAhluuS5qNtDiHNBwAA0KPoTAEAABSgMwUA\nAFCg78ZM+Vyp3c7D58XtY5/fbXUp/NwUz1x+174ut1WJ3/7ETtm1v5skzZo1K5aff/75pu9ZR3aH\n+cceeyyp+/CHPxzLfmsLm/O3OffclOrc+A1/3levXt30uYOGtjmkDm1z6tSpyWM7JsWPMbLncNeu\nXUldboxNs3bmx9HkXmOfm5tK76f/2+vFfxfYWNolWfoZbXPISLZN7kwBAAAUoDMFAABQoC/SfPa2\nnb9da2/v+RRPbgqmfZybnpm7jZzbGTv3/rlbzPZ9/G7e/vGgWrt2bfLYTncdThyaye1y7m8T12Xq\ndLtomwd/3O/s1HkpPU8+zrbOt4fhpOyavSa3KnYuJW+vOR8fO2zAX5s+JdavaJsHfzxSuDMFAABQ\n4JCdqRDC90MIW0IIK8zPJocQ7gshrG38f1LuPdA7iGd9EMt6IZ71QSwHTyt3pm6TdIX72a2S7q+q\naoGk+xuP0R9uE/Gsi9tELOvkNhHPurhNxHKgHHLMVFVVvw0hzHM/XiTpY43y7ZIekHRLB48rMXny\n5Fj203LtFMncWJdcfjc3ddMaTv44N1YgN73U/j7+d/XL5LejF+JZaufOnclje858Lt2e61y87DRq\nH3879iC3o3239UIsaZtD6tY2/RYj9rq3bcU/9vGydf7cNotDLj65WPq2accCDWcKvh9f1I5eiCVt\nc0gn2mYr2h2APq2qqgOblG2SNK3ZE0MIN0m6qc3PQXe0FE9i2Rdom/VC26wP2maNFc/mq6qqCiE0\nnVJRVdUSSUskKfc89IZcPIllf6Ft1gttsz5om/XTbmdqcwhhelVVG0MI0yVt6eRBeTNmzIhlv/Kp\nvV3rbwPu3bs3lnNTKT1bl1vJNXdL0t7e9s+zaSo7RVdKbzH7KasjOMWzq/Es5a8Be15yU6Vt3XCm\nbNtp4vbWeY+ibYq22Q4bB58qsSug27KUnkOfAmz2PP84t/xBq+/hP9u+jz9me734ayf3+YVom6pV\n20y0uzTCXZJubJRvlLS0M4eDUUI864NY1gvxrA9iWWOtLI3wY0kPS1oYQtgQQlgs6RuSLgshrJV0\naeMx+gDxrA9iWS/Esz6I5eBpZTbfdU2qLunwsaALiGd9EMt6IZ71QSwHT19sJzNp0jtrm+Wm5eZy\nvz5vmtu5utly98PZsTw3Psfme1977bWkbsqUKbHs89x12eag1PHHH588zk19zU3DtXJxthYsWNDK\nIQ4M2uaQOrRNOzbQxsc/9nVvvvlmLPuxLLk4tNo2c+NvcteAHSflj9kep782c+OC+gltc0i32mY9\n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\n2Fjmth8ZzrIl9nfwv4//3euAtvnu9+807kwBAAAUoDMFAABQoC/SfPZ2sE+zbNu2LZZfeumlpG7L\nlndW6j/++OOTOrvLtL9daT/D3hbM3ZL07K1G/zq74q49Rimd4unfP3erve5sOm04q5c3q8ulC3yd\nvT58TI466qim7zMIaJtD6tA27Xnxq0bb32nr1q1JnU255FZOz62mbePq22wuXjYO/nX2uTt27Gh6\nXP66rUuaj7Y5pFttkztTAAAABehMAQAAFKAzBQAAUKAvxkzZpeP9VE2bR33yySeTOpvf9Xl+W+en\nt9vxArlpljYX6/O0uZyxze+uWbMmqTv77LNjOTedNTfmp+5yu4LnpkPb5w1niqx9T//+fizCoKFt\nvvs9+7Vt2m1F/BYjNiYbN25s+jo/xiY3Zsqeexsvv4WJvY78tij2+vPjF+37+GvMXjuTJk1K6vzv\n3q9om+9+z5Fsm9yZAgAAKEBnCgAAoEBf5CjsbTt/W9Dednz++eeTOnsr8Fe/+lVSl9ttvNnz/NRb\n+7rczti+LrcC7OrVq2PZ3+62v7td8XUQ2N/X36q1t5v9rX6bFsitxmz5W9Q2VeGnjPtbyoOGtjmk\nDm3Tpn6WLVuW1Nk4L1++PKl78cUXY/kLX/hCUjdhwoRY9mmhZvHzsWzWhqU0Rj49t2rVqli+++67\nkzr7PhMnTkzqnnnmGdUBbXNIt9omd6YAAAAK0JkCAAAoQGcKAACgQF+MmfrP//zPWN60aVNSt379\n+lj2WxmMtFZ3Pc/x+d2lS5fG8tFHH53U2Vy+3x6h7uzUXj8u4/LLL4/lOXPmJHVHHnnkQcuejaWf\nRmynGD/++ONJ3T333JM77NqjbQ6pQ9u0Y0uee+65pM4/tux2JI8++mhSN3v27FieMmVKUjdv3rxY\ntmMd/fgeGwc71kdKp8uvXbs2qbPXYyeuh35D2xzSrbbJnSkAAIACdKYAAAAKhG7e/gwhbJX0vKQp\nkl7u2gc3N2jHMbeqqqmdeCNimdWNY+lYLKUYz90arHPYCtpmuV45Dom22Qm9Es+eaptd7UzFDw1h\neVVVH+r6B3McHdcrx94rxyH11rEMRy8dd68cS68cRzt65dh75Tik3jqW4eil4+6VY+mV4ziANB8A\nAEABOlMAAAAFRqsztWSUPtfjOMr1yrH3ynFIvXUsw9FLx90rx9Irx9GOXjn2XjkOqbeOZTh66bh7\n5Vh65TgkjdKYKQAAgLogzQcAAFCgq52pEMIVIYTVIYR1IYRbu/zZ3w8hbAkhrDA/mxxCuC+EsLbx\n/0ldOI7ZIYRfhxBWhRBWhhC+NFrHUoJY1ieWEvFsfGYt4kks6xNLiXj2Syy71pkKIYyR9C+SPinp\nNEnXhRBO69bnS7pN0hXuZ7dKur+qqgWS7m88Hmn7JX2lqqrTJJ0v6ebGeRiNY2kLsYz6PpYS8TT6\nPp7EMur7WErEs6E/YllVVVf+k/RhSfeax1+V9NVufX7jM+dJWmEer5Y0vVGeLml1N4+n8blLJV3W\nC8dCLAcvlsSzXvEklvWJJfHsr1h2M803U9IL5vGGxs9G07SqqjY2ypskTevmh4cQ5kk6W9Ijo30s\nw0QsnT6OpUQ836WP40ksnT6OpUQ8E70cSwagN1RD3duuTW0MIYyTdIekL1dVtXM0j6VuiGW9EM/6\nIJb10s1z2Oux7GZn6kVJs83jWY2fjabNIYTpktT4/5ZufGgI4XANXRQ/qqrqztE8ljYRy4YaxFIi\nnlEN4kksG2oQS4l4qvE5PR/LbnamlklaEEI4MYRwhKRrJd3Vxc8/mLsk3dgo36ihXOyICiEESd+T\n9GRVVd8ezWMpQCxVm1hKxFNSbeJJLFWbWErEs39i2eWBY1dKWiPpaUl/0+XP/rGkjZL2aSjvvFjS\ncRqaBbBW0i8lTe7CcVyooduRj0t6rPHflaNxLMSSWBLP+sWTWNYnlsSzf2LJCugAAAAFGIAOAABQ\ngM4UAABAATpTAAAABehMAQAAFKAzBQAAUIDOFAAAQAE6UwAAAAXoTAEAABSgMwUAAFCAzhQAAEAB\nOlMAAAAF6EwBAAAUoDMFAABQgM4UAABAATpTAAAABehMAQAAFKAzBQAAUIDOFAAAQAE6UwAAAAXo\nTAEAABSgMwUAAFCAzhQAAEABOlMAAAAF6EwBAAAUoDMFAABQgM4UAABAATpTAAAABehMAQAAFKAz\nBQAAUIDOFAAAQAE6UwAAAAXoTAEAABSgMwUAAFCAzhQAAEABOlMAAAAF6EwBAAAUoDMFAABQgM4U\nAABAATpTAAAABehMAQAAFKAzBQAAUIDOFAAAQAE6UwAAAAXoTAEAABSgMwUAAFCAzhQAAEABOlMA\nAAAF6EwBAAAUoDMFAABQgM4UAABAATpTAAAABehMAQAAFKAzBQAAUKCoMxVCuCKEsDqEsC6EcGun\nDgqjg3jWB7GsF+JZH8SynkJVVe29MIQxktZIukzSBknLJF1XVdWqzGva+7ARMGPGjFg+7LDDkrq3\n3norlu35efvtt5Pnvec97/RFQwhJnX385ptvJnVbtmxp44g7o6qqcLCfDzeevRRLy8fh2GOPjWUb\nS3/d22tg9+7dSZ2PX6/oVCwbr+nJeA6SurfNQULbrJdm8bQOO9QTMs6VtK6qqmckKYTwE0mLJDW9\nKEbTmDFjksdf+MIXYnnatGlJ3c6dO2P5jTfeiOW9e/cmzxs7dmws+w7Z4YcfHssvvfRSUvdP//RP\nsdxuZ3YE9FU8m7HnXZIuuuiiWLadon379iXPmzp1aiwvX748qXv22WdjuYfilVOLWCIinvVBLGuq\nJM03U9IL5vGGxs8SIYSbQgjLQwjLfR16yiHjSSz7Bm2zXmib9UHbrKmSO1MtqapqiaQl0ujerpw0\naVLy+Itf/GIsjxs3LqmzqSJ7R2v//v1Nn+fvWu3ZsyeWt27dmtT967/+a9PX9bJeiaW/CzhnzpxY\n/uY3v5nULVq0KJZtTHLpwKeffjqpu+WWW2L5Zz/7WVJn73b1yV2rqFfiiXLEsl6IZ/8puTP1oqTZ\n5vGsxs/Qn4hnfRDLeiGe9UEsa6qkM7VM0oIQwokhhCMkXSvprs4cFkYB8awPYlkvxLM+iGVNtZ3m\nq6pqfwjhi5LulTRG0verqlrZsSNDVxHP+iCW9UI864NY1lfbSyO09WGjmPu99NJLk8f//u//Hst+\n3FJuyQPLLqFgy1I6W8yO1ZGk66+/PpZXruxuO2plimcrRjqWxxxzTPL4mmuuieXzzjsvqTv55JNj\n+aSTTkrqJkyYEMt2XNRRRx2VPO+1116L5c2bNyd127dvj+UnnngiqVu2bFks33333Und+vXrY9kv\nq9EJnYqlxLiMXtAvbROHRtusl1biyQroAAAABehMAQAAFBjxpRF6xQc+8IHksU3f+RSdZVN+nk3d\n+Pew728X95SkU045JZa7nebrZaeffnos33zzzUndggULYtkvjWD51cttGtsuwHrEEUckz7OpWLto\nq5SmgRcuXJjUzZ8/P5Y//vGPJ3U//elPY/mOO+5oelwAgP7GnSkAAIACdKYAAAAK0JkCAAAoMDBj\npmbPnp08zi1r0GyclF8mwT7Pj4Gx24z497PbnwwyvzzB4sWLY9mPTbIxsudWko488shYfv3115M6\n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\nO++8pM6OS/bXSG6VfHsN+nGCth378X4HYt/q3wPuTAEAABSgMwUAAFBgYNJ8fmkEeyvT3wK2t/7s\npsT+dt/mzZtjef78+UmdvZXZi1NlR4tdidgvf2Bjkqvzt2pzm1w2S/PltLqKuj9On861x+mnWJeu\ntttNuY2ebV0uBZNL1+Vuo/t0mn1PWzecVE1u9XWfPmiV/fzc+3dj5fuxY8fGTWEvvfTSpM6mPHxa\nw6bT/LR/m+bzSwnY1+U2lfbXgH1dLpWXO5+WvwbsY3/ec8tv5L6H7LXkv9db/X7pFvsds3jx4qZ1\n/rzZ7+j169cndc8880ws+xTgiy++GMt22Rt/vdgV9D/ykY8kdRdccEEs+xSgvUb8SuY2nv4atH+b\nfczsefAbZR+4XltNzXNnCgAAoACdKQAAgAJ0pgAAAAoMzJip4UxXtXnV3Ot8zthqNc8/aGzeOze9\n3C/73+r01Nz4mNyYBptnz4298Pl4O6bCj69o9h5Sfy2NYMfZDOe6bneJiVa3vhiJMXCt1g1nGr59\nbqe34ziYqqq0d+9eSem4TkkaN27cQY9LSreF8W3Tv3+zx74utwSNHWNon+fHHtoxN34LKtse/XgY\n+55+3MuB83OwOrvEia975ZVXYtkvDXBg+Z1ubhlk26NfEuCqq66K5ZkzZyZ1dimf3HIBU6ZMSerm\nzJkTy/5vY7NxaH4pmwPj+STphBNOSOrsY39+rQ0bNiSP7XevvY4ladKkSbHsv7/sEjz2edI77TjX\nFpLnt/QsAAAAHBSdKQAAgAIDk+azt3Wl9HafT93YabS5qcw2zZfbsbwb06H7UW4FdH/LvtnK115u\nxeJciij3nrn0neVTk/Z1uSUFel2ryxh4ud8xly60sfFts9kq5LnU03BinVtKw35e7j18e7fH4pdo\nGQn79u2L6b0HHnggqZs9e3Ys+10b7FIJPg1tUzU+nWQf+9fZOPuY2/Nk67Zt25Y8z54/n1pqdecC\nH6/ccjU2veSP2U7J96u9H7heurlEgv29cit/+90ZbLo318bsMglSet7897dNz+bOod2NxJ9DG/t1\n69YldStXroxl38bscgt2lX8p/d1zS9I8+uijyeMDn8EK6AAAAF1AZwoAAKAAnSkAAIACAzNmyuZp\npdbHrOSmRdpplZ7Nzfrl9AeZzXXnxiL5Op9bbya3nUxumYTc+JtWxwz5Ovu7+unSrU637QWtjkXx\n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\nZ2eI+FkmdrqmHTPln2ft3LkzeWzHAPjZKZs3b45lmyOWpAcffDCWf/jDHyZ1nRhD1coUz1Ywxmb0\ndSqWEvHsBf3SNv109muuuSaWzzvvvKTu5JNPjuWTTjopqZswYUIs23FRfsq9neFlvzslafv27bH8\nxBNPJHXLli2LZT/GZv369bE8EmNTe61tHnHEEcnjxYsXx7KPmR1DNW7cuKTOxt7HyT62M9/9uGM7\ns97+nZTSpS/87Hl7HfjX2Xh+5zvfSepWrFihUq3EkxXQAQAACtCZAgAAKNB3ab7x48cnj7/2ta/F\n8ty5c5M6O1XTlqX09qWfimvlUns2feeneOZW9N22bVss2yUUJGnLli2x/N3vfjepW7myPLXeL6kE\nHFqvpRJQppfb5umnnx7LN998c1K3YMGCWPZLI1h+6Zqjjz46lm2KyKekbErHr4pt00I+nWS/k+33\nqiT99Kc/jeU77rgjqevE38Rea5vXXntt8vjqq6+OZZ+2tX8rbYykdAX0XPou9/fPpu/83037t9in\nX22s/fIHNgXol8+wfQS/TEOrSPMBAACMMDpTAAAABehMAQAAFBjx7WQ6zW4DI0nz58+P5RNOOCGp\ns+OdbK5XSvO4fgqmrfM5Xcu+Lpdn93V23Jc/rrFjx8byxRdfnNR1YswUAByKn/Zup9LbTeKl9HvQ\nj2Wx32+vv/56Ume34PJT3S07dsZ/V9vH/v3t2Cu7hYkkfeYzn4llPw7LbvfVz+z4tQsuuOD/Z+/e\nY+6q6vyPf5bcodILtKW0hTJQEOQyqCgKCBPAQSMiZpxICJLYBP/ARBP/AJn5z2Ti+IcZY2YmIVFB\nf0RnEjXgMECwCmOxo4BhtAWhRUsv9AaFtpS77t8fPd1815eeb/dz1nnOs89+3q+EdJ1nnct+9vfs\n/SzWd12yOrsVjP2bI+V/N/3fLhtfP9bYPjcah2yf58dF2cf+s+0YLT+uzn5f7WbMknTJJZfU5Xvv\nvbfvcZWiZwoAAKAAjSkAAIACY5fmO/vss7PHdmVzP/XWdhPaaZtS3p0YpfLs8/xU0GjlXNvN6bum\no/Sj7Zr13ZX28ydj1d5x4buQ58yZU5f9UhZbtmwp/jz/3bGibmlgXL3nPe/JHtuVzKP7meefa9mU\nkb0HR/dZf9+z7x/d4z071MIPp/jZz35Wl8f5mj7//PPr8vz587M6+3fHx8+ef3+vbTq0JRK9runf\nNR9r+3fT/j2QpHPPPbcuk+YDAABoKRpTAAAABWhMAQAAFBi7MVMLFy7MHtsxU35Z/GgHarsVjM/h\n9lsKP5rG6XO40XL69rn+dfZ38Nvj2Omf9nebDux5Ouecc7K6U089tS7bbQWkPEcejY2z7HdKkt71\nrnfV5eg79uijj2Z1fqo2MC7sFjFSvsWI3zImWmbGXnP++vNjo/q9R7/P2t+x9OPHptpxQvPmzev7\n3HG+hu0SFjNnzszq7HII/eIgxcsGNTWRZYMi0XHaePq/qSeddFJd9t+DQbeX2R96pgAAAArQmAIA\nACgwdmk+P8XTpr5mzJiR1dlUnl+Z13Y5+67GftMz/TRR+zxfZ7skffekfa6douuP2XatS3n6qQtp\nPn/ObFet363cTvM966yzsroTTjihLu/YsSOrW7duXV22u4n77mvb7X3eeef1/WwfSxuvBQsWZHUr\nVqyoyy+88ELf10VpDWAq+BXD7fXh77N29fLoPusNMs3eP8/eQ/y1aVOAfpVv+z4+9WNTYuOc5ps7\nd25d9vdT/9iyMZvI8JhhL9cTDZ3xK6BHq7bb76vfJcX+fShFzxQAAEABGlMAAAAFaEwBAAAUGLsx\nU36Mkc39+ry4fezzqE23kImWRojGRdnXRVM6o9yvz2svWrSoLj/zzDN937PN7DgGu+SAlE/H9tOV\n7e/ut9mxefD169dndR/60If2+x4+/nbcxJlnnpnV2TFZfssiuxSDj5ddxmPr1q1Z3fPPP1+Xn3ji\niaxu48aNdXmct7OYSnYsjZ0iLuVTpe+7776sbjpv02TZ8TZSPlbGjzGy97fdu3dnddHY1H7fbT+W\nMnqNfW60BI1f0sTG2S+vYO8Tw9iOaqrY39mOa5Py+5iPZ3T+7Riq6O+hNZFrqunfVH+M9t7rx6fa\ncW+MmQIAAGgpGlMAAAAFxiLNZ7vwfHetTYv53a+jpQvs42hZg6gb2b5/tPxBtKSC72K27+NTSv7x\nOPDTWy+++OK6fOGFF2Z1NrXn0592WQi/mq/tprZd9FJ+rm26x8fSTun2SxzYrmH//bPTbn187Pv4\nrm7bFf3ud787q/vlL39Zl/2q6qT99s+npZYtW1aXr7zyyqzOpjz86773ve8VH4u/D9nP8GmjtqYV\n7ZIzUn4P89eArfNLCUwkZdfvNdFuEtH1YOPgr83XXnttv8+T3j6UZFzt2rWrLr/44otZnb2n+Xu0\nf2xFw2P6xSka5hL9XY7SfP66scfsd8Gwqeemu2AMgp4pAACAAgdsTKWUvpNS2pZSWmV+NieldH9K\naU3v39nRe6A9iGd3EMtuIZ7dQSynnyY9U7dJusL97GZJy6uqWippee8xxsNtIp5dcZuIZZfcJuLZ\nFbeJWE4rBxwzeHTZQwAAIABJREFUVVXV/6SUlrgfXyXpkl75dkkPSLppiMeVmTNnTl320zjt2Bqf\nY2263UvTKZ4TGXcVjRWI8rb29/G/q99eZhCjjucpp5ySPb7sssvqsl+CwI6F8nl7GxO/nYU9T378\nQ79d5f02CfY7EG0v4eNqn+vHctlxXv47ZseW+C2S7HPXrFmT1e3cubMut+HaHDV7/j/xiU/U5c9+\n9rPZ86Kd4u35vu6667K65cuX1+VNmzY1Pi77nbzxxhuzOjsm7utf/3pWt2pV3XHRqnj6a8xeL9EY\nm2gsi7/v9btHRvfO6D7rr2l7L5jI0jV+TNgg2hDLlStX1mV/H7T3H3utSPn4Mv+6icRmn2g5i+j9\noq277H1QyseE/eEPf8jq7LZeq1ev7vt5pQYdgD6/qqrNvfIWSfP7PTGldIOkGwb8HIxGo3gSy7HA\ntdktXJvdwbXZYcWz+aqqqlJKfadUVFV1q6RbJSl6HtohiiexHC9cm93CtdkdXJvdM2hjamtKaUFV\nVZtTSgskbRvmQXnHH398XfZT5m0Xou9GfvXVV+tytASBZ+ui6ZhRF6Xt3vbPs1NW7RRdKe9i9imr\nSVwaYajxtOfPrkAu5Wk/n7a0v1+0y7v/Dthp3P470G9FXf+8aHVdeyx+yrj9Tvg0g/0M/3n2ffzn\nnXzyyXX5xBNPzOp+97vf6QBGem1OBhunU089Nauzabmzzz67LvsV8+1yKj5mNu3nV+G//fbb67Jf\nHf2pp56qy35JhQsuuKAun3HGGVndMcccU5evvvrqrM6m+foYWTztPdKnRm2KxZal/PsbTauPUnTR\n8gdN38N/tn0ff8z2uvX39UlcfmSk16ZNb/3qV7/K6uwSMtdee21W98lPfrIu+5Sn/XsVpU6j+2nT\nNF8Uz2effTaru+OOO+rygw8+mNXZZW8m06BLI9wl6fpe+XpJdw7ncDBFiGd3EMtuIZ7dQSw7rMnS\nCD+QtFLSaSmljSmlZZK+JunylNIaSZf1HmMMEM/uIJbdQjy7g1hOP01m813Tp+rSIR8LRoB4dgex\n7Bbi2R3EcvoZi+1kZs9+a22zaFpuNGbKjzeKdqfut03MRHYsj3LGNu/sl7630+n92KBx2ebAHvcJ\nJ5yQ1dmxLX7MlB3nEo1x8/GyY5Xse0j5uDP7/YiWw/CfbR9HSzZEY6Z8XTSd3J6jxYsXZ3UNxkyN\nBXtN+O10rrrqqrq8dOnSrM5ug2HvCz7udpybH/9jH/vXnXfeeXX5nHPOyer27NlTl6PxIn6ciX3u\nxz72sazuq1/9qtrCji2z907/2NfZMSl+DGh0j2w6diYatxrdn+04KX/M9jijcZZd4c/b+vXr6/JP\nf/rTrO7yyy+vy365l+jc2HtcFJfob6M9zuj7snbt2qzOLmkyVVs0de9bAwAAMEI0pgAAAAqMRZrP\ndsX7NIvt+vNdzDaFFqXIfHei/YxopdyoCzuaImy7nP1KrtFUX5+uaCu7erI/7zYFEq1kPpGdzKNp\nzjbNZ7uhfdotSvPZOr9cRfQdsOkDX2dTI76r26akxyXm+xMtcfDxj3+8LtslDqQ8zelT3fb7Y+8L\nPrVmY+hjFsU6StfZ77Kfam9F30E7JV16K7Xm01BTwV6Pfjq5PT4/NKGppqtdR2mapvcBKf8ddu/e\nndVFKfhoh4ouilb69+c7ik2/e2H0Hk2XKPKve/755xsf16jQMwUAAFCAxhQAAECBsUjzNd0A13c/\n28c+zdIv/ePZrkvf9W2PJUobefa5O3bs6Fvnf1e74bNPT7Spa9oemz8P0cw4W+d/v36pVylehXyQ\n1Yz9MdvPjup8DOzvEM3ma/pdmSr2+Hzaze5O4DdMfe9731uX/UrjdlVwP2PIzirzK+Hbz7dln8rz\nr7Oi75K93qMdD/z72zhF16JPe+/73aO04ajY8/nyyy9nddF90D6O7kvRUIhoeEN0Pu3ros/2fxui\nlOM4p9YHYTc9lvKUrj9P9hxHM/Hs9eDjHs3MtqLvSxvuix49UwAAAAVoTAEAABSgMQUAAFBgLMZM\n2TEUfmyE5ae/2lx+tGq212/chH+PprnfyK5du7LHTacF+7z+oNOVJ4ONkT9OWxeNf5sIG6+m452i\nZS4mEufodU1Xbo7GlY1ybMC+c/WRj3wk+7ldCdzH065ib8f0SfnSBfYa9q/zddH1bh/bMT5+vEz0\nPYvGfURxsfGMxuL597TP9edv/vz5kt6+RMpUsOc9Gi8WLTPgd5ro9x5Sfn6j1dCj8TdN+ftjNC4q\n+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\nrkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e0391b38>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" \n",
"generated_images = cgenerator_patch_fashion.predict(y_noise, verbose=0)\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 124,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e063e358>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"t_shirts=keras.utils.to_categorical(np.array([0]), num_classes=10)\n",
"generated_images = cgenerator_patch_fashion.predict(t_shirts, verbose=0)\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 126,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e03b6630>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"long_shirts=keras.utils.to_categorical(np.array([2]), num_classes=10)\n",
"generated_images = cgenerator_patch_fashion.predict(long_shirts, verbose=0)\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 127,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e401a630>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"dress=keras.utils.to_categorical(np.array([3]), num_classes=10)\n",
"generated_images = cgenerator_patch_fashion.predict(dress, verbose=0)\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 142,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"y_input (InputLayer) (None, 10) 0 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 200) 2200 \n",
"_________________________________________________________________\n",
"batch_norm_1 (BatchNormaliza (None, 200) 800 \n",
"_________________________________________________________________\n",
"activation_1 (Activation) (None, 200) 0 \n",
"_________________________________________________________________\n",
"dropout_1 (Dropout) (None, 200) 0 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 1200) 241200 \n",
"_________________________________________________________________\n",
"batch_norm_2 (BatchNormaliza (None, 1200) 4800 \n",
"_________________________________________________________________\n",
"activation_2 (Activation) (None, 1200) 0 \n",
"_________________________________________________________________\n",
"dropout_2 (Dropout) (None, 1200) 0 \n",
"_________________________________________________________________\n",
"dense_3 (Dense) (None, 6272) 7532672 \n",
"_________________________________________________________________\n",
"batch_norm_3 (BatchNormaliza (None, 6272) 25088 \n",
"_________________________________________________________________\n",
"activation_3 (Activation) (None, 6272) 0 \n",
"=================================================================\n",
"Total params: 7,806,760\n",
"Trainable params: 7,791,416\n",
"Non-trainable params: 15,344\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"intermediate_layer_model = Model(inputs=cgenerator_patch_fashion.input,\n",
" outputs=cgenerator_patch_fashion.get_layer(\"activation_3\").output)\n",
"intermediate_layer_model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 131,
"metadata": {},
"outputs": [],
"source": [
"def intermediate_layer_generator():\n",
" y_input = Input(shape=(6272,), dtype='float32', name='y_input')\n",
" \n",
" x=Reshape((7, 7, 128), input_shape=(128*7*7,), name='reshape_1')(y_input)\n",
" x=UpSampling2D((2, 2), name='upsampling_1')(x)\n",
" x=Convolution2D(64, (5, 5), border_mode='same', name='conv2d_1')(x)\n",
" x=BatchNormalization(name='batch_norm_4')(x)\n",
" x=Activation('relu', name='activation_4')(x)\n",
" x=UpSampling2D((2, 2), name='upsampling_2')(x)\n",
" x=Convolution2D(1, (5, 5), border_mode='same', name='conv2d_2')(x)\n",
" output=Activation('tanh', name='output')(x)\n",
" model = Model(inputs=[y_input], outputs=[output, y_input])\n",
"\n",
" return model"
]
},
{
"cell_type": "code",
"execution_count": 132,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/site-packages/ipykernel_launcher.py:6: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(64, (5, 5), name=\"conv2d_1\", padding=\"same\")`\n",
" \n",
"/Users/Mami/.pyenv/versions/3.6.2/lib/python3.6/site-packages/ipykernel_launcher.py:10: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(1, (5, 5), name=\"conv2d_2\", padding=\"same\")`\n",
" # Remove the CWD from sys.path while we load stuff.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"y_input (InputLayer) (None, 6272) 0 \n",
"_________________________________________________________________\n",
"reshape_1 (Reshape) (None, 7, 7, 128) 0 \n",
"_________________________________________________________________\n",
"upsampling_1 (UpSampling2D) (None, 14, 14, 128) 0 \n",
"_________________________________________________________________\n",
"conv2d_1 (Conv2D) (None, 14, 14, 64) 204864 \n",
"_________________________________________________________________\n",
"batch_norm_4 (BatchNormaliza (None, 14, 14, 64) 256 \n",
"_________________________________________________________________\n",
"activation_4 (Activation) (None, 14, 14, 64) 0 \n",
"_________________________________________________________________\n",
"upsampling_2 (UpSampling2D) (None, 28, 28, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_2 (Conv2D) (None, 28, 28, 1) 1601 \n",
"_________________________________________________________________\n",
"output (Activation) (None, 28, 28, 1) 0 \n",
"=================================================================\n",
"Total params: 206,721\n",
"Trainable params: 206,593\n",
"Non-trainable params: 128\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"intermediate_layer_generator = intermediate_layer_generator()\n",
"intermediate_layer_generator.load_weights('cgenerator_patch.h5', by_name=True)\n",
"intermediate_layer_generator.summary()"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
" [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
" [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
" [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])"
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y_noise[t_shirts]"
]
},
{
"cell_type": "code",
"execution_count": 143,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e7e546d8>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"image0 = intermediate_layer_model.predict(t_shirts)\n",
"image1 = intermediate_layer_model.predict(long_shirts)\n",
"image2 = intermediate_layer_model.predict(dress)\n",
"generated_images=intermediate_layer_generator.predict(np.array(image0))\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 144,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e401a5c0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"generate_space=[]\n",
"image_num=4\n",
"for i in range(image_num+1):\n",
" generate_space.append(image0*i/image_num+image1*(1-i/image_num))\n",
"generated_images=intermediate_layer_generator.predict(np.array(generate_space)[:,0,:])\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "code",
"execution_count": 145,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAACDCAYAAACp4J7uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAHNxJREFUeJztnWusXVW1x/9TBLG0HPvyWPqgrTQo\nWKUGr9ReldgSuUajMXjVkGsTSYgJ16jRBOTqd77oF3O/kKD4oUpuokaMSsUGvGlAEEqFUmkPrZS2\nnD6QR0sftOi6H8529j/HPWuctffaj7Xn/v+SpmOdsfdas+u/5jqzc4w5ZiiKAkIIIYQQojPeNOgG\nCCGEEEIMMxpMCSGEEELUQIMpIYQQQogaaDAlhBBCCFEDDaaEEEIIIWqgwZQQQgghRA00mBJCCCGE\nqEGtwVQI4foQwq4QwrMhhNu61SgxGKRnPkjLvJCe+SAt8yR0WrQzhHAegN0ArgNwAMCfAHyxKIqd\n3Wue6BfSMx+kZV5Iz3yQlvlSZ2bqXwA8WxTF3qIozgC4B8Cnu9MsMQCkZz5Iy7yQnvkgLTPlzTW+\nuxjAfjo+AOCD3hdCCI3Zu+bNbz73T3/rW9+a+F5//fVov/HGG9G2s3ghhGjPmjUr8fFnT5w4Ua+x\nXaQoilDiakvPJml5/vnnR9vqwFqePXs22lbLN73p3P8rLrroosT397//PdpWy0Fux9QtLYFm6fmW\nt7wl2rZvnjlzJtqs5z/+8Y/kc9y/Z8+enfj4e8ePH098OejZVC1t32QdWFfub4CvJb+frZb2megn\nufbNCy+8MNpe32Tb65v2XcufffXVVxNfQ/tmpM5gqhIhhJsB3Nzr67TLggULor169erEt3v37mgf\nPXo02tz5gfTBWrNmTeLjh+mxxx5LfPwCGCaaoiUPYgHgHe94R7Tf9773Jb69e/dGe3JyMto8yALS\nl/QHP5i+2/gl/dBDDyU+1nnYaKqeS5YsifZ73/vexHfw4MFpbTvI5f79oQ99KPFxn37wwQcT3+nT\np6M9TPuWNkVL/k8JACxfvjzatm++8MIL0T5w4EC0jx07lnyOtbzmmmsSH//Cvf/++xMfaznIgVUn\nDKOe+/fvn9Z+7bXXks/Nnz8/2lZP/uzmzZsTX9P7Zp3B1EEAS+l4SetnCUVR3AngTmCwI+wvfelL\nyfGNN94YbRYXSDsvd+xTp04lnxsbG4v2yZMnEx8/FH/+858T36233lr6vQEyo56D1PLiiy+O9je+\n8Y3Et379+mizJkCqJd9r7pgAMG/evGk/B6SDqT179iS+7373u9F+5plnyv8B/aVxfZNnDwFgw4YN\n0f785z+f+N7znvdE+21ve1vimzt3brR5IGsHx6yn7bf8C/jQoUOJ79e//nW0f/KTnyQ+Hrz1+Zfz\nwPsmD3j5Py8AcMMNN0T7Yx/7WOJ717veFW3WBEi15f9g2r7Jn7O+l156KdpWy4mJiWj/7ne/S3z3\n3HNP6Tl7TCP6Jut5ySWXJL7Pfe5z0f7oRz+a+N797ndH2/7eZJ144sHeX+7DdmKB/6Pz3HPPJb7t\n27dH+7e//W3i44HXoP6DWydn6k8AVoUQVoQQLgDwBQD3dqdZYgBIz3yQlnkhPfNBWmZKxzNTRVG8\nEUL4TwCbAZwH4IdFUTzdtZaJviI980Fa5oX0zAdpmS+1cqaKovgNgN90qS1iwEjPfJCWeSE980Fa\n5knHdaY6ulif82wuuOCCaH/nO99JfB/5yEeibVcl8Pd4ZYm9V5w3YeO0/L19+/YlPo7X29hvr6my\nKqEK/daSExVvueWWxMdJkVZLXk3kPeuelhz/5xwNAHjiiSeifccddyS+XufDdUtLoDd6Xn311dF+\n//vfn/jWrl0b7WXLliU+1tCu9mEfa2aT2NlnczY4T8NqxInsNgeOc3B+9KMfJb5u5N00qW/y4hoA\n+OpXvxrtq666KvEtXLgw2nPmzEl8rJddzVdVS8bmv3GunF0FyJpYnQ8fPhzt733ve4nv8ccfL71+\nVZrWN/l3GgDcdNNN0bYLbjiHyq6e5P5o37V8zFrYJPbzzjsv2l7/s3pyHrL93vPPPx/tH/zgB4lv\nx44dqEsVPbWdjBBCCCFEDTSYEkIIIYSoQc/rTA2Syy67LNq8tB7wCz2WhYO8MJENR/D0s51itcu9\nxRQ8vW+n+j/wgQ9E295P1pLDeu3AYQZ7fm4LF5wD0ufK6uqFIHJk8eLFyTGXI7GlEXiZvA0D8P23\nPtaJbXt/2eeFGayP22mXjHPoy9a/2rZtW7SHuI5ctDdu3Jj4OCxr34N8z2z/4Httv8f9g3227ARr\na3XmNntpGNwOIC2Z8pWvfCXxfetb34q2LRw5rHz2s59Njj/84Q9H2/7u4neo7bfcX2zdRb7frIXV\nhTW0fcX7HcDXtu9oLtfx5S9/OfHdfvvt0e5lGQzNTAkhhBBC1ECDKSGEEEKIGmgwJYQQQghRg6xz\npjiHxS715di+t4Gxt7Se4702ls8+m0fAMWobF27inkP9gmPiNpeFl+h6cXybb8E+b8m1d46qGyTb\nvDwuo5BrzhTrwlvEAOm2EXbJPOc82P7B2PvG95/1tJqV5W8A1bebsG3mc1555ZWJj7edatC2Qm3B\nuaN2r1H22bxE1s8rUdHpNh9e/o3XN7kt9p3Bz9X4+Hji++QnPxntTZs2ddDiZsC6rFu3LvHxVjBW\nT75XXt/xfnd571ovP87rt17OFJdl4FI5AHDttddG+7777ittV100MyWEEEIIUQMNpoQQQgghapB1\nmM+bFuQpUOtjvFCCDUUxPFVqp5h5ylxhvulp5754S93LNLJa8vW8c9gl1l6JDW+qOxdWrlwZbVst\n2QvP2PvfCV5IwLu25/NCQ/wc2DIYixYtivawhvk4TPv2t7898fH70vYBPvbCfJ1SVWfvWrZdfGwr\nefMzPczwrhE2lMlpL95zbu+btyNIVaruROFhn0F+PrnsCpCGrBXmE0IIIYRoKBpMCSGEEELUQIMp\nIYQQQogaZJ0zdejQoWh7y929pdmMjdN6+VS8u/nLL7+c+HjJvHKkzuFtAfLKK69M+zkgLUNhS2Dw\nefheWy3L2mG/x1tgAOn2BHZrhG7kiwwT9t5wH7B5KYy3FUzVfKdOc6Y8bLu4pAlvX2EZ1jxI3n5r\nbGws8XFeqe07/O/zSll4+Wll35npHN6zwni5jvZdw/lv9n3Sy+1Ius3ll18ebasnl0Pwcn89Pavi\nfaed81XNUbZar1ixItq91FMzU0IIIYQQNdBgSgghhBCiBlmH+fbv3x/tPXv2JD6ukmqXAZdNPXrT\n1HYKkivFTk5OJr4dO3bMeK1RxAsX7N27N9ovvvhi4mP9vOX5VX4+HRy+O378eOLj8COHb4HOKz4P\nK7YPnDhxItp26p1DZjY8ysfe1H6npRe873nn4DbbsCWnDQxrmI8r+Nv7zv9e+++z4V2marmCTpfL\nVw0h2eX/fMzhaCCt3G/Duc8991zp9ZrGwoULo23LtthjxtvZw6s43+20Bi+cbMsZeVXb+XdCL/XU\nzJQQQgghRA00mBJCCCGEqIEGU0IIIYQQNcg6Z4pj+du3b098a9eujbaNp5ftjO2VUPBi9/v27UuO\nd+3aVfpZMYWNv+/cuTPaV111VeJbtWpVtG2cnWP+rKX9nFeWgbU9fPhw4nv00UejffTo0dLv5Qrf\nX5sjdvDgwWhz/hSQ5i7YrVmYTnem92Ct7XPG/x6bH8efff755xMf514Mq+78HnzttdcSH+fY2Hwx\nvmde3+mUqjp7W8ZYnb1njvOC5s+fn/iGKWeKc/xOnjyZ+Dg/zpYL8O43a111e7V2cqn4HN6zZNvI\nz6ctRcQ5ccqZEkIIIYRoKBpMCSGEEELUIOswHzMxMZEcc9jBTifyFGLVKWZ7Dp7atGE+uxRXzMzf\n/va3aHNle8Bfms14pSy8JfisJYeuAOCBBx5oux05wf3K6rJ69epor1u3LvFxSNDeNy+UUFa53ut/\nHrYvcvjukUceSXwHDhyI9tatW93zDCOvvvpqtG2Ik5fZ23QHr1/xMvtOw7Ie3rW9nQs4pGnD0/zs\nDFPFc8uxY8eizSVcgDTcZfuUtzuELWPClJUc8d6tXmjW09N7L9gQNT/LXvvropkpIYQQQogazDiY\nCiH8MIRwJISwg342L4RwfwhhovX3XO8cojlIz3yQlnkhPfNBWo4eVWam7gZwvfnZbQC2FEWxCsCW\n1rEYDu6G9MyFuyEtc+JuSM9cuBvScqSYMWeqKIr/DSEsNz/+NIBrW/aPATwI4NYutqvrcPwYSMvR\n2xyAsji/je9ynNbGd3mppi3JP0iGVU9ermy3bWH9vPIVrJHV0ovr87Niv8ft6jdN0JLzTeySZC5n\nwVt0AOmu9bxMG0i3B/LyN9hncyiq5sfZXBrOb3zqqacS3+7du6PdixypQevJ+X82t4TzUJYuXZr4\neLsOWzah6lJ31tLbpsT2v6pbzdh3Bv/7nnjiicT3i1/8Itr8DLfDoLUEgIcffjja9r3Iz++KFSsS\nH/dHLz/OUubztmHzzmefF37Xcn4fkOaEPfPMM4mP8xuffvrp0uvVpdOcqfGiKP654dwhAONdao8Y\nDNIzH6RlXkjPfJCWGVN7NV9RFEUIobQyWwjhZgA3172O6A+entJyuFDfzAv1zXxQ38yPTgdTh0MI\ni4qimAwhLAJwpOyDRVHcCeBOAPAenl5jd5nmqcyqO497U5L2HDzdPW/evMrtHBCV9Bykljydb6ee\nOWTk0Wn1bH52vN3WG8LA+qYNuXBF+D/+8Y+J753vfGe0vTCcV/LAW37tVbTn58e2+YUXXoj2/v37\nE59NFegTfeubXM2fbQBYvHhxtG+44YbE96lPfSraNmTbSWmEdipfe+fk0CGXtQCAu+66K9rbtm1L\nfO1U7G6TvvZNDm899NBDiW/JkiXRvvHGGxPfZz7zmWhzFXUgDYt7OlXVrKp+9pzcTwFg06ZN0f7D\nH/6Q+Gzpi17RaZjvXgAbW/ZGAL/sTnPEgJCe+SAt80J65oO0zJgqpRF+CuBhAJeHEA6EEG4CcAeA\n60IIEwA2tI7FECA980Fa5oX0zAdpOXpUWc33xRLX+i63RfQB6ZkP0jIvpGc+SMvRY2S2k+Hl1kD1\nneqrLt308q5WrVpVpYmiIgsWLEiOOY/JxvHLyldYvdjnlbKwu8hX/d4owveYtwMC0i0ebA4cb/Vh\n8yb4fnulEar2Tfu8eNvcjDK8jdKWLVsS34YNG6LtbfNhteT+wjp4ZS6897Et58DPld0G6vHHH4+2\n93zkgr2nvG3Sr371q8R33XXXRXtsbCzxeSVkyvS099fLpyrLibSfffbZZxMfP5M9zHlz0XYyQggh\nhBA10GBKCCGEEKIGIxPms1Ve58yZE21vOtHDq7LMU9rLli1LfLyUX6GEarBGvKwXAC688MJoe8t1\nGW+5rreL+qJFixLfypUro80Vsr1rjyI2BMNlBmy5CQ7PcMgPKA+ltlMagfXk9wAArFmzJtp2yTxX\nWR5ljhxJV/R7OxCwDt5Sd8Z+zgvz8fNgfXx+ruDuXXsUsSFQxmrhhdD4/pdVt7fn8MKGXp+2aQOD\nCu0xmpkSQgghhKiBBlNCCCGEEDUYmTAfV1wG0tCQnfIt21zV24DTTklyeIKrBwNpRfTJyUmI9rCh\nNq42721GzVSteg+koQu7CpTDfBMTE5WvMWrYaXgOmdkK9t4m5GUhn3am+ctWBALpJr7eit9Rxm7y\nzCFcL0TubULOtNNv+Pw2lOytEBTnsHqePn062vZ9yhp6K/E4/OqtnPbCfN7v5SaunNbMlBBCCCFE\nDTSYEkIIIYSogQZTQgghhBA1GJmcqfHx8eTYi9uWLfH0qix757C5F3Pnzo22cqbaxy5n93Qoy7/w\ntPTg/Cwg1VY5UuV4y9ZtzlRVPauWMLHwOW0ej5cTIqbw8hKr7hhhv+fpWlZZ22JzpsquJXz4/tvc\nJL7/Xp9mbHmTsmsBfgV05UwJIYQQQmSMBlNCCCGEEDUYmTCfDbV5VXXLNq/1Qg7eFLad5uRSCTt3\n7pyx7SLViMtaWF/VkG078FJ9G5LiTZcV5qsOh0u9UJu30TFjw7Z87G2+a58l/iwvERfnsH2Aj733\noBdq88pcVO3D9j3LYT8v1DTq2Hvjhbr5s94GxvzO7PS96FXCv+iiizo6Zy/RzJQQQgghRA00mBJC\nCCGEqIEGU0IIIYQQNRiZnKnZs2cnx1XjuJwD4H3Hxpb5mOPHAHDxxRdXurY4B8fxbZ6LR9lS7XaW\nvfNnbRzflkoQ02PvN+cwVt1mZLrzlP28G/1WTI99n3EeTTv3r2yZvdXLy6fiZ8fLtWrnnTFq2Jwp\n1tfTs2rfqVpCAaheosbm7TUBzUwJIYQQQtRAgykhhBBCiBqMTJjPTk17lE05txMS8Hyacm4fnor2\nlsxW1chbpu1V3rXf05Lratjpew7zdUPPqpXvgVQzWzW7aphhlLGhbX63elp699bTnPEqX3vPytjY\nWOn3Rh37+8gLoXkallXCbyds61VA5+/xLiJNQW8OIYQQQogaaDAlhBBCCFEDDaaEEEIIIWqQdc6U\ntzt81XwnPoeN73p4y+nbyd8SU3Acv50d4MtyMTwtbayenwF77SYu0R0GuFRJp+UIvL5ZNe/Kvhe4\nb86aNaujduWOLTPTaWmEqnlSVT/nvReamGPTFKyenf5+KtPJ5iWW5VYB1X/fzpkzp6M29pIZZ6ZC\nCEtDCA+EEHaGEJ4OIXyt9fN5IYT7QwgTrb/1tA4B0jIf1DfzQlrmg/rm6FElzPcGgG8WRXEFgGsA\n3BJCuALAbQC2FEWxCsCW1rFoPtIyH9Q380Ja5oP65ogxY5ivKIpJAJMt+3gI4S8AFgP4NIBrWx/7\nMYAHAdzak1Z2SNUp53aWZjM8DemFEmzYqJ2Kz92mKIptrb+HSktejm2X5/Kx5/Ngjex3qoYW2qn0\n2w2GuW/yru9e37G+slCO7VN8773+d+bMmdLz9zuUMCx904bM+J7Z0IzXP8r6VaflRmzZBD7u904F\nw9Q329GT8d6T3Oe8sKHtm3xs9eR2NXEXkbYS0EMIywGsAfAIgPHWAwMAhwCMd7VloqdIy7yQnvkg\nLfNCeo4GladIQgizAfwMwNeLojhmRqFFCGHa/4aHEG4GcHPdhoruIS3zQnrmg7TMC+k5OlSamQoh\nnI+pB2JTURQ/b/34cAhhUcu/CMCR6b5bFMWdRVFcXRTF1d1osKiHtMwL6ZkP0jIvpOdoMePMVJga\nSt8F4C9FUXyfXPcC2Ajgjtbfv+xJC2vgbQPSCe1sWcF4yz8HwFBqWTXnwctbYp/VoOo2BvY54vP0\nOkfKMkx9095vzovxSlFUperSenvs5X0MILdxKLScP39+csx9wtOy6nuwHS2rnA/ofzmaYeqbNmfK\ne6d5epbRznvR276NaeKWbFXeFusA/AeAp0II21s/ux1TD8P/hBBuArAPwL/3pomiy0jLfFDfzAtp\nmQ/qmyNGldV8WwGUDRHXd7c5otcURSEtM0F9My/UN/NBfXP0yLoCetWpXW+q31um7U1JepVctTN9\n+3i7vlcN2zBVdz8H0gq+drkuV0Dvd2mEYcLe76pL5r1Qmxd+ZZ28pfanTp1KjvmdweUbxDm8khFe\naRKvBI13Du5HVks+h1eWwX6v050tcsSWGfD6ZtVSMFXDdV5pBC8Vw+484ZUi6hf6rS6EEEIIUQMN\npoQQQgghaqDBlBBCCCFEDbLOmeI4+dmzZyt/ryyfxssH8GLLNu/DxnvFzHD+Sjsx8ap5Gd7WQKyf\n/d4gtwYaJmzOSjd2pmc8PT3s5zjXyi6/Vp7NFDZnquq98PJKq+bKWLxl/Kylfd68LYVGjVmzZpX6\n2tmeq6x/VM2tsp9tR09+vwxKT81MCSGEEELUQIMpIYQQQogaZB2j4HBaO9XLy3zedLP18XQlL60H\n+r+DeQ5wyKXTSvRVv+PpbEsj8PSySiOU4y1pb6fkSCd4pUm8MIb3vVEO89kQixeiY6pq2c5S+qrn\ntHo1ISzUFLy0E5vGwPexaokfq5HXd7z3Al/Pew8rzCeEEEIIMYRoMCWEEEIIUQMNpoQQQgghapB1\nzhTjbWdRdWsRm/tU9XpaTl+f119/Pdre9iNVl+56+UztbKHglU0Y5byameC+5OXBePlUVfX0tjHx\n8jLUT6fHu5/eM+9tHcLnsPkw3jL7snbYY/vu7kYuXi54ZUra+Z1XNde4qp4Wb/uoJmzRNvgWCCGE\nEEIMMRpMCSGEEELUIOt57OPHj0fbTjXyclBbqqBsubsXSrAV1nl5pp2S5JCVqMbLL78cbTstzdXR\nZ8+enfg4VONNKfPzYcMMPNV97NixxOeVRhDnsP2P+4TVbGxsLNq2CnlZyNVO87OGtt+ynrbfWn0Z\nhW2neOWVV5Jj7mOsHZC+Z+0SfNaSNbLvS09LPrbvBS98Zfv4KGNDeayT1dPb2YPxSijw9bww+8mT\nJxMf91WrbRP6pmamhBBCCCFqoMGUEEIIIUQNNJgSQgghhKhB6OeWFyGEge2vcckllyTHH//4x6O9\nbNmyxMd5GjZng+F7d+LEicTH8d4nn3wy8d13333R7nfsviiKriT29FtLjtVfeeWViW/dunXRHh8f\nT3wc/2ctbV4Gx+NtrJ5z3Hbt2pX4Nm/eHG0v36YXdEtLoPd62tyISy+9NNqrV69OfJdddlm0586d\nm/g4V4Jtu10N5yzaHMVTp05F+8CBA4nv0UcfjfaePXsS3+nTp9FLhqVv2nfi2rVro71y5crEt3Dh\nwmhzbqM9D+ff2Nwqvu82x421fOmllxLf4cOHo2377fbt29FLhqlv2pzF9evXR9v+3uQcqlmzZiW+\nsi2/bN9kzWyuE2ttc/M4b/avf/1r4tu6dSt6SRU9NTMlhBBCCFEDDaaEEEIIIWrQ7zDfUQD7ACwA\n8GLfLlzOqLXj0qIoFs78sZmRli79aEvXtASinicwWvewCuqb9WlKOwD1zW7QFD0b1Tf7OpiKFw3h\nsaIoru77hdWOrtOUtjelHUCz2tIOTWp3U9rSlHZ0QlPa3pR2AM1qSzs0qd1NaUtT2vFPFOYTQggh\nhKiBBlNCCCGEEDUY1GDqzgFd16J21KcpbW9KO4BmtaUdmtTuprSlKe3ohKa0vSntAJrVlnZoUrub\n0pamtAPAgHKmhBBCCCFyQWE+IYQQQoga9HUwFUK4PoSwK4TwbAjhtj5f+4chhCMhhB30s3khhPtD\nCBOtv+d65+hSO5aGEB4IIewMITwdQvjaoNpSB2mZj5aA9GxdMws9pWU+WgLSc1i07NtgKoRwHoD/\nBvBvAK4A8MUQwhX9uj6AuwFcb352G4AtRVGsArClddxr3gDwzaIorgBwDYBbWvdhEG3pCGkZGXot\nAelJDL2e0jIy9FoC0rPFcGhZFEVf/gBYC2AzHX8bwLf7df3WNZcD2EHHuwAsatmLAOzqZ3ta1/0l\ngOua0BZpOXpaSs+89JSW+WgpPYdLy36G+RYD2E/HB1o/GyTjRVFMtuxDAMa9D3ebEMJyAGsAPDLo\ntrSJtDQMsZaA9Px/DLGe0tIwxFoC0jOhyVoqAb1FMTW87dvSxhDCbAA/A/D1oiiODbItuSEt80J6\n5oO0zIt+3sOma9nPwdRBAEvpeEnrZ4PkcAhhEQC0/j7Sj4uGEM7H1EOxqSiKnw+yLR0iLVtkoCUg\nPSMZ6CktW2SgJSA90bpO47Xs52DqTwBWhRBWhBAuAPAFAPf28frTcS+AjS17I6ZisT0lhBAA3AXg\nL0VRfH+QbamBtEQ2WgLSE0A2ekpLZKMlID2HR8s+J459AsBuAHsA/Fefr/1TAJMAzmIq7nwTgPmY\nWgUwAeD3AOb1oR3/iqnpyCcBbG/9+cQg2iItpaX0zE9PaZmPltJzeLRUBXQhhBBCiBooAV0IIYQQ\nogYaTAkhhBBC1ECDKSGEEEKIGmgwJYQQQghRAw2mhBBCCCFqoMGUEEIIIUQNNJgSQgghhKiBBlNC\nCCGEEDX4P/Zj+qYpkxXhAAAAAElFTkSuQmCC\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1ed7d3f98>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"generate_space=[]\n",
"for i in range(image_num+1):\n",
" generate_space.append(image0*i/image_num+image2*(1-i/image_num))\n",
"generated_images=intermediate_layer_generator.predict(np.array(generate_space)[:,0,:])\n",
"# 生成画像を出力\n",
"show_images(generated_images[0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Patch GAN without L1 loss"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"def DCGAN_patch2(generator, discriminator_model, img_dim, patch_size):#, image_dim_ordering):\n",
"\n",
" gen_input = Input(shape=(100,), name=\"DCGAN_input\")\n",
"\n",
" generated_image = generator(gen_input)\n",
"\n",
" #if image_dim_ordering == \"th\":\n",
" # h, w = img_dim[1:]\n",
" #else:\n",
" h, w = img_dim[:-1]\n",
" ph, pw = patch_size\n",
"\n",
" list_row_idx = [(i * ph, (i + 1) * ph) for i in range(int(h / ph))]\n",
" list_col_idx = [(i * pw, (i + 1) * pw) for i in range(int(w / pw))]\n",
"\n",
" list_gen_patch = []\n",
" for row_idx in list_row_idx:\n",
" for col_idx in list_col_idx:\n",
" #if image_dim_ordering == \"tf\":\n",
" # x_patch = Lambda(lambda z: z[:, row_idx[0]:row_idx[1], col_idx[0]:col_idx[1], :])(generated_image)\n",
" #else:\n",
" x_patch = Lambda(lambda z: z[ :, row_idx[0]:row_idx[1], col_idx[0]:col_idx[1],:])(generated_image)\n",
" list_gen_patch.append(x_patch)\n",
"\n",
" DCGAN_output = discriminator_model(list_gen_patch)\n",
" DCGAN = Model(input=[gen_input],\n",
" output=[DCGAN_output],\n",
" name=\"DCGAN\")\n",
"\n",
" return DCGAN"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"def train_patch(X_train, y_train):\n",
" \n",
" X_train = (X_train.astype(np.float32) - 127.5)/127.5\n",
" X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],1)\n",
" y_train= keras.utils.to_categorical(y_train, num_classes=10)\n",
" #print(y_train.shape)\n",
" img_dim=[28,28,1]\n",
" nb_patch=16\n",
" \n",
" discriminator = cdiscriminator_patch(img_dim, nb_patch, model_name=\"DCGAN_discriminator\", use_mbd=True)\n",
" d_opt = Adam(lr=1e-5, beta_1=0.1)\n",
" discriminator.compile(loss='binary_crossentropy', optimizer=d_opt)\n",
"\n",
" # generator+discriminator (discriminator部分の重みは固定)\n",
" discriminator.trainable = False\n",
" generator = generator_model()\n",
" patch_size=[7,7]\n",
" dcgan=DCGAN_patch2(generator, discriminator, img_dim, patch_size)\n",
" g_opt = Adam(lr=2e-4, beta_1=0.5)\n",
" loss = ['binary_crossentropy']\n",
" loss_weights = [1]\n",
" dcgan.compile(loss=loss, loss_weights=loss_weights, optimizer=g_opt)\n",
" \n",
" num_batches = int(X_train.shape[0] / BATCH_SIZE)\n",
" print('Number of batches:', num_batches)\n",
" for epoch in range(NUM_EPOCH):\n",
"\n",
" for index in range(num_batches):\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" #print(y_noise)\n",
" image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" y_batch = y_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]\n",
" #print(y_batch)\n",
" generated_images = generator.predict(noise, verbose=0)\n",
" #print(generated_images[0].shape)\n",
" # 生成画像を出力\n",
" if index % 500 == 0:\n",
" show_images(generated_images)\n",
" \n",
"\n",
" # discriminatorを更新\n",
" #print(image_batch.shape)\n",
" #print(generated_images.shape)\n",
" \n",
" X=np.concatenate((image_batch,generated_images))\n",
" #print(y_batch.shape)\n",
" #print(y_noise.shape)\n",
" #Y = np.concatenate((y_batch, y_noise))\n",
" y = [1]*BATCH_SIZE + [0]*BATCH_SIZE\n",
" h, w = img_dim[:-1]\n",
" ph, pw = patch_size\n",
"\n",
" list_row_idx = [(i * ph, (i + 1) * ph) for i in range(int(h / ph))]\n",
" list_col_idx = [(i * pw, (i + 1) * pw) for i in range(int(w / pw))]\n",
" list_gen_patch = []\n",
" list_gen_func=lambda z: z[:,row_idx[0]:row_idx[1], col_idx[0]:col_idx[1],:]\n",
" \n",
" for row_idx in list_row_idx:\n",
" for col_idx in list_col_idx:\n",
"\n",
" x_patch = list_gen_func(X)\n",
" \n",
" list_gen_patch.append(np.array(x_patch))\n",
" d_loss = discriminator.train_on_batch(list_gen_patch, np.array(y))\n",
"\n",
" # generatorを更新\n",
" noise = np.array([np.random.uniform(-1, 1, 100) for _ in range(BATCH_SIZE)])\n",
" #y_noise= keras.utils.to_categorical(np.array([np.random.randint(0, 9, 1) for _ in range(BATCH_SIZE)]), num_classes=10)\n",
" g_loss = dcgan.train_on_batch(noise, np.array([1]*BATCH_SIZE))\n",
" print(\"epoch: %d, batch: %d, g_loss: , d_loss: %f\" % (epoch, index, d_loss))\n",
" print(g_loss)\n",
"\n",
" generator.save_weights('cgenerator_patch.h5')\n",
" discriminator.save_weights('cdiscriminator_patch.h5')\n",
" return generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(X_train, y_train), (_, _) = fashion_mnist.load_data()\n",
"generator_patch_fashion=train_patch(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment