Keras复杂网络的搭建

概述

在我们刚接触keras时候用的都是用的Sequential模型实现的,但是这种网络只能有一个输入和一个输出,如果我们要搭建多模态的网络(多输入多输出,层与层之间的跨越连接等)就要用keras函数式API了。

Sequential To 函数API

函数式API就是建立一个层,接受张量并返回张量。我们俩看看Sequential模型以及对应的函数式API实现

from keras.models import Sequential, Model
from keras import layers
from keras import Input
seq_model = Sequential()
seq_model.add(layers.Dense(32, activation='relu', input_shape=(64,)))
seq_model.add(layers.Dense(32, activation='relu'))
seq_model.add(layers.Dense(10, activation='softmax'))

input_tensor = Input(shape=(64,))
x = layers.Dense(32, activation='relu')(input_tensor)
x = layers.Dense(32, activation='relu')(x)
output_tensor = layers.Dense(10, activation='softmax')(x)
model = Model(input_tensor, output_tensor)
model.summary()

多输入模型

典型的问答模型有两个输入:一个自然语言描述的问题和一个文本片段(比如新闻文章),后者提供用于回答问题的信息。然后模型要生成一个回答,在最简单的情况下,这个回答只包含一个词,可以通过对某个预定义的词表做softmax 得到。
在这里插入图片描述

from keras.models import Model
from keras import layers
from keras import Input
text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500
#参考文本
text_input = Input(shape=(None,), 
 				   dtype='int32', 
 				   name='text')
embedded_text = layers.Embedding(text_vocabulary_size, 64)(text_input)
encoded_text = layers.LSTM(32)(embedded_text)
#问题
question_input = Input(shape=(None,),
                       dtype='int32',
                       name='question')
embedded_question = layers.Embedding(question_vocabulary_size, 32)(question_input)
encoded_question = layers.LSTM(16)(embedded_question)
#联合
concatenated = layers.concatenate([encoded_text, encoded_question],axis=-1)
answer = layers.Dense(answer_vocabulary_size,
					  activation='softmax')(concatenated)
model = Model([text_input, question_input], answer)
model.compile(optimizer='rmsprop',
			  loss='categorical_crossentropy',
              metrics=['acc'])

如何输入和训练模型呢?

import numpy as np
num_samples = 1000
max_length = 100
text = np.random.randint(1, text_vocabulary_size,
						size=(num_samples, max_length))
question = np.random.randint(1, question_vocabulary_size,
							size=(num_samples, max_length))
answers = np.random.randint(answer_vocabulary_size, size=(num_samples))
answers = keras.utils.to_categorical(answers, answer_vocabulary_size)
model.fit([text, question], answers, epochs=10, batch_size=128)
#也可用这种方法,清晰一点
model.fit({'text': text, 'question': question}, answers,
		  epochs=10, batch_size=128)

多输出模型

一个网络,输入某个匿名人士的一系列社交媒体发帖,然后尝试预测那个人的属性,比如年龄、性别和收入水平

在这里插入图片描述
代码如下:

from keras import layers
from keras import Input
from keras.models import Model
vocabulary_size = 50000
num_income_groups = 10
posts_input = Input(shape=(None,), dtype='int32', name='posts')
embedded_posts = layers.Embedding(256, vocabulary_size)(posts_input)
x = layers.Conv1D(128, 5, activation='relu')(embedded_posts)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.GlobalMaxPooling1D()(x)
x = layers.Dense(128, activation='relu')(x)
age_prediction = layers.Dense(1, name='age')(x)#要命名
income_prediction = layers.Dense(num_income_groups,
								 activation='softmax',
								 name='income')(x)#要命名
gender_prediction = layers.Dense(1, activation='sigmoid', name='gender')(x)#要命名
model = Model(posts_input,
              [age_prediction, income_prediction, gender_prediction])

与多输入不同的是,多输出训练时需要不同的损失函数,可能还需要不同的权重

model.compile(optimizer='rmsprop',
			  loss=['mse', 'categorical_crossentropy', 'binary_crossentropy'])
model.compile(optimizer='rmsprop',
              loss={'age': 'mse',
			  'income': 'categorical_crossentropy',
			  'gender': 'binary_crossentropy'}
			  loss_weights={'age': 0.25,
							'income': 1.,
							'gender': 10.})
model.fit(posts, {'age': age_targets,
				  'income': income_targets,
				  'gender': gender_targets},
          epochs=10, batch_size=64)

有向无环

Inception 模块

在这里插入图片描述

from keras import layers
branch_a = layers.Conv2D(128, 1,
						activation='relu', strides=2)(x)
branch_b = layers.Conv2D(128, 1, activation='relu')(x)
branch_b = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_b)
branch_c = layers.AveragePooling2D(3, strides=2)(x)
branch_c = layers.Conv2D(128, 3, activation='relu')(branch_c)
branch_d = layers.Conv2D(128, 1, activation='relu')(x)
branch_d = layers.Conv2D(128, 3, activation='relu')(branch_d)
branch_d = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_d)
output = layers.concatenate([branch_a, branch_b, branch_c, branch_d], axis=-1)

残差连接

from keras import layers
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.MaxPooling2D(2, strides=2)(y)
#使用1×1 卷积,将原始x 张量线性下采样为与y 具有相同的形状
residual = layers.Conv2D(128, 1, strides=2, padding='same')(x)
y = layers.add([y, residual])

把层作为模型

通过重复使用模型实例可以构建一个简单的例子,就是一个使用双摄像头作为输入的视觉模型:两个平行的摄像头,相距几厘米。这样的模型可以感知深度,这在很多应用中都很有用。你不需要两个单独的模型从左右两个摄像头中分别提取视觉特征,然后再将二者合并。这样的底层处理可以在两个输入之间共享,即通过共享层(使用相同的权重,从而共享相同的表示)来实现。在Keras 中实现连体视觉模型(共享卷积基)的代码如下所示。

扫描二维码关注公众号,回复: 9115077 查看本文章
from keras import layers
from keras import applications
from keras import Input
xception_base = applications.Xception(weights=None,
									  include_top=False)
left_input = Input(shape=(250, 250, 3))
right_input = Input(shape=(250, 250, 3))
left_features = xception_base(left_input)
right_features = xception_base(right_input)
merged_features = layers.concatenate([left_features, right_features], axis=-1)
发布了25 篇原创文章 · 获赞 41 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_32796253/article/details/89183664