x = Dense(784, activation='relu')(x)
x = Dense(784, activation='relu')(x) # 跟前面的不共享权重
x = Dense(784, activation='relu')(x) # 跟前面的不共享权重
Keras 的模型有着类似层的表现,在调用时可以用跟层一样的方式,比如:
x_in = Input(shape=(784,))
x = x_in
x = Dense(10, activation='softmax')(x)
model = Model(x_in, x) # 建立模型
x_in = Input(shape=(100,))
x = x_in
x = Dense(784, activation='relu')(x)
x = model(x) # 将模型当层一样用
model2 = Model(x_in, x)
模型克隆跟模型重用类似,只不过得到的新模型跟原模型不共享权重了,也就是说,仅仅保留完全一样的模型结构,两个模型之间的更新是独立的。Keras 提供了模型可用专用的函数,直接调用即可:
from keras.models import clone_model
model2 = clone_model(model1)
注意,clone_model 完全复制了原模型模型的结构,并重新构建了一个模型,但没有复制原模型的权重的值。也就是说,对于同样的输入,model1.predict 和 model2.predict 的结果是不一样的。
如果要把权重也搬过来,需要手动 set_weights 一下:
model2.set_weights(K.batch_get_value(model1.weights))
这里的交叉引用是指在定义一个新层的时候,沿用已有的某个层的权重,注意这个自定义层可能跟旧层的功能完全不一样,它们之间纯粹是共享了某个权重而已。比如,Bert 在训练 MLM 的时候,最后预测字词概率的全连接层,权重就是跟 Embedding 层共享的。
参考写法如下:
class EmbeddingDense(Layer):
"""运算跟Dense一致,只不过kernel用Embedding层的embedding矩阵
def __init__(self, embedding_layer, activation='softmax', **kwargs):
super(EmbeddingDense, self).__init__(**kwargs)
self.kernel = K.transpose(embedding_layer.embeddings)
self.activation = activation
self.units = K.int_shape(self.kernel)[1]
def build(self, input_shape):
super(EmbeddingDense, self).build(input_shape)
self.bias = self.add_weight(name='bias',
shape=(self.units,),
initializer='zeros')
def call(self, inputs):
outputs = K.dot(inputs, self.kernel)
outputs = K.bias_add(outputs, self.bias)
outputs = Activation(self.activation).call(outputs)
return outputs
def compute_output_shape(self, input_shape):
return input_shape[:-1] + (self.units,)
embedding_layer = Embedding(10000, 128)
x = embedding_layer(x) # 调用Embedding层
x = EmbeddingDense(embedding_layer)(x) # 调用EmbeddingDense层
提取中间层
有时候我们需要从搭建好的模型中提取中间层的特征,并且构建一个新模型,在 Keras 中这同样是很简单的操作:
from keras.applications.resnet50 import ResNet50
model = ResNet50(weights='imagenet')
Model(
inputs=model.input,
outputs=[
model.get_layer('res5a_branch1').output,
model.get_layer('activation_47').output,
从中间拆开
最后,来到本文最有难度的地方了,我们要将模型从中间拆开,搞懂之后也可以实现往已有模型插入或替换新层的操作。这个需求看上去比较奇葩,但是还别说,stackoverflow 上面还有人提问过,说明这确实是有价值的。
https://stackoverflow.com/questions/49492255/how-to-replace-or-insert-intermediate-layer-in-keras-model
假设我们有一个现成的模型,它可以分解为:
那可能我们需要将 h2 替换成一个新的输入,然后接上后面的层,来构建一个新模型,即新模型的功能是:
但是,如果模型是比较复杂的结构,比如残差结构这种不是一条路走到底的,就没有这么简单了。事实上,这个需求本来没什么难度,该写的 Keras 本身已经写好了,只不过没有提供现成的接口罢了。为什么这么说,因为我们通过 model(x) 这样的代码调用已有模型的时候,
实际上 Keras 就相当于把这个已有的这个 model 从头到尾重新搭建了一遍,既然可以重建整个模型,那搭建“半个”模型原则上也是没有任技术难度的,只不过没有现成的接口。具体可以参考 Keras 源码的 keras/engine/network.py 的 run_internal_graph 函数:
完整重建一个模型的逻辑在 run_internal_graph 函数里边,并且可以看到它还不算简单,所以如无必要我们最好不要重写这个代码。但如果不重写这个代码,又想调用这个代码,实现从中间层拆解模型的功能,唯一的办法是“移花接木”了:通过修改已有模型的一些属性,欺骗一下 run_internal_graph 函数,使得它以为模型的输入层是中间层,而不是原始的输入层。有了这个思想,再认真读读 run_internal_graph 函数的代码,就不难得到下述参考代码:
def get_outputs_of(model, start_tensors, input_layers=None):
"""start_tensors为开始拆开的位置
# 为此操作建立新模型
model = Model(inputs=model.input,
outputs=model.output,
name='outputs_of_' + model.name)
# 适配工作,方便使用
if not isinstance(start_tensors, list):
start_tensors = [start_tensors]
if input_layers is None:
input_layers = [
Input(shape=K.int_shape(x)[1:], dtype=K.dtype(x))
for x in start_tensors
elif not isinstance(input_layers, list):
input_layers = [input_layers]
# 核心:覆盖模型的输入
model.inputs = start_tensors
model._input_layers = [x._keras_history[0] for x in input_layers]
# 适配工作,方便使用
if len(input_layers) == 1:
input_layers = input_layers[0]
# 整理层,参考自 Model 的 run_internal_graph 函数
layers, tensor_map = [], set()
for x in model.inputs:
tensor_map.add(str(id(x)))
depth_keys = list(model._nodes_by_depth.keys())
depth_keys.sort(reverse=True)
for depth in depth_keys:
nodes = model._nodes_by_depth[depth]
for node in nodes:
n = 0
for x in node.input_tensors:
if str(id(x)) in tensor_map:
n += 1
if n == len(node.input_tensors):
if node.outbound_layer not in layers:
layers.append(node.outbound_layer)
for x in node.output_tensors:
tensor_map.add(str(id(x)))
model._layers = layers # 只保留用到的层
# 计算输出
outputs = model(input_layers)
return input_layers, outputs
model.inputs = start_tensors
model._input_layers = [x._keras_history[0] for x in input_layers]
outputs = model(input_layers)
也就是覆盖模型的 model.inputs 和 model._input_layers 就可以实现欺骗模型从中间层开始构建的效果了,其余的多数是适配工作,不是技术上的,而 model._layers = layers 这一句是只保留了从中间层开始所用到的层,只是为了统计模型参数量的准确性,如果去掉这一部分,模型的参数量依然是原来整个 model 那么多。
Keras 是最让人赏心悦目的深度学习框架,至少到目前为止,就模型代码的可读性而言,没有之一。可能读者会提到 PyTorch,诚然 PyTorch 也有不少可取之处,但就可读性而言,我认为是比不上 Keras 的。
在深究 Keras 的过程中,我不仅惊叹于 Keras 作者们的深厚而优雅的编程功底,甚至感觉自己的编程技能也提高了不少。不错,我的很多 Python 编程技巧,都是从读 Keras 源码中学习到的。
如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。
总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。
PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得或技术干货。我们的目的只有一个,让知识真正流动起来。
? 来稿标准:
• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向)
• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接
• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志
? 投稿邮箱:
• 投稿邮箱:hr@paperweekly.site
• 所有文章配图,请单独在附件中发送
• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通
关于PaperWeekly
PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。
▽ 点击 | 阅读原文 | 查看作者博客
将batch_renorm.py脚本添加到您的存储库中,然后导入 BatchRenormalization 层。
例如。您可以将 Keras BatchNormalization 层替换为 BatchRenormalization 层。
from batch_renorm import BatchRenormalization
使用 BatchRenormalization 层需要比更简单的 BatchNormalization 层稍多的时间。
在 980M GPU 上观察到 WRN-16-4 相对于 BatchNormalization 的速度差异:
批量标准化:每个 epoch 137 秒。
批量重归一化(模式 0):每个 epoch 152 秒。
批量重归一化(模式 2):每个 epoch 142 秒。
更多详情、使用方法,请下载后阅读README.md文件
在有些应用中,我们需要高阶的AR或MA
模型才能充分地描述数据的动态结构,这样问题会变得很繁琐。为了克服这个困难,提出了自回归滑动平均(ARMA)
模型。
基本思想是把AR和MA
模型结合在一起,使所使用的参数个数保持很小。
模型的形式为:
https://deeplearningsandbox.com/how-to-use-transfer-learning-and-fine-tuning-in-
keras-and-tensorflow-to-build-an-image-recognition-94b0b02444f2
def add_new_last_layer(base_model, nb_classes):
传统机器学习的输入数据中一般含有分类特征,对这些特征或字段的处理是特征工程的重要内容之一。分类(Categorical)特征也被称为离散特征,而机器学习模型通常只能处理数值数据,所以需要将分类数据转换成数值数据。
有序(Ordinal)类型
有序类型的分类特征存在自然的顺序结构,所以可以对该类型数据进行升序或者降序排列,比如关于衣服型号特征的值可能有SSS(Small)、MMM(Middle)、LLL(Large)、XLXLXL(eXtra Large)等不同尺码,它们之间存在XL>L>M>
mdl_A = keras.models.load("mdl_A.hf")
mdl_B_on_A = keras.models.Sequential(mdl_A.layers[:-1])
mdl_B_on_A.add(keras.layers.Dense(1, activation = "sigmoid")
需要注意的是,此时mdl_A和mdl_B共享神经网络的权重。解决的方法是使用c...
本文利用的demo的是之前写好的: addition_lstm.py, 详细的源代码请看: http://blog.csdn.net/zjm750617105/article/details/51321889
json_string = model.to_json() #等价于 json_string = model.get_config()
open('my_model_architec
好的,我可以用中文来向你介绍如何使用 Keras 来构建光谱 transformer 分类模型。
首先,你需要准备好你的输入数据。在这里,你可能需要对光谱数据进行预处理,比如标准化或去噪。
然后,你可以使用 Keras 的 `Sequential` 模型来构建你的模型。首先,你可以添加一个输入层,用于接收你的光谱数据。接下来,你可以使用不同类型的层来构建你的模型,比如卷积层、循环层或全连接层。具体使用哪些层,取决于你的数据和问题。
最后,你可以添加一个输出层,用于预测你的分类结果。你可以使用不同的激活函数来定义输出层,比如 `sigmoid` 或 `softmax`。
最后,你可以使用 Keras 的 `compile` 方法来编译你的模型,并指定损失函数和优化器。然后,你可以使用 `fit` 方法来训练你的模型,并使用 `evaluate` 方法来评估模型的性能。
希望以上介绍能帮助你使用 Keras 来构建光谱 transformer 分类模型。