Tensorflow: логиты и метки должны иметь одно и то же первое измерение

Я новичок в tensoflow и хочу адаптировать учебник MNIST https://www.tensorflow.org/tutorials/layers с моими данными (изображения 40х40). Это моя модельная функция:

def cnn_model_fn(features, labels, mode):
        # Input Layer
        input_layer = tf.reshape(features, [-1, 40, 40, 1])

        # Convolutional Layer #1
        conv1 = tf.layers.conv2d(
                inputs=input_layer,
                filters=32,
                kernel_size=[5, 5],
                #  To specify that the output tensor should have the same width and height values as the input tensor
                # value can be "same" ou "valid"
                padding="same",
                activation=tf.nn.relu)

        # Pooling Layer #1
        pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

        # Convolutional Layer #2 and Pooling Layer #2
        conv2 = tf.layers.conv2d(
                inputs=pool1,
                filters=64,
                kernel_size=[5, 5],
                padding="same",
                activation=tf.nn.relu)
        pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

        # Dense Layer
        pool2_flat = tf.reshape(pool2, [-1, 10 * 10 * 64])
        dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
        dropout = tf.layers.dropout(
                inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)

        # Logits Layer
        logits = tf.layers.dense(inputs=dropout, units=2)

        predictions = {
            # Generate predictions (for PREDICT and EVAL mode)
            "classes":       tf.argmax(input=logits, axis=1),
            # Add `softmax_tensor` to the graph. It is used for PREDICT and by the
            # `logging_hook`.
            "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
        }

        if mode == tf.estimator.ModeKeys.PREDICT:
            return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

        # Calculate Loss (for both TRAIN and EVAL modes)
        loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

        # Configure the Training Op (for TRAIN mode)
        if mode == tf.estimator.ModeKeys.TRAIN:
            optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
            train_op = optimizer.minimize(
                    loss=loss,
                    global_step=tf.train.get_global_step())
            return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

        # Add evaluation metrics (for EVAL mode)
        eval_metric_ops = {
            "accuracy": tf.metrics.accuracy(
                    labels=labels, predictions=predictions["classes"])}
        return tf.estimator.EstimatorSpec(
                mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

У меня ошибка размера формы между метками и логитами:

InvalidArgumentError (трассировку см. выше): логиты и метки должны иметь одно и то же первое измерение, полученную форму логитов [3,2] и форму меток [1] ​​

filenames_array - это массив из 16 строк

["file1.png", "file2.png", "file3.png", ...]

и labels_array - это массив из 16 целых чисел

[0,0,1,1,0,1,0,0,0,...]

Основная функция:

# Create the Estimator
mnist_classifier = tf.estimator.Estimator(model_fn=cnn_model_fn, model_dir="/tmp/test_convnet_model")

# Train the model
cust_train_input_fn = lambda: train_input_fn_custom(
        filenames_array=filenames, labels_array=labels, batch_size=1)

mnist_classifier.train(
        input_fn=cust_train_input_fn,
        steps=20000,
        hooks=[logging_hook])

Я безуспешно пытался переделать логиты:

logits = tf.reshape (logits, [1, 2])

Мне нужна твоя помощь спасибо


ИЗМЕНИТЬ

По прошествии большего количества времени на поиск в первой строке моей модели функции

input_layer = tf.reshape(features, [-1, 40, 40, 1])

«-1», означающее, что размер партии будет вычисляться динамически, имеет здесь значение «3». Та же цифра 3, что и в моей ошибке: логиты и метки должны иметь одно и то же первое измерение, форму логитов [3,2] и форму меток [1] ​​

Если я установлю значение «1», у меня появится новая ошибка:

Входными данными для изменения формы является тензор с 4800 значениями, но запрошенная форма имеет 1600

Может проблема с моими функциями?


РЕДАКТИРОВАТЬ2:

полный код находится здесь: https://gist.github.com/geoffreyp/cc8e97aab1bff4d39e10001118c6322e


РЕДАКТИРОВАТЬ3

Я обновил суть

logits = tf.layers.dense(inputs=dropout, units=1)

https://gist.github.com/geoffreyp/cc8e97aab1bff4d39e10001118c6322e

Но я не совсем понимаю ваш ответ о размере партии, как здесь размер партии может быть 3, тогда как я выбираю размер партии 1?

Если я выберу batch_size = 3, у меня будет такая ошибка: логиты и метки должны иметь одно и то же первое измерение, форму логитов [9,1] и форму меток [3]

Я попытался изменить форму ярлыков:

labels = tf.reshape(labels, [3, 1])

и обновил структуру функций и меток:

    filenames_train = [['blackcorner-data/1.png', 'blackcorner-data/2.png', 'blackcorner-data/3.png',
                   'blackcorner-data/4.png', 'blackcorner-data/n1.png'],
                   ['blackcorner-data/n2.png',
                   'blackcorner-data/n3.png', 'blackcorner-data/n4.png',
                   'blackcorner-data/11.png', 'blackcorner-data/21.png'],
                   ['blackcorner-data/31.png',
                   'blackcorner-data/41.png', 'blackcorner-data/n11.png', 'blackcorner-data/n21.png',
                   'blackcorner-data/n31.png']
                   ]

labels = [[0, 0, 0, 0, 1], [1, 1, 1, 0, 0], [0, 0, 1, 1, 1]]

но безуспешно ...


person Geoffrey Pruvost    schedule 07.03.2018    source источник


Ответы (5)


Проблема заключается в вашей целевой форме и связана с правильным выбором подходящей функции потерь. у вас есть 2 возможности:

1. возможность: если у вас есть 1D целочисленная цель, вы можете использовать sparse_categorical_crossentropy в качестве функции потерь

n_class = 3
n_features = 100
n_sample = 1000

X = np.random.randint(0,10, (n_sample,n_features))
y = np.random.randint(0,n_class, n_sample)

inp = Input((n_features,))
x = Dense(128, activation='relu')(inp)
out = Dense(n_class, activation='softmax')(x)

model = Model(inp, out)
model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
history = model.fit(X, y, epochs=3)

2. возможность: если у вас есть горячая кодировка вашей цели, чтобы иметь 2D-форму (n_samples, n_class), вы можете использовать categorical_crossentropy

n_class = 3
n_features = 100
n_sample = 1000

X = np.random.randint(0,10, (n_sample,n_features))
y = pd.get_dummies(np.random.randint(0,n_class, n_sample)).values

inp = Input((n_features,))
x = Dense(128, activation='relu')(inp)
out = Dense(n_class, activation='softmax')(x)

model = Model(inp, out)
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
history = model.fit(X, y, epochs=3)
person Marco Cerliani    schedule 09.06.2020

Я решил, что он изменился с sparse_categorical_crossentropy на categorical_crossentropy, и теперь все работает нормально.

person Raevel    schedule 07.05.2020
comment
Это мне помогло. Я тоже не знаю почему. - person T3rm1; 24.05.2020
comment
Вот объяснение: stackoverflow.com/questions/49161174/ - person Marco Cerliani; 09.06.2020

У меня уже была эта проблема в первый раз, когда я использовал тензорный поток, я понял, что моя проблема заключалась в том, что я забыл добавить атрибут class_mode='sparse' / class_mode='binary' к функции, которая загружает данные обучения и данные проверки:

Так что постарайтесь присмотреть за опцией class_mode

image_gen_val = ImageDataGenerator(rescale=1./255)
val_data_gen = image_gen_val.flow_from_directory(batch_size=batch_size,
                                                 directory=val_dir,
                                                 target_size=(IMG_SHAPE, IMG_SHAPE),
                                                 class_mode='sparse')
person Yassine Birouk    schedule 30.05.2020

Форма вашего логита выглядит правильно, размер пакета 3, а выходной слой размера 2, который вы определили как свой выходной слой. Ваши ярлыки также должны иметь форму [3, 2]. Партия из 3, и каждая партия имеет 2 [1,0] или [0,1].

Также обратите внимание, что когда у вас есть логический вывод классификации, у вас не должно быть 2 нейронов на уровне вывода / логитов. Вы можете просто вывести одно значение, которое принимает 0 или 1, вы, вероятно, увидите, как 2 выхода [1,0] и [0,1] являются избыточными и могут быть выражены как простое значение [0 | 1]. Также вы, как правило, получаете лучшие результаты, когда делаете это таким образом.

Таким образом, ваши логиты должны быть [3,1], а ваши метки должны быть массивом из 3 значений, по одному для каждого из образцов в вашем пакете.

person David Parks    schedule 09.03.2018
comment
Я обновил свой вопрос, я не совсем понимаю ваш ответ о размере партии, как размер партии может быть здесь 3, тогда как я выбираю размер партии 1? - person Geoffrey Pruvost; 11.03.2018

У меня была аналогичная проблема, и оказалось, что один слой объединения не был правильно изменен. В моем случае я неправильно использовал tf.reshape(pool, shape=[-1, 64 * 7 * 7]) вместо tf.reshape(pool, shape=[-1, 64 * 14 * 14]), что привело к аналогичному сообщению об ошибках в логитах и ​​метках. Изменение факторов, например tf.reshape(pool, shape=[-1, 64 * 12 * 12]) приведет к совершенно другому, менее вводящему в заблуждение сообщению об ошибке.

Возможно, здесь тоже так. На всякий случай рекомендую пройтись по коду, проверяя формы узлов.

person Eric    schedule 20.03.2018