keras学习笔记(三)

我是研究僧i 提交于 2019-12-05 10:36:46

数据归一化

通过上次对cifar10数据集分类的任务,我的分类精度在0.79,但是当我对输入的数据做了归一化后,精度达到了0.99,实现的语句如下:

X_train = X_train.astype('float32')/255
X_test = X_test.astype('float32')/255
Y_train =Y_train.reshape(Y_train.shape[0])/10
Y_test = Y_test.reshape(Y_test.shape[0])/10

对输入进行归一化处理。对标签也进行归一化处理。是数据预处理的一种常见的手段。

数据归一化与标准化存在一定区别,归一化是数据标准化的一种典型做法,即将数据统一映射到[0,1]区间上. 数据的标准化是指将数据按照比例缩放,使之落入一个特定的区间.

归一化最明显的在神经网络中的影响有如下几个方面:

1.有利于初始化的进行

2.避免给梯度数值的更新带来数字的问题

3.有利于学习率的调整

4.加快寻找最优解的速度

上篇博客说了上面那段是自己写的,下面那段是网上别人写的。我自己写的进行了标准化前是0.79的精度,标准化后是0.99的精度,很显然看出数据标准化对精度是有一定影响的。但是后面的那段我并没有看到有数据归一化,结果仍然能达到0.99.暂时还不清楚原因。可能是我选用了不同的损失函数的原因吧,可以自己进行更改验证。

做了归一化后可以使各个特征都集中在固定的区间内,为什么可以加快优化速度和学习率的调整呢?拿简单的房价拟合问题来讲,一个房子有很多个特征,比如说面积,距离市中心的距离(km),卧室数量,楼层等等特征。但是面积的数值较大(100-200),卧室数量一般为2-4,距离市中心距离(1-10),这么多特征,数值特别分散,如果使用统一的学习率,那么每次如果距离减小一点点,可能相对于距离来说从3减到2.5变化很明显,但是同样的对于面积从200减到199.5变化速度太慢了。所以,将所有的正压缩到同样大小的空间中,这样可以加快优化速度。

批量标准化(BatchNormalization)

下面是批量标准化的两张图,这两张图说明了为什么要进行批量标准化(BatchNormalization)。批量标准化可以用于隐藏层中。进行了标准化后可以让特征集中分布在中央。然后经过一个sigmoid或者tanh的处理,这样可以得到一个很好的值,想象一下,如果一个特征值为3,一个特征为30,经过tanh处理后,得到的值分别为0.96和0.99,这就相当于我的神经网络对输入得数据缺少了感知能力。但是如果标准化到一定的区间内,比如把这个范围缩小10倍,得到了0.3和3两个特征值,在经过激活函数处理,那么处理过后的结果可能就是0.2和0.96,这样有利于更深层次的前向和反向传播。网络搭的越深,往往后面梯度就消失了,因为特征值太大了,因此加入BN层可以使网络得到更加有效的数据。

用keras写一个GAN网络:

import keras
from keras import layers
import numpy as np
import os
from keras.preprocessing import image

pre_data=32
height     = 32
width      = 32
channels   = 3
#获取数据
(x_train,y_train),(x_test,y_test)=keras.datasets.cifar10.load_data()
x_train = x_train[y_train.flatten() == 5]
x_test  = x_test [y_test.flatten()  == 5]
#数据标准化
x_train=x_train.reshape((x_train.shape[0],)+(height,width,channels)).astype('float32')/255
x_test=x_test.reshape((x_test.shape[0],)+(height,width,channels)).astype('float32')/255
#构建生成器网络(从输入到输出的方式构建)generator_network
generator_input=keras.Input(shape=(pre_data,)) #generator_input.shape=(?, 32)
#用一个全连接层把相关特征提出来,用16*16*128=32768个特征。方便之后做卷积
x=layers.Dense(32768)(generator_input)#x.shape=(?, 32768)
x=layers.ReLU()(x)
x=layers.Reshape((16,16,128))(x)#x.shape=(?, 16, 16, 128)
#之后就可以做卷积了
x = layers.Conv2D(filters=128, kernel_size=3, padding='same')(x)
x = layers.ReLU()(x)

x = layers.Conv2D(filters=256, kernel_size=5, padding='same')(x)
x = layers.ReLU()(x)
#上采样,用Conv2DTranspose,从16*16跨达到32*32
x = layers.Conv2DTranspose(filters=256, kernel_size=4, strides=2, padding='same')(x)
x = layers.ReLU()(x)

x = layers.Conv2D(filters=256, kernel_size=5, padding='same')(x)
x = layers.ReLU()(x)
#生成32*32*3的图片
x = layers.Conv2D(filters = 3, kernel_size=7, padding='same')(x)
x = layers.Activation('tanh')(x)

generator = keras.models.Model(generator_input, x)
generator.summary()#打印生成网络

#构建判别器网络discriminator_network
discriminator_input = layers.Input(shape=(height, width, channels))#输入的是32*32*3的图片
x = layers.Conv2D(filters=128, kernel_size=3 ,padding='same')(discriminator_input)
x = layers.LeakyReLU()(x)

x = layers.Conv2D(filters=128, kernel_size=4 , strides=2,padding='same')(x)
x = layers.LeakyReLU()(x)

x = layers.Conv2D(filters=128, kernel_size=4 , strides=2,padding='same')(x)
x = layers.LeakyReLU()(x)

x = layers.Conv2D(filters=128, kernel_size=4 , strides=2,padding='same')(x)
x = layers.LeakyReLU()(x)

x = layers.Flatten()(x)
x = layers.Dropout(0.4)(x)#添加一个Dropout层
x = layers.Dense(1, activation = 'sigmoid')(x)#输出一个一维的概率值

discriminator = keras.models.Model(discriminator_input, x)
discriminator.summary()#打印判别网络
#对判别器选用了优化器,损失函数
discriminator_optimizer = keras.optimizers.RMSprop(lr=0.0008, clipvalue=1.0, decay=1e-8)
discriminator.compile(optimizer=discriminator_optimizer, loss='binary_crossentropy')
#固定辨别器的参数,这样可以去训练生成器
discriminator.trainable = False

gan_input=generator_input
gan_output=discriminator(generator(gan_input))
gan=keras.models.Model(gan_input,gan_output)
#对整个模型选用优化器和损失函数
optimizer=keras.optimizers.RMSprop(lr=0.001,rho=0.9,epsilon=1e-8,decay=0.0)
gan.compile(loss='binary_crossentropy',optimizer=optimizer)

iterations = 1000   #迭代1000次
batch_size = 32     #每批送入32张图片
save_dir = 'E://Desktop//gan_image//'#为生成器生成的图片找一个目录保存
start=0
for step in range(iterations):
    random_latent_vectors = np.random.normal(size=(batch_size, pre_data))
    generated_images=generator.predict(random_latent_vectors)#对于输入得样本预测输出
    #每次放入一个batch_size的图片,通过这种索引的方式放入
    stop=start+batch_size
    real_images=x_train[start:stop]
    #联合生成图片与真实图片,生成图片的标签设置为1,真实图片的标签为0
    combined_images = np.concatenate([generated_images, real_images])
    labels = np.concatenate([np.ones((batch_size, 1)) , np.zeros((batch_size, 1))])
    #给标签加一个很小的噪声
    labels += 0.05 * np.random.random(labels.shape)
    #用正确的标签去训练判别器
    d_loss = discriminator.train_on_batch(combined_images, labels)
    #生成一组假的图像,然后将这组图片的标签设置为0(真),用于误导判别器,让判别器去判断这个到底是不是真的。迭代训练
    random_latent_vectors = np.random.normal(size=(batch_size, pre_data))
    mislead_targets = np.zeros((batch_size,1))
    #训练整个网络
    a_loss = gan.train_on_batch(random_latent_vectors,mislead_targets)
    #计数器每次累加一个batch
    start += batch_size
    #确保送入的图片能够被索引到,如果图片的索引不存在,则会报错
    if start > len(x_train) - batch_size:
        start = 0
    #打印结果,总体损失和判别器损失
    if step%100==0:
        print('discriminator loss at step %s: %s' % (step, d_loss))
        print('adversarial   loss at step %s: %s' % (step, a_loss))

        # 保存生成的图片
        img = image.array_to_img(generated_images[0] * 255., scale=False)
        img.save(os.path.join(save_dir, 'generated_dog' + str(step) + '.png'))

        # 保存训练过程中输入的真实的图片,可以形成对比
        img = image.array_to_img(real_images[0] * 255., scale=False)
        img.save(os.path.join(save_dir, 'real_dog' + str(step) + '.png'))

之后打算用TensorFlow的框架写一个GAN网络

数据归一化参考博客:https://blog.csdn.net/fontthrone/article/details/74067064

GAN网络参考了书籍:deep learning with python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!