具有 3D 卷积和卷积 LSTM 的自动编码器
Autoencoder with 3D convolutions and convolutional LSTMs
我已经在编码器和解码器中实现了一个带有 CNN 层的变分自编码器。代码如下所示。我的训练数据 (train_X
) 包含 40'000 张尺寸为 64 x 80 x 1 的图像,我的验证数据 (valid_X
) 包含 4500 张尺寸为 64 x 80 x 1 的图像。
我想通过以下两种方式调整我的网络:
我不想使用 2D 卷积(Conv2D 和 Conv2DTranspose),而是想使用 3D 卷积来考虑时间(作为三维)。为此,我想使用 10 张图像的切片,即我将拥有大小为 64 x 80 x 1 x 10 的图像。我可以只使用 Conv3D 和 Conv3DTranspose 还是需要进行其他更改?
我想在编码器和解码器中尝试使用卷积 LSTM (ConvLSTM2D),而不是普通的 2D 卷积。同样,图像的输入大小将为 64 x 80 x 1 x 10(即 10 张图像的时间序列)。如何调整我的网络以使用 ConvLSTM2D?
import keras
from keras import backend as K
from keras.layers import (Dense, Input, Flatten)
from keras.layers import Lambda, Conv2D
from keras.models import Model
from keras.layers import Reshape, Conv2DTranspose
from keras.losses import mse
def sampling(args):
z_mean, z_log_var = args
batch = K.shape(z_mean)[0]
dim = K.int_shape(z_mean)[1]
epsilon = K.random_normal(shape=(batch, dim))
return z_mean + K.exp(0.5 * z_log_var) * epsilon
inner_dim = 16
latent_dim = 6
image_size = (64,78,1)
inputs = Input(shape=image_size, name='encoder_input')
x = inputs
x = Conv2D(32, 3, strides=2, activation='relu', padding='same')(x)
x = Conv2D(64, 3, strides=2, activation='relu', padding='same')(x)
# shape info needed to build decoder model
shape = K.int_shape(x)
# generate latent vector Q(z|X)
x = Flatten()(x)
x = Dense(inner_dim, activation='relu')(x)
z_mean = Dense(latent_dim, name='z_mean')(x)
z_log_var = Dense(latent_dim, name='z_log_var')(x)
z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var])
# instantiate encoder model
encoder = Model(inputs, [z_mean, z_log_var, z], name='encoder')
# build decoder model
latent_inputs = Input(shape=(latent_dim,), name='z_sampling')
x = Dense(inner_dim, activation='relu')(latent_inputs)
x = Dense(shape[1] * shape[2] * shape[3], activation='relu')(x)
x = Reshape((shape[1], shape[2], shape[3]))(x)
x = Conv2DTranspose(64, 3, strides=2, activation='relu', padding='same')(x)
x = Conv2DTranspose(32, 3, strides=2, activation='relu', padding='same')(x)
outputs = Conv2DTranspose(filters=1, kernel_size=3, activation='sigmoid', padding='same', name='decoder_output')(x)
# instantiate decoder model
decoder = Model(latent_inputs, outputs, name='decoder')
# instantiate VAE model
outputs = decoder(encoder(inputs)[2])
vae = Model(inputs, outputs, name='vae')
def vae_loss(x, x_decoded_mean):
reconstruction_loss = mse(K.flatten(x), K.flatten(x_decoded_mean))
reconstruction_loss *= image_size[0] * image_size[1]
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
return vae_loss
optimizer = keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.000)
vae.compile(loss=vae_loss, optimizer=optimizer)
vae.fit(train_X, train_X,
epochs=500,
batch_size=128,
verbose=1,
shuffle=True,
validation_data=(valid_X, valid_X))
非常感谢您的帮助。非常感谢。
将您的输入形状设置为 (10, 64 , 80, 1)
并仅替换图层。
无聊的部分是组织输入数据,如果你打算使用滑动 windows 或者只是从 (images, 64,80,1)
重塑到 (images//10, 10, 64,80,1)
。
是否滑动windows(重叠)?
1 - 好的....如果您希望您的模型理解 10 张图像的各个部分,您可能会重叠或不重叠。你的选择。重叠时性能可能会更好,但不一定。
图片没有真正的顺序,只要10帧是有序的即可。
Conv3D
和 LSTM
支持 stateful=False
。
2 - 但是如果你想让你的模型理解整个序列,仅仅因为内存而划分序列,只有 LSTM
和 stateful=True
可以支持这个。
(内核大小为 (frames, w, h)
的 Conv3D
可以工作,但限于 frames
,从不理解长度超过 frames
的序列。它可能仍然能够检测准时事件的存在,但不是长序列关系)
在这种情况下,对于 LSTM
您将需要:
- 在训练中设置
shuffle = False
- 使用
sequences
的固定批量大小
- 不重叠 个图像
- 每次为训练和预测提供“新序列”时,
model.reset_states()
创建一个手动训练循环
循环结构为:
for epoch in range(epochs):
for group_of_sequences in range(groups):
model.reset_states()
sequences = getAGroupOfCompleteSequences() #shape (sequences, total_length, ....)
for batch in range(slide_divisions):
batch = sequences[:,10*batch : 10*(batch+1)]
model.train_on_batch(batch, ....)
我已经在编码器和解码器中实现了一个带有 CNN 层的变分自编码器。代码如下所示。我的训练数据 (train_X
) 包含 40'000 张尺寸为 64 x 80 x 1 的图像,我的验证数据 (valid_X
) 包含 4500 张尺寸为 64 x 80 x 1 的图像。
我想通过以下两种方式调整我的网络:
我不想使用 2D 卷积(Conv2D 和 Conv2DTranspose),而是想使用 3D 卷积来考虑时间(作为三维)。为此,我想使用 10 张图像的切片,即我将拥有大小为 64 x 80 x 1 x 10 的图像。我可以只使用 Conv3D 和 Conv3DTranspose 还是需要进行其他更改?
我想在编码器和解码器中尝试使用卷积 LSTM (ConvLSTM2D),而不是普通的 2D 卷积。同样,图像的输入大小将为 64 x 80 x 1 x 10(即 10 张图像的时间序列)。如何调整我的网络以使用 ConvLSTM2D?
import keras
from keras import backend as K
from keras.layers import (Dense, Input, Flatten)
from keras.layers import Lambda, Conv2D
from keras.models import Model
from keras.layers import Reshape, Conv2DTranspose
from keras.losses import mse
def sampling(args):
z_mean, z_log_var = args
batch = K.shape(z_mean)[0]
dim = K.int_shape(z_mean)[1]
epsilon = K.random_normal(shape=(batch, dim))
return z_mean + K.exp(0.5 * z_log_var) * epsilon
inner_dim = 16
latent_dim = 6
image_size = (64,78,1)
inputs = Input(shape=image_size, name='encoder_input')
x = inputs
x = Conv2D(32, 3, strides=2, activation='relu', padding='same')(x)
x = Conv2D(64, 3, strides=2, activation='relu', padding='same')(x)
# shape info needed to build decoder model
shape = K.int_shape(x)
# generate latent vector Q(z|X)
x = Flatten()(x)
x = Dense(inner_dim, activation='relu')(x)
z_mean = Dense(latent_dim, name='z_mean')(x)
z_log_var = Dense(latent_dim, name='z_log_var')(x)
z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var])
# instantiate encoder model
encoder = Model(inputs, [z_mean, z_log_var, z], name='encoder')
# build decoder model
latent_inputs = Input(shape=(latent_dim,), name='z_sampling')
x = Dense(inner_dim, activation='relu')(latent_inputs)
x = Dense(shape[1] * shape[2] * shape[3], activation='relu')(x)
x = Reshape((shape[1], shape[2], shape[3]))(x)
x = Conv2DTranspose(64, 3, strides=2, activation='relu', padding='same')(x)
x = Conv2DTranspose(32, 3, strides=2, activation='relu', padding='same')(x)
outputs = Conv2DTranspose(filters=1, kernel_size=3, activation='sigmoid', padding='same', name='decoder_output')(x)
# instantiate decoder model
decoder = Model(latent_inputs, outputs, name='decoder')
# instantiate VAE model
outputs = decoder(encoder(inputs)[2])
vae = Model(inputs, outputs, name='vae')
def vae_loss(x, x_decoded_mean):
reconstruction_loss = mse(K.flatten(x), K.flatten(x_decoded_mean))
reconstruction_loss *= image_size[0] * image_size[1]
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
return vae_loss
optimizer = keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.000)
vae.compile(loss=vae_loss, optimizer=optimizer)
vae.fit(train_X, train_X,
epochs=500,
batch_size=128,
verbose=1,
shuffle=True,
validation_data=(valid_X, valid_X))
非常感谢您的帮助。非常感谢。
将您的输入形状设置为 (10, 64 , 80, 1)
并仅替换图层。
无聊的部分是组织输入数据,如果你打算使用滑动 windows 或者只是从 (images, 64,80,1)
重塑到 (images//10, 10, 64,80,1)
。
是否滑动windows(重叠)?
1 - 好的....如果您希望您的模型理解 10 张图像的各个部分,您可能会重叠或不重叠。你的选择。重叠时性能可能会更好,但不一定。
图片没有真正的顺序,只要10帧是有序的即可。
Conv3D
和 LSTM
支持 stateful=False
。
2 - 但是如果你想让你的模型理解整个序列,仅仅因为内存而划分序列,只有 LSTM
和 stateful=True
可以支持这个。
(内核大小为 (frames, w, h)
的 Conv3D
可以工作,但限于 frames
,从不理解长度超过 frames
的序列。它可能仍然能够检测准时事件的存在,但不是长序列关系)
在这种情况下,对于 LSTM
您将需要:
- 在训练中设置
shuffle = False
- 使用
sequences
的固定批量大小
- 不重叠 个图像
- 每次为训练和预测提供“新序列”时,
model.reset_states()
创建一个手动训练循环
循环结构为:
for epoch in range(epochs):
for group_of_sequences in range(groups):
model.reset_states()
sequences = getAGroupOfCompleteSequences() #shape (sequences, total_length, ....)
for batch in range(slide_divisions):
batch = sequences[:,10*batch : 10*(batch+1)]
model.train_on_batch(batch, ....)