【问题标题】:How to Split the Input into different channels in Keras如何在 Keras 中将输入拆分为不同的通道
【发布时间】:2018-11-15 01:09:24
【问题描述】:

我有 20 个通道数据,每个通道有 5000 个值(总共 150,000 多条记录以 .npy 文件存储在 HD 上)。

我正在关注https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly.html 上提供的 keras fit_generator 教程来读取数据(每条记录被读取为 float32 类型的 (5000, 20) numpy 数组。

我理论化的网络,每个通道都有并行的卷积网络,它们在末端连接起来,因此需要并行馈送数据。 从数据中仅读取和馈送单个通道并馈送到单个网络是成功的

def __data_generation(self, list_IDs_temp):
    'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
    # Initialization
    if(self.n_channels == 1):
        X = np.empty((self.batch_size, *self.dim))
    else:
        X = np.empty((self.batch_size, *self.dim, self.n_channels))
    y = np.empty((self.batch_size), dtype=int)

    # Generate data
    for i, ID in enumerate(list_IDs_temp):
        # Store sample
        d = np.load(self.data_path + ID + '.npy')
        d = d[:, self.required_channel]
        d = np.expand_dims(d, 2)
        X[i,] = d

        # Store class
        y[i] = self.labels[ID]

    return X, keras.utils.to_categorical(y, num_classes=self.n_classes)

但是,当读取整个记录并尝试使用 Lambda 层将其提供给网络进行切片时,我得到了

读取整条记录

 X[i,] = np.load(self.data_path + ID + '.npy')

使用位于 https://github.com/keras-team/keras/issues/890 的 Lambda 切片层实现并调用

input = Input(shape=(5000, 20))
slicedInput = crop(2, 0, 1)(input)

我能够编译模型并显示预期的层大小。

当数据被输入到这个网络时,我得到了

ValueError: could not broadcast input array from shape (5000,20) into shape (5000,1)

任何帮助将不胜感激......

【问题讨论】:

    标签: python tensorflow keras multiprocessing keras-layer


    【解决方案1】:

    正如您所引用的 Github thread 中所述,Lambda 层只能返回一个输出,因此建议的 crop(dimension, start, end) 仅返回一个“给定维度上从头到尾的张量”。

    我相信你想要达到的目标可以通过这样的方式完成:

    from keras.layers import Dense, Concatenate, Input, Lambda
    from keras.models import Model
    
    num_channels = 20
    input = Input(shape=(5000, num_channels))
    
    branch_outputs = []
    for i in range(num_channels):
        # Slicing the ith channel:
        out = Lambda(lambda x: x[:, i])(input)
    
        # Setting up your per-channel layers (replace with actual sub-models):
        out = Dense(16)(out)
        branch_outputs.append(out)
    
    # Concatenating together the per-channel results:
    out = Concatenate()(branch_outputs)
    
    # Adding some further layers (replace or remove with your architecture):
    out = Dense(10)(out)
    
    # Building model:
    model = Model(inputs=input, outputs=out)    
    model.compile(optimizer=keras.optimizers.Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
    
    # --------------
    # Generating dummy data:
    import numpy as np
    data = np.random.random((64, 5000, num_channels))
    targets = np.random.randint(2, size=(64, 10))
    
    # Training the model:
    model.fit(data, targets, epochs=2, batch_size=32)
    # Epoch 1/2
    # 32/64 [==============>...............] - ETA: 1s - loss: 37.1219 - acc: 0.1562
    # 64/64 [==============================] - 2s 27ms/step - loss: 38.4801 - acc: 0.1875
    # Epoch 2/2
    # 32/64 [==============>...............] - ETA: 0s - loss: 38.9541 - acc: 0.0938
    # 64/64 [==============================] - 0s 4ms/step - loss: 36.0179 - acc: 0.1875
    

    【讨论】:

    • 您可以创建自定义层而不是使用 Lambda 并将多个输出作为列表返回。
    • 对。循环也是在这里设置“每个通道的并行卷积网络”OP提到的。
    • 直到 model.summary() 的代码运行完美,我得到了模型层/参数信息,但是当我编译模型开始训练时,就像 ---> model.compile(optimizer=optimizers. Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy']) 我得到同样的错误---> ValueError: could not broadcast input array from shape (5000,20) into shape (5000,1 )
    • 你的模型输入是如何定义的?应该是input = Input(shape=(5000, 20))。从我更新的答案中可以看出,事情正在顺利编译和训练......
    • 为了不取消一个维度,您可以将out = Lambda(lambda x: x[:, i])(input) 转为out = Lambda(lambda x: x[:, i:i+1])(input)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2018-05-20
    • 2013-10-30
    • 1970-01-01
    • 2015-02-05
    • 2017-04-18
    • 1970-01-01
    相关资源
    最近更新 更多