如何在TensorFlow中将信号与1D内核进行卷积?

时间:2019-03-19 09:06:39

标签: python tensorflow

我正在尝试过滤形状为(N_batch, N_data)的TensorFlow张量,其中N_batch是批处理大小(例如32),而N_data是(嘈杂的)时间序列数组的大小。我有一个一维的高斯核(取自here)。然后,我想使用tensorflow.nn.conv1d使该内核与信号卷积。

整个上午,我一直在努力获取正确的输入信号和内核尺寸,但是显然没有成功。从我从互连网上收集的信息来看,输入信号和内核的尺寸都需要以一种挑剔的方式进行对齐,而我只是想不出那是哪种方式。 TensorFlow错误消息也不是特别有意义(Shape must be rank 4 but is rank 3 for 'conv1d/Conv2D' (op: 'Conv2D') with input shapes: [?,1,1000], [1,81])。下面,我包含了一些代码来重现这种情况:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# Based on: https://stackoverflow.com/a/52012658/1510542
# Credits to @zephyrus


def gaussian_kernel(size, mean, std):
    d = tf.distributions.Normal(tf.cast(mean, tf.float32), tf.cast(std, tf.float32))
    vals = d.prob(tf.range(start=-size, limit=size+1, dtype=tf.float32))

    kernel = vals   # Some reshaping is required here

    return kernel / tf.reduce_sum(kernel)


def gaussian_filter(input, sigma):
    size = int(4*sigma + 0.5)

    x = input   # Some reshaping is required here

    kernel = gaussian_kernel(size=size, mean=0.0, std=sigma)
    conv = tf.nn.conv1d(x, kernel, stride=1, padding="SAME")
    return conv


def run_filter():

    tf.reset_default_graph()

    # Define size of data, batch sizes
    N_batch = 32
    N_data = 1000

    noise = 0.2 * (np.random.rand(N_batch, N_data) - 0.5)
    x = np.linspace(0, 2*np.pi, N_data)
    y = np.tile(np.sin(x), N_batch).reshape(N_batch, N_data)
    y_noisy = y + noise

    input = tf.placeholder(tf.float32, shape=[None, N_data])
    smooth_input = gaussian_filter(input, sigma=10)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        y_smooth = smooth_input.eval(feed_dict={input: y_noisy})

        plt.plot(y_noisy[0])
        plt.plot(y_smooth[0])
        plt.show()


if __name__ == "__main__":
    run_filter()

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

由于TF卷积通常用于多通道输入/输出,因此需要在输入/内核中添加通道尺寸。在使用简单的1通道输入/输出时,这仅相当于添加一些大小为1的“虚拟”轴。
由于默认情况下,卷积会期望通道排在最后,因此您的占位符应为​​[None, N_data, 1]形状,并且您的输入将像

一样进行修改
y_noisy = y + noise
y_noisy = y_noisy[:, :, np.newaxis] 

类似地,您需要将输入和输出通道尺寸添加到过滤器中:

kernel = gaussian_kernel(size=size, mean=0.0, std=sigma)
kernel = kernel[:, tf.newaxis, tf.newaxis]

也就是说,过滤器的形状应为[width, in_channels, out_cannels]