【问题标题】:How to reshape 3 channel dataset for input to neural network如何重塑 3 通道数据集以输入到神经网络
【发布时间】:2019-08-14 05:06:23
【问题描述】:

我正在尝试将第 k 个动作数据集提供给 cnn。我很难重塑数据。我创建了这个数组 (99,75,120,160) type=uint8 ,即属于一个类的 99 个视频,每个视频有 75 帧,每帧尺寸为 120x160。

model = Sequential()
model.add(TimeDistributed(Conv2D(64, (3, 3), activation='relu', padding='same'), 
                          input_shape=())) 
###need to reshape data in input_shape

我应该先指定一个密集层吗?

这是我的代码

model = Sequential()
model.add(TimeDistributed(Conv2D(64, (3, 3), activation='relu', padding='same'), 
                          input_shape=(75,120,160)))
###need to reshape data in input_shape

model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Conv2D(32, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Conv2D(16, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))

model.add(TimeDistributed(Flatten()))
model.add(LSTM(units=64, return_sequences=True))

model.add(TimeDistributed(Reshape((8, 8, 1))))
model.add(TimeDistributed(UpSampling2D((2,2))))
model.add(TimeDistributed(Conv2D(16, (3,3), activation='relu', padding='same')))
model.add(TimeDistributed(UpSampling2D((2,2))))
model.add(TimeDistributed(Conv2D(32, (3,3), activation='relu', padding='same')))
model.add(TimeDistributed(UpSampling2D((2,2))))
model.add(TimeDistributed(Conv2D(64, (3,3), activation='relu', padding='same')))
model.add(TimeDistributed(UpSampling2D((2,2))))
model.add(TimeDistributed(Conv2D(1, (3,3), padding='same')))

model.compile(optimizer='adam', loss='mse')

data = np.load(r"C:\Users\shj_k\Desktop\Project\handclapping.npy")
print (data.shape)
(x_train,x_test) = train_test_split(data)


x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.




print (x_train.shape)
print (x_test.shape)


model.fit(x_train, x_train,
                epochs=100,
                batch_size=1,
                shuffle=False,
                validation_data=(x_test, x_test))

变量是 x_test (25,75,120,160) 类型=float32 x_train (74,75,120,160) type=float32

评论中的完全错误是

runfile('C:/Users/shj_k/Desktop/Project/cnn_lstm.py', wdir='C:/Users/shj_k/Desktop/Project') (99, 75, 120, 160) (74, 75, 120, 160) (25, 75, 120, 160) Traceback(最近一次调用最后一次):

文件“”,第 1 行,在 runfile('C:/Users/shj_k/Desktop/Project/cnn_lstm.py', wdir='C:/Users/shj_k/Desktop/Project')

文件 "C:\Users\shj_k\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", 第 668 行,在运行文件中 execfile(文件名,命名空间)

文件 "C:\Users\shj_k\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", 第 108 行,在 execfile 中 exec(编译(f.read(),文件名,'exec'),命名空间)

文件“C:/Users/shj_k/Desktop/Project/cnn_lstm.py”,第 63 行,在 验证数据=(x_test, x_test))

文件 "C:\Users\shj_k\Anaconda3\lib\site-packages\keras\engine\training.py", 第 952 行,合适 batch_size=batch_size)

文件 "C:\Users\shj_k\Anaconda3\lib\site-packages\keras\engine\training.py", 第 751 行,在 _standardize_user_data exception_prefix='输入')

文件 "C:\Users\shj_k\Anaconda3\lib\site-packages\keras\engine\training_utils.py", 第 128 行,在 standardize_input_data 中 '带形状' + str(data_shape))

ValueError:检查输入时出错:预期 time_distributed_403_input 有 5 个维度,但是得到了数组 形状(74、75、120、160)

感谢您的回复

【问题讨论】:

  • 尝试指定 input_shape=(75, 120, 160)
  • 我刚刚做了并且得到了错误返回 self._dims[key] IndexError: list index out of range
  • 我尝试了 input_shape=(1,120,160,75) 并得到了错误 ValueError: Error when checks input: expected time_distributed_403_input to have 5 个维度,但得到了形状为 (74, 75, 120, 160) 的数组)
  • 所以 Keras 中的 TimeDistributed 层需要一个时间维度,所以这里的视频图像处理可能是 75(每秒帧数)。然后,它期望图像以 120,60, 3 格式发送。所以最终的 input_shape 应该是 (75, 120, 160, 3)。在 Keras.preprocessing.image 中有 image.img_to_array(img) ,您可以在其中将 PIL 图像转换为 numpy 数组。
  • 我尝试按照你说的替换 input_shape 仍然返回相同的错误

标签: python numpy opencv keras deep-learning


【解决方案1】:

两件事:

Keras 中的 TimeDistributed 层需要一个时间维度,因此对于视频图像处理,这可能是 75(帧)。

它还期望图像以 (120, 60, 3) 形状发送。所以 TimeDistributed 层 input_shape 应该是 (75, 120, 160, 3)。 3 代表 RGB 通道。如果您有灰度图像,则应将 1 作为最后一个维度。

input_shape 总是忽略示例的“行”维度,在您的情况下为 99。

要查看模型每一层创建的输出形状,编译后输入model.summary()

见:https://www.tensorflow.org/api_docs/python/tf/keras/layers/TimeDistributed

您可以使用 Keras.preprocessing.image 将图像转换为形状为 (X, Y, 3) 的 numpy 数组。

from keras.preprocessing import image

# loads RGB image as PIL.Image.Image type
img = image.load_img(img_file_path, target_size=(120, 160))
# convert PIL.Image.Image type to 3D tensor with shape (120, 160, 3)
x = image.img_to_array(img)

更新: 似乎您必须使所有图像平方 (128,128,1) 的原因是在 model.fit() 中,训练示例 (x_train) 和标签 (通常是 y_train) 是同一组。如果您查看下面的模型摘要,在 Flatten 层之后,一切都变成了正方形。因此,它期望标签是正方形。这是有道理的:使用此模型进行预测会将 (120,160,1) 图像转换为 (128, 128, 1) 形状的图像。因此,将模型训练更改为以下代码应该可以工作:

x_train = random.random((90, 5, 120, 160, 1)) # training data
y_train = random.random((90, 5, 128, 128, 1)) # labels
model.fit(x_train, y_train)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
time_distributed_1 (TimeDist (None, 5, 120, 160, 64)   320       
_________________________________________________________________
time_distributed_2 (TimeDist (None, 5, 60, 80, 64)     0         
_________________________________________________________________
time_distributed_3 (TimeDist (None, 5, 60, 80, 32)     18464     
_________________________________________________________________
time_distributed_4 (TimeDist (None, 5, 30, 40, 32)     0         
_________________________________________________________________
time_distributed_5 (TimeDist (None, 5, 30, 40, 16)     4624      
_________________________________________________________________
time_distributed_6 (TimeDist (None, 5, 15, 20, 16)     0         
_________________________________________________________________
time_distributed_7 (TimeDist (None, 5, 4800)           0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 5, 64)             1245440   
_________________________________________________________________
time_distributed_8 (TimeDist (None, 5, 8, 8, 1)        0         
_________________________________________________________________
time_distributed_9 (TimeDist (None, 5, 16, 16, 1)      0         
_________________________________________________________________
time_distributed_10 (TimeDis (None, 5, 16, 16, 16)     160       
_________________________________________________________________
time_distributed_11 (TimeDis (None, 5, 32, 32, 16)     0         
_________________________________________________________________
time_distributed_12 (TimeDis (None, 5, 32, 32, 32)     4640      
_________________________________________________________________
time_distributed_13 (TimeDis (None, 5, 64, 64, 32)     0         
_________________________________________________________________
time_distributed_14 (TimeDis (None, 5, 64, 64, 64)     18496     
_________________________________________________________________
time_distributed_15 (TimeDis (None, 5, 128, 128, 64)   0         
_________________________________________________________________
time_distributed_16 (TimeDis (None, 5, 128, 128, 1)    577       
=================================================================
Total params: 1,292,721
Trainable params: 1,292,721
Non-trainable params: 0

更新 2: 要使其在不更改 y 的情况下处理非方形图像,请设置 LSTM(300)、Reshape(15, 20, 1),然后删除其中一个 Conv2D + 上采样层。然后,即使在自动编码器中,您也可以使用形状为 (120,160) 的图片。诀窍是查看模型摘要,并确保在 LSTM 之后以正确的形状开始,以便在添加所有其他层后,最终结果是 (120,160) 的形状。

model = Sequential()
model.add(
    TimeDistributed(Conv2D(64, (2, 2), activation="relu", padding="same"), =(5, 120, 160, 1)))

model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Conv2D(32, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Conv2D(16, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))

model.add(TimeDistributed(Flatten()))
model.add(LSTM(units=300, return_sequences=True))

model.add(TimeDistributed(Reshape((15, 20, 1))))
model.add(TimeDistributed(UpSampling2D((2, 2))))
model.add(TimeDistributed(Conv2D(16, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(UpSampling2D((2, 2))))
model.add(TimeDistributed(Conv2D(32, (3, 3), activation='relu', padding='same')))
model.add(TimeDistributed(UpSampling2D((2, 2))))
model.add(TimeDistributed(Conv2D(1, (3, 3), padding='same')))


model.compile(optimizer='adam', loss='mse')

model.summary()

x_train = random.random((90, 5, 120, 160, 1))
y_train = random.random((90, 5, 120, 160, 1))

model.fit(x_train, y_train)

【讨论】:

  • 我认为如果您指定 input_shape=(75, 120, 160, 1),忽略任何 rgb 通道,它也可能有效。
  • 确切地说,您必须在将单个视频帧作为图像的位置应用此功能。然后,您将使用上面的代码对其进行处理,并将生成的“x”存储在 Keras 模型的训练数组中,现在每个图像的形状为 (120, 160, 3)。
  • 现在代码运行速度超级慢。实际上在预处理的早些时候,我已经将每一帧转换为灰度并将每一帧附加到一个列表中,然后将该列表附加到另一个列表(frame->frame_list->video_list)并将其转换为一个数组。 PIL 与此有何不同?
  • 我尝试使用 (75,120,160,1) 并返回 ValueError: Error when checks target: expected time_distributed_548 to have shape (75, 128, 128, 1) 但得到了形状为 (75, 120, 160, 1)
  • 我尝试了你用 PIL 说的改变,现在我的数组是 (100,75,120,160,1),每帧都是灰度。我需要尝试使用 rgb 框架吗?上面的错误伴随着这个新数据
【解决方案2】:

感谢Kai Aeberli 先生的协助。将图像大小调整为 128x128 尺寸后,我能够运行模型。数据集的大小可能会导致系统在没有 gpu 的情况下崩溃。根据需要减小尺寸。如果您有任何疑问,请参阅整个评论部分。可以在github找到代码here

【讨论】:

  • 很高兴听到这个消息!你能发布完整的工作代码吗?也许有一些随机样本数据,如x_train = random.random((10, 75, 128, 128, 1)),理想情况下所有正确的导入都在顶部。
  • 哦,是的..一旦我正确评论它,我将上传帧提取代码和 lstm-cnn 代码。我也会上传 numpy 文件。
  • 用方形图像问题的原因更新了答案
  • @KaiAeberli 我看到了你关于重塑的更新,但因为这是一个自动编码器,我的没有任何y_train 我应该把它放在哪里?我也尝试训练模型,但起初训练损失和验证损失很低并且在相同的范围内,但在随后的训练中它们似乎偏离并且验证损失往往高于训练损失。 mse 图中有尖峰
  • 是的,你是对的 - 使用自动编码器,方形图像有点棘手,因为卷积层在展平后将所有内容平方。在末尾或 LSTM() 层之后添加 Reshape() 层可能会起作用。
猜你喜欢
  • 2019-11-03
  • 2017-12-25
  • 2013-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2022-11-18
  • 2013-06-06
相关资源
最近更新 更多