如何在Keras中使用Lambda层?

10

我想定义Lambda层来使用叉积组合特征,然后合并这些模型,就像图中那样,我该怎么做?

enter image description here

测试model_1,从dense层获取128维度,使用pywt获取两个64维度的特征(cA,cD),然后返回cA*cD //当然我想要结合两个模型,但首先尝试model_1。

from keras.models import Sequential,Model
from keras.layers import Input,Convolution2D,MaxPooling2D
from keras.layers.core import Dense,Dropout,Activation,Flatten,Lambda
import pywt

def myFunc(x):
    (cA, cD) = pywt.dwt(x, 'db1')
#    x=x*x
    return cA*cD

batch_size=32
nb_classes=3
nb_epoch=20
img_rows,img_cols=200,200
img_channels=1
nb_filters=32
nb_pool=2
nb_conv=3

inputs=Input(shape=(1,img_rows,img_cols))
x=Convolution2D(nb_filters,nb_conv,nb_conv,border_mode='valid',
                  input_shape=(1,img_rows,img_cols),activation='relu')(inputs)
x=Convolution2D(nb_filters,nb_conv,nb_conv,activation='relu')(x)
x=MaxPooling2D(pool_size=(nb_pool,nb_pool))(x)
x=Dropout(0.25)(x)
x=Flatten()(x)
y=Dense(128,activation='relu')(x)
cross=Lambda(myFunc,output_shape=(64,))(y)   
predictions=Dense(nb_classes,activation='softmax')(cross)
model = Model(input=inputs, output=predictions)
model.compile(loss='categorical_crossentropy',optimizer='adadelta',metrics=['accuracy'])

model.fit(X_train,Y_train,batch_size=batch_size,nb_epoch=nb_epoch,
          verbose=1,validation_data=(X_test,Y_test))

抱歉,我可以问一个张量相关的问题吗?

import tensorflow as tf
W1 = tf.Variable(np.array([[1,2],[3,4]]))
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
array = W1.eval(sess)
print (array)

没错!不过,

from keras import backend as K
import numpy as np
kvar=K.variable(np.array([[1,2],[3,4]]))
K.eval(kvar)
print(kvar)

我得到了 <CudaNdarrayType(float32, matrix)>kvar.eval()。我使用keras,那么如何在keras中获取类似于tensorflow的数组?


1
所以,Keras Lambda函数需要所有操作都使用“张量”。常见的操作都列在https://keras.io/backend/中。您必须找到一种重写pywt.dwt的张量方式。不幸的是,这不是一项容易的任务。我认为这个问题非常重要,我无法正确回答它。 - Daniel Möller
Lambda层必须使用Keras后端函数吗?我可以将张量转换为数组,然后使用pywt.dwt,然后再将数组转换为张量吗? - Ting Li
可以实现,但这会中断“图形”并引发错误。要将张量转换为数组,请使用“tensorVar.eval()”。要从数组创建张量,请使用“K.variable(arrayVar)”,其中K是keras.backend。 - Daniel Möller
非常感谢!我会尝试的。 - Ting Li
Try karr = kvar.eval() - Daniel Möller
我执行了 print(karr),得到了 b'CudaNdarray([[ 1. 2.]\n [ 3. 4.]])' - Ting Li
1个回答

7

我建议将密集层进行复制。不要使用2个拥有128个单元的层,而是使用4个拥有64个单元的层。结果相同,但你能更好地执行交叉乘积。

from keras.models import Model

#create dense layers and store their output tensors, they use the output of models 1 and to as input    
d1 = Dense(64, ....)(Model_1.output)   
d2 = Dense(64, ....)(Model_1.output)   
d3 = Dense(64, ....)(Model_2.output)   
d4 = Dense(64, ....)(Model_2.output)   

cross1 = Lambda(myFunc, output_shape=....)([d1,d4])
cross2 = Lambda(myFunc, output_shape=....)([d2,d3])

#I don't really know what kind of "merge" you want, so I used concatenate, there are Add, Multiply and others....
output = Concatenate()([cross1,cross2])
    #use the "axis" attribute of the concatenate layer to define better which axis will be doubled due to the concatenation    

model = Model([Model_1.input,Model_2.input], output)

现在,关于lambda函数:

import keras.backend as K

def myFunc(x):
    return x[0] * x[1]

非常感谢!当我使用model.add(Dense(128))时,会得到128个维度,我添加了model.add(Lambda(wavelets,output_shape=input_shape[0])),但我不知道如何使用lambda层。我想使用小波函数((cA,cD)=pywt.dwt(x,'db1'))来获取近似和细节系数(它们都是64维的,就像那个图)。然后将近似系数与模型1和2进行叉积。最后使用concat模式合并近似和细节系数。你能帮忙编写lambda层吗? - Ting Li
抱歉,不是叉积,而是乘法符号 *。 - Ting Li
抱歉,output_shape=..?我使用Theano作为后端,它无法自动推断。 - Ting Li
是的,您必须在Lambda层中放置output_shape。如果您正在使用一维向量,则密集层将输出(64,),因此Lambda中的输出形状也将是(64,) - Daniel Möller
import pywt y=Dense(128,activation='relu')(x) cross=Lambda(myFunc,output_shape=(64,))(y) def myFunc(x): (cA, cD) = pywt.dwt(x, 'db1') return cA*cD - Ting Li
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接