1. 定义模型
Sequential模型是层的线性堆栈
Sequential通过将一系列图层实例传递给构造函数来创建模型:
.add()
方法简单地添加图层:
model = Sequential()
model.add(Dense(32, input_dim=784))
model.add(Activation('relu'))
1.1 Dense
keras.layers.Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
Dense层,即全连接层,实现的运算是output = activation(dot(input, kernel)+bias)
。其中activation是逐元素计算的激活函数,kernel是本层的权值矩阵,bias为偏置向量,只有当use_bias=True才会添加。
- units: 正整数,输出空间维度。
- activation: 激活函数 (详见 activations)。 若不指定,则不使用激活函数 (即,「线性」激活: a(x) = x)。
- use_bias: 布尔值,该层是否使用偏置向量。
- kernel_initializer: kernel 权值矩阵的初始化器 (详见 initializers)。
- bias_initializer: 偏置向量的初始化器 (详见 initializers).
- kernel_regularizer: 运用到 kernel 权值矩阵的正则化函数 (详见 regularizer)。
- bias_regularizer: 运用到偏置向的的正则化函数 (详见 regularizer)。
- activity_regularizer: 运用到层的输出的正则化函数 (它的 “activation”)。 (详见 regularizer)。
- kernel_constraint: 运用到 kernel 权值矩阵的约束函数 (详见 constraints)。
- bias_constraint: 运用到偏置向量的约束函数 (详见 constraints)。
输入尺寸:
nD 张量,尺寸: (batch_size, ..., input_dim)
。 最常见的情况是一个尺寸为 (batch_size, input_dim)
的 2D 输入。
输出尺寸:
nD 张量,尺寸: (batch_size, ..., units)
。 例如,对于尺寸为 (batch_size, input_dim) 的 2D 输入, 输出的尺寸为 (batch_size, units)
。
1.2 Dropout
keras.layers.Dropout(rate, noise_shape=None, seed=None)
Dropout 包括在训练中每次更新时, 将输入单元的按比率随机设置为 0, 这有助于防止过拟合。
rate
: 在 0 和 1 之间浮动。需要丢弃的输入比例。noise_shape
: 1D 整数张量, 表示将与输入相乘的二进制 dropout 掩层的形状。 例如,如果你的输入尺寸为(batch_size, timesteps, features)
,然后 你希望 dropout 掩层在所有时间步都是一样的, 你可以使用noise_shape=(batch_size, 1, features)
。seed
: 一个作为随机种子的 Python 整数。
1.3 Flatten
keras.layers.Flatten(data_format=None)
将输入展平。不影响批量大小。
1.4 Conv2D
keras.layers.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
2D 卷积层 (例如对图像的空间卷积)。
该层创建了一个卷积核, 该卷积核对层输入进行卷积, 以生成输出张量。 如果 use_bias
为 True
, 则会创建一个偏置向量并将其添加到输出中。 最后,如果 activation
不是 None
,它也会应用于输出。
当使用该层作为模型第一层时,需要提供 input_shape
参数 (整数元组,不包含样本表示的轴),例如, input_shape=(128, 128, 3)
表示 128x128
RGB 图像, 在 data_format="channels_last"
时。
参数
- filters: 整数,输出空间的维度 (即卷积中滤波器的输出数量)。
- kernel_size: 一个整数,或者 2 个整数表示的元组或列表, 指明 2D 卷积窗口的宽度和高度。 可以是一个整数,为所有空间维度指定相同的值。
- strides: 一个整数,或者 2 个整数表示的元组或列表, 指明卷积沿宽度和高度方向的步长。 可以是一个整数,为所有空间维度指定相同的值。 指定任何 stride 值 != 1 与指定 dilation_rate 值 != 1 两者不兼容。
- padding: “valid” 或 “same” (大小写敏感)。
- activation: 要使用的激活函数 (详见 activations)。 如果不指定,则不使用激活函数 (即线性激活: a(x) = x)。
1.5 MaxPooling2D
keras.layers.MaxPooling2D(pool_size=(2, 2), strides=None, padding='valid', data_format=None)
- pool_size:2个整数的整数或元组,用于缩减的因子(垂直,水平)。(2,2)将在两个空间维度上将输入减半。如果仅指定一个整数,则两个尺寸将使用相同的窗口长度。
- 步幅strides:整数,2个整数的元组或无。跨越价值观。如果为None,则默认为pool_size。
- 填充padding:其中一个"valid"或"same"(不区分大小写)。
2. 指定输入形状
模型需要知道它应该期望什么样的输入形状。因此,Sequential模型中的第一层(并且只有第一层,因为随后的层可以进行自动形状推断)需要接收有关其输入形状的信息。有几种方法可以做到这一点:
将input_shape参数传递给第一层。这是一个形状元组(整数或None条目的元组,其中None表示可以期望任何正整数)。在中input_shape,不包含批次尺寸。
某些2D图层(例如Dense,通过参数支持输入形状的指定)input_dim
,而某些3D时间层则支持参数input_dim
和input_length
。
如果需要为输入指定固定的批处理大小(这对于有状态循环网络很有用),则可以将batch_size参数传递给图层。如果同时传递batch_size=32
和传递input_shape=(6, 8)
到图层,则它将期望每一批输入都具有批处理形状(32, 6, 8)
。
3. compile 编译模型
compile(self, optimizer, loss, metrics=None)
在训练模型之前,通过compile方法完成配置学习过程。它接收三个参数:
- 优化器optimizer。这可以是现有优化器(例如
rmsprop
或adagrad
)的字符串标识符,也可以是Optimizer该类的实例。请参阅:优化程序。 - 损失函数loss。这是模型将尝试最小化的目标。它可以是现有损失函数(例如
categorical_crossentropy
或mse
)的字符串标识符,也可以是目标函数。请参阅:损失。 - 指标列表metrics。对于任何分类问题,您都需要将此设置为
metrics=['accuracy']
。指标可以是现有指标或自定义指标函数的字符串标识符。请参阅:指标。
# For a multi-class classification problem
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# For a binary classification problem
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
# For a mean squared error regression problem
model.compile(optimizer='rmsprop',
loss='mse')
# For custom metrics
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred])
4.fit 训练模型
it(self, X=None, y=None, batch_size=None, epochs=1, verbose=1, validation_data=None)
- X:输入数据。
- y:输入数据集的标签。
- batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
- epochs:整数,训练终止时的epoch值,训练将在达到该epoch值时停止,如果未指定,默认为 32。
- verbose:0 为不在标准输出流输出日志信息,1 为输出进度条记录,2 为每个epoch输出一行记录。
- validation_data:验证数据集,用于在每个 epoch 验证 model 的效果。
5. evaluate 评估模型
evaluate(self, x=None, y=None, batch_size=None, verbose=1)
在测试模式,返回误差值和评估标准值。计算逐批次进行。
Keras 手写数字识别
import keras
from keras import layers
import matplotlib.pyplot as plt
%matplotlib inline
import keras.datasets.mnist as mnist
# 1.输入数据
(train_image, train_label),(test_image,test_label) = mnist.load_data()
# 2.构建模型
model = keras.Sequential()
# (60000,28,28)--> (60000, 28*28)
model.add(layers.Flatten())
# 全连接层
model.add(layers.Dense(64,activation = 'relu'))
model.add(layers.Dense(10,activation = 'softmax'))
# 3.编译模型
model.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics=['acc'])
# 4.模型训练
model.fit(train_image, train_label, epochs = 50, batch_size = 512)
5.模型评估:
model.evaluate(test_image, test_label)
输出:
10000/10000 [==============================] - 1s 88us/step
[0.5225099971218286, 0.9659]
model.evaluate(train_image, train_label)
输出:
60000/60000 [==============================] - 4s 63us/step
[0.3641383859386498, 0.9760166666666666]
6.模型优化
model = keras.Sequential()
# (60000,28,28)--> (60000, 28*28)
model.add(layers.Flatten())
# 全连接层
model.add(layers.Dense(64,activation = 'relu'))
model.add(layers.Dense(64,activation = 'relu'))
model.add(layers.Dense(10,activation = 'softmax'))
model.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics=['acc'])
model.fit(train_image, train_label, epochs = 50, batch_size = 512,validation_data = (test_image,test_label))
Keras GAN mnist
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
import numpy as np
import glob
import os
# 1.导入数据
(train_images, train_label), (_,_) = tf.keras.datasets.mnist.load_data()
# 转换数据类型,并reshape为四维变量
train_images = train_images.reshape(train_images.shape[0],28,28,1).astype('float32')
# 归一化数据
train_images = (train_images - 127.5)/127.5
# 批训练大小
BATCH_SIZE = 256
# 取多少张图片用来操作,比如shuffle操作
BUFFER_SIZE = 60000
datasets = tf.data.Dataset.from_tensor_slices(train_images)
datasets = datasets.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
2.定义生成器
def generator_model():
model = keras.Sequential()
model.add(layers.Dense(256, input_shape=(100,), use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(512, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(28*28*1, use_bias=False, activation='tanh'))
model.add(layers.BatchNormalization())
# Reshape() 接收元组参数
model.add(layers.Reshape((28,28,1)))
return model
3.定义鉴别器
def discriminator_model():
model =keras.Sequential()
model.add(layers.Flatten())
model.add(layers.Dense(512, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(256, use_bias=False))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
model.add(layers.Dense(1))
return model
# 因为在上一步的输出没有激活,所以要设置from_logits = True
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)
3.定义鉴别器的损失
def discriminator_loss(real_out, fake_out):
# 希望真实的图片被判别为1
real_loss = cross_entropy(tf.ones_like(real_out), real_out)
# 生成的图片被判别为0
fake_loss = cross_entropy(tf.zeros_like(fake_out), fake_out)
return real_loss + fake_loss
4.定义生成器的损失
def generator_loss(fake_out):
# 期望生成的图片被鉴别器判定为真
return cross_entropy(tf.ones_like(fake_out), fake_out)
5.定义优化器
generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)
6.设置训练参数
EPOCHS = 100
# 长度为100的随机向量
noise_dim = 100
# 生成16个随机向量,观察生成的手写数字情况
num_example_to_generator = 16
seed = tf.random.normal([num_example_to_generator,noise_dim])
7.初始化
generator = generator_model()
discriminator = discriminator_model()
def train_step(images):
# 生成长度为100的随机数
noise = tf.random.normal([BATCH_SIZE,noise_dim])
# 自定义训练过程
# 因为要追踪两个model,所以定义两个梯度
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
# 真实图片的输出,
real_out = discriminator(images, training=True)
# 生成图片的输出
gen_image = generator(noise, training=True)
# 假图片的输出
fake_out = discriminator(gen_image, training=True)
gen_loss = generator_loss(fake_out)
disc_loss = discriminator_loss(real_out, fake_out)
# 生成器损失和随机变量之间的梯度。取出可训练参数:trainable_variables
gradient_gen = gen_tape.gradient(gen_loss, generator.trainable_variables)
# 鉴别器的损失函数和鉴别器的可训练参数之间的梯度
gradient_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
# 优化
generator_optimizer.apply_gradients(zip(gradient_gen, generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(gradient_disc, discriminator.trainable_variables))
显示每个epoch生成的图片
def generator_plot_image(gen_model, test_noise):
pre_images = gen_model(test_noise, training=False)
fig = plt.figure(figsize=(4,4))
for i in range(pre_images.shape[0]):
plt.subplot(4,4,i+1)
plt.imshow((pre_images[i,:,:,0] + 1)/2, cmap='gray')
plt.axis('off')
plt.show()
训练
def train(dataset, epochs):
for epoch in range(epochs):
for image_batch in dataset:
train_step(image_batch)
print('.',end='')
generator_plot_image(generator, seed)
train(datasets, EPOCHS)
训练最后一轮生成结果:
可以看出,效果并不是很好,要优化的话可以使用DCGAN。
参考:
https://keras.io/zh/layers/convolutional/#conv2d
https://keras.io/layers/core/
https://www.bilibili.com/video/av89610076/?p=7&t=857