Модель TensorFlow получает нулевые потери

import tensorflow as tf
import numpy as np
import os
import re
import PIL


def read_image_label_list(img_directory, folder_name):
    # Input:
    #   -Name of folder (test\\\\train)
    # Output:
    #   -List of names of files in folder
    #   -Label associated with each file

    cat_label = 1
    dog_label = 0
    filenames = []
    labels = []

    dir_list = os.listdir(os.path.join(img_directory, folder_name))  # List of all image names in 'folder_name' folder

    # Loop through all images in directory
    for i, d in enumerate(dir_list):
        if re.search("train", folder_name):
            if re.search("cat", d):  # If image filename contains 'Cat', then true
                labels.append(cat_label)
            else:
                labels.append(dog_label)
        filenames.append(os.path.join(img_dir, folder_name, d))

    return filenames, labels


# Define convolutional layer
def conv_layer(input, channels_in, channels_out):
    w_1 = tf.get_variable("weight_conv", [5,5, channels_in, channels_out], initializer=tf.contrib.layers.xavier_initializer())
    b_1 = tf.get_variable("bias_conv", [channels_out], initializer=tf.zeros_initializer())
    conv = tf.nn.conv2d(input, w_1, strides=[1,1,1,1], padding="SAME")
    activation = tf.nn.relu(conv + b_1)
    return activation


# Define fully connected layer
def fc_layer(input, channels_in, channels_out):
    w_2 = tf.get_variable("weight_fc", [channels_in, channels_out], initializer=tf.contrib.layers.xavier_initializer())
    b_2 = tf.get_variable("bias_fc", [channels_out], initializer=tf.zeros_initializer())
    activation = tf.nn.relu(tf.matmul(input, w_2) + b_2)
    return activation


# Define parse function to make input data to decode image into
def _parse_function(img_path, label):
    img_file = tf.read_file(img_path)
    img_decoded = tf.image.decode_image(img_file, channels=3)
    img_decoded.set_shape([None,None,3])
    img_decoded = tf.image.resize_images(img_decoded, (28, 28), method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
    img_decoded = tf.image.per_image_standardization(img_decoded)
    img_decoded = tf.cast(img_decoded, dty=tf.float32)
    label = tf.one_hot(label, 1)
    return img_decoded, label


tf.reset_default_graph()

# Define parameterspe
EPOCHS = 10
BATCH_SIZE_training = 64
learning_rate = 0.001
img_dir = 'C:/Users/tharu/PycharmProjects/cat_vs_dog/data'
batch_size = 128

# Define data
features, labels = read_image_label_list(img_dir, "train")

# Define dataset
dataset = tf.data.Dataset.from_tensor_slices((features, labels))  # Takes slices in 0th dimension
dataset = dataset.map(_parse_function)
dataset = dataset.batch(batch_size)
iterator = dataset.make_initializable_iterator()

# Get next batch of data from iterator
x, y = iterator.get_next()

# Create the network (use different variable scopes for reuse of variables)
with tf.variable_scope("conv1"):
    conv_1 = conv_layer(x, 3, 32)
    pool_1 = tf.nn.max_pool(conv_1, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")

with tf.variable_scope("conv2"):
    conv_2 = conv_layer(pool_1, 32, 64)
    pool_2 = tf.nn.max_pool(conv_2, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")
    flattened = tf.contrib.layers.flatten(pool_2)

with tf.variable_scope("fc1"):
    fc_1 = fc_layer(flattened, 7*7*64, 1024)
with tf.variable_scope("fc2"):
    logits = fc_layer(fc_1, 1024, 1)


# Define loss function
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=tf.cast(y, dtype=tf.int32)))

# Define optimizer
train = tf.train.AdamOptimizer(learning_rate).minimize(loss)


with tf.Session() as sess:
    # Initiliaze all the variables
    sess.run(tf.global_variables_initializer())

    # Train the network
    for i in range(EPOCHS):
        # Initialize iterator so that it starts at beginning of training set for each epoch
        sess.run(iterator.initializer)
        print("EPOCH", i)
        while True:
            try:
                _, epoch_loss = sess.run([train, loss])

            except tf.errors.OutOfRangeError:  # Error given when out of data
                if i % 2 == 0:
                    # [train_accuaracy] = sess.run([accuracy])
                    # print("Step ", i, "training accuracy = %{}".format(train_accuaracy))
                    print(epoch_loss)
                break

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

  • Features = список местоположений файлов для каждого изображения (например, ['\ data \ train \ cat.0.jpg', /data\train\cat.1.jpg])
  • Ярлыки = [размер партии, 1] вектор one_hot

Сначала я подумал, что что-то не так с моими данными. Но я просмотрел данные после изменения размера, и изображения кажутся нормальными.

Затем я попробовал несколько разных функций потерь, потому что подумал, что, может быть, я неправильно понимаю, что делает функция тензорного потока softmax_cross_entropy, но это ничего не исправило.

Я пробовал запустить только раздел «logits», чтобы посмотреть, каков результат. Это всего лишь небольшой пример, и цифры мне кажутся хорошими:

 [[0.06388957]
 [0.        ]
 [0.16969752]
 [0.24913025]
 [0.09961276]]

Конечно, тогда функция softmax_cross_entropy должна быть способна вычислить эту потерю, учитывая, что соответствующие метки равны 0 или 1? Я не уверен, что что-то упускаю. Любая помощь будет принята с благодарностью.


person Tharuka Devendra    schedule 19.04.2018    source источник


Ответы (1)


Как задокументировано:

logits и labels должны иметь одинаковую форму, например [batch_size, num_classes] и того же типа dtype (float16, float32 или float64).

Поскольку вы упомянули, что ваша метка - «[размер_пакета, 1] вектор one_hot», я предполагаю, что ваши logits и labels имеют форму [размер_пакета, 1]. Это обязательно приведет к нулевым потерям. Концептуально говоря, у вас есть только 1 класс (num_classes=1), и вы не можете ошибаться (loss=0).

Так что, по крайней мере для вас labels, вы должны преобразовать его: tf.one_hot(indices=labels, depth=num_classes). Ваш прогноз logits также должен иметь форму [batch_size, num_classes].

В качестве альтернативы вы можете использовать sparse_softmax_cross_entropy_with_logits, где:

Типичный вариант использования - иметь логиты формы [batch_size, num_classes] и метки формы [batch_size]. Но поддерживаются более высокие размеры.

person Y. Luo    schedule 19.04.2018
comment
Спасибо! Это устранило проблему. Моя следующая проблема в том, что сейчас убыток, кажется, совсем не снижается. Я изменил его так, что метки теперь [batch_size, num_classes], а выходы [batch_size, num_classes]. Моя функция ошибки неверна? - person Tharuka Devendra; 20.04.2018
comment
@TharukaDevendra Хотя мне это кажется правильным, никто не может быть уверен, пока не увидит полный код. Может быть, вы сможете открыть новый вопрос с помощью своего нового MCVE, чтобы люди могли помочь с лучшей идеей? - person Y. Luo; 20.04.2018