让我们从一个简单时间序列的输入开始,并尝试构建一个自动编码器,只需进行四次变换,然后在keras中转换我们的数据。
如果我们尝试这样做:
inputs = Input(shape=(MAXLEN,1), name='main_input')
x = tf.spectral.rfft(inputs)
decoded = Lambda(tf.spectral.irfft)(x)
然后第三行在输入时抛出错误:
>> ValueError: Tensor conversion requested dtype complex64 for Tensor with dtype float32
你看,tf.spectral.irfft的输出是float32,但看起来Lambda认为它是复杂的64? (Complex64是上一步的输入x)
我们可以在模型输入时使用以下方法修复该错误:
inputs = Input(shape=(MAXLEN,1), name='main_input')
x = tf.spectral.rfft(inputs)
decoded = Lambda(tf.cast(tf.spectral.irfft(x),dtype=tf.float32)))
这在输入时接受,但是当我们尝试构建模型时:
autoencoder = Model(inputs, decoded)
它会生成错误:
TypeError: Output tensors to a Model must be Keras tensors. Found: <keras.layers.core.Lambda object at 0x7f24f0f7bbe0>
我认为这是合理的,也是我不想把它放在首位的原因。
主要问题:如何成功包装输出float32的tf.spectral.irfft函数?
更一般的学习问题: 让我们假设我实际上想要在rfft和irfft之间做一些事情,如何在不破坏keras的情况下将这些虚数转换成绝对值,以便我可以应用各种卷积等?
答案 0 :(得分:3)
我认为您只需要更多Lambda
包装(使用tf.keras
,因为我已经安装了它):
import numpy
import tensorflow as tf
K = tf.keras
inputs = K.Input(shape=(10, 8), name='main_input')
x = K.layers.Lambda(tf.spectral.rfft)(inputs)
decoded = K.layers.Lambda(tf.spectral.irfft)(x)
model = K.Model(inputs, decoded)
output = model(tf.ones([10, 8]))
with tf.Session():
print(output.eval())
irfft
的输出应该是真实的,所以可能不需要施放它。但是如果你确实需要强制转换它(或者通常在Lambda
层中组合操作),我将它包装在Python lambda中:K.layers.Lambda(lambda v: tf.cast(tf.spectral.whatever(v), tf.float32))
例如,如果您知道您的中间值(rfft
和irfft
之间)的假想成分为零,则可以将其截断:
import numpy
import tensorflow as tf
K = tf.keras
inputs = K.Input(shape=(10, 8), name='main_input')
x = K.layers.Lambda(lambda v: tf.real(tf.spectral.rfft(v)))(inputs)
decoded = K.layers.Lambda(
lambda v: tf.spectral.irfft(tf.complex(real=v, imag=tf.zeros_like(v))))(x)
model = K.Model(inputs, decoded)
output = model(tf.reshape(tf.range(80, dtype=tf.float32), [10, 8]))
with tf.Session():
print(output.eval())
请注意,对于一般序列,这不是真的,因为即使是实值输入也可以在转换后具有虚部。它适用于上面的tf.ones
输入,但tf.range
输入被破坏:
[[ 0. 4. 4. 4. 4. 4. 4. 4.]
[ 8. 12. 12. 12. 12. 12. 12. 12.]
[16. 20. 20. 20. 20. 20. 20. 20.]
[24. 28. 28. 28. 28. 28. 28. 28.]
[32. 36. 36. 36. 36. 36. 36. 36.]
[40. 44. 44. 44. 44. 44. 44. 44.]
[48. 52. 52. 52. 52. 52. 52. 52.]
[56. 60. 60. 60. 60. 60. 60. 60.]
[64. 68. 68. 68. 68. 68. 68. 68.]
[72. 76. 76. 76. 76. 76. 76. 76.]]
(没有施法,我们得到0.到79.重建完美)
答案 1 :(得分:1)
只需为从搜索引擎到达此处的任何人添加更多内容。以下是在this google group discussion中提供的,将使用卷积和其他层之间运行rfft:
inputs = Input(shape=(10, 8), name='main_input')
x = Lambda(lambda v: tf.to_float(tf.spectral.rfft(v)))(inputs)
x = Conv1D(filters=5, kernel_size=3, activation='relu', padding='same')(x)
x = Lambda(lambda v: tf.to_float(tf.spectral.irfft(tf.cast(v, dtype=tf.complex64))))(x)
x = Flatten()(x)
output = Dense(1)(x)
model = Model(inputs, output)
model.summary()
它使用与Allen的答案相同的概念,但略有不同允许与中间卷积兼容。
答案 2 :(得分:1)
在尝试解决相同的问题时,我偶然发现了这一点。您可以通过将tf.real
和tf.imag
包装到Lambda
层中来使转换无损(我使用stft
是因为没有等效的实值):
x = tf.keras.layers.Lambda(
lambda v: tf.signal.stft(
v,
frame_length=1024,
frame_step=256,
fft_length=1024,
), name='gen/FFTLayer')(inputs)
real = tf.keras.layers.Lambda(tf.real)(x)
imag = tf.keras.layers.Lambda(tf.imag)(x)
...
# transform real and imag either separately or by concatenating them in the feature space.
...
x = tf.keras.layers.Lambda(lambda x: tf.complex(x[0], x[1]))([real, imag])
x = tf.keras.layers.Lambda(
lambda v: tf.signal.inverse_stft(
v,
frame_length=1024,
frame_step=256,
fft_length=1024,
))(x)
答案 3 :(得分:0)
tensorflow 1.13.1中的fft2d函数被破坏。