【问题标题】:Proper and definitive explanation about how to build a CNN 1D in Keras关于如何在 Keras 中构建 CNN 1D 的正确和明确的解释
【发布时间】:2019-12-24 18:42:32
【问题描述】:

喏,

这是我在使用 CNN 1d 时遇到的问题的第二部分。第一部分是这个

How does it works the input_shape variable in Conv1d in Keras?

我正在使用此代码:

from keras.models import Sequential
from keras.layers import Dense, Conv1D
import numpy as np

N_FEATURES=5
N_TIMESTEPS=10
X = np.random.rand(100, N_FEATURES)
Y = np.random.randint(0,2, size=100)

model = Sequential()
model.add(Conv1D(filters=32, kernel_size=N_TIMESTEPS, activation='relu', input_shape=(N_TIMESTEPS, N_FEATURES)))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

现在,我想做什么?

我想在具有 5 个特征的时间序列上训练 CNN 1d。实际上我想使用时间窗口 og 长度 N_TIMESTEPS 而不是它自己的时间序列。这意味着我想在时间序列上使用一种维度为 N_TIMESTEPS x N_FEATURES 的“放大镜”在本地工作。这就是我决定使用 CNN 的原因

第一个问题来了。完全不清楚我是否必须将时间序列转换为张量,或者这是 Keras 将为我做的事情,因为我已经指定了 kernel_size 变量。

如果我必须提供张量,我会这样做:

X_tensor = []
for i in range(len(X)-N_TIMESTEPS):
    X_tensor+=[X_tensor[range(i, N_TIMESTEPS+i), :]]
X_tensor = np.asarray(X_tensor)

当然,在这种情况下,我还应该提供一个根据某些标准从 Y 计算得到的 Y_tensor 向量。假设我已经有了这个 X_tensor 长度相同的 Y_tensor 布尔向量,即 len(X)-N_TIMESTEPS-1

Y_tensor = np.random.randint(0,2,len(X)-N_TIMESTEPS-1)

现在,如果我尝试输入模型,我会得到 CNN 1d 最常见的错误:

  ValueError: Error when checking input: expected conv1d_4_input to have 3 dimensions, but got array with shape (100, 5)

通过查看十几篇关于它的帖子,我无法理解我做错了什么。这是我尝试过的:

model.fit(X,Y)
model.fit(np.expand_dims(X, axis=0),Y)
model.fit(np.expand_dims(X, axis=2),Y)
model.fit(X_tensor,Y_tensor)

对于所有这些情况,我总是得到相同的错误(最终元组中的维度值不同)。

问题:

  1. Keras 对我的数据有什么期望?我可以为模型提供整个时间序列,还是必须将其切成张量?

  2. 我必须如何根据数据结构为模型提供数据?即我必须以某种奇怪的方式指定数据的维度?

你能帮帮我吗?我发现这是在 Keras 中实现 CNN 的最令人困惑的一点之一,即不同的帖子具有不同的解决方案,不符合我的数据结构(即使它们在我看来具有非常常见的结构)。

注意:有一些帖子建议在 input_shape 变量中传递数据的长度。这对我来说毫无意义,因为我不应该向模型提供数据的维度(它是一个变量)。根据理论,我唯一应该给它的是过滤器维度和特征数量(即将翻转时间序列的矩阵的维度)。

谢谢,

上午

【问题讨论】:

    标签: python tensorflow keras deep-learning conv-neural-network


    【解决方案1】:

    简单地说,Conv1D 需要 3 个维度:

    • 系列数(1)
    • 步数(100 - 您的全部数据)
    • 特征数 (5)

    所以,model.fit(np.expand_dims(X, axis=0),Y)X 是正确的。

    现在,如果X(1, 100, 5),自然是你的input_shape=(100,5)

    如果您的Y 有 100 步,那么您需要确保您的 Conv1D 将输出 100 步。你需要padding='same',否则会变成91。 (我建议您实际使用 91,因为您希望每 10 步都有一个结果,并且可能不希望边框效果破坏您的结果)

    Y 也必须遵循相同的形状规则:

    • 系列数(1)
    • 步数(如果padding='same',则为100;如果padding='valid',则为91)
    • 特征数(1 = 密集输出)

    所以,Y = Y.reshape((1,-1,1))

    由于您只有一个类(真/假),因此使用'categorical_crossentropy' 毫无意义。你应该选择'binary_crossentropy'

    一般来说,您使用此卷积与kernel_size=10 来模拟 10 步的滑动窗口的总体想法将按预期工作(它是否有效是另一个问题,只能通过尝试来回答)。


    如果您想要更好的序列网络,您可能应该尝试LSTM 层。尺寸的工作方式完全相同。您将需要return_sequences=False

    主要区别在于您需要像在该循环中那样分离数据。然后:

    • X.shape == (91, 10, 5)
    • Y.shape == (91, 1)

    【讨论】:

      【解决方案2】:

      我认为您对一维卷积神经网络的工作原理并不清楚:

      如果您想从时间序列 x 中预测 y 值,而您只有 1 个时间序列,那么您的方法将行不通。网络需要大量样本来训练,只有 1 个样本可以让它轻松记住输入而不是学习。例如,如果时间序列是给定一天的湿度,而 y 是特定时间步长下雨的可能性,那么您现在拥有的只是一天的数据(时间步长例如是一天中的几个小时)。为了让网络学习,您需要收集很多天的数据,最终得到形状为 x=(n_days, timesteps, features) y=(n_days, timesteps, 1) 的数据集。

      如果您描述您的实际问题,则更有机会获得更多有用的答案

      [编辑] 通过坚持您的代码,并且只使用一个时间序列,您最好使用不涉及深度学习的其他方法。您可以定期拆分您的时间序列,获得允许您的网络训练的 n 个样本,但除非您有一个可能不是有效替代方案的非常长的时间序列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-21
        • 1970-01-01
        • 1970-01-01
        • 2019-12-14
        • 2018-02-17
        • 1970-01-01
        • 2011-04-03
        • 2018-10-31
        相关资源
        最近更新 更多