Неожиданные результаты при использовании tfrecords, загруженных с помощью tf.data.Dataset.list_files() с аргументом shuffle

#python #tensorflow #tfrecord

#python #тензорный поток #tfrecord

Вопрос:

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

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

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

tensorflow== 1.13.1, keras==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)
  

Комментарии:

1. Смог ответить на мой собственный вопрос — на самом деле это было связано с Y = [y[0] for _ in range(steps) for y in sess.run(Y)] тем, что это был отдельный и независимый вызов