#python #tensorflow #keras #deep-learning
#python #тензорный поток #keras #глубокое обучение
Вопрос:
Я использую transfer learning с MobileNet, а затем отправляю извлеченные функции в LSTM для классификации видеоданных.
Изображения изменяются до (224,224), когда я устанавливаю набор данных train, test, validation с помощью image_dataset_from_directory().
РЕДАКТИРОВАТЬ: Итак, мне нужно заполнить последовательности данных, но при этом я получаю следующую ошибку, я не слишком уверен, как я могу это сделать, когда я использую image_dataset_from_directory():
train_dataset = sequence.pad_sequences(train_dataset, maxlen=BATCH_SIZE, padding="post", truncating="post")
InvalidArgumentError: assertion failed: [Unable to decode bytes as JPEG, PNG, GIF, or BMP]
[[{{node decode_image/cond_jpeg/else/_1/decode_image/cond_jpeg/cond_png/else/_20/decode_image/cond_jpeg/cond_png/cond_gif/else/_39/decode_image/cond_jpeg/cond_png/cond_gif/Assert/Assert}}]] [Op:IteratorGetNext]
Я проверил тип train_dataset:
<BatchDataset shapes: ((None, None, 224, 224, 3), (None, None)), types: (tf.float32, tf.int32)>
Глобальные переменные:
TARGETX = 224
TARGETY = 224
CLASSES = 3
SIZE = (TARGETX,TARGETY)
INPUT_SHAPE = (TARGETX, TARGETY, 3)
CHANNELS = 3
NBFRAME = 5
INSHAPE = (NBFRAME, TARGETX, TARGETY, 3)
Функция Mobilenet:
def build_mobilenet(shape=INPUT_SHAPE, nbout=CLASSES):
# INPUT_SHAPE = (224,224,3)
# CLASSES = 3
model = MobileNetV2(
include_top=False,
input_shape=shape,
weights='imagenet')
base_model.trainable = True
output = GlobalMaxPool2D()
return Sequential([model, output])
Функция LSTM:
def action_model(shape=INSHAPE, nbout=3):
# INSHAPE = (5, 224, 224, 3)
convnet = build_mobilenet(shape[1:])
model = Sequential()
model.add(TimeDistributed(convnet, input_shape=shape))
model.add(LSTM(64))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(512, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(128, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(64, activation='relu'))
model.add(Dense(nbout, activation='softmax'))
return model
model = action_model(INSHAPE, CLASSES)
model.summary()
Model: "sequential_16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
time_distributed_6 (TimeDist (None, 5, 1280) 2257984
_________________________________________________________________
lstm_5 (LSTM) (None, 64) 344320
_________________________________________________________________
dense_45 (Dense) (None, 1024) 66560
_________________________________________________________________
dropout_18 (Dropout) (None, 1024) 0
_________________________________________________________________
dense_46 (Dense) (None, 512) 524800
_________________________________________________________________
dropout_19 (Dropout) (None, 512) 0
_________________________________________________________________
dense_47 (Dense) (None, 128) 65664
_________________________________________________________________
dropout_20 (Dropout) (None, 128) 0
_________________________________________________________________
dense_48 (Dense) (None, 64) 8256
_________________________________________________________________
dense_49 (Dense) (None, 3) 195
=================================================================
Total params: 3,267,779
Trainable params: 3,233,667
Non-trainable params: 34,112
Комментарии:
1. Набор данных. Если это просто пакет изображений, то в этом проблема.
2. Из того, что говорится в ошибке. Вы пытаетесь передать что-то вроде (32, 224, 224, 3), но ваша модель нуждается (32, 5, 224, 224, 3)
3. Должно быть из INSHAPE, тогда его форма должна быть (224,224,3). Я читал код из статьи, где они отправляют количество кадров в виде последовательности в свою модель. Я попробую это и посмотрю, работает ли это.
Ответ №1:
Ваша модель в полном порядке. Проблема в том, как вы передаете данные.
Ваш код модели:
import tensorflow as tf
import keras
from keras.layers import GlobalMaxPool2D, TimeDistributed, Dense, Dropout, LSTM
from keras.applications import MobileNetV2
from keras.models import Sequential
import numpy as np
from keras.preprocessing.sequence import pad_sequences
TARGETX = 224
TARGETY = 224
CLASSES = 3
SIZE = (TARGETX,TARGETY)
INPUT_SHAPE = (TARGETX, TARGETY, 3)
CHANNELS = 3
NBFRAME = 5
INSHAPE = (NBFRAME, TARGETX, TARGETY, 3)
def build_mobilenet(shape=INPUT_SHAPE, nbout=CLASSES):
# INPUT_SHAPE = (224,224,3)
# CLASSES = 3
model = MobileNetV2(
include_top=False,
input_shape=shape,
weights='imagenet')
model.trainable = True
output = GlobalMaxPool2D()
return Sequential([model, output])
def action_model(shape=INSHAPE, nbout=3):
# INSHAPE = (5, 224, 224, 3)
convnet = build_mobilenet(shape[1:])
model = Sequential()
model.add(TimeDistributed(convnet, input_shape=shape))
model.add(LSTM(64))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(512, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(128, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(64, activation='relu'))
model.add(Dense(nbout, activation='softmax'))
return model
Теперь давайте попробуем эту модель с некоторыми фиктивными данными:
Итак, ваша модель принимает последовательность изображений (т. Е. кадры видео) и классифицирует их (видео) в один из 3 классов.
Давайте создадим фиктивные данные с 4 видео, каждое из 10 кадров, т. Е. размер пакета = 4 и временные шаги = 10
X = np.random.randn(4, 10, TARGETX, TARGETY, 3)
y = model(X)
print (y.shape)
Вывод:
(4,3)
Как и ожидалось, выходной размер равен (4,3)
Теперь проблема, с которой вы столкнетесь при использовании image_dataset_from_direcctory
, будет заключаться в том, как группировать видео переменной длины, поскольку количество кадров в каждом видео будет / может отличаться. Способ справиться с этим — использовать pad_sequences
.
Например, если первое видео содержит 10 кадров, второе — 9 и так далее, вы можете сделать что-то вроде приведенного ниже
X = [np.random.randn(10, TARGETX, TARGETY, 3),
np.random.randn(9, TARGETX, TARGETY, 3),
np.random.randn(8, TARGETX, TARGETY, 3),
np.random.randn(7, TARGETX, TARGETY, 3)]
X = pad_sequences(X)
y = model(X)
print (y.shape)
Вывод:
(4,3)
Итак, как только вы прочитаете изображения с помощью image_dataset_from_direcctory
, вам придется вставить кадры переменной длины в пакет.
Комментарии:
1. Итак, мне придется применить pad_sequences() к моему набору данных для обучения, тестирования и проверки перед обучением модели? Я немного смущен частью количества кадров, поскольку в моем исходном наборе данных было много видео каждой категории (60 для каждого, и каждое длилось около 10 минут, я снимал кадр каждые 5 секунд), затем после их обработки я объединил их в большую папку для каждой категории.
2. Да, поэтому в зависимости от длины видео у вас будет разное количество кадров. Поэтому при создании пакета вам придется дополнять более короткие кадры. Это потому, что все выборки в пакете должны иметь одинаковое количество временных шагов. Вы можете иметь размер пакета 1 и не беспокоиться о заполнении, но это замедлит время вашего обучения.
3. Ок, понял, поэтому мне нужно дополнить последовательности кадров, чтобы сохранить фиксированную форму во всех пакетах. Разве это не похоже на NLP, где последовательности слов дополняются, чтобы получить фиксированную последовательность, поскольку предложения различаются по длине?
4. Да, точно, это то же самое, как вы обрабатываете предложения переменной длины. Фактически, все модели, использующие RNNS, должны иметь дело с этой проблемой.
5. Эй, не могли бы вы проверить отредактированный пост? У меня проблемы с заполнением фреймов.