Как* на самом деле * читать данные CSV в TensorFlow?
Я относительно новичок в мире тензорного потока, и довольно озадачен тем, как вы бы на самом деле прочитайте данные CSV в полезный пример / тензоры меток в TensorFlow. Пример из TensorFlow учебное пособие по чтению в формате CSV данных довольно фрагментирован и только дает вам часть пути к тому, чтобы иметь возможность тренироваться на данных CSV.
вот мой код, который я собрал вместе, основываясь на этом учебнике CSV:
from __future__ import print_function
import tensorflow as tf
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
filename = "csv_test_data.csv"
# setup text reader
file_length = file_len(filename)
filename_queue = tf.train.string_input_producer([filename])
reader = tf.TextLineReader(skip_header_lines=1)
_, csv_row = reader.read(filename_queue)
# setup CSV decoding
record_defaults = [[0],[0],[0],[0],[0]]
col1,col2,col3,col4,col5 = tf.decode_csv(csv_row, record_defaults=record_defaults)
# turn features back into a tensor
features = tf.stack([col1,col2,col3,col4])
print("loading, " + str(file_length) + " line(s)n")
with tf.Session() as sess:
tf.initialize_all_variables().run()
# start populating filename queue
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(file_length):
# retrieve a single instance
example, label = sess.run([features, col5])
print(example, label)
coord.request_stop()
coord.join(threads)
print("ndone loading")
и здесь это краткий пример из файла CSV, который я загружаю-довольно основные данные - 4 столбца функций и 1 столбец меток:
0,0,0,0,0
0,15,0,0,0
0,30,0,0,0
0,45,0,0,0
все код выше делает это печать каждого примера из файла CSV, один за другим, что, хотя и приятно, довольно бесполезно для обучения.
то, с чем я борюсь здесь,-это то, как вы на самом деле превратите эти отдельные примеры, загруженные один за другим, в набор данных для обучения. Например, вот записная книжка я работал на курсе глубокого обучения Udacity. Я в основном хочу взять данные CSV, которые я загружаю, и плюхнуть его в что-то вроде train_dataset и train_labels:
def reformat(dataset, labels):
dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)
# Map 2 to [0.0, 1.0, 0.0 ...], 3 to [0.0, 0.0, 1.0 ...]
labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)
return dataset, labels
train_dataset, train_labels = reformat(train_dataset, train_labels)
valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)
test_dataset, test_labels = reformat(test_dataset, test_labels)
print('Training set', train_dataset.shape, train_labels.shape)
print('Validation set', valid_dataset.shape, valid_labels.shape)
print('Test set', test_dataset.shape, test_labels.shape)
Я пробовал использовать tf.train.shuffle_batch
, как это, но он просто необъяснимо висит:
for i in range(file_length):
# retrieve a single instance
example, label = sess.run([features, colRelevant])
example_batch, label_batch = tf.train.shuffle_batch([example, label], batch_size=file_length, capacity=file_length, min_after_dequeue=10000)
print(example, label)
Итак, чтобы подвести итог, вот мои вопросы:
-
что мне не хватает в этом процессе?
- похоже, что есть какая-то ключевая интуиция что мне не хватает о том, как правильно построить входной трубопровод.
-
есть ли способ избежать необходимости знать длину файла CSV?
- он чувствует себя довольно неэлегантно, чтобы знать количество строк, которые вы хотите обработать (
for i in range(file_length)
строка кода выше)
- он чувствует себя довольно неэлегантно, чтобы знать количество строк, которые вы хотите обработать (
Edit: Как только Ярослав указал, что я, скорее всего, перепутал императив и построение графика части здесь, это начало становиться яснее. Я смог собрать следующий код, который, я думаю, ближе к тому, что обычно делается при обучении модели из CSV (исключая любой код обучения модели):
from __future__ import print_function
import numpy as np
import tensorflow as tf
import math as math
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('dataset')
args = parser.parse_args()
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
def read_from_csv(filename_queue):
reader = tf.TextLineReader(skip_header_lines=1)
_, csv_row = reader.read(filename_queue)
record_defaults = [[0],[0],[0],[0],[0]]
colHour,colQuarter,colAction,colUser,colLabel = tf.decode_csv(csv_row, record_defaults=record_defaults)
features = tf.stack([colHour,colQuarter,colAction,colUser])
label = tf.stack([colLabel])
return features, label
def input_pipeline(batch_size, num_epochs=None):
filename_queue = tf.train.string_input_producer([args.dataset], num_epochs=num_epochs, shuffle=True)
example, label = read_from_csv(filename_queue)
min_after_dequeue = 10000
capacity = min_after_dequeue + 3 * batch_size
example_batch, label_batch = tf.train.shuffle_batch(
[example, label], batch_size=batch_size, capacity=capacity,
min_after_dequeue=min_after_dequeue)
return example_batch, label_batch
file_length = file_len(args.dataset) - 1
examples, labels = input_pipeline(file_length, 1)
with tf.Session() as sess:
tf.initialize_all_variables().run()
# start populating filename queue
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
try:
while not coord.should_stop():
example_batch, label_batch = sess.run([examples, labels])
print(example_batch)
except tf.errors.OutOfRangeError:
print('Done training, epoch reached')
finally:
coord.request_stop()
coord.join(threads)
3 ответа:
я думаю,что вы смешиваете императивные и графические части здесь. Операция
tf.train.shuffle_batch
создает новый узел очереди, и один узел может быть использован для обработки всего набора данных. Так что я думаю, что вы висите, потому что вы создали кучуshuffle_batch
очереди в вашем цикле for и не запускали очереди для них.нормальное использование входного трубопровода выглядит следующим образом:
- добавить узлы, такие как
shuffle_batch
к входному трубопроводу- (опционально, в предотвратить непреднамеренное изменение графика) завершить график
--- конец построения графа, начало императивного программирования--
tf.start_queue_runners
while(True): session.run()
чтобы быть более масштабируемым (чтобы избежать Python GIL), вы можете генерировать все свои данные с помощью конвейера TensorFlow. Однако, если производительность не критична, вы можете подключить массив NumPy к входному трубопроводу с помощью
slice_input_producer.
вот пример с некоторыхtf.reset_default_graph() num_examples = 5 num_features = 2 data = np.reshape(np.arange(num_examples*num_features), (num_examples, num_features)) print data (data_node,) = tf.slice_input_producer([tf.constant(data)], num_epochs=1, shuffle=False) data_node_debug = tf.Print(data_node, [data_node], "Dequeueing from data_node ") data_batch = tf.batch([data_node_debug], batch_size=2) data_batch_debug = tf.Print(data_batch, [data_batch], "Dequeueing from data_batch ") sess = tf.InteractiveSession() sess.run(tf.initialize_all_variables()) tf.get_default_graph().finalize() tf.start_queue_runners() try: while True: print sess.run(data_batch_debug) except tf.errors.OutOfRangeError as e: print "No more inputs."
вы должны увидеть что-то вроде этого
[[0 1] [2 3] [4 5] [6 7] [8 9]] [[0 1] [2 3]] [[4 5] [6 7]] No more inputs.
номера "8, 9" не заполнили всю партию, поэтому они не были произведены. Также
tf.Print
печатаются в sys.stdout, поэтому они появляются отдельно в терминале для меня.PS: минимальное подключение
batch
чтобы вручную инициализированная очередь была в проблема github 2193кроме того, для целей отладки вы можете установить
timeout
на вашем сеансе, чтобы ваш ноутбук IPython не висел на пустых очередях. Я использую эту вспомогательную функцию для моих сессийdef create_session(): config = tf.ConfigProto(log_device_placement=True) config.gpu_options.per_process_gpu_memory_fraction=0.3 # don't hog all vRAM config.operation_timeout_in_ms=60000 # terminate on long hangs # create interactive session to register a default session sess = tf.InteractiveSession("", config=config) return sess
Примечания По Масштабируемости:
tf.constant
inlines копирование ваших данных в график. Существует фундаментальный предел 2 ГБ на размер определения графика, так что это верхний предел размера данных- вы могли бы обойти это ограничение с помощью
v=tf.Variable
и сохранение данных в там работаетv.assign_op
Сtf.placeholder
С правой стороны и подача массива numpy в заполнитель (feed_dict
)- это все еще создает две копии данных, так что для экономии памяти вы можете сделать свою собственную версию
slice_input_producer
который работает на массивах numpy и загружает строки по одному, используяfeed_dict
или вы можете попробовать это, код загружает набор данных Iris в tensorflow с помощью pandas и numpy, и в сеансе печатается простой выход одного нейрона. Надеюсь, это поможет для базового понимания.... [ Я не добавил способ одного горячего декодирования ярлыков].
import tensorflow as tf import numpy import pandas as pd df=pd.read_csv('/home/nagarjun/Desktop/Iris.csv',usecols = [0,1,2,3,4],skiprows = [0],header=None) d = df.values l = pd.read_csv('/home/nagarjun/Desktop/Iris.csv',usecols = [5] ,header=None) labels = l.values data = numpy.float32(d) labels = numpy.array(l,'str') #print data, labels #tensorflow x = tf.placeholder(tf.float32,shape=(150,5)) x = data w = tf.random_normal([100,150],mean=0.0, stddev=1.0, dtype=tf.float32) y = tf.nn.softmax(tf.matmul(w,x)) with tf.Session() as sess: print sess.run(y)