使用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
猜你喜欢
- 在网站或软件的策划和设计过程中,我们经常听到这样的讨论:“这个功能设计得太重了”又或“我们希望能够处理得轻一些”。似乎轻设计是时下炙手可热的
- 这篇文章主要介绍了Python检查 云备份进程是否正常运行代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- salt分发后,主动将已完成的任务数据推送到redis中,使用redis的生产者模式,进行消息传送#coding=utf-8import f
- QTableWidget介绍QTableWidget是Qt程序中常用的显示数据表格的控件,类似于c#中的DataGrid。QTableWid
- TensorFlow是一款优秀的深度学习框架,支持多种常见的操作系统,例如Windows10,Mac Os等等,同时也支持运行在NVIDIA
- 在项目里碰到需要把类似'450000'的数字转换为会计记账所用的格式,'450,000.00',分隔千分位和
- 前言Supervisor(‘http://supervisord.org/’)是用Python开发的
- 说明1、通过特征本身的方差来筛选特征。特征的方差越小,特征的变化越不明显。2、变化越不明显的特征对我们区分标签没有太大作用,因此应该消除这些
- 在做实验时,我们常常会使用用开源的数据集进行测试。而Pytorch中内置了许多数据集,这些数据集我们常常使用DataLoader类进行加载。
- 啥也不说了,还是看代码吧! [root@yyjk DATABASE]# cat DBI.py# -*- coding: utf-8 -*-
- Method通过一条指令即可完成:os.system('所需指令')Note: os.system('所需指令
- 在应用系统中,尤其在联机事务处理系统中,对数据查询及处理速度已成为衡量应用系统成败的标准。而采用索引来加快数据处理速度也成为广大数据库用户所
- 参考的一些文章以及论文我都会给大家分享出来 —— 链接就贴在原文,论文我上传到资源中去,大家可以免费下载学习,如果当天资源区找不到论文,那就
- 前言单例模式(Singleton Pattern),是一种软件设计模式,是类只能实例化一个对象,目的是便于外界的访问,节约系统资源,如果希望
- 本文实例讲述了Python实现曲线拟合操作。分享给大家供大家参考,具体如下:这两天学习了用python来拟合曲线。一、环境配置本人比较比较懒
- 如下所示:#简单来说 LabelEncoder 是对不连续的数字或者文本进行编号from sklearn.preprocessing imp
- 车牌识别在高速公路中有着广泛的应用,比如我们常见的电子收费(ETC)系统和交通违章车辆的检测,除此之外像小区或地下车库门禁也会用到,基本上凡
- 最近经常需要出一些临时性的报表,于是就用python 的smtplib 和email 两模块写了个小程序,当数据处理完后通过邮箱把报表文件从
- 本文介绍基于Python语言arcpy模块,实现栅格影像图层建立与多幅遥感影像数据批量拼接(Mosaic)的操作。首先,相关操作所需具体代码
- #!/usr/bin/env python## Copyright 2009 Facebook## Licensed under the A