使用Keras实现Tensor的相乘和相加代码
作者:guofuzheng 时间:2021-08-04 14:10:57
前言
最近在写行为识别的代码,涉及到两个网络的融合,这个融合是有加权的网络结果的融合,所以需要对网络的结果进行加权(相乘)和融合(相加)。
最初的想法
最初的想法是用Keras.layers.Add和Keras.layers.Multiply来做,后来发现这样会报错。
rate_rgb = k.variable(np.ones((1024,),dtype='float32')*0.8)
rate_esti = k.variable(np.ones((1024,),dtype='float32')*0.2)
weight_gru1 = Multiply()([rate_rgb,gru1])
weight_gru2 = Multiply()([rate_esti,gru2])
last = Add()([weight_gru1,weight_gru2])
这么写会报错,如下
AttributeError: 'Variable' object has no attribute '_keras_history'
正确做法
后来在网上参考大神的博客,改为如下
weight_1 = Lambda(lambda x:x*0.8)
weight_2 = Lambda(lambda x:x*0.2)
weight_gru1 = weight_1(gru1)
weight_gru2 = weight_2(gru2)
last = Add()([weight_gru1,weight_gru2])
这样就没问题了。
补充知识:Keras天坑:想当然的对层的直接运算带来的问题
天坑
keras如何操作某一层的值(如让某一层的值取反加1等)?keras如何将某一层的神经元拆分以便进一步操作(如取输入的向量的第一个元素乘别的层)?keras如何重用某一层的值(如输入层和输出层乘积作为最终输出)?
这些问题都指向同一个答案,即使用Lambda层。
另外,如果想要更加灵活地操作层的话,推荐使用函数式模型写法,而不是序列式。
Keras当中,任何的操作都是以网络层为单位,操作的实现都是新添一层,不管是加减一个常数还是做乘法,或者是对两层的简单拼接。所以,将一层单独劈一半出来,是一件难事。强调,Keras的最小操作单位是Layer,每次操作的是整个batch。自然,在keras中,每个层都是对象,可以通过dir(Layer对象)来查看具有哪些属性。然而,Backend中Tensorflow的最小操作单位是Tensor,而你搞不清楚到底是Layer和Tensor时,盲目而想当然地进行层的操作,就会出问题。到底是什么?通过type和shape是看不出来的。
如果你只是想对流经该层的数据做个变换,而这个变换本身没有什么需要学习的参数,那么直接用Lambda Layer是最合适的了。
也就是说,对每一层的加减乘除都得用keras的函数,你不能简单使用形如 ‘new_layer' =1−= 1-=1−'layer'这样的表达方式来对层进行操作。
当遇到如下报错信息:
AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
或
TypeError: 'Tensor' object is not callable
等等
这是就要考虑一下将程序中层的操作改成Lambda的方式表达。
使用Lambda编写自己的层
Lamda层怎么用?官方文档给了这样一个例子。
# add a x -> x^2 layer
model.add(Lambda(lambda x: x ** 2))
# add a layer that returns the concatenation
# of the positive part of the input and
# the opposite of the negative part
def antirectifier(x):
x -= K.mean(x, axis=1, keepdims=True)
x = K.l2_normalize(x, axis=1)
pos = K.relu(x)
neg = K.relu(-x)
return K.concatenate([pos, neg], axis=1)
def antirectifier_output_shape(input_shape):
shape = list(input_shape)
assert len(shape) == 2 # only valid for 2D tensors
shape[-1] *= 2
return tuple(shape)
model.add(Lambda(antirectifier,
output_shape=antirectifier_output_shape))
乍一看,有点懵逼,什么乱七八糟的。事实上,很简单,假设L0和L1是两层,你只要将你形如下面这样的表达:
L1 = F(L0);
改成
L1 = Lambda( lambda L0:F(L0) ) (L0)
即可。为了看得清楚,多加了几个空格。
事实上,无非就是将原来的变换,通过Lambda(lambda 输入:表达式)这样的方式,改成了Lambda型函数,再把输入传进去,放在尾巴上即可。
参考
https://keras-cn.readthedocs.io/en/latest/layers/core_layer/#lambda
(个人觉得这份文档某些地方比官方中文要完整许多)
keras许多简单操作,都需要新建一个层,使用Lambda可以很好完成需求。当你不知道有这个东西存在的时候,就会走不少弯路。
来源:https://blog.csdn.net/weixin_40289171/article/details/80416089
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
基于PyQt5制作Excel文件数据去重小工具
![](https://img.aspxhome.com/file/2023/3/97413_0s.png)
Python函数定义及传参方式详解(4种)
ASP中SESSION无法保存问题的解决办法
![](https://img.aspxhome.com/file/UploadPic/201211/30/20121130203846956s.jpg)
Frontpage2003的怪bug,自动添加“../”的父级目录
![](https://img.aspxhome.com/file/UploadPic/20079/30/2007930133147256s.jpg)
Python常见异常类型处理
Python爬虫使用bs4方法实现数据解析
![](https://img.aspxhome.com/file/2023/2/86172_0s.png)
Keras预训练的ImageNet模型实现分类操作
![](https://img.aspxhome.com/file/2023/3/123813_0s.jpg)
Python实现文件内容批量追加的方法示例
Python的iOS自动化打包实例代码
![](https://img.aspxhome.com/file/2023/4/95774_0s.jpg)
uwsgi+nginx部署Django项目操作示例
![](https://img.aspxhome.com/file/2023/5/97045_0s.png)
Go语言中的Array、Slice、Map和Set使用详解
Flask框架运用Ajax实现数据交互的示例代码
教你快速掌握数据库查询优化的实用技巧
python replace 空格数据处理的实现
![](https://img.aspxhome.com/file/2023/3/124343_0s.png)
Oracle数据库中的级联查询、级联删除、级联更新操作教程
![](https://img.aspxhome.com/file/2023/4/63714_0s.png)
django实现后台显示媒体文件
Python数学形态学实例分析
![](https://img.aspxhome.com/file/2023/6/92526_0s.png)
python实现MD5进行文件去重的示例代码
![](https://img.aspxhome.com/file/2023/0/97550_0s.png)