#python #tensorflow #machine-learning #keras
Вопрос:
Я выполняю задачу классификации временных рядов, и у меня возникают проблемы с поиском правильного способа использования tf.data.Dataset
. Я могу создать рабочую модель, используя массивы numpy, как в приведенном ниже коде (данные уже предварительно заполнены нулями до максимальной длины 180).:
tf_data.shape, labels.shape
> ((225970, 180, 1), (225970,))
Таким образом, у меня есть 225970 экземпляров 180 временных шагов с 1 функцией.
И я могу подогнать модель следующим образом. Это прекрасно работает и создает соответствующие выходные данные/прогнозы:
model = keras.Sequential(
[
layers.Masking(mask_value=0, input_shape=(180,1)),
layers.LSTM(16),
layers.Dense(1, activation='sigmoid')
]
)
model.compile(
optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.fit(tf_data, labels, epochs=5)
Однако, когда я пытаюсь выполнить следующее, используя tf.data.Dataset.from_tensors
:
tf_dataset = tf.data.Dataset.from_tensors((tf_data, labels.astype(int)))
tf_dataset = tf_dataset.shuffle(buffer_size=1024).batch(64)
model_v1 = keras.Sequential(
[
layers.Input(shape=(180,1), batch_size=64),
layers.Masking(mask_value=0),
layers.LSTM(16),
layers.Dense(1, activation='sigmoid')
]
)
model_v2 = keras.Sequential(
[
layers.Masking(mask_value=0, shape=(180,1), batch_size=64),
layers.LSTM(16),
layers.Dense(1, activation='sigmoid')
]
)
<model_v1 or model_v2>.compile(
optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy']
)
<model_v1 or model_v2>.fit(tf_dataset, epochs=10, steps_per_epoch=30)
Я сталкиваюсь с ошибками
model_v1 - ValueError: Error when checking input: expected input_48 to have 3 dimensions, but got array with shape (None, 225970, 180, 1)
model_v2 - ValueError: Error when checking input: expected masking_70_input to have 3 dimensions, but got array with shape (None, 225970, 180, 1)
Может ли кто-нибудь объяснить, что мне нужно сделать с моим набором данных tensorflow или с моей моделью, чтобы убедиться, что он будет работать с tf.data.Dataset
массивом numpy, а не только с ним?
Ответ №1:
Вместо этого вы должны использовать tf.data.Dataset.from_tensor_slices
,
tf_dataset = tf.data.Dataset.from_tensor_slices((tf_data, labels.astype(int)))
В соответствии с официальной документацией метода tf.data.Dataset.from_tensors
,
from_tensors
создает набор данных, содержащий только один элемент. Чтобы разделить входной тензор на несколько элементов, используйтеfrom_tensor_slices
вместо этого.
В то время как официальные документы для tf.data.Dataset.from_tensor_slices
говорит,
Данные тензоры разрезаны по их первому измерению. Эта операция сохраняет структуру входных тензоров, удаляя первое измерение каждого тензора и используя его в качестве измерения набора данных. Все входные тензоры должны иметь одинаковый размер в своих первых измерениях.
*.from_tensor_slices
Метод разрезает входной тензор и рассматривает данный массив ( тензор в нашем случае ) как 225970 экземпляров данных. Это позволяет вызывать такие методы, как *.shuffle
и *.batch()
которые перемешивают и пакуют экземпляры данных соответственно.
Мы можем понять это на примере. Сначала давайте сгенерируем несколько фиктивных экземпляров данных.
x = np.random.rand( 2500 , 180 , 1 )
y = np.random.rand( 2500 , 1 )
С *.from_tensors
,
tensor_ds = tf.data.Dataset.from_tensors( ( x , y ) )
for sample in tensor_ds.take( 1 ):
print( sample[ 0 ].shape )
print( sample[ 1 ].shape )
На выходе получается,
(2500, 180, 1)
(2500, 1)
И с *.from_tensor_slices
,
tensor_ds = tf.data.Dataset.from_tensor_slices( ( x , y ) )
for sample in tensor_ds.take( 1 ):
print( sample[ 0 ].shape )
print( sample[ 1 ].shape )
На выходе получается,
(180, 1)
(1,)
Комментарии:
1. Спасибо. Это сработало и было очень хорошим объяснением.