前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Keras基本用法

Keras基本用法

作者头像
狼啸风云
修改2022-09-03 19:49:37
1.3K0
修改2022-09-03 19:49:37
举报

Keras是目前使用最为广泛的深度学习工具之一,它的底层可以支持TensorFlow、MXNet、CNTK和Theano。如今,Keras更是被直接引入了TensorFlow的核心代码库,成为TensorFlow官网提供的高层封装之一。下面首先介绍最基本的Keras API,斌哥给出一个简单的样例,然后介绍如何使用Keras定义更加复杂的模型以及如何将Keras和原生态TensorFlow结合起来。

1、Keras基本用法

和TFLearn API类似,Keras API也对模型定义、损失函数、训练过程等进行了封装,而且封装之后的整个训练过程和TFLearn是基本一致的,可以分为数据处理、模型定义和模型训练三个部分。使用原生态的Keras API需要先安装Keras包,安装的方法如下:

pip install keras

以下代码展示了如何使用原生态Keras在MNIST数据集上实现LeNet-5模型。

# -*- coding: utf-8 -*-

import keras
from keras.datasets import mnist
from keras.models import Sequential 
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D

num_class = 10

im_rows, im_cols = 28, 28

# 通过Keras封装好的API加载MNIST数据。其中trainX就是一个60000x28x28的数组,trainY是每一张图片对应的数字。
(trainX, trainY), (testX, testY) = mnist.load_data()

# 因为不同的底层(TensorFlow或者MXNet)对输入的要求基本不一样,所以这里需要根据图像编码的格式要求来设置输入层的格式。
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)
   # 因为MNIST中的图片是黑白的,所以第一维的取值为1,
   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_shapes = (img_rows, img_cols, 1)
# 将图像像素转化为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_categories(testY, num_classes)

# 使用Keras API定义模型。
model = Sequential()

# 一层深度为32,滤波器大小为5x5的卷积层。
model.add(MaxPooling2D(pool_size=(2,2)))
# 一层深度为64,滤波器大小为5x5的卷积层。
model.add(Conv2D(64, (5,5), activation='relu'))
# 一层滤波器大小为2x2的最大池化层。
model.add(MaxPooling2D(pool_size=(2,2)))
# 将卷积层的输出拉直后作为下面全连接层的输入。
model.add(Flatten())
# 全连接层,有500个节点。
model.add(Flatten())
# 全连接层,有500个节点。
model.add(Dense(500, activate='relu'))
# 全连接层,得到最后的输出
model.add(Dense(num_classes, activate='softmax'))

# 定义损失函数、优化函数和测评方法。
model.compile(loss=losses.categorical_crossentropy,
              optimazer = keras.optimizer.SGD()
              metric = ['accuracy'])
# 类似TFLearn中的训练过程,给出训练数据、Batch大小、训练论事和验证数据,Keras可以自动完成模型训练过程。
model.fit(trainX, trainY, batch_size=128, epochs=20, 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、GRU),全连接层等常用的神经网络结构都做了封装,可以很方便地实现深层神经网络。在神经网络结构定义好之后,Sequential实例可以通过compile函数,指定优化函数、损失函数以及训练过程中需要监控等指标。Keras对优化函数、损失函数以及监控指标都有封装,同时也支持使用自定义的方式,在Keras的API文档中有详细的介绍,这里不再赘述。最后在网络结构、损失函数和优化函数都定义好之后,Sequential实例可以通过fit函数来训练模型。类似TFLearn中的fit函数,Keras的fit函数只需给出训练数据,batch大小和训练轮数,Keras就可以自动完成模型训练的整个过程。

除了能够很方便地处理图像问题,Keras对训练神经网络的支持也是非常出色的。有了Keras APA,循环神经网络的训练体系也可以通过简单的一句命令完成。以下代码给出了如何通过Keras实现自然语言感情分类问题。使用循环网络判断语言的感情(比如在以下例子中需要判断一个评价是好评还是差评)和自然语言建模问题类似,唯一的区别在于除了最后一个时间点的输出是有意义的,其他时间点的输出都可以忽略,下图展示了使用循环网络处理感情分析问题的模型结构。

# -*- coding: utf-8 -*-

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给出了最多使用的单词数。和自然语言模型类似,会将出现频率 # 较低的单词替换为统一的ID,通过Keras封装的API生成25000条训练数据和25000条测试数据,每一条数据可以
# 摆看成一段话,并且每段话都有一个好评或者差评的标签。
(trainX, trainY), (testX, testY) = imdb.load_data(num_words=max_features)
print(len(trainX), 'train sequences')
print(len(trainY), 'test_sequences')

# 在自然语言处理中,每一段话的长度都是不一样的,但循环神经网络的循环长度是固定的,所以这里需要首先
# 将所有段落统一成固定长度。对于长度不够的段落,要使用默认值0来填充,对于超过长度
# 的段落则直接忽略掉超过的部分。
trainX = sequence.pad_sequences(trainX, maxlen = maxlen)
testX  = sequence.pad_sequences(testX, maxlen=mexlen)

# 输出统一长度之后的数据维度:
# ('x_train shape:', (25000, 80))
# ('x_test shape:', (25000, 80))
print('trainX shape:', trainX.shape)
print('testX shape:', trainX.shape)

# 再完成数据预处理之后的模型结构
model = Sequential()
# 构建embedding层。128代表了embedding层的向量维度。
model.add(Embedding(max_features, 128))
# 构建LSTM层。
model.add(LSTM(128,dropout=0.2))
# 构建最后的全连接层。注意在上面构建LSTM层时只会得到最后一个节点输出,
# 如果需要输出每个时间点的结果,那么可以将return_sequence参数设置为true。
model.add(Dense(1, activation='sigmoid'))

# 与MNIST样例类似地指定损失函数,优化函数和评测指标。
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
# 与MNIST样例类似地指定训练数据,训练轮数,batch大小以及验证数据。
model.fitt(trainX, trainY, batch_size=batch_size, epochs=15, validation_data=(testX, testY))

# 在测试数据上评测模型
score = model.evaluate(testX, testY, batch_size=batch_size)
print('Test loss:', score[0])
print('Test accuracy:',score[1])

以上两个样例针对Keras的基本用法做了详细的介绍。虽然Keras的封装,很多经典的神经网络结构能很快地被实现,不过要实现一些更加灵活的网络结构、损失函数或者数据输入方法,就需要对Keras的高级用法有更多的了解。

2、Keras高级用法

上面样例中最重要的封装就是Sequential类,所有的神经网络定义和训练都是通过Sequential实例来实现的。然而从这个类的名称可以看出,它只支持顺序模型的定义。类似Inception这样的模型结构,通过Sequential类就不容易直接实现了。为了支持更加灵活的模型定义方法,Keras支持以返回值的形式定义网络层结构。以下代码展示了如何使用这种方式定义模型。

# -*- coding:utf-8 -*-

import keras
from keras.datasets import mnist
from keras.layers import Input, Dense
from keras.models import Model

# 使用1中介绍的类似方法生成trainingX、trainingY、testX、testY,唯一的
# 不同是这里只使用了全连接层,所以不需要将输入整理成三维矩阵。

...

# 定义输入,这里指定的维度不用考虑batch大小。
inputs = Input(shape=(784,))
# 定义一层全连接,该层有500隐藏节点,使用ReLU激活函数,这一层的输入为inputs。
x = Dense(500, activate='relu')(inputs)
# 定义输出层。注意因为keras封装需要指定softmax作为激活函数。
predictions = Dense(10, activate='softmax')(x)

# 通过Model类创建模型,和Sequential类不同的是Model类在初始化的时候需要指定模型的输入和输出。
model = Model(inputs=inputs, outputs=predictions)

# 与1中类似的方法定义损失函数、优化函数和评测方法。
model.complie(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.SGD(),metrics=['accuracy'])

# 与1中类似的方法训练模型。
model.fit(trainX, trainY, batch_size=128, epoches=20, validation_data=(testX, testY))

通过这样的方式,Keras就可以实现类似Inception这样大的模型结构。以下代码展示了如何通过Keras实现Inception结构。

from keras.layers import Conv2D, MaxPooling2D, Input

# 定义输入图像尺寸
input_img = Input(shape=(256,256,3))

# 定义第一个分支。
tower_1 = Conv2D(64,(1,1),padding='same',activation='relu')(input_img)
tower_1 = COnv2D(64,(3,3),padding='same',activation='relu')(tower_1)

# 定义第二个分支。与顺序模型不同,第二个分支的输入使用的是input_img,而不是第一个分支的输出。
tower_2 = Conv2D(64,(1,1),padding='same',activation='relu')(input_img)
tower_2 = Conv2D(65,(5,5),padding='same',activation='relu')(tower_2)

# 定义第三个分支。类似地,第三个分支的输入也是input_img,
tower_3 = MaxPooling2D((3,3),strides=(1,1),padding='same')(input_img)
tower_3 = Conv2D(64, (1,1), padding='same', activation='relu')(tower_3)

# 将第三个分支通过concatenate的方式拼接在一起
output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis = 1)

除了可以支持顺序模型,Keras也可以支持有多个输入或者输出的模型。以下代码实现了下图所示的网络结构。

# -*- coding: utf-8 -*-

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

# 类似1的方式生成trainX, trainY, testX, testY
# 定义两个输入,一个输入为原始的图片信息,另一个输入为正确答案。
input1 = Input(shape=(784,), name="input1")
input2 = Input(shape=(10,), name="input2")

# 定义一个只有一个隐藏节点的全连接网络。
x = Dense(1, activation='relu')(input1)
# 定义只使用了一个隐藏节点的网络结构的输出层。
output1 = Desnse(10, activation='softmax',name="output1")(x)

# 将一个隐藏节点的输出和正确答案拼接在一起,这个将作为第二个输出层的输入。
y = keras.layers.concatenate([x, input2])
# 定义第二个输出层。
input3 = Dense(10, activation='softmax', name = "output2")(y)

# 定义一个有多个输入和多个输出的模型。这里只需要将所有的输入和输出给出即可。
model = Model(inputs=[inputs1, inputs2], outputs = [output1, output2])

# 定义损失函数、优化函数和测评方法。若多个输出的损失函数相同,可以只指定一个损失函数。
# 如果多个输出的损失函数不同,则可以通过一个列表或一个字典来指定每一个输出的损失函数。
# 比如可以使用:
# loss = {'output1':binary_crossentropy,'output2':binary_crossentropy}
# 求为不同的输出指定不同的损失函数。类似地,Keras也支持为不同输出产生的损失指定权重,
# 这可以通过loss_weights参数来完成。在下面的定义中,输出output1的权重为1,output2的
# 权重为0.1,所以这个模型会更加偏向于优化的第一个输出。

model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.SGD(), loss_weights = [1,0.1], metrics = ['accuracy'])

# 模型训练过程。因为有两个输入和输出,所以这里提供的数据也需要有两个输入和两个期待的正确答案输出。
# 通过列表的方式提供数据时,Keras会假设数据给出的顺序和定义Model类时输入会给出的顺序是对应的。为 # 了避免顺序不一致导致的问题,推荐使用字典的形式给出:
#  model.fit( 
#          {'input1':trainX, 'input2':trainY}
#          {'output1':trainX, 'output2':trainY}
#          ...)

model.fit([trainX, trainY], [trainY, trainY], batch_size=128, epochs=20, validation_data=([testX, testY], [testX, testY]))

从以上输出可以看出Keras在训练过程中会展示每个输出层的loss和accuracy。因为输出层output1只使用了一个维度为1的隐藏点,所以正确率只有29.85%。虽然输出层output2使用了正确答案作为输入,但是因为在损失函数中权重较低(只有0.1),所以它的收敛速度较慢,在20个epoch时准确率也只有92.1%。如果将两个输出层的损失权重设为一样,那么输出层output1在20个epoch时的准确率将只有27%,而输出层output2的准确率可以达到99.9%。虽然通过返回值的方式已经可以实现大部分的神经网络模型,然而Keras API还存在两大问题。第一,原生态Keras API对训练数据的处理流程支持得不太好,基本上需要一次性将数据全部全部加载到内存。第二,原生态Keras API无法支持分布式训练。为了解决这两个问题,Keras提供了一种与原生态TensorFlow结合地更加紧密的方式。以下代码显示了如何将Keras和原生态TensorFlow API联合起来解决MNIST问题。

# -*- coding: utf-8 -*-

import tensorflow as tf
from tensorflow.example.tutorials.mnist import input_data

mnist_data=input_data.read_data_sets('/path/to/MNIST_data', one_hot=True)

# 通过TensorFlow中的placeholder定义输入。类似的,Keras封装数据的网络层结构也可以支持队列输入。
# 这样可以有效避免一次性加载所有数据的问题。

x = tf.placeholder(tf.float32, shape=(None, 764))
y_ = tf.placeholder(tf.float32, shape=(None, 10))


# 直接使用TensorFlow中提供的Keras API定义网络层结构。
net = tf.keras.layers.Dense(500, activate='relu')(x)
y = tf.keras.layers.Dense(10, activation='softmax')(net)

# 定义损失函数和优化方法。注意这里可以混用Keras的API和原生态TensorFlow的API。
loss = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_, y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

# 定义正确的预测率作为指标。
acc_value = tf.reduce_mean(tf.keras.metric.categorical_accuracy(y_, y))

# 使用原生态TensorFlow的方式训练模型。这样就可以有效的实现分布式。
with tf.Session() as sess:
   tf.global_variables_initializer().run()
   for i in range(10000):
       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})
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Keras基本用法
  • 2、Keras高级用法
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档