本文转载自keras中最常用深度学习的API
写在前面,如果执行本文代码有以下报错,你再回来看解决方案,现在可以直接看正文部分:
pydot failed to call GraphViz
或者GraphViz’s executables not found
那就需要以下操作
(1)打开Anaconda Propmt,在tensorflow-gpu环境中
pip uninstall pydot
pip install pydotplus
然后找到keras里面的C:\ProgramData\Anaconda3\envs\tensorflow-gpu\Lib\site-packages\keras\utils\vis_utils.py,把里面的pydot的都替换成pydotplus。
(2)下载release.7z,解压到位置 D:\Graphviz(解压位置自己定义),
再将D:\Graphviz\release\bin添加到系统环境变量中
正文
序贯模型(Sequential)允许你为大多数问题逐层的创建模型,但它却不能创建共享层或者是具有多个输入或输出的模型。
本文将带你发现如何在Keras中使用灵活的API函数来定义深度学习模型。
1.Keras序贯模型
2.Keras功能函数模型
3.标准网络模型
4.共享层模型
5.多个输入和输出模型
6.自编码器的应用
1.Keras序贯模型
序贯模型就是前面所讲的建立Keras模型的方法:
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(2, input_dim=1))
model.add(Dense(1))
序贯模型(Sequential)允许你为大多数问题逐层的创建模型,但它却不能创建共享层或者是具有多个输入或输出的模型。
2.Keras功能函数模型
Keras功能API为定义模型提供了更灵活的方式。
它允许你定义多个输入或输出的模型以及可以共享图层的模型。除此之外,它还允许你定义临时的非循环网络图。
2.1定义输入
首先,你必须创建并定义一个独立的输入层,该层指定输入数据的形状。
输入层采用一个模型参数,它是一个代表输入数据维度的元组。
from keras.layers import Input
#定义输入层及形状
input_data = Input(shape=(784,))
2.2连接层
使用括号符号,使得在创建图层之后,指定从当前图层的输入到即将到达的图层。
from keras.layers import Input
from keras.layers import Dense
#定义输入层及形状
input_data = Input(shape=(784,))
#定义连接层
hidden = Dense(256,activation='relu')(input_data)
out = Dense(10,activation='relu')(hidden)
这样创建更具有灵活性。
2.3创建模型
Keras提供了一个Model类,你可以使用它从创建的图层时创建模型,你需要指定输入和输出层。例如:
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
#定义输入层及形状
input_data = Input(shape=(784,))
#定义连接层
hidden = Dense(256,activation='relu')(input_data)
out = Dense(10,activation='relu')(hidden)
model = Model(inputs=input_data, outputs=out)
3.标准网络模型
3.1多层感知器
在本节中,我们为二进制分类定义了一个多层Perceptron模型。该模型有10个输入,3个隐藏层,10个神经元,输出层有1个输出。在每个隐藏层中使用整流线性激活函数,在输出层使用S形激活函数进行二进制分类。
# Multilayer Perceptron
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
visible = Input(shape=(10,))
hidden1 = Dense(10, activation='relu')(visible)
hidden2 = Dense(20, activation='relu')(hidden1)
hidden3 = Dense(10, activation='relu')(hidden2)
output = Dense(1, activation='sigmoid')(hidden3)
model = Model(inputs=visible, outputs=output)
3.2卷积神经网络
该模型接收黑白64×64图像作为输入,然后两个卷积层和汇集层的序列作为特征提取器,随后是完全连接的层来解释特征,并且输出层是具有S形激活函数。
# Convolutional Neural Network
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
visible = Input(shape=(64,64,1))
conv1 = Conv2D(32, kernel_size=4, activation='relu')(visible)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
conv2 = Conv2D(16, kernel_size=4, activation='relu')(pool1)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
hidden1 = Dense(10, activation='relu')(pool2)
output = Dense(1, activation='sigmoid')(hidden1)
model = Model(inputs=visible, outputs=output)
3.3循环神经网络
在本节中,我们将定义一个LSTM循环神经网络用于序列分类。
该模型是100个时间步长作为输入,该模型具有单个LSTM隐藏层,用于从序列中提取特征,然后是完全连接的层以解释LSTM输出,随后是用于进行二进制预测的输出层。
# Recurrent Neural Network
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers.recurrent import LSTM
visible = Input(shape=(100,1))
hidden1 = LSTM(10)(visible)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(1, activation='sigmoid')(hidden2)
model = Model(inputs=visible, outputs=output)
4.共享层模型
多层可以共享一层的输出。
例如,可能存在来自输入的多个不同的特征提取层,或者用于解释特征提取层输出的多个层。
4.1共享输入层
在本节中,我们使用不同大小的内核定义多个卷积层来解释图像输入。
该模型输入采用大小为64×64像素的黑白图像。有两个CNN特征提取子模型共享该输入:第一个内核大小为4,第二个内核大小为8。这些特征提取子模型的输出被平坦化为向量,并连接成一个长向量,并传递到完全连接的层,以便在最终输出层之前进行二进制分类。
# Shared Input Layer
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
from keras.layers.merge import concatenate
# input layer
visible = Input(shape=(64,64,1))
# first feature extractor
conv1 = Conv2D(32, kernel_size=4, activation='relu')(visible)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
flat1 = Flatten()(pool1)
# second feature extractor
conv2 = Conv2D(16, kernel_size=8, activation='relu')(visible)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
flat2 = Flatten()(pool2)
# merge feature extractors
merge = concatenate([flat1, flat2])
# interpretation layer
hidden1 = Dense(10, activation='relu')(merge)
# prediction output
output = Dense(1, activation='sigmoid')(hidden1)
model = Model(inputs=visible, outputs=output)
# summarize layers
print(model.summary())
# plot graph
plot_model(model, to_file='shared_input_layer.png')
运行示例总结模型层。
模型图的被创建并保存到文件:
4.2共享特征提取层
在本节中,我们使用两个并行子模型解释LSTM特征提取器的输出以进行序列分类。
模型的输入是一个特征为100的时间步长,具有10个存储单元的LSTM层解释该序列。第一种解释模式是浅层的单层完全连接层,第二种是深层的3层模型。两个解释模型的输出都被连接成一个长向量,传递给用于进行二进制预测的输出层。
# Shared Feature Extraction Layer
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers.recurrent import LSTM
from keras.layers.merge import concatenate
# define input
visible = Input(shape=(100,1))
# feature extraction
extract1 = LSTM(10)(visible)
# first interpretation model
interp1 = Dense(10, activation='relu')(extract1)
# second interpretation model
interp11 = Dense(10, activation='relu')(extract1)
interp12 = Dense(20, activation='relu')(interp11)
interp13 = Dense(10, activation='relu')(interp12)
# merge interpretation
merge = concatenate([interp1, interp13])
# output
output = Dense(1, activation='sigmoid')(merge)
model = Model(inputs=visible, outputs=output)
# summarize layers
print(model.summary())
# plot graph
plot_model(model, to_file='shared_feature_extractor.png')
运行示例总结模型层。
模型图被创建并保存到文件。
5.多个输入和输出模型
5.1多输入模型
我们将开发一个图像分类模型,它将两个版本的图像作为输入,每个版本的大小不同。具体是黑白64×64版,彩色32×32版。单独的特征提取CNN模型在每个模型上运行,然后将两个模型的结果连接起来进行解释和最终预测。
在创建Model()实例时,我们将两个输入图层定义为数组:
#两个输入图层定义为数组
model = Model(inputs=[visible1, visible2], outputs=output)
完整的示例如下所示。
# Multiple Inputs
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
from keras.layers.merge import concatenate
# first input model
visible1 = Input(shape=(64,64,1))
conv11 = Conv2D(32, kernel_size=4, activation='relu')(visible1)
pool11 = MaxPooling2D(pool_size=(2, 2))(conv11)
conv12 = Conv2D(16, kernel_size=4, activation='relu')(pool11)
pool12 = MaxPooling2D(pool_size=(2, 2))(conv12)
flat1 = Flatten()(pool12)
# second input model
visible2 = Input(shape=(32,32,3))
conv21 = Conv2D(32, kernel_size=4, activation='relu')(visible2)
pool21 = MaxPooling2D(pool_size=(2, 2))(conv21)
conv22 = Conv2D(16, kernel_size=4, activation='relu')(pool21)
pool22 = MaxPooling2D(pool_size=(2, 2))(conv22)
flat2 = Flatten()(pool22)
# merge input models
merge = concatenate([flat1, flat2])
# interpretation model
hidden1 = Dense(10, activation='relu')(merge)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(1, activation='sigmoid')(hidden2)
model = Model(inputs=[visible1, visible2], outputs=output)
# summarize layers
print(model.summary())
# plot graph
plot_model(model, to_file='multiple_inputs.png')
模型图被创建并保存到文件。
5.2多输出模型
在本节中,我们将开发出一种可以进行两种不同类型预测的模型。给定一个特征的100个时间步长的输入序列,该模型将对序列进行分类并输出具有相同长度的新序列。
LSTM层解释输入序列,并返回每个时间步长的隐藏状态。第一个输出模型创建一个堆栈的LSTM,解释特征,并进行二进制预测。第二个输出模型使用相同的输出层对每个输入时间步长进行实值预测。
# Multiple Outputs
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers.recurrent import LSTM
from keras.layers.wrappers import TimeDistributed
# input layer
visible = Input(shape=(100,1))
# feature extraction
extract = LSTM(10, return_sequences=True)(visible)
# classification output
class11 = LSTM(10)(extract)
class12 = Dense(10, activation='relu')(class11)
output1 = Dense(1, activation='sigmoid')(class12)
# sequence output
output2 = TimeDistributed(Dense(1, activation='linear'))(extract)
# output
model = Model(inputs=visible, outputs=[output1, output2])
# summarize layers
print(model.summary())
# plot graph
plot_model(model, to_file='multiple_outputs.png')
模型图的创建并保存到文件:
6.自编码器的应用
import keras
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import plot_model
#导入model类
from keras.models import Model
#导入keras.layers中相关模块
from keras.layers import Dense,Dropout,Input
#导入优化器
from keras.optimizers import Adam
#导入callback回调函数
from keras.callbacks import Callback
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data/',one_hot=True)
#读取数据
x_train = mnist.train.images
x_test = mnist.test.images
#实例化输入
input_data = Input(shape=(784,))
#编码层
encoded = Dense(400,activation='relu')(input_data)
encoded = Dropout(0.2)(encoded)
encoded_out = Dense(4,activation='relu')(encoded)
#解码层
decoded = Dense(400,activation='relu')(encoded_out)
pred = Dense(784,activation='relu')(decoded)
autoencoder = Model(inputs = input_data, outputs = pred)
encoded_layer = Model(inputs= input_data,outputs=encoded_out)
#修改优化器中的学习率
adam = Adam(lr=0.001,decay=0.0005)
#编译模型
autoencoder.compile(optimizer=adam,loss='mse')
# summarize layers
print(autoencoder.summary())
# plot graph
plot_model(autoencoder, to_file='shared_feature_extractor.png')
#自定义每轮结束后操作
def epoch_end_operation(epoch):
if epoch%4 == 0:
#测试模型
loss = autoencoder.evaluate(x_test,x_test,verbose=1)
print('第%s轮测试后结果:%.4f' % (epoch,loss))
a = np.random.randint(0,5000,1)[0]
x_pred = autoencoder.predict(x_test[a:a+8])
x_encode = encoded_layer.predict(x_test[a:a+8])
#绘制测试结果
fig, ax = plt.subplots(3, 8, figsize=(8, 3))
for i in range(8):
ax[0][i].imshow(np.reshape(x_test[i+a], (28, 28)))
ax[1][i].imshow(np.reshape(x_encode[i], (2, 2)))
ax[2][i].imshow(np.reshape(x_pred[i], (28, 28)))
ax[0][i].get_xaxis().set_visible(False)
ax[0][i].get_yaxis().set_visible(False)
ax[1][i].get_xaxis().set_visible(False)
ax[1][i].get_yaxis().set_visible(False)
ax[2][i].get_xaxis().set_visible(False)
ax[2][i].get_yaxis().set_visible(False)
plt.show()
print()
#自定义回调类
class PltPred(Callback):
def on_epoch_end(self, epoch, logs={}):
epoch_end_operation(epoch+1)
#定义回调函数
pltpred_callback = PltPred()
#回调函数列表
callbacks_list = [pltpred_callback]
#训练模型
autoencoder.fit(x_train,x_train,batch_size=100,epochs=20,verbose=0,callbacks=callbacks_list)