和 TFLeamAPI 类似, KerasAPI 也对模型定义、损失函数、训练过程等进行了封装,而且封装之后的 整个训练过程和 TFLearn是基本一致的,可以分为数据处理、模型定义和模型训练三个部分 。 使用原生态的 KerasAPI 需要先安装 Keras 包,安装的方法如下:
pip install keras
#pip3 install keras
使用Keras实现卷积神经网络
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
from keras import backend as K
num_classes = 10
img_rows, img_cols = 28, 28
# 通过Keras封装好的API加载MNIST数据。其中trainX就是一个60000 * 28 * 28的数组,
# trainY是每一张图片对应的数字。
(trainX, trainY), (testX, testY) = mnist.load_data()
# 根据对图像编码的格式要求来设置输入层的格式。
if K.image_data_format() == 'channels_first':
trainX = trainX.reshape(trainX.shape[0], 1, img_rows, img_cols)
testX = testX.reshape(testX.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
trainX = trainX.reshape(trainX.shape[0], img_rows, img_cols, 1)
testX = testX.reshape(testX.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
trainX = trainX.astype('float32')
testX = testX.astype('float32')
trainX /= 255.0
testX /= 255.0
# 将标准答案转化为需要的格式(one-hot编码)。
trainY = keras.utils.to_categorical(trainY, num_classes)
testY = keras.utils.to_categorical(testY, num_classes)
# 使用Keras API定义模型。
model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(500, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
# 定义损失函数、优化函数和评测方法。
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.SGD(),
metrics=['accuracy'])
model.fit(trainX, trainY,
batch_size=128,
epochs=10,
validation_data=(testX, testY))
# 在测试数据上计算准确率。
score = model.evaluate(testX, testY)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
从以上代码可以看出使用 Keras API 训练模型可以先定义一个 Sequential 类 ,然后在Sequential 实例中通过 add 函数添加网络层。 Keras 把卷积层、池化层、RNN 结构 (LSTM 、GRN )、全连接层等常用的神经网络结构都做了封装,可以很方便地实现深层神经网络。 在神经网络结构定义好之后, Sequential 实例可以通过 compile 函数,指定优化函数、损失函数@以及训练过程中需要监控的指标等。 Keras 对优化函数、损失函数以及监控指标都有封装,同时也支持使用自定义的方式 。最后在网络结构、损失函数和优化函数都定义好之后, Sequential 实例可以通过fit函数来训练模型。类似 TFLeam 中的fit函数, Keras 的fit函数只须给出训练数据、batch 大小和训练轮数, Keras 就可以自动完成模型训练的整个过程。
使用Keras实现循环神经网络
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Embedding
from keras.layers import LSTM
from keras.datasets import imdb
max_features = 20000
maxlen = 80
batch_size = 32
# 加载数据并将单词转化为ID,max_features给出了最多使用的单词数。
(trainX, trainY), (testX, testY) = imdb.load_data(num_words=max_features)
print(len(trainX), 'train sequences')
print(len(testX), 'test sequences')
# 在自然语言中,每一段话的长度是不一样的,但循环神经网络的循环长度是固定的,
# 所以这里需要先将所有段落统一成固定长度。
trainX = sequence.pad_sequences(trainX, maxlen=maxlen)
testX = sequence.pad_sequences(testX, maxlen=maxlen)
print('trainX shape:', trainX.shape)
print('testX shape:', testX.shape)
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.fit(trainX, trainY,
batch_size=batch_size,
epochs=10,
validation_data=(testX, testY))
score = model.evaluate(testX, testY, batch_size=batch_size)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
为了支持更加灵活的模型定义方法, Keras 支持以返回值的形式定义网络层结构 。 以下代码展示了如何使用这种方式定义模型。
import keras
from tflearn.layers.core import fully_connected
from keras.datasets import mnist
from keras.layers import Input, Dense
from keras.models import Model
num_classes = 10
img_rows, img_cols = 28, 28
# 通过Keras封装好的API加载MNIST数据。
(trainX, trainY), (testX, testY) = mnist.load_data()
trainX = trainX.reshape(trainX.shape[0], img_rows * img_cols)
testX = testX.reshape(testX.shape[0], img_rows * img_cols)
# 将图像像素转化为0到1之间的实数。
trainX = trainX.astype('float32')
testX = testX.astype('float32')
trainX /= 255.0
testX /= 255.0
# 将标准答案转化为需要的格式(one-hot编码)。
trainY = keras.utils.to_categorical(trainY, num_classes)
testY = keras.utils.to_categorical(testY, num_classes)
inputs = Input(shape=(784,))
# 定义两个输入。
input1 = Input(shape=(784,), name = "input1")
input2 = Input(shape=(10,), name = "input2")
# 定义第一个输出。
x = Dense(1, activation='relu')(input1)
output1 = Dense(10, activation='softmax', name = "output1")(x)
# 定义第二个输出。
y = keras.layers.concatenate([x, input2])
output2 = Dense(10, activation='softmax', name = "output2")(y)
model = Model(inputs=[input1, input2], outputs=[output1, output2])
# 定义损失函数、优化函数和评测方法。
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.SGD(),
loss_weights = [1, 0.1],
metrics=['accuracy'])
model.fit(trainX, trainY,
batch_size=32,
epochs=10,
validation_data=(testX, testY))
代码实现结构图如下:
原生态 KerasAPI 对训练数据的处理流程支持得不太好, 基本上需要一次性将数据全部加载到内存。另外,原生态 KerasAPI 无法支持分布式训练 。为了解决这两个问题, Keras 提供了 一种与原生态 TensorFlow 结合得更加紧密 的方式 。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist_data = input_data.read_data_sets('../../datasets/MNIST_data', one_hot=True)
# 通过TensorFlow中的placeholder定义输入。
x = tf.placeholder(tf.float32, shape=(None, 784))
y_ = tf.placeholder(tf.float32, shape=(None, 10))
net = tf.keras.layers.Dense(500, activation='relu')(x)
y = tf.keras.layers.Dense(10, activation='softmax')(net)
acc_value = tf.reduce_mean(
tf.keras.metrics.categorical_accuracy(y_, y))
loss = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_, y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)
with tf.Session() as sess:
tf.global_variables_initializer().run()
for i in range(3000):
xs, ys = mnist_data.train.next_batch(100)
_, loss_value = sess.run([train_step, loss], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
print("After %d training step(s), loss on training batch is "
"%g." % (i, loss_value))
print acc_value.eval(feed_dict={x: mnist_data.test.images,
y_: mnist_data.test.labels})
通过和原生态 TensorFlow 更紧密地结合,可以使建模的灵活性进一步提高,但是同时也会损失一部分封装带来的易用性 。