Keras多输入多输出模型构建

  • 1. 多输出模型构建
    • 多输出模型构建
    • 自定义loss函数
    • 批量训练
    • 调试
  • 2. 多输入多输出模型(上)
    • 多输入多输出模型
    • (关键)定义这个具有两个输入和输出的模型:
    • 编译模型时候分配损失函数权重
    • 训练模型
    • 另外一种编译、训练方式(利用字典)
  • 多输入多输出模型(下)--GoogleNet
    • 模型结构
    • Inception模块
    • 辅助输出轴
    • 前面的推断过程
    • 模型构建
  • 多输入多输出模型示例-3

1. 多输出模型构建

reference from : https://www.jianshu.com/p/6bcd63a0165c

多输出模型构建

使用keras函数式API构建网络:

# 输入层
inputs = tf.keras.layers.Input(shape=(64,64,3))# 卷积层及全连接层等相关层
x = tf.keras.layers.Dense(256, activation=tf.nn.relu)(inputs)# 多输出,定义两个输出,指定名字标识
fc_a=tf.keras.layers.Dense(name='fc_a',units=CLASS_NUM,activation=tf.nn.softmax)(x)
fc_b=tf.keras.layers.Dense(name='fc_b',units=CLASS_NUM,activation=tf.nn.softmax)(x)
# 单输入多输出
model = tf.keras.Model(inputs=inputs, outputs=[fc_a, fc_b])# 目标函数定义,需与输出层名字对应
losses = {'fc_a': 'categorical_crossentropy','fc_b': 'categorical_crossentropy'}model.compile(optimizer=tf.train.AdamOptimizer(),loss=losses,metrics=['accuracy'])

自定义loss函数

def loss_a(y_true, y_pred):return tf.keras.losses.categorical_crossentropy(y_true, y_pred)def loss_b(y_true, y_pred):return tf.keras.losses.meas_squared_error(y_true, y_pred)losses = {'fc_a': loss_a,'fc_b': loss_b}model.compile(optimizer=tf.train.AdamOptimizer(),loss=losses,metrics=['accuracy'])

批量训练

# data_generator返回的标签形式要是与多输出的数量对应的数组
def data_generator(sample_num, batch_size):while True:max_num = sample_num - (sample_num % batch_size)for i in range(0, max_num, batch_size):...yield (batch_x, [batch_a, batch_b])model.fit_generator(generator=data_generator(sample_num, batch_size),steps_per_epoch=sample_num//batch_size,epoches=EPOCHES,verbose=1)

调试

在自定义的loss函数中,是以Sequence的方式来输入的,如果想调试查看loss的计算过程中的输出,直接print是无法打印值的,这是因为tensorflow的每次op都要以sess为基础来启动,如果想调试,可以用eager_execution模式:

import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
np.set_printoptions(threshold=np.nan) # 输出所有元素

2. 多输入多输出模型(上)

reference from : https://blog.csdn.net/weixin_40920290/article/details/80917353

多输入多输出模型

主要输入(main_input): 新闻标题本身,即一系列词语.

辅助输入(aux_input): 接受额外的数据,例如新闻标题的发布时间等.

该模型将通过 两个损失函数 进行监督学习.
较早地在模型中使用主损失函数,是深度学习模型的一个良好正则方法.

下面用函数式API来实现它。

主要输入:接受新闻标题本身,即一个整数序列(每个整数编码一个词)。这些整数在 1 到 10000之间(10000个词的词汇表),且序列长度为100个词:

from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model# 标题输入:接收一个含有 100 个整数的序列,每个整数在 1 到 10000 之间。
# 注意我们可以通过传递一个 `name` 参数来命名任何层。
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)

此时,我们将辅助输入数据与LSTM层的输出连接起来,输入到模型中:

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])

编译模型时候分配损失函数权重

编译模型的时候,给 辅助损失 分配一个0.2的权重.

如果要为不同的输出指定不同的 loss_weights 或 loss,可以使用列表或字典.
在这里,我们给 loss 参数传递单个损失函数,这个损失将用于所有的输出。:

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)

另外一种编译、训练方式(利用字典)

由于输入和输出均被命名了(在定义时传递了一个 name 参数),我们也可以通过以下方式编译模型:

model.compile(optimizer='rmsprop',loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},loss_weights={'main_output': 1., 'aux_output': 0.2})# 然后使用以下方式训练:
model.fit({'main_input': headline_data, 'aux_input': additional_data},{'main_output': labels, 'aux_output': labels},epochs=50, batch_size=32)

多输入多输出模型(下)–GoogleNet

reference from : https://blog.csdn.net/weixin_40920290/article/details/80925228

模型结构

注意:

  1. LocalRespNorm一般不太使用了,取而代之的是BatchNormal
  2. 因为图像数据不同,有部分参数也会发生改变
  3. 我们只实现**GoogelNet(v1)**版本

Inception模块

def inception(x, filter_size, layer_number):"""由1x1,3x3,5x5以及Maxpool构成的Inception模块Args:x(Tesnsor): 输入张量filter_size: 卷积核列表,总共有6个卷积核。layer_number: Inception序号Returns:经过Inception模块后的Tensor"""layer_number = str(layer_number)with K.name_scope('Inception_' + layer_number):# 1x1卷积with K.name_scope("conv_1x1"):conv_1x1 = Conv2D(filters=filter_size[0], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_1x1' + layer_number)(x)# 3x3 Bottleneck layer(瓶颈模块)和 3x3 卷积with K.name_scope('conv_3x3'):conv_3x3 = Conv2D(filters=filter_size[1], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_3x3_bottleneck' + layer_number)(x)conv_3x3 =  Conv2D(filters=filter_size[2], kernel_size=(3, 3),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_3x3' + layer_number)(conv_3x3)with K.name_scope('conv_5x5'):# 5x5 Bottleneck layer(瓶颈层)和 5x5 卷积conv_5x5 = Conv2D(filters=filter_size[3], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_5x5_bottleneck' + layer_number)(x)conv_5x5 = Conv2D(filters=filter_size[4], kernel_size=(5, 5),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_5x5' + layer_number)(conv_5x5)with K.name_scope('Max_Conv'):# Max pooling(最大池化层) 和 Bottleneck layer(瓶颈层)max_pool = MaxPooling2D(pool_size=3, strides=1, padding='same',name='maxpool'+layer_number)(x)max_pool = Conv2D(filters=filter_size[5], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='maxpool_conv1x1' + layer_number)(max_pool)with K.name_scope('concatenate'):# 将所有张量拼接在一起x = concatenate([conv_1x1, conv_3x3, conv_5x5, max_pool], axis=-1)# high/width上相同,channels拼接在一起return x

辅助输出轴

def aux_classifier(x, filter_size, layer_number):"""辅助轴,输出softmax分类结果Args:x: 输入张量filter_size: 卷积核列表,长度为3layer_number: 序列Returns: 辅助轴分类结果"""layer_number = str(layer_number)with K.name_scope('aux_ckassifier'+layer_number):# 平均池化层x = AveragePooling2D(pool_size=3, strides=2, padding='same',name='AveragePooling2D'+layer_number)(x)# (0)1x1 卷积层x = Conv2D(filters=filter_size[0], kernel_size=1, strides=1,padding='valid', activation='relu',kernel_regularizer=l2(L2_RATE),name='aux_conv' + layer_number)(x)# 展平x = Flatten()(x)# (1)全连接层1x = Dense(units=filter_size[1], activation='relu',kernel_regularizer=l2(L2_RATE),name='aux_dense1_' + layer_number)(x)x = Dropout(0.7)(x)# (3)softmax输出层x = Dense(units=NUM_CLASS, activation='softmax',kernel_regularizer=l2(L2_RATE),name='aux_output' + layer_number)(x)return x

前面的推断过程

def front(x, filter_size):# (0)conv2dx = Conv2D(filters=filter_size[0], kernel_size=5, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)x = MaxPooling2D(pool_size=3, strides=2, padding='same')(x)x = BatchNormalization(axis=-1)(x)# (1)conv2dx = Conv2D(filters=filter_size[1], kernel_size=1, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)# (2)conv2dx = Conv2D(filters=filter_size[2], kernel_size=3, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)x = BatchNormalization(axis=-1)(x)x = MaxPooling2D(pool_size=3,strides=1,padding='same')(x)return x

模型构建

知识点

  1. 多输入多输出模型
  2. GoogelNet(V1)
  3. K.name_scope()

Note

  • 模型的参数不完全一样,因为输入的是cifar-10数据集
  • 训练的时候没有用生成器,也没有图像增强; 因为多输入多输出模型利用fit_generator比较麻烦,可以自己百度一下,在这里就不用了
  • 利用TensorBoard查看计算图以及训练进程
  • 并没有去保存训练模型等操作
  • K.name_scope是可以用的,利用它组织好网络结构,使用时只需要训练的时候将TensorBoard回调对象传回去
import keras.backend as K
from keras.datasets import cifar10
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, AveragePooling2D
from keras.layers import concatenate, BatchNormalization, Flatten, Dropout
from keras.regularizers import l2
from keras.utils import to_categorical
from keras.models import Model
from keras.callbacks import TensorBoard
from keras.optimizers import AdamL2_RATE = 0.002
NUM_CLASS = 10
BATCH_SIZE = 128
EPOCH = 10def inception(x, filter_size, layer_number):"""由1x1,3x3,5x5以及Maxpool构成的Inception模块Args:x(Tesnsor): 输入张量filter_size: 卷积核列表,总共有6个卷积核。layer_number: Inception序号Returns:经过Inception模块后的Tensor"""layer_number = str(layer_number)with K.name_scope('Inception_' + layer_number):# 1x1卷积with K.name_scope("conv_1x1"):conv_1x1 = Conv2D(filters=filter_size[0], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_1x1' + layer_number)(x)# 3x3 Bottleneck layer(瓶颈模块)和 3x3 卷积with K.name_scope('conv_3x3'):conv_3x3 = Conv2D(filters=filter_size[1], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_3x3_bottleneck' + layer_number)(x)conv_3x3 = Conv2D(filters=filter_size[2], kernel_size=(3, 3),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_3x3' + layer_number)(conv_3x3)with K.name_scope('conv_5x5'):# 5x5 Bottleneck layer(瓶颈层)和 5x5 卷积conv_5x5 = Conv2D(filters=filter_size[3], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_5x5_bottleneck' + layer_number)(x)conv_5x5 = Conv2D(filters=filter_size[4], kernel_size=(5, 5),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='conv_5x5' + layer_number)(conv_5x5)with K.name_scope('Max_Conv'):# Max pooling(最大池化层) 和 Bottleneck layer(瓶颈层)max_pool = MaxPooling2D(pool_size=3, strides=1, padding='same',name='maxpool'+layer_number)(x)max_pool = Conv2D(filters=filter_size[5], kernel_size=(1, 1),strides=1, padding='same', activation='relu',kernel_regularizer=l2(L2_RATE),name='maxpool_conv1x1' + layer_number)(max_pool)with K.name_scope('concatenate'):# 将所有张量拼接在一起x = concatenate([conv_1x1, conv_3x3, conv_5x5, max_pool], axis=-1)  # high/width上相同,channels拼接在一起return xdef aux_classifier(x, filter_size, layer_number):"""辅助轴,输出softmax分类结果Args:x: 输入张量filter_size: 卷积核列表,长度为3layer_number: 序列Returns:"""layer_number = str(layer_number)with K.name_scope('aux_ckassifier'+layer_number):# 平均池化层x = AveragePooling2D(pool_size=3, strides=2, padding='same',name='AveragePooling2D'+layer_number)(x)# (0)1x1 卷积层x = Conv2D(filters=filter_size[0], kernel_size=1, strides=1,padding='valid', activation='relu',kernel_regularizer=l2(L2_RATE),name='aux_conv' + layer_number)(x)# 展平x = Flatten()(x)# (1)全连接层1x = Dense(units=filter_size[1], activation='relu',kernel_regularizer=l2(L2_RATE),name='aux_dense1_' + layer_number)(x)x = Dropout(0.7)(x)# (3)softmax输出层x = Dense(units=NUM_CLASS, activation='softmax',kernel_regularizer=l2(L2_RATE),name='aux_output' + layer_number)(x)return xdef front(x, filter_size):# (0)conv2dx = Conv2D(filters=filter_size[0], kernel_size=5, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)x = MaxPooling2D(pool_size=3, strides=2, padding='same')(x)x = BatchNormalization(axis=-1)(x)# (1)conv2dx = Conv2D(filters=filter_size[1], kernel_size=1, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)# (2)conv2dx = Conv2D(filters=filter_size[2], kernel_size=3, strides=1,padding='same', activation='relu',kernel_regularizer=l2(L2_RATE))(x)x = BatchNormalization(axis=-1)(x)x = MaxPooling2D(pool_size=3, strides=1, padding='same')(x)return xdef load():(x_train, y_train), (x_test, y_test) = cifar10.load_data()y_train = to_categorical(y_train, NUM_CLASS)y_test = to_categorical(y_test, NUM_CLASS)x_train = x_train.astype('float32') / 255x_test = x_test.astype('float32') / 255return x_train, y_train, x_test, y_testdef googlenet_model():# 搭建模型X_Input = Input(shape=input_shape, name='Input')X = front(X_Input, [64, 64, 192])# Inception_0X = inception(X, filter_size=[64, 96, 128, 16, 32, 32], layer_number=0)# Inception_1X = inception(X, [128, 128, 192, 32, 96, 64], layer_number=1)X = MaxPooling2D(pool_size=3, strides=2, padding='same')(X)# Inception_2X = inception(X, [192, 96, 208, 16, 48, 64], layer_number=2)# aux1aux_output_1 = aux_classifier(X, [128, 1024], layer_number=1)# Inception_3X = inception(X, [160, 112, 225, 24, 64, 64], layer_number=3)# Inception_4X = inception(X, [128, 128, 256, 24, 64, 64], layer_number=4)# Incepetion_5X = inception(X, [112, 144, 288, 32, 64, 64], layer_number=5)# aux2aux_output_2 = aux_classifier(X, [128, 1024], layer_number=2)# Inception_6X = inception(X, [256, 160, 320, 32, 128, 128], layer_number=6)X = MaxPooling2D(pool_size=3, strides=2, padding='same')(X)# Inception_7X = inception(X, [256, 160, 320, 32, 128, 128], layer_number=7)# Inception_8X = inception(X, [386, 192, 384, 48, 128, 128], layer_number=8)# 输出模型X = AveragePooling2D(pool_size=4, strides=1, padding='valid')(X)X = Flatten()(X)X = Dropout(0.4)(X)main_output = Dense(NUM_CLASS, activation='softmax', kernel_regularizer=l2(L2_RATE))(X)# 定义多输入多输出模型model = Model(inputs=X_Input, outputs=[main_output, aux_output_1, aux_output_2])return modelif __name__ == '__main__':x_train, y_train, x_test, y_test = load()input_shape = x_train.shape[1:]# 创建模型GoogleNet = googlenet_model()optimizer = Adam(epsilon=1e-08)GoogleNet.compile(optimizer=optimizer, loss='categorical_crossentropy',metrics=['accuracy'], loss_weights=[1, 0.3, 0.3])GoogleNet.summary()tfck = TensorBoard(log_dir='logs/GoogleNet')GoogleNet.fit(x=x_train, y=[y_train, y_train, y_train], validation_data=(x_test, [y_test, y_test, y_test]),epochs=EPOCH, callbacks=[tfck], batch_size=BATCH_SIZE)

多输入多输出模型示例-3

reference from : https://blog.csdn.net/zzc15806/article/details/84067017

假设我们需要搭建如下的模型,输入数据分别为100维和50维的向量,输出为0或1:

from keras.layers import Conv1D, Dense, MaxPool1D, concatenate, Flatten
from keras import Input, Model
from keras.utils import plot_model
import numpy as npdef multi_input_model():"""构建多输入模型"""input1_= Input(shape=(100, 1), name='input1')input2_ = Input(shape=(50, 1), name='input2')x1 = Conv1D(16, kernel_size=3, strides=1, activation='relu', padding='same')(input1_)x1 = MaxPool1D(pool_size=10, strides=10)(x1)x2 = Conv1D(16, kernel_size=3, strides=1, activation='relu', padding='same')(input2_)x2 = MaxPool1D(pool_size=5, strides=5)(x2)x = concatenate([x1, x2])x = Flatten()(x)x = Dense(10, activation='relu')(x)output_ = Dense(1, activation='sigmoid', name='output')(x)model = Model(inputs=[input1_, input2_], outputs=[output_])model.summary()return modelif __name__ == '__main__':# 产生训练数据x1 = np.random.rand(100, 100, 1)x2 = np.random.rand(100, 50, 1)# 产生标签y = np.random.randint(0, 2, (100,))model = multi_input_model()# 保存模型图plot_model(model, 'Multi_input_model.png')model.compile(optimizer='adam', loss='binary_crossentropy')model.fit([x1, x2], y, epochs=10, batch_size=10)

keras多输出模型相关推荐

  1. CV:基于Keras利用训练好的hdf5模型进行目标检测实现输出模型中的脸部表情或性别的gradcam(可视化)

    CV:基于Keras利用训练好的hdf5模型进行目标检测实现输出模型中的脸部表情或性别的gradcam(可视化) 目录 设计思路 核心代码 设计思路 核心代码 #CV:基于keras利用训练好的hdf ...

  2. 获取keras中间层输出、模型保存与加载

    1. 获取keras中间层输出 # model summary and plot import keras from keras.models import Model from keras.util ...

  3. build_transformer_model如果不返回keras的bert模型返回的是什么?

    build_transformer_model 还有两个问题: 1.如果不返回keras的bert模型返回的是什么? bert = build_transformer_model( config_pa ...

  4. DL之Keras:基于Keras框架建立模型实现【预测】功能的简介、设计思路、案例分析、代码实现之详细攻略(经典,建议收藏)

    DL之Keras:基于Keras框架建立模型实现[预测]功能的简介.设计思路.案例分析.代码实现之详细攻略(经典,建议收藏) 目录 Keras框架使用分析 Keras框架设计思路 案例分析 代码实现 ...

  5. 【Keras速成】Keras图像分类从模型自定义到测试

    文章首发于微信公众号<与有三学AI> [Keras速成]Keras图像分类从模型自定义到测试 这是给大家准备的Keras速成例子 这一次我们讲讲keras这个简单.流行的深度学习框架,一个 ...

  6. as转html5工具,将keras的h5模型转换为tensorflow的pb模型

    背景:目前keras框架使用简单,很容易上手,深得广大算法工程师的喜爱,但是当部署到客户端时,可能会出现各种各样的bug,甚至不支持使用keras,本文来解决的是将keras的h5模型转换为客户端常用 ...

  7. 为什么将表格的method改为post后就无法工作_用Python将Keras深度学习模型部署为Web应用程序...

    构建一个很棒的机器学习项目是一回事,但归根结底,你希望其他人能够看到你的辛勤工作.当然,你可以将整个项目放在GitHub上,但是怎么让你的祖父母也看到呢?我们想要的是将深度学习模型部署为世界上任何人都 ...

  8. 多输出模型实例的数据加载

    多输出模型实例的数据加载 相关的数据集放在C:/Users/Administrator/data/moc import tensorflow as tf from tensorflow import ...

  9. 使用Keras进行单模型多标签分类

    原文:https://www.pyimagesearch.com/2018/05/07/multi-label-classification-with-keras/ 作者:Adrian Rosebro ...

最新文章

  1. 《Android/OPhone 开发完全讲义》样章和目录下载
  2. elk系列7之通过grok分析apache日志
  3. 关闭 Sublime Text 3 自动更新
  4. 动态代码生成 静态代码生成_将速度提升到自己的个人代码生成器中
  5. 【AI视野·今日Robot 机器人论文速览 第二十八期】Wed, 1 Dec 2021
  6. 智能客服究竟该怎么玩?
  7. 这位 50 岁的海归程序员,当着老板还在天天改 Bug
  8. Linux NFS 服务部署
  9. 嵌入式Ubuntu 搭建caffee环境
  10. dnf php的补丁放哪,DNF模型文件在哪 补丁玩家必备知识
  11. 测试开发面试题(一)-----appium相关
  12. 提高微服务安全性的11个方法
  13. javascript开发简易画板
  14. scilab中文简介
  15. Win10开机时怎么跳过磁盘检查?
  16. Jacobi(雅可比)迭代原理与matlab代码
  17. matlab合并两个矩阵。
  18. Windows+CentOS 7双系统(最完全攻略!!)-------囊括所有安装CentOS双系统的问题!
  19. C++ PI(π)的表示
  20. 前端必经之路:CSS页面布局(深入理解浮动布局、定位布局、圣杯布局和双飞翼布局等重要布局方案)

热门文章

  1. r shiny内部支持的输入函数
  2. 命令前面加一个!的意思如!python
  3. 傅雷家书摘抄:怎么脱单
  4. U3D屏幕坐标,世界坐标,像素坐标之间的关系
  5. noj 邮票分你一半z的生日
  6. Silverlight实用窍门系列:54.详解Silverlight中的矩阵变换MatrixTransform,实现其余各种变换【附带实例源码】...
  7. 高性能MySQL读书笔记---查询优化
  8. php正则表达式匹配img中任意属性的方法
  9. Java剖析工具JProfiler入门使用教程:离线剖析和触发器
  10. nyoj904 search