《Python深度学习》实验之高级神经网络

高级神经网络

实验环境

keras 2.1.5
tensor 1.4.0

实验工具

Jupyter Notebook

实验一:MNIST生成对抗性网络

思路

训练两个模型,一个来生成某种给定随机噪声作为输入的输出例子G,一个从实际例子中识别生成的模型示例A。然后,通过训练A成为一种有效的鉴别器,我们可以将G和A叠加成我们的GAN,冻结网络对抗性部分的权重,并训练生成的网络权重,将随机噪声输入推到对抗性半类的“真实”类输出。

工作过程:
在这里插入图片描述

实验过程

1.加载依赖项:

%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

import keras
from keras.layers import Dense, Activation, Dropout, Flatten, Reshape, LeakyReLU 
from keras.layers import Conv2D, Conv2DTranspose, UpSampling2D, BatchNormalization
from keras.layers import Cropping2D
from keras.datasets import mnist
from keras.models import Sequential
from keras.optimizers import RMSprop

from sklearn.utils import shuffle

2.加载和准备数据集:

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.astype("float32")/255.

尽管图像是灰度的,但我们将增加1的通道维数,因为卷积层需要它们。

x_train = x_train.reshape((x_train.shape[0],x_train.shape[1],x_train.shape[2],1))
x_test = x_test.reshape((x_test.shape[0],x_test.shape[1],x_test.shape[2],1))

y_train = y_train.reshape((y_train.shape[0],-1))
y_test = y_test.reshape((y_test.shape[0],-1))

train_data_shape = x_train.shape
test_data_shape = x_test.shape

train_label_shape = y_train.shape
test_label_shape = y_test.shape
#输出看一下:
print("train data shape:",train_data_shape)
print("train label shape:",train_label_shape)
print("test data shape:",test_data_shape)
print("test label shape:",test_label_shape)
'''
train data shape: (60000, 28, 28, 1)
train label shape: (60000, 1)
test data shape: (10000, 28, 28, 1)
test label shape: (10000, 1)
'''

3.建立网络模型:
Discriminator:
  我们建立了一个判别器网络来接收[1,28,28]图像向量,并通过使用多个卷积层、密集层、大量丢失和两个元素的Softmax输出层编码:[0,1]=假和[1,0]=实来判断它们是真还是假。

D = Sequential()

dropout = 0.4

input_shape = train_data_shape[1:]

D.add(Conv2D(16, 3, strides=2, input_shape=input_shape,padding='same'))
D.add(LeakyReLU(alpha=0.2))

D.add(Dropout(dropout))

D.add(Conv2D(32, 3, strides=2, padding='same'))
D.add(LeakyReLU(alpha=0.2))

D.add(Dropout(dropout))

D.add(Conv2D(64, 3, strides=2, padding='same'))
D.add(LeakyReLU(alpha=0.2))

D.add(Dropout(dropout))

D.add(Flatten())

D.add(Dense(1))

D.add(Activation('sigmoid'))

D.summary()

optimizer1 = RMSprop(lr=0.0008, clipvalue=1.0, decay=6e-8)
D.compile(loss='binary_crossentropy', optimizer=optimizer1,metrics=['accuracy'])
'''
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 14, 14, 16)        160       
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 14, 14, 16)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 14, 14, 16)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 7, 7, 32)          4640      
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU)    (None, 7, 7, 32)          0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 7, 7, 32)          0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 4, 4, 64)          18496     
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU)    (None, 4, 4, 64)          0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 4, 4, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 1024)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 1025      
_________________________________________________________________
activation_1 (Activation)    (None, 1)                 0         
=================================================================
Total params: 24,321
Trainable params: 24,321
Non-trainable params: 0
_________________________________________________________________
'''

Gernerator:
  我们使用函数API在Keras中建立了一个相对简单的生成模型,获取100个随机输入,并最终将它们映射到一个[1,28,28]像素以匹配MNIST数据形状。首先生成一组密集的14×14值,然后运行几个不同大小和信道数的滤波器,并最终训练二进制交叉熵的使用和adam优化器。我们使用输出层上的Sigmiod帮助将像素饱和到0或1状态,而不是介于0或1之间的灰度范围,并使用批处理归一化来帮助加速训练,并确保在每一层中使用范围广泛的激活。

G = Sequential()

dropout = 0.4

G.add(Dense(4*4*128, input_dim=100))
G.add(BatchNormalization(momentum=0.9))
G.add(Activation('relu'))

G.add(Reshape((4, 4, 128)))

G.add(UpSampling2D())
G.add(Conv2DTranspose(64, 3, padding='same'))
G.add(BatchNormalization(momentum=0.9))
G.add(Activation('relu'))

G.add(UpSampling2D())
G.add(Conv2DTranspose(32, 3, padding='same'))
G.add(BatchNormalization())
G.add(Activation('relu'))

G.add(UpSampling2D())

G.add(Cropping2D(cropping=((2, 2), (2, 2))))
      
G.add(Conv2DTranspose(16, 3, padding='same'))
G.add(BatchNormalization(momentum=0.9))
G.add(Activation('relu'))

G.add(Conv2DTranspose(8, 3, padding='same'))
G.add(BatchNormalization(momentum=0.9))
G.add(Activation('relu'))

G.add(Conv2DTranspose(1, 3, padding='same'))
G.add(Activation('sigmoid'))

G.summary()
'''
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_2 (Dense)              (None, 2048)              206848    
_________________________________________________________________
batch_normalization_1 (Batch (None, 2048)              8192      
_________________________________________________________________
activation_2 (Activation)    (None, 2048)              0         
_________________________________________________________________
reshape_1 (Reshape)          (None, 4, 4, 128)         0         
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 8, 8, 128)         0         
_________________________________________________________________
conv2d_transpose_1 (Conv2DTr (None, 8, 8, 64)          73792     
_________________________________________________________________
batch_normalization_2 (Batch (None, 8, 8, 64)          256       
_________________________________________________________________
activation_3 (Activation)    (None, 8, 8, 64)          0         
_________________________________________________________________
up_sampling2d_2 (UpSampling2 (None, 16, 16, 64)        0         
_________________________________________________________________
conv2d_transpose_2 (Conv2DTr (None, 16, 16, 32)        18464     
_________________________________________________________________
batch_normalization_3 (Batch (None, 16, 16, 32)        128       
_________________________________________________________________
activation_4 (Activation)    (None, 16, 16, 32)        0         
_________________________________________________________________
up_sampling2d_3 (UpSampling2 (None, 32, 32, 32)        0         
_________________________________________________________________
cropping2d_1 (Cropping2D)    (None, 28, 28, 32)        0         
_________________________________________________________________
conv2d_transpose_3 (Conv2DTr (None, 28, 28, 16)        4624      
_________________________________________________________________
batch_normalization_4 (Batch (None, 28, 28, 16)        64        
_________________________________________________________________
activation_5 (Activation)    (None, 28, 28, 16)        0         
_________________________________________________________________
conv2d_transpose_4 (Conv2DTr (None, 28, 28, 8)         1160      
_________________________________________________________________
batch_normalization_5 (Batch (None, 28, 28, 8)         32        
_________________________________________________________________
activation_6 (Activation)    (None, 28, 28, 8)         0         
_________________________________________________________________
conv2d_transpose_5 (Conv2DTr (None, 28, 28, 1)         73        
_________________________________________________________________
activation_7 (Activation)    (None, 28, 28, 1)         0         
=================================================================
Total params: 313,633
Trainable params: 309,297
Non-trainable params: 4,336
_________________________________________________________________
'''

生成回归模型:
  使用functional API,将生成模型和对抗性模型结合。

D.trainable = False  

gan = Sequential()
gan.add(G)
gan.add(D)
gan.summary()

optimizer2 = RMSprop(lr=0.0004, clipvalue=1.0, decay=3e-8)
gan.compile(loss='binary_crossentropy', optimizer=optimizer2, metrics=['accuracy'])
'''
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
sequential_2 (Sequential)    (None, 28, 28, 1)         313633    
_________________________________________________________________
sequential_1 (Sequential)    (None, 1)                 24321     
=================================================================
Total params: 337,954
Trainable params: 309,297
Non-trainable params: 28,657
_________________________________________________________________
'''

4.训练:
定义一个函数来绘制和保存发生器的输出:

扫描二维码关注公众号,回复: 8532913 查看本文章
def plot_images(save2file=False, fake=True, samples=16, noise=None, step=0):
    filename = 'mnist.png'
    if fake:
        if noise is None:
            noise = np.random.uniform(-1.0, 1.0, size=[samples, 100])
        else:
            filename = "mnist_%d.png" % step
        images = G.predict(noise)
    else:
        i = np.random.randint(0, self.x_train.shape[0], samples)
        images = x_train[i, :, :, :]

    plt.figure(figsize=(10,10))
    for i in range(images.shape[0]):
        plt.subplot(4, 4, i+1)
        image = images[i, :, :, :]
        image = np.reshape(image, [train_data_shape[1], train_data_shape[2]])
        plt.imshow(image, cmap='gray')
        plt.axis('off')
    plt.tight_layout()
    if save2file:
        plt.savefig(filename)
        plt.close('all')
    else:
        plt.show()

设置超参数:

save_interval = 20   #save a plot that includes the output of the generator every number of steps 
train_steps=2000      # end number of steps
start_step = 0        # start number of steps
batch_size=256       # batch size

对判别模型进行了预训练,使用未经训练的生成模型生成了几幅随机图像,将它们与相同数量的真实数字图像连接起来,对它们进行适当的标记,然后进行拟合,直到我们达到一个相对稳定的损失值,这个损失值要超过20000个例子。

num_pretrain = 5000
images_train = x_train[np.random.randint(0,x_train.shape[0], size=num_pretrain), :, :, :]  #selecting random num_pretrain images from training data
noise = np.random.uniform(0, 1.0, size=[num_pretrain, 100])   #generating random num_pretrain noise vectors
images_fake = G.predict(noise)   #generating fake images from the generator
x = np.concatenate((images_train, images_fake))  #stacking both real and fake images
#generating labels in which real=1, fake =0
y = np.ones([2*num_pretrain, 1])
y[num_pretrain:, :] = 0

x,y = shuffle(x,y)  #shuffling the data and labels

d_loss = D.fit(x, y, batch_size=batch_size, epochs=1, validation_split=0.15) #the pretraining step
'''
Train on 8500 samples, validate on 1500 samples
Epoch 1/1
8500/8500 [==============================] - 3s 335us/step - loss: 0.1738 - acc: 0.9426 - val_loss: 0.0033 - val_acc: 1.0000
'''

发生器可以在两个网络的叠加模型中被训练。
GaN的训练的核心如下:
(1)生成图像使用G和随机噪声(仅向前通过)。
(2)在给定的生成图像、真实图像和标签中执行权重的批量更新。
(3)执行一批更新的重量在G给定的噪音和强制“真实”标签在整个GaN。
(4)重复…

#noise input for generator output plotting
noise_input = None
if save_interval>0:
    noise_input = np.random.uniform(0.0, 1.0, size=[16, 100])
#the training loop
d_losses = []
g_losses = []
for i in range(start_step,train_steps):
    # train the discriminator 2 times
    for dis_iter in range(1):
        #training the discriminator
        images_train = x_train[np.random.randint(0,x_train.shape[0], size=batch_size), :, :, :] #selecting random real images whose count equals the batch size
        noise = np.random.uniform(0.0, 1.0, size=[batch_size, 100]) # generating the noise vectors whose count equals batch size
        images_fake = G.predict(noise) #generate fake images from generator
        x = np.concatenate((images_train, images_fake)) #stack real and fake images
        #generating the labels
        y = np.ones([2*batch_size, 1]) 
        y[batch_size:, :] = 0
        # Add random noise to the labels - important trick!
        # y += 0.05 * np.random.random(y.shape)
        x,y = shuffle(x,y) #shuffling the images and labels
        d_loss = D.train_on_batch(x, y) #train the discriminator on this batch of data
    d_losses.append(d_loss)
    
    #training the adverserial model, aka training the generator
    y = np.ones([batch_size, 1]) #the labels, they are always one
    noise = np.random.uniform(0.0, 1.0, size=[batch_size, 100]) #input noise for generator
    g_loss = gan.train_on_batch(noise, y) #train the adeveserial model, with the discrimimator frozen only the generator is updated\
                                         # and with all the labels equal (1), we are telling the generator to strive to generate data that will make the]
                                         # discriminator always output (1) aka fooling it.
    g_losses.append(g_loss)
    
    #print the losses and accuracy values 
    log_mesg = "%d: [D loss: %f, acc: %f]" % (i, d_loss[0], d_loss[1])
    log_mesg = "%s  [G loss: %f, acc: %f]" % (log_mesg, g_loss[0], g_loss[1])
    print(log_mesg)
    #save the plots of generator outputs
    if save_interval>0:
        if (i+1)%save_interval==0:
            plot_images(save2file=True, samples=noise_input.shape[0],noise=noise_input, step=(i+1))
'''
#等了很久,不要轻易关掉。
0: [D loss: 0.005583, acc: 1.000000]  [G loss: 6.771719, acc: 0.000000]
1: [D loss: 0.004642, acc: 1.000000]  [G loss: 5.488572, acc: 0.003906]
2: [D loss: 0.006872, acc: 1.000000]  [G loss: 6.208431, acc: 0.000000]
3: [D loss: 0.008283, acc: 1.000000]  [G loss: 4.167761, acc: 0.015625]
4: [D loss: 0.011295, acc: 0.998047]  [G loss: 6.652860, acc: 0.000000]
5: [D loss: 0.020132, acc: 0.994141]  [G loss: 3.805618, acc: 0.023438]
······
省略几千条
······
1995: [D loss: 0.686364, acc: 0.550781]  [G loss: 0.707710, acc: 0.433594]
1996: [D loss: 0.682135, acc: 0.552734]  [G loss: 0.706227, acc: 0.460938]
1997: [D loss: 0.682364, acc: 0.552734]  [G loss: 0.696030, acc: 0.519531]
1998: [D loss: 0.687504, acc: 0.529297]  [G loss: 0.695345, acc: 0.511719]
1999: [D loss: 0.692645, acc: 0.498047]  [G loss: 0.717447, acc: 0.425781]
'''

5.绘图:

fig, ax = plt.subplots()
losses = np.array(g_losses)
plt.plot(d_losses, label='Discriminator')
plt.plot(g_losses, label='Generator')
plt.title("Training Losses")
plt.legend()

在这里插入图片描述

发布了173 篇原创文章 · 获赞 6 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/shidonghang/article/details/103676244