Можем ли мы использовать функции Фурье в Керасе? - PullRequest
0 голосов
/ 25 апреля 2018

Давайте начнем с ввода, представляющего собой простой временной ряд, и попытаемся создать автоэнкодер, который просто преобразует Фурье, а затем преобразует наши данные в кератах.

Если мы попытаемся сделать это:

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, но похоже, что лямбда думает, что он сложный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>

То, что я считаю разумным, и было причиной, по которой я не хотел его разыгрывать.

Основной вопрос: как мне успешно обернуть функцию tf.spectral.irfft, которая выводит float32?

Более общий вопрос для изучения: Давайте предположим, что я действительно хочу сделать что-то между rfft и irfft, как я могу преобразовать эти мнимые числа в абсолютные значения, не разбивая кера, чтобы я мог применять различные свертки и тому подобное?

Ответы [ 4 ]

0 голосов
/ 26 апреля 2019

Функция fft2d в тензорном потоке 1.13.1 не работает.

0 голосов
/ 03 мая 2018

Просто чтобы добавить больше к тому, что происходит выше для тех, кто попадает сюда из поисковых систем. Следующее, внесенное в это обсуждение группы Google , запустит 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()

В нем используются те же понятия, что и в ответе Аллена, но небольшие различия позволяют совместить его с промежуточными свертками.

0 голосов
/ 13 апреля 2019

Я наткнулся на это, пытаясь решить ту же проблему. Вы можете сделать переход без потерь, обернув 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)
0 голосов
/ 26 апреля 2018

Я думаю, вам просто нужно больше 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: 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. реконструированы отлично)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...