Неожиданные результаты при использовании tfrecords, загруженных с использованием tf.data.Dataset.list_files () с аргументом shuffle - PullRequest
1 голос
/ 22 апреля 2019

Я надеюсь получить разъяснение о том, как работает аргумент shuffle в tf.data.Dataset.list_files(). В документации говорится, что при shuffle=True имена файлов будут случайным образом перемешиваться. Я сделал модельные прогнозы, используя набор данных tfrecords, который был загружен с использованием tf.data.Dataset.list_files(), и я ожидал, что метрика точности будет одинаковой независимо от порядка файлов (т. Е. Будет ли shuffle True или False), но вижу иначе.

Это ожидаемое поведение или что-то не так с моим кодом или интерпретацией? У меня есть воспроизводимый пример кода ниже.

Как ни странно, до тех пор, пока tf.random.set_random_seed() установлен изначально (и кажется, что даже не имеет значения, какое начальное значение установлено), результаты прогнозов остаются одинаковыми, независимо от того, является ли случайное значение истинным или ложным в list_files() .

тензор потока == 1.13.1, керас == 2.2.4

Спасибо за любые разъяснения!

Редактировать: переосмыслить и задаться вопросом, является ли Y = [y[0] for _ in range(steps) for y in sess.run(Y)] отдельным и независимым вызовом?

# Fit and Save a Dummy Model
import numpy as np
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from sklearn import datasets, metrics

seed = 7
np.random.seed(seed)
tf.random.set_random_seed(seed)

dataset = datasets.load_iris()

X = dataset.data
Y = dataset.target
dummy_Y = np_utils.to_categorical(Y)

# 150 rows
print(len(X))

model = Sequential()
model.add(Dense(8, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, dummy_Y, epochs=10, batch_size=10,  verbose=2)
model.save('./iris/iris_model')

predictions = model.predict(X)
predictions = np.argmax(predictions, axis=1)

# returns accuracy = 0.3466666666666667
print(metrics.accuracy_score(y_true=Y, y_pred=predictions))

Разделить набор данных на несколько файлов tfrecords, чтобы мы могли перезагрузить его с помощью list_files () позже:

numrows = 15
for i, j in enumerate(range(0, len(X), numrows)):
    with tf.python_io.TFRecordWriter('./iris/iris{}.tfrecord'.format(i)) as writer:
        for x, y in zip(X[j:j+numrows, ], Y[j:j+numrows, ]):
            features = tf.train.Features(feature=
                {'X': tf.train.Feature(float_list=tf.train.FloatList(value=x)), 
                'Y': tf.train.Feature(int64_list=tf.train.Int64List(value=[y]))
                })
            example = tf.train.Example(features=features)
            writer.write(example.SerializeToString())

На этом этапе я выхожу (ipython) и перезапускаюсь снова:

import numpy as np
import tensorflow as tf
from keras.models import load_model
from sklearn import metrics

model = load_model('./iris/iris_model')

batch_size = 10
steps = int(150/batch_size)
file_pattern = './iris/iris*.tfrecord'

feature_description = {
    'X': tf.FixedLenFeature([4], tf.float32),
    'Y': tf.FixedLenFeature([1], tf.int64)
}

def _parse_function(example_proto):
    return tf.parse_single_example(example_proto, feature_description)

def load_data(filenames, batch_size):
    raw_dataset = tf.data.TFRecordDataset(filenames)
    dataset = raw_dataset.map(_parse_function)
    dataset = dataset.batch(batch_size, drop_remainder=True)
    dataset = dataset.prefetch(2)
    iterator = dataset.make_one_shot_iterator()
    record = iterator.get_next()
    return record['X'], record['Y']

def get_predictions_accuracy(filenames):
    X, Y = load_data(filenames=filenames, batch_size=batch_size)

    predictions = model.predict([X], steps=steps)
    predictions = np.argmax(predictions, axis=1)
    print(len(predictions))

    with tf.Session() as sess:
        Y = [y[0] for _ in range(steps) for y in sess.run(Y)]

    print(metrics.accuracy_score(y_true=Y, y_pred=predictions))
# No shuffle results:
# Returns expected accuracy = 0.3466666666666667
filenames_noshuffle = tf.data.Dataset.list_files(file_pattern=file_pattern, shuffle=False)
get_predictions_accuracy(filenames_noshuffle)
# Shuffle results, no seed value set:
# Returns UNEXPECTED accuracy (non-deterministic value)
filenames_shuffle_noseed = tf.data.Dataset.list_files(file_pattern=file_pattern, shuffle=True)
get_predictions_accuracy(filenames_shuffle_noseed)
# Shuffle results, seed value set:
# Returns expected accuracy = 0.3466666666666667
# It seems like it doesn't even matter what seed value you set, as long as you you set it
seed = 1000
tf.random.set_random_seed(seed)
filenames_shuffle_seed = tf.data.Dataset.list_files(file_pattern=file_pattern, shuffle=True)
get_predictions_accuracy(filenames_shuffle_seed)
...