{"cells":[{"metadata":{"_uuid":"baff2752922fc86a6d62d3c8e02dd5d868a9d296","collapsed":true},"cell_type":"markdown","source":"# Whale GAN\n\nAn attempt to generate fake whale images for testing. Also for learning GAN networks.\n\nBased on code from:\n* [Bounding Box Model](http://www.kaggle.com/martinpiotte/bounding-box-model)\n* [Whale Classification Model](https://www.kaggle.com/martinpiotte/whale-recognition-model-with-score-0-78563)\n"},{"metadata":{"_uuid":"d9cdf1780bfb6ca377156c4c6935e039f44dd212"},"cell_type":"markdown","source":"## Code from Whale Classification Model\nThe image loading, bouding box, and code is directy from the above referenced kernels with only minor changes. I've removed the text descriptions to save space. If you are interested in how this works, view the original kernels."},{"metadata":{"trusted":true,"_uuid":"1ede17d2bf4b48afa17a2a991d44a5a7df7b3295"},"cell_type":"code","source":"import os\nimport gc\nimport pickle\nimport numpy as np\nfrom pathlib import Path\n#force to a gpu\n#os.environ['CUDA_VISIBLE_DEVICES'] = '1'\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"code_folding":[],"trusted":true,"_uuid":"f69f9b42c083f6fca8f838f82743b702a3197081"},"cell_type":"code","source":"#config\nINPUT_SHAPE = (384,384,1)\n\ninput_path = Path(\"../input/humpback-whale-identification\")\ntrain_dir = input_path / \"train\"\ntest_dir = input_path / \"test\"\ntrain_csv = input_path / \"train.csv\"\nsubmission_file = input_path / \"sample_submission.csv\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"34d1be7393ae2c49babbb540fc766fbc3274c579","code_folding":[],"trusted":true},"cell_type":"code","source":"# Read the dataset description\nfrom pandas import read_csv\n\ntagged = dict([(p,w) for _,p,w in read_csv(str(train_csv)).to_records()])\nsubmit = [p for _,p,_ in read_csv(str(submission_file)).to_records()]\njoin   = list(tagged.keys()) + submit\nlen(tagged),len(submit),len(join),list(tagged.items())[:5],submit[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d7f6587ff07710abe0cc3d4de54eb03b6f2c4c86","scrolled":true},"cell_type":"code","source":"# Determise the size of each image\nfrom os.path import isfile\nfrom PIL import Image as pil_image\nfrom tqdm import tqdm\n\ndef expand_path(p):\n    if isfile(str(train_dir / p)): return str(train_dir / p)\n    if isfile(str(test_dir / p)): return str(test_dir / p)\n    return p\n\np2size = {}\nfor p in tqdm(join):\n    size      = pil_image.open(expand_path(p)).size\n    p2size[p] = size\nlen(p2size), list(p2size.items())[:5]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7e768fbcafade78a656c42a1db326cdd7c24478d","trusted":true},"cell_type":"code","source":"# Show an example of a duplicate image (from training of test set)\nimport matplotlib.pyplot as plt\n\ndef show_whale(imgs, per_row=2):\n    n         = len(imgs)\n    rows      = (n + per_row - 1)//per_row\n    cols      = min(per_row, n)\n    fig, axes = plt.subplots(rows,cols, figsize=(24//per_row*cols,24//per_row*rows))\n    for ax in axes.flatten(): ax.axis('off')\n    for i,(img,ax) in enumerate(zip(imgs, axes.flatten())): ax.imshow(img.convert('RGB'))\n\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"237fba51c8e460e2c362a8876ef963a37b60bbab","trusted":true},"cell_type":"code","source":"# TODO: find if current challenge has any\n# with open('../input/humpback-whale-identification-model-files/rotate.txt', 'rt') as f: rotate = f.read().split('\\n')[:-1]\n# rotate = set(rotate)\n# rotate","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b4687ab632f33f5afc7d2f813a3be441927cd9ae","trusted":true},"cell_type":"code","source":"def read_raw_image(p):\n    img = pil_image.open(expand_path(p))\n    #if p in rotate: img = img.rotate(180)\n    return img\n\n# p    = list(rotate)[0]\n# imgs = [pil_image.open(expand_path(p)), read_raw_image(p)]\n# show_whale(imgs)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b1b9bff9cbec6d6120abd1d11a94929481780acb","trusted":true},"cell_type":"code","source":"# Read the bounding box data from the bounding box kernel (see reference above)\nwith open('../input/whale-competition-bounding-boxes/bounding-box.pickle', 'rb') as f:\n    p2bb = pickle.load(f)\nlist(p2bb.items())[:5]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"97c4192e165c301719289053cd8e66ce1cd2367d","trusted":true},"cell_type":"code","source":"# Suppress annoying stderr output when importing keras.\nimport sys\nimport platform\nold_stderr = sys.stderr\nsys.stderr = open('/dev/null' if platform.system() != 'Windows' else 'nul', 'w')\nimport keras\nsys.stderr = old_stderr\n\nimport random\nfrom keras import backend as K\nfrom keras.preprocessing.image import img_to_array,array_to_img\nfrom scipy.ndimage import affine_transform\n\nimg_shape    = INPUT_SHAPE # The image shape used by the model\nanisotropy   = 2.15 # The horizontal compression ratio\ncrop_margin  = 0.05 # The margin added around the bounding box to compensate for bounding box inaccuracy\n\ndef build_transform(rotation, shear, height_zoom, width_zoom, height_shift, width_shift):\n    \"\"\"\n    Build a transformation matrix with the specified characteristics.\n    \"\"\"\n    rotation        = np.deg2rad(rotation)\n    shear           = np.deg2rad(shear)\n    rotation_matrix = np.array([[np.cos(rotation), np.sin(rotation), 0], [-np.sin(rotation), np.cos(rotation), 0], [0, 0, 1]])\n    shift_matrix    = np.array([[1, 0, height_shift], [0, 1, width_shift], [0, 0, 1]])\n    shear_matrix    = np.array([[1, np.sin(shear), 0], [0, np.cos(shear), 0], [0, 0, 1]])\n    zoom_matrix     = np.array([[1.0/height_zoom, 0, 0], [0, 1.0/width_zoom, 0], [0, 0, 1]])\n    shift_matrix    = np.array([[1, 0, -height_shift], [0, 1, -width_shift], [0, 0, 1]])\n    return np.dot(np.dot(rotation_matrix, shear_matrix), np.dot(zoom_matrix, shift_matrix))\n\ndef read_cropped_image(p, augment):\n    \"\"\"\n    @param p : the name of the picture to read\n    @param augment: True/False if data augmentation should be performed\n    @return a numpy array with the transformed image\n    \"\"\"\n    size_x,size_y = p2size[p]\n    \n    # Determine the region of the original image we want to capture based on the bounding box.\n    x0,y0,x1,y1   = p2bb[p]\n    #if p in rotate: x0, y0, x1, y1 = size_x - x1, size_y - y1, size_x - x0, size_y - y0\n    dx            = x1 - x0\n    dy            = y1 - y0\n    x0           -= dx*crop_margin\n    x1           += dx*crop_margin + 1\n    y0           -= dy*crop_margin\n    y1           += dy*crop_margin + 1\n    if (x0 < 0     ): x0 = 0\n    if (x1 > size_x): x1 = size_x\n    if (y0 < 0     ): y0 = 0\n    if (y1 > size_y): y1 = size_y\n    dx            = x1 - x0\n    dy            = y1 - y0\n    if dx > dy*anisotropy:\n        dy  = 0.5*(dx/anisotropy - dy)\n        y0 -= dy\n        y1 += dy\n    else:\n        dx  = 0.5*(dy*anisotropy - dx)\n        x0 -= dx\n        x1 += dx\n\n    # Generate the transformation matrix\n    trans = np.array([[1, 0, -0.5*img_shape[0]], [0, 1, -0.5*img_shape[1]], [0, 0, 1]])\n    trans = np.dot(np.array([[(y1 - y0)/img_shape[0], 0, 0], [0, (x1 - x0)/img_shape[1], 0], [0, 0, 1]]), trans)\n    if augment:\n        trans = np.dot(build_transform(\n            random.uniform(-5, 5),\n            random.uniform(-5, 5),\n            random.uniform(0.8, 1.0),\n            random.uniform(0.8, 1.0),\n            random.uniform(-0.05*(y1 - y0), 0.05*(y1 - y0)),\n            random.uniform(-0.05*(x1 - x0), 0.05*(x1 - x0))\n            ), trans)\n    trans = np.dot(np.array([[1, 0, 0.5*(y1 + y0)], [0, 1, 0.5*(x1 + x0)], [0, 0, 1]]), trans)\n\n    # Read the image, transform to black and white and comvert to numpy array\n    img   = read_raw_image(p).convert('L')\n    img   = img_to_array(img)\n    \n    # Apply affine transformation\n    matrix = trans[:2,:2]\n    offset = trans[:2,2]\n    img    = img.reshape(img.shape[:-1])\n    img    = affine_transform(img, matrix, offset, output_shape=img_shape[:-1], order=1, mode='constant', cval=np.average(img))\n    img    = img.reshape(img_shape)\n\n    # Normalize to zero mean and unit variance\n    #img  -= np.mean(img, keepdims=True)\n    #img  /= np.std(img, keepdims=True) + K.epsilon()\n    #normalize to -1,1\n    img /= 127.5\n    img -= 1.\n    return img\n\ndef read_for_training(p):\n    \"\"\"\n    Read and preprocess an image with data augmentation (random transform).\n    \"\"\"\n    return read_cropped_image(p, True)\n\ndef read_for_validation(p):\n    \"\"\"\n    Read and preprocess an image without data augmentation (use for testing).\n    \"\"\"\n    return read_cropped_image(p, False)\n\np = list(tagged.keys())[32]\nimgs = [\n    read_raw_image(p),\n    array_to_img(read_for_validation(p)),\n    array_to_img(read_for_training(p))\n]\nshow_whale(imgs, per_row=3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bba8837b2b3d223bc3138c2c91e8754abbc6b2c0"},"cell_type":"code","source":"\nnp.max(read_for_validation(p))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e671c843a32506b635f92e75a7574346fe339254"},"cell_type":"markdown","source":"The left image is the original picture. The center image does the test transformation. The right image adds a random data augmentation transformation."},{"metadata":{"_uuid":"5ad782dc3bec34b421217b73f71f352c2b119426"},"cell_type":"markdown","source":"## NEW CODE STARTS HERE"},{"metadata":{"trusted":true,"_uuid":"85e03cbec9a72a408897671fb6beb263e6aefc56"},"cell_type":"code","source":"from keras.layers import *\nfrom keras.optimizers import *\nfrom keras.models import *\n\nfrom keras.utils.data_utils import *\n\n#data generator\nimport random\nclass ImageGenerator(keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, image_file_list, batch_size):\n        self.image_file_list = np.array(image_file_list)\n        self.samples = self.image_file_list.shape[0]\n        self.batch_size = batch_size\n        self.on_epoch_end()\n\n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return int(np.floor(self.samples / self.batch_size))\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        # Generate data\n        X = self.__data_generation(indexes)\n        return X\n\n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\n        self.indexes = np.arange(self.samples)\n\n    def __data_generation(self, indices):\n        'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)\n        # Initialization\n        batch_data = np.empty((self.batch_size, INPUT_SHAPE[0], INPUT_SHAPE[1], INPUT_SHAPE[2]), dtype=np.float32)\n\n        # Generate data\n        for j, idx in enumerate(indices):\n            img_name = self.image_file_list[idx]\n            batch_data[j] = read_for_validation(img_name)\n\n        return batch_data\n\ndef gaussian(x, mu, sigma):\n    return np.exp(-(float(x) - float(mu)) ** 2 / (2 * sigma ** 2))\n\n\ndef make_2dkernel(size,sigma=1.0):\n    kernel_size = size\n    mean = np.floor(0.5 * kernel_size)\n    kernel_1d = np.array([gaussian(x, mean, sigma) for x in range(kernel_size)])\n    # make 2D kernel\n    np_kernel = np.outer(kernel_1d, kernel_1d).astype(dtype=K.floatx())\n    # normalize kernel by sum of elements\n    kernel = np_kernel / np.sum(np_kernel)\n    return kernel    \n\ndef blur_init(shape, dtype=None):\n    return make_2dkernel(shape[0]).reshape(shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9a98839b7ba3c35a7cbe001ad36d9d8c5be7e01c"},"cell_type":"code","source":"class GAN():\n    def __init__(self):\n        self.img_rows = INPUT_SHAPE[0]\n        self.img_cols = INPUT_SHAPE[1]\n        self.channels = INPUT_SHAPE[2]\n        self.img_shape = (self.img_rows, self.img_cols, self.channels)\n        self.latent_dim = 4250\n        \n        self.cleanup_memory()\n        self.build_models()\n        self.discriminator.summary()\n        self.generator.summary()\n        self.combined.summary()\n    \n    def build_models(self):\n        self.desc_optimizer = Adam(lr=1e-6)\n        self.gen_optimizer = SGD(lr=0.01, clipvalue=0.5)\n\n        self.discriminator = self.build_discriminator()\n        self.generator = self.build_generator()\n\n        # build the combined model\n        self.discriminator.trainable = False\n        self.combined = self.build_combined()\n\n        \n    def save(self,path):\n        model_name = path+'-generator.h5'\n        self.generator.save(model_name)\n        self.generator.save_weights(model_name+\".weights\")\n\n        model_name = path+'-discriminator.h5'\n        self.discriminator.save(model_name)\n        self.discriminator.save_weights(model_name+\".weights\")\n\n#         model_name = path+'-combined.h5'\n#         self.combined.save(model_name)\n#         self.combined.save_weights(model_name+\".weights\")\n\n    def load(self,path):\n        model_name = path+'-generator.h5'\n        self.generator.load_weights(model_name+\".weights\")\n\n        model_name = path+'-discriminator.h5'\n        self.discriminator.load_weights(model_name+\".weights\")\n\n#         model_name = path+'-combined.h5'\n#         self.combined.load_weights(model_name+\".weights\")\n        \n    def set_lr(self,lr):\n        lr = lr #do nothing\n        #K.set_value(self.discriminator.optimizer.lr, lr)\n#         K.set_value(self.combined.optimizer.lr, lr)\n\n    def build_generator(self):\n        noise_input = Input(shape=(self.latent_dim,))\n        x = Dense(self.latent_dim,activation='relu')(noise_input)\n        x = Dense(np.prod(self.img_shape)//16,activation='relu')(x)\n        x = Reshape((img_shape[0]//4,img_shape[1]//4,img_shape[2]))(x)\n        x = Conv2D(16,kernel_size=(9,9),activation='tanh',padding='same')(x)\n        x = Conv2D(16,kernel_size=(9,9),dilation_rate=2,activation='tanh',padding='same')(x)\n        x = UpSampling2D()(x)\n        x = Conv2D(8,kernel_size=(5,5),activation='tanh',padding='same')(x)\n        x = Conv2D(8,kernel_size=(3,3),activation='tanh',padding='same')(x)\n        x = Conv2DTranspose(8,kernel_size=(3,3),activation='tanh',strides=2,padding='same')(x)\n        x = Conv2D(1,kernel_size=(3,3),activation='tanh',padding='same')(x)\n        x = Conv2D(1,kernel_size=(5,5),kernel_initializer=blur_init,activation='softsign',padding='same',name='blur')(x)\n\n        m = Model(noise_input, x, name='SGW_generator_1')\n        # Freezing these keeps it a blur layer. Otherwise training changes it...        \n        m.get_layer('blur').trainable=False\n        return m\n    \n    def build_discriminator(self):\n        img_input = Input(shape=self.img_shape)\n        x = Conv2D(img_shape[2]*2,kernel_size=(3,3),strides=2)(img_input)\n        x = Activation('relu')(x)\n        x = BatchNormalization()(x)\n        x = MaxPooling2D()(x)\n        x = Conv2D(img_shape[2]*4,kernel_size=(3,3))(x)\n        x = Activation('relu')(x)\n        x = BatchNormalization()(x)\n        x = MaxPooling2D()(x)\n        x = Conv2D(img_shape[2]*8,kernel_size=(3,3))(x)\n        x = Activation('relu')(x)\n        x = BatchNormalization()(x)\n        x = MaxPooling2D()(x)\n        x = Conv2D(img_shape[2]*16,kernel_size=(3,3))(x)\n        x = Activation('relu')(x)\n        x = BatchNormalization()(x)\n        x = MaxPooling2D()(x)\n        x = Conv2D(img_shape[2]*32,kernel_size=(3,3))(x)\n        x = Activation('relu')(x)\n        x = BatchNormalization()(x)\n        x = Flatten()(x)\n        x = Dense(self.latent_dim)(x)\n        x = Activation('relu')(x)\n        x = Dense(1, activation='sigmoid')(x)\n        m = Model(img_input, x, name='SGW_discriminator_1')\n        return m\n\n    def build_combined(self):\n        # The generator takes noise as input and generates imgs\n        z = Input(shape=(self.latent_dim,))\n        img = self.generator(z)\n\n        # The discriminator takes generated images as input and determines validity\n        validity = self.discriminator(img)\n\n        # The combined model  (stacked generator and discriminator)\n        # Trains the generator to fool the discriminator\n        return Model(z, validity)\n            \n    def cleanup_memory(self):\n        sess = K.get_session()\n        K.clear_session()\n        try:\n            del self.combined\n            del self.discriminator\n            del self.generator\n        except:\n            pass\n        sess.close()\n        config = tf.ConfigProto()\n        config.gpu_options.per_process_gpu_memory_fraction = 1\n        K.set_session(tf.Session(config=config))\n        gc.collect()\n        \n    def train(self, epochs, batch_size=128, sample_interval=50):\n        print(\"Get image list\")\n        img_loader = ImageGenerator(np.array(list(tagged.keys())),batch_size)\n\n        enqueuer = OrderedEnqueuer(img_loader)\n        enqueuer.start(workers=24)\n        datas = enqueuer.get()\n\n        # Adversarial ground truths\n        valid = np.ones((batch_size, 1))\n        fake = np.zeros((batch_size, 1))\n\n        lr = 1e-4\n        drop_interval = 5000\n        drop_factor = 0.5\n        for epoch in range(epochs):\n            self.cleanup_memory()\n            self.build_models()\n            try:\n                self.load('whale-gan-1-checkpoint')\n            except:\n                print(\"Checkpoint didn't load\")\n            \n            batches_per_epoch = img_loader.samples // batch_size\n\n            # ---------------------\n            #  Train Discriminator\n            # ---------------------\n            self.discriminator.trainable = True\n            self.discriminator.compile(loss='binary_crossentropy',\n                optimizer=self.desc_optimizer,\n                metrics=['accuracy'])\n            \n            d_loss_samples = []\n            d_acc_samples = []\n            pbar = tqdm(range(batches_per_epoch))\n            for i in pbar:\n                imgs = next(datas)\n                noise = np.random.uniform(-1, 1, (batch_size, self.latent_dim))\n                gen_imgs = self.generator.predict(noise)\n\n                # Train the discriminator\n                d_loss_real = self.discriminator.train_on_batch(imgs, valid)\n                d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)\n                d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)\n                d_loss_samples.append(d_loss[0])\n                d_acc_samples.append(d_loss[1])\n                pbar.set_description(\"[Disc. loss: %f, acc.: %.2f%%]\" % (np.average(d_loss_samples),100*np.average(d_acc_samples)))\n\n            attempts = 0    \n            while 100*np.average(d_acc_samples) < 70.0 and attempts < 3:\n                attempts+=1\n                print(\"Discriminator accuracy too low. Continue training\")\n                d_loss_samples = []\n                d_acc_samples = []\n                pbar = tqdm(range(batches_per_epoch))\n                for i in pbar:\n                    imgs = next(datas)\n                    noise = np.random.uniform(-1, 1, (batch_size, self.latent_dim))\n                    gen_imgs = self.generator.predict(noise)\n\n                    # Train the discriminator\n                    d_loss_real = self.discriminator.train_on_batch(imgs, valid)\n                    d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)\n                    d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)\n                    d_loss_samples.append(d_loss[0])\n                    d_acc_samples.append(d_loss[1])\n                    pbar.set_description(\"[Disc. loss: %f, acc.: %.2f%%]\" % (np.average(d_loss_samples),100*np.average(d_acc_samples)))                \n\n            # ---------------------\n            #  Train Generator\n            # ---------------------\n            self.discriminator.trainable = False\n            #self.combined = self.build_combined()\n            self.combined.compile(loss='binary_crossentropy', optimizer=self.gen_optimizer)\n\n            g_loss_samples = []\n            pbar = tqdm(range(batches_per_epoch))\n            for i in pbar:\n                noise = np.random.uniform(-1, 1, (batch_size, self.latent_dim))\n                g_loss = self.combined.train_on_batch(noise, valid)\n                g_loss_samples.append(g_loss)\n                pbar.set_description(\"[G loss: %f]\" % (np.average(g_loss_samples)))\n\n\n            attempts = 0    \n            while np.average(d_loss_samples) < np.average(g_loss_samples) and attempts < 3:\n                attempts+=1\n                g_loss_samples = []\n                lr = K.get_value(self.combined.optimizer.lr) * 0.667\n                K.set_value(self.combined.optimizer.lr, lr)\n                print(\"Discriminator winning, continue to train generator with new lr: %0.8f\" % lr)\n                g_loss_samples = []\n                pbar = tqdm(range(batches_per_epoch))\n                for i in pbar:\n                    noise = np.random.uniform(-1, 1, (batch_size, self.latent_dim))\n                    g_loss = self.combined.train_on_batch(noise, valid)\n                    g_loss_samples.append(g_loss)\n                    pbar.set_description(\"[G loss: %f]\" % (np.average(g_loss_samples)))\n\n                \n\n            print (\"%d [D loss: %f, acc.: %.2f%%] [G loss: %f]\" % (epoch, \n                                                                   np.average(d_loss_samples), \n                                                                   100*np.average(d_acc_samples), \n                                                                   np.average(g_loss_samples) ))\n            if (epoch+1) % drop_interval == 0:\n                lr = lr * drop_factor\n                self.set_lr(lr)\n\n            # If at save interval => save generated image samples\n            if epoch % sample_interval == 0:\n                self.sample_images(epoch)\n\n            try:\n                self.save('whale-gan-1-checkpoint')\n            except:\n                print(\"Checkpoint didn't save\")\n        enqueuer.stop()\n\n\n    def sample_images(self, epoch):\n        r, c = 3, 3\n        sample_noise = np.random.normal(0, 1, (r * c, self.latent_dim))\n        gen_imgs = self.generator.predict(sample_noise)\n\n        # Rescale images 0 - 1\n        gen_imgs = 0.5 * gen_imgs + 0.5\n\n        \n        fig, axs = plt.subplots(r, c,figsize=(10,10))\n        cnt = 0\n        for i in range(r):\n            for j in range(c):\n                axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')\n                axs[i,j].axis('off')\n                cnt += 1\n        #fig.savefig(\"images/%d.png\" % epoch)\n        plt.show()\n        plt.close()\n    ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e4a44dc8687466914a6f56a5f624832ec8ca9a87"},"cell_type":"markdown","source":"## Run the model\nIn this notebook \"epochs\" are set to only 1600 to take a short time. This isn't really epochs but number of batches. Really this should be downloaded and ran locally for 50000 or more to get good results."},{"metadata":{"scrolled":false,"trusted":true,"_uuid":"9e9586fd33653aca5d889d407bcc753584ca6c92"},"cell_type":"code","source":"gc.collect()\nkeras.backend.clear_session()\nconfig = tf.ConfigProto()\nconfig.gpu_options.allow_growth=True\nsess = tf.Session(config=config)\nK.set_session(sess)\n\ngan = GAN()\ngan.train(epochs=20, batch_size=128, sample_interval=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c1994be826f8ccf8e57410e8094c9e3af0571b08"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}