keras学习笔记-----快速开始keras函数式API

Keras函数式API是定义复杂模型的方法,比如说多输出模型,有向无环图,或具有共享层的模型。当然在使用函数式API的时候,要对顺序模型有一定的了解,我们可以通过一些例子来学习函数式API的使用。

一、全连接网络

我们使用函数式API来实现一个全连接网络。在定义网络时,网络层的示例是可调用的,它以张量为参数,并且会返回一个张量,输入和输出都是张量,然后用来定义一个Model模型。下面我们通过这个例子,来看一下函数式API的使用。

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

# 返回一个张量
inputs = Input(shape=(784,))

# 定义网络层实例,输入和输出都是张量,可被调用
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)

# 创建模型
model = Model(inputs=inputs, outputs=predictions)
# 配置网络
model.compile(optimizer='rmsprop',
             loss='categorical_crossentropy',
             metrics=['accuracy'])
# 训练
model.fit(data, labels)

这样,我们就定义好了一个简单的模型,在keras中,利用函数式API,可以轻易地重用训练好的模型,所有的模型可以被调用,就像网络层一样。通过传递一个张量来调用它,在调用模型时,不仅重用了模型的结构,也重用了模型的参数。这样,我们可以快速创建可以处理序列输入的模型。只需一行代码就将图像分类模型转换为视频分类模型。

from keras.layers import TimeDistributed

# 创建一个20个时间步的序列,每个时间步是一个784的向量
input_sequences = Input(shape=(20, 784))

# 将之前定义的模型应用到这个输入上,输入为维度为10的20个向量的序列
processed_sequences = TimeDistributed(model)(input_sequences)

二、多输入多输出模型

对于多输入多输出模型,函数式API使处理大量交织的数据流变得容易。我们来预测Twitter上的一条新闻标题有多少转发和点赞数。模型的主要输入是新闻标题本身,即一系列词语,我们增加了辅助输入来接受额外的数据,例如新闻的发布时间。该模型也通过来那个损失函数进行监督学习。模型结构图如下:

from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model

# 标题输入,是一个含有100个整数的序列,值在1-10000之间,10000个词的词汇表
main_input = Input(shape=(100,), dtype='int32', name='main_input')

# Embedding层将输入编码为一个稠密向量的序列,维度为512
x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)

# LSTM层,把向量序列转换为单个向量,包含序列的上下文信息
lstm_out = LSTM(32)(x)

# 插入辅助损失,使LSTM和Embedding能平稳训练
auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)

# 添加一个辅助输入,并连接起来
auxiliary_input = Input(shape=(5,), name='aux_input')
x = keras.layers.concatenate([lstm_out, auxiliary_input])

# 堆叠多个全连接层
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)

# 逻辑回归
main_output = Dense(1, activation='sigmoid', name='main_output')(x)

# 定义模型
model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])

# 编译模型,配置网络
model.compile(optimizer='rmsprop', 
              loss='binary_crossentropy',
             loss_weights=[1., 0.2])

# 训练模型
model.fit([headline_data, additional_data], [labels, labels], epochs=50, batch_size=32)

三、共享网络层

共享网络层是函数式API的另一个用途。假如我们想建立一个模型分辨两条推文是否来自同一个人,我们可以将两条推文编码成两个向量,连接向量,然后添加逻辑回归层。输出两条推文来自同一作者的概率。我们可以使用同一个LSTM来编码两条推文。

from keras.layers import Input, LSTM, Dense
from keras.models import Model
import keras

tweet_a = Input(shape(280, 256))
tweet_b = Input(shape(280, 256))

# 这一层可以输入一个矩阵,并返回一个64维向量
shared_lstm = LSTM(64)

# 重用相同的图层示例多次,权重也会重用
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)

# 连接两个向量
merged_vector = keras.layers.concatenate([encoded_a, encoded_b])

# 添加逻辑回归层
predictions = Dense(1, activation='sigmoid')(merged_vector)

# 定义模型
model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)

# 编译
model.compile(optimizer='rmsprop',
             loss='bianry_crossentropy',
             metrics=['accuracy'])

# 训练
model.fit([data_a, data_b], labels, epoch=10)

我们还需要注意的问题是,模型的输入和输处形状的问题,假如一个单输出单输出的模型。

a = Input(shape=(200, 256))
lstm = LSTM(32)
encoded_a = lstm(a)

assert lstm.output == encoded_a

但是,如果多输入就会遇到问题。需要如下判断

a = Input(shape=(280, 256))
b = Input(shape=(280, 256))

lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)

assert lstm.get_output_at(0) == encoded_a
assert lstm.get_output_at(1) == encoded_b

猜你喜欢

转载自blog.csdn.net/gyt15663668337/article/details/89355054