我正在尝试在Keras中卷积两个1D张量。 我从其他模型中得到了两个输入:
x
-长度为100 ker
-长度为5 我想使用内核x
获得ker
的一维卷积。
我写了一个Lambda层来做到这一点:
import tensorflow as tf
def convolve1d(x):
y = tf.nn.conv1d(value=x[0], filters=x[1], padding='VALID', stride=1)
return y
x = Input(shape=(100,))
ker = Input(shape=(5,))
y = Lambda(convolve1d)([x,ker])
model = Model([x,ker], [y])
我收到以下错误:
ValueError: Shape must be rank 4 but is rank 3 for 'lambda_67/conv1d/Conv2D' (op: 'Conv2D') with input shapes: [?,1,100], [1,?,5].
有人可以帮助我了解如何解决此问题吗?
答案 0 :(得分:1)
从给定的代码中很难指出您说的意思
有可能
但是,如果您的意思是合并两层并将合并的层馈送给转换,是可以的。
x = Input(shape=(100,))
ker = Input(shape=(5,))
merged = keras.layers.concatenate([x,ker], axis=-1)
y = K.conv1d(merged, 'same')
model = Model([x,ker], y)
@ user2179331感谢您澄清您的意图。现在,您错误地使用了Lambda类,这就是显示错误消息的原因。
但是,您可以尝试使用keras.backend层来实现。
尽管要注意的是,在使用较低级别的层时,您将失去一些较高级别的抽象。例如,当使用keras.backend.conv1d时,您需要输入形状为(BATCH_SIZE,宽度,通道)和内核形状为(kernel_size,input_channels,output_channels)。因此,在您的情况下,假设x
的通道数为1(输入通道== 1),而y的通道数也相同(输出通道== 1)。
因此您的代码现在可以按以下方式重构
from keras import backend as K
def convolve1d(x,kernel):
y = K.conv1d(x,kernel, padding='valid', strides=1,data_format="channels_last")
return y
input_channels = 1
output_channels = 1
kernel_width = 5
input_width = 100
ker = K.variable(K.random_uniform([kernel_width,input_channels,output_channels]),K.floatx())
x = Input(shape=(input_width,input_channels)
y = convolve1d(x,ker)
答案 1 :(得分:1)
这比我想象的要困难得多,因为Keras和Tensorflow在卷积内核中不希望有任何批处理维,因此我不得不自己为批处理维编写循环,这需要指定batch_shape
而不是仅仅shape
层中的Input
。这是:
import numpy as np
import tensorflow as tf
import keras
from keras import backend as K
from keras import Input, Model
from keras.layers import Lambda
def convolve1d(x):
input, kernel = x
output_list = []
if K.image_data_format() == 'channels_last':
kernel = K.expand_dims(kernel, axis=-2)
else:
kernel = K.expand_dims(kernel, axis=0)
for i in range(batch_size): # Loop over batch dimension
output_temp = tf.nn.conv1d(value=input[i:i+1, :, :],
filters=kernel[i, :, :],
padding='VALID',
stride=1)
output_list.append(output_temp)
print(K.int_shape(output_temp))
return K.concatenate(output_list, axis=0)
batch_input_shape = (1, 100, 1)
batch_kernel_shape = (1, 5, 1)
x = Input(batch_shape=batch_input_shape)
ker = Input(batch_shape=batch_kernel_shape)
y = Lambda(convolve1d)([x,ker])
model = Model([x, ker], [y])
a = np.ones(batch_input_shape)
b = np.ones(batch_kernel_shape)
c = model.predict([a, b])
当前状态:
x
)。答案 2 :(得分:0)
我想我已经理解你的意思了。鉴于以下错误的示例代码:
input_signal = Input(shape=(L), name='input_signal')
input_h = Input(shape=(N), name='input_h')
faded= Lambda(lambda x: tf.nn.conv1d(input, x))(input_h)
您想用不同的衰落系数矢量对每个信号矢量进行卷积。 TensorFlow等tf.nn.conv1d中的'conv'操作仅支持固定值内核。因此,上面的代码无法按您希望的方式运行。
我也不知道。您提供的代码可以正常运行,但是它太复杂且效率不高。在我的想法中,另一种可行但效率低下的方法是与Toeplitz矩阵相乘,该矩阵的行向量是移位的衰落系数向量。当信号矢量过长时,矩阵将非常大。