【问题标题】:How do I run an iterative 2D convolution for each slice of a tensor?如何为张量的每个切片运行迭代 2D 卷积?
【发布时间】:2021-07-19 20:25:44
【问题描述】:

我正在使用 Python 中的 TF/Keras 进行卷积神经网络的机器学习项目,我的目标是将图像分割成块,分别对每个块运行卷积,然后将其重新组合在一起.

我不知道该怎么做是为 3D 数组的每个切片运行卷积。

例如,如果我有一个大小为 (500,100,100) 的张量,我想对大小为 (100 x 100) 的所有 500 个切片进行单独的卷积。我正在自定义 Keras 层中实现这一点,并希望这些是可训练的权重,我尝试了一些不同的方法:

  1. 使用map.fn() 为数组的每个切片运行卷积
    • 这似乎没有分别为每一层附加权重。
  2. 使用DepthwiseConv2D 层:
    • 这适用于第一次调用层,但当我使用更多过滤器第二次调用层时失败,因为它想在之前的每个过滤层上执行 depthwise 卷积
    • 这当然不是我想要的,因为我想为前一层的每组过滤器进行一次卷积。

感谢任何想法,因为我真的被困在这里。谢谢!

【问题讨论】:

  • 不确定我是否完全理解您的问题,但是如果您有一个形状为 (500,100,100) 的张量并且想要输入该张量的某个子集,以同时分离 conv2d 层,您可以这样做通过在同一级别定义 conv2d 层。例如,如果要将张量提供给 5 个单独的 conv2d 层,则应创建其输出为 (500,100,100) 的层的 5 个分支到 5 个 lambda 层,这些层提取形状 (100,100,100) 的补丁并将它们中的每一个连接到分离 conv2d 层,然后连接它们的输出。
  • @Kaveh 感谢您的回复!这是有道理的,但我不完全确定如何实现这一点。我尝试使用 map.fn() 每次都应用 lambda 函数:out = tf.map_fn(Lambda(lambda x: self.Conv2Dee(x)),img) 其中“img”是我的张量堆栈,“Conv2Dee”是我编写的自定义卷积函数,但出现以下错误:The following Variables were created within a Lambda layer (lambda) but are not tracked by said layer: The layer cannot safely ensure proper Variable reuse across multiple calls, and consquently this behavior is disallowed for safety...

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


【解决方案1】:

如果您有一个形状为(500,100,100) 的张量,并且想要馈送该张量的某个子集,以同时分离conv2d 层,您可以通过在同一级别定义conv2d 层来做到这一点。您应该首先定义Lambda 层来拆分输入,然后将它们的输出提供给Conv2D 层,然后是concatenate 它们。

让我们以一个形状为(100,28,28,1) 的张量为例,我们想将它分成2 个子张量,并在每个子集上分别应用conv2d 层:

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D, Input, concatenate, Lambda
from tensorflow.keras.models import Model

# define a sample dataset
x = tf.random.uniform((100, 28, 28, 1))
y = tf.random.uniform((100, 1), dtype=tf.int32, minval=0, maxval=9)
ds = tf.data.Dataset.from_tensor_slices((x, y))
ds = ds.batch(16)

def create_nn_model():
    input = Input(shape=(28,28,1))
    b1 = Lambda(lambda a: a[:,:14,:,:], name="first_slice")(input)
    b2 = Lambda(lambda a: a[:,14:,:,:], name="second_slice")(input)
    d1 = Conv2D(64, 2, padding='same', activation='relu', name="conv1_first_slice")(b1)
    d2 = Conv2D(64, 2, padding='same', activation='relu', name="conv2_second_slice")(b2)
    x =  concatenate([d1,d2], axis=1)
    x = Flatten()(x)
    x = Dense(64, activation='relu')(x)
    out = Dense(10, activation='softmax')(x)
    model = Model(input, out)
    model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

model = create_nn_model()
tf.keras.utils.plot_model(model, show_shapes=True) 

这是绘制的模型架构:

【讨论】:

  • 谢谢,这真的很有帮助!一个问题 - 有没有办法扩展这个?例如,如果我想运行 100 个不同的单独卷积,我可以这样做而无需手动定义 100 个 Conv2D 层吗?
  • 是的。您可以在循环中定义图层;-)
猜你喜欢
  • 1970-01-01
  • 2020-10-28
  • 2020-11-08
  • 2017-03-17
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 2019-03-14
相关资源
最近更新 更多