преобразовать tf.dataset в тензор 4D - PullRequest
0 голосов
/ 03 апреля 2020

Я просто изучаю TensorFlow и столкнулся с этой проблемой - когда я передаю tf.dataset в model.fit, я получаю сообщение об ошибке

ValueError: Ошибка при проверке ввода: ожидается, что conv2d_input имеет 4 измерения, но получил массив с формой (28, 28, 1)

Я понимаю, что это должен быть четырехмерный тензор - (количество элементов, строк, столбцов, каналов), когда параметр data_format равен "channel_last". но у меня есть только tf.Ddaseaset, который я получил после загрузки набора данных. Таким образом, мой вопрос заключается в том, как преобразовать tf.Dataset в 4D-тензор, чтобы иметь возможность передавать его в модель? Может кто-нибудь показать мне код или указать подходящую статью? Вот мой код

import tensorflow as tf
import tensorflow_datasets as tfds

builder = tfds.builder('mnist')
builder.download_and_prepare()

(raw_train, raw_test) = builder.as_dataset(split=[tfds.Split.TRAIN, tfds.Split.TEST])

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=6, kernel_size=5, activation=tf.keras.activations.sigmoid, input_shape=(28, 28 ,1)))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Conv2D(filters=16, kernel_size=5, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
# model.add(Flatten())
model.add(tf.keras.layers.Dense(120, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(84, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(10))

result = model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

# model.summary()
train_images = []
train_labels = []
for i in raw_train:
    image = i["image"]
    # image = image.reshape(-1,28, 28, 1) 
    train_images.append(image)

    label = i["label"]
    train_labels.append(label)

model.fit(train_images, train_labels, epochs=10)

ОБНОВЛЕНИЕ:

Я попробовал совет преобразовать список в numpy .array. Я попробовал, но не смог дождаться результата, потому что он занимал только 1 ядро ​​процессора и использовал его на 100%. Я потратил 30 минут, но пока не получил результат. Я считаю, что должен быть другой, более правильный подход. Я смотрю в сторону пакетной и предварительной выборки, но в любом случае я не знаю, как получить результат

новый код выглядит следующим образом

import tensorflow as to
tf.debugging.set_log_device_placement(True)
import tensorflow_datasets as tfds
import numpy as np

builder = tfds.builder('mnist')
builder.download_and_prepare()

(raw_train, raw_test) = builder.as_dataset(split=[tfds.Split.TRAIN, tfds.Split.TEST])

raw_train = raw_train.batch(128).prefetch(128)
raw_test = raw_test.batch(128).prefetch(128)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=6, kernel_size=5, activation=tf.keras.activations.sigmoid, input_shape=(28, 28 ,1)))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Conv2D(filters=16, kernel_size=5, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
        # model.add(Flatten())
model.add(tf.keras.layers.Dense(120,activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(84,activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(10))

result = model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
                      metrics=['accuracy'])

train_images = []
train_labels = []
for i in raw_train:
   image = i["image"]
   train_images.append(image)

   label = i["label"]
   train_labels.append(label)

with tf.device('/GPU:0'):
   model.fit(train_images, train_labels, epochs=10)

У меня все еще есть ошибка: ValueError: Ошибка при проверке цели модели: список Numpy массивов, передаваемых в вашу модель, не соответствует размеру, ожидаемому моделью. Ожидается увидеть 1 массив (ов) для входных данных ['dens_5'], но вместо этого он получил следующий список из 469 массивов: [

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

Это еще не закончено, но у меня есть следующий шаг. чтобы заставить предыдущий код работать, я добавил one_hot_y = tf.one_hot (label_batch, 10)

import tensorflow as tf
tf.debugging.set_log_device_placement(True)
import tensorflow_datasets as tfds
import numpy as np
from time import time

builder = tfds.builder('mnist')
builder.download_and_prepare()

(raw_train, raw_test) = builder.as_dataset(split=[tfds.Split.TRAIN, tfds.Split.TEST],shuffle_files=False)

def divide(record):
    image = record["image"]
    image = tf.image.resize_with_pad(image, 32,32)
    label = record["label"]
    return image,label

train_ds = raw_train.map(divide, num_parallel_calls=tf.data.experimental.AUTOTUNE).batch(128).prefetch(128)
test_ds = raw_test.map(divide , num_parallel_calls=tf.data.experimental.AUTOTUNE).batch(128).prefetch(128)
print(type(train_ds))

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=6, kernel_size=(5,5), activation=tf.keras.activations.sigmoid, input_shape=(32, 32 ,1)))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Conv2D(filters=16, kernel_size=(5,5), activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(120, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(84, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(10))

result = model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])


image_batch, label_batch = next(iter(train_ds))

print(image_batch.shape)
print(label_batch.shape)

one_hot_y = tf.one_hot(label_batch, 10)
print(one_hot_y.shape)

with tf.device('/GPU:0'):
    model.fit(image_batch, one_hot_y, epochs=10)

Следующим шагом является выяснение, какие шаги являются правильными для перемещения по всем элементам в наборе данных используя партии.

0 голосов
/ 03 апреля 2020

это не совсем ответ ... потому что это решает мою проблему, но приносит другую) Прежде всего, я думаю, что не самая лучшая идея преобразовать список тензоров в один 4-мерный тензор, потому что он выполнен с использованием NumPy, который использует одно ядро ​​моего процессора - я не смог дождаться результата этой операции. Я выяснил, что есть другой подход, который мне нравится больше, и с моей точки зрения, он выглядит лучше - он использует tf.dataset.map, затем пакетную, а затем предварительную выборку функций. Я пока не знаю, как их использовать, но я копаюсь в эту сторону ... и сейчас, я думаю, это более правильный и перспективный способ.

import tensorflow as tf
tf.debugging.set_log_device_placement(True)
import tensorflow_datasets as tfds
import numpy as np


builder = tfds.builder('mnist')
builder.download_and_prepare()

(raw_train, raw_test) = builder.as_dataset(split=[tfds.Split.TRAIN, tfds.Split.TEST],shuffle_files=False)

def divide(record):
    image = record["image"]
    label = record["label"]
    return image,label

train_ds = raw_train.map(divide , num_parallel_calls=tf.data.experimental.AUTOTUNE).batch(128).prefetch(128)
test_ds = raw_test.map(divide , num_parallel_calls=tf.data.experimental.AUTOTUNE).batch(128).prefetch(128)
print(type(train_ds))

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=6, kernel_size=(5,5), activation=tf.keras.activations.sigmoid, input_shape=(28, 28 ,1)))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Conv2D(filters=16, kernel_size=(5,5), activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(120, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(84, activation=tf.keras.activations.sigmoid))
model.add(tf.keras.layers.Dense(10))

result = model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

image_batch, label_batch = next(iter(train_ds))

print(image_batch.shape)
print(label_batch.shape)

with tf.device('/GPU:0'):
    model.fit(image_batch, label_batch, epochs=10)

Этот код также не работает, но я думаю, что это потому, что модель ожидает 32x32 вместо 28x28, которые я скормил модели. Я все еще работаю - если вы знаете, как решить проблему и как управлять партиями, пожалуйста, дайте мне знать. Я ценю ваши советы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...