七月GAN第一集

今天我们来讲一下使用Keras实现GAN的具体过程。

我们用MINST数据集来做这个测试。

首先我们导入需要的所有库

%matplotlib inline
import os,random
os.environ["KERAS_BACKEND"] = "tensorflow"
import numpy as np
import theano as th
import theano.tensor as T
from keras.utils import np_utils
import keras.models as models
from keras.layers import Input,merge
from keras.layers.core import Reshape,Dense,Dropout,Activation,Flatten
from keras.legacy.layers import MaxoutDense
from keras.layers.advanced_activations import LeakyReLU
from keras.activations import *
from keras.layers.wrappers import TimeDistributed
from keras.layers.noise import GaussianNoise
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D, Deconv2D, UpSampling2D
from BatchNorm_GAN import BatchNormGAN
from keras.layers.recurrent import LSTM
from keras.regularizers import *
from keras.layers.normalization import *
from keras.optimizers import *
from keras.datasets import mnist
import matplotlib.pyplot as plt
import pickle, random, sys, keras
from keras.models import Model
from IPython import display

sys.path.append("../common")
from keras.utils import np_utils
from tqdm import tqdm

K.set_image_dim_ordering('th')

准备训练集

# 28 x 28 的图片
img_rows, img_cols = 28, 28

# 把数据集洗一洗
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# 排好
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

# 看看我们所有数据的个数和长相
print(np.min(X_train), np.max(X_train))
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
#底下那个(60000,1,28,28)中的1表示28*28是一个整体
# 做个指示器,告诉算法,现在这个net(要么是dis要么是gen),能不能被继续train
def make_trainable(net, val):
    net.trainable = val
    for l in net.layers:
        l.trainable = val
# 看一个每一个训练数据的长相
shp = X_train.shape[1:]
print(shp)

dropout_rate = 0.25#使得学习曲线不是一直往下掉,是稍微偏差一些的往下掉,使之不会落入OVERFITING中,而且0.25表示有25%的数据被忽略掉了

# 设置gen和dis的opt(优化器)
# 大家可以尝试各种组合
opt = Adam(lr=1e-3)#给“匪”
dopt = Adam(lr=1e-4)#给“警”
#opt = Adam(lr=1e-3)
#opt = Adamax(lr=1e-4)
#opt = Adam(lr=0.0002)
#opt = Adam(lr=0.0002, beta_1=0.5, beta_2=0.999, epsilon=1e-08)
nch = 200

# 造个GEN“匪”  (而且这一过程相当于CNN的反向)
#“警”和“匪”是完全分开的,它们之间的唯一交流就是最后由警来判断生成的图片是否为真
nch = 200
g_input = Input(shape=[100])
# 倒过来的CNN第一层(也就是普通CNN那个flatten那一层)
H = Dense(nch*14*14, init='glorot_normal')(g_input)
H = BatchNormGAN()(H)
H = Activation('relu')(H)
H = Reshape( [nch, 14, 14] )(H)
# upscale上去2倍大。也就是从14x14 到 28x28
H = UpSampling2D(size=(2, 2))(H)
# CNN滤镜 (滤镜的作用是将一个看起来没有用的东西变成一个有用的东西)
H = Convolution2D(int(nch/2), 3, 3, border_mode='same', init='glorot_uniform')(H)
H = BatchNormGAN()(H)
H = Activation('relu')(H)
# CNN滤镜
H = Convolution2D(int(nch/4), 3, 3, border_mode='same', init='glorot_uniform')(H)
H = BatchNormGAN()(H)
H = Activation('relu')(H)
# 合成一个大图片
H = Convolution2D(1, 1, 1, border_mode='same', init='glorot_uniform')(H)
g_V = Activation('sigmoid')(H)#这里不用ReLu是因为ReLu得到的是一个cutoff的值,而sigmoid得到的值比较平缓,用ReLu得到的图片是一个黑白分明的图片
generator = Model(g_input,g_V)#输入、输出
generator.compile(loss='binary_crossentropy', optimizer=opt)
generator.summary()


# 造个DIS discrimitor,即就是一个CNN的正向的过程
# 这就是一个正常的CNN
d_input = Input(shape=shp)
# 滤镜
H = Convolution2D(256, 5, 5, subsample=(2, 2), border_mode = 'same', activation='relu')(d_input)#第一层是256个滤镜,每一个是5*5
H = LeakyReLU(0.2)(H)
H = Dropout(dropout_rate)(H)
# 滤镜
H = Convolution2D(512, 5, 5, subsample=(2, 2), border_mode = 'same', activation='relu')(H)
H = LeakyReLU(0.2)(H)
H = Dropout(dropout_rate)(H)
H = Flatten()(H)#flatten之后数据就变成了一个长长的一维的数据链
# flatten之后,接MLP
H = Dense(256)(H)
H = LeakyReLU(0.2)(H)
H = Dropout(dropout_rate)(H)
# 出一个结果,『是』或者『不是』
d_V = Dense(2,activation='softmax')(H)#Dense出一个二维的“是”或者“否”(即0或者1)
discriminator = Model(d_input,d_V)
discriminator.compile(loss='categorical_crossentropy', optimizer=dopt)
discriminator.summary()

make_trainable(discriminator, False)#让警察先不训练,勿让新数据干扰警察的判断
# 为stacked GAN做准备
# 然后合成一个GAN的构架
gan_input = Input(shape=[100])#100维的随机数据
H = generator(gan_input)
gan_V = discriminator(H)
GAN = Model(gan_input, gan_V)

GAN.compile(loss='categorical_crossentropy', optimizer=opt)
GAN.summary()
#运行结束之后会出现可训练的参数和不可训练的参数
#因为用了BatchNormal之后会出现不可训练的参数,因为在整个数据流中出现batchnormal的话,都用一个钢铁标准把
#数据归一化到一个-1到1或者0到1之间的一个分布

接下来两个画图功能。

def plot_loss(losses):
        display.clear_output(wait=True)
        display.display(plt.gcf())
        plt.figure(figsize=(10,8))
        plt.plot(losses["d"], label='discriminitive loss')
        plt.plot(losses["g"], label='generative loss')
        plt.legend()
        plt.show()

def plot_gen(n_ex=16,dim=(4,4), figsize=(10,10) ):
    noise = np.random.uniform(0,1,size=[n_ex,100])
    generated_images = generator.predict(noise)

    plt.figure(figsize=figsize)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0],dim[1],i+1)
        img = generated_images[i,0,:,:]
        plt.imshow(img)
        plt.axis('off')
    plt.tight_layout()
    plt.show()

提前训练DIS

让它学会区别对错

#提前训练警察
ntrain = 10000
trainidx = random.sample(range(0,X_train.shape[0]), ntrain)
XT = X_train[trainidx,:,:,:]

noise_gen = np.random.uniform(0,1,size=[XT.shape[0],100])
generated_images = generator.predict(noise_gen)
#此时的gen是一个弱智
X = np.concatenate((XT, generated_images))
n = XT.shape[0]
y = np.zeros([2*n,2])
y[:n,1] = 1
y[n:,0] = 1

make_trainable(discriminator,True)
discriminator.fit(X,y, nb_epoch=1, batch_size=32)
y_hat = discriminator.predict(X)

简单判断一下DIS的训练效果:

y_hat_idx = np.argmax(y_hat,axis=1)
y_idx = np.argmax(y,axis=1)
diff = y_idx-y_hat_idx
n_tot = y.shape[0]
n_rig = (diff==0).sum()
acc = n_rig*100.0/n_tot
print("Accuracy: %0.02f pct (%d of %d) right"%(acc, n_rig, n_tot))
# 设置一下存储D和G的格式
losses = {"d":[], "g":[]}
# 训练正经去了
def train_for_n(nb_epoch=5000, plt_frq=25,BATCH_SIZE=32):

    for e in tqdm(range(nb_epoch)):  
        
        # 生成图片(警察的一个pre-train过程)
        image_batch = X_train[np.random.randint(0,X_train.shape[0],size=BATCH_SIZE),:,:,:]    
        noise_gen = np.random.uniform(0,1,size=[BATCH_SIZE,100])
        generated_images = generator.predict(noise_gen)
        
        # 训练DIS
        X = np.concatenate((image_batch, generated_images))
        y = np.zeros([2*BATCH_SIZE,2])
        y[0:BATCH_SIZE,1] = 1
        y[BATCH_SIZE:,0] = 1
        # 当然,要让DIS可以被训练
        make_trainable(discriminator,True)
        d_loss  = discriminator.train_on_batch(X,y)
        losses["d"].append(d_loss)
    
        # 训练 Generator-Discriminator stack
        noise_tr = np.random.uniform(0,1,size=[BATCH_SIZE,100])
        y2 = np.zeros([BATCH_SIZE,2])
        y2[:,1] = 1
        # 这个时候,让DIS不能被变化。保证判断结果一致性
        make_trainable(discriminator,False)
        g_loss = GAN.train_on_batch(noise_tr, y2 )
        losses["g"].append(g_loss)
        
        # 看看新图长什么样子
        if e%plt_frq==plt_frq-1:
            plot_loss(losses)
            plot_gen()

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值