Tensorflow – чтение файлов
Содержание:
TensorFlow поддерживает чтение больших наборов данных таким образом, чтобы данные никогда не хранились в памяти полностью (было бы не очень хорошо, если бы он имел это ограничение).
Есть несколько функций и опций из стандартной библиотеки Python, которые вы можете использовать для решения этой задачи.
Более того, TensorFlow поддерживает создание произвольных обработчиков данных, и на это определенно стоит обратить внимание, если в своем проекте вы работаете с большим количеством данных. Написание собственной функции загрузки данных — это небольшое усилие с вашей стороны, которое может сэкономить много времени позже на проекте. Ознакомьтесь с официальной документацией для получения дополнительной информации по этой теме.
В этой статье мы рассмотрим основы чтения CSV-файла при помощи TensorFlow и использования этих данных в ваших графах.
Placeholder-ы
Самый простой способ чтения данных — просто прочитать их при помощи стандартного кода на Python. Давайте рассмотрим базовый пример и прочитаем данные из файла олимпийских игр 2016 года.
Первое, что мы сделаем, это создадим граф, который берет одну строку данных за другой и суммирует общие медали.
import tensorflow as tf
import urllib2, cStringIO
# URL csv файла
URL = 'https://storage.dev-ops-notes.ru/The_2016_Olympic_Games_medal.csv'
# Установим Uset-Agent и скачаем файл
opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
response = opener.open(URL)
# читаем содержимое csv файла
buf = cStringIO.StringIO(response.read())
# определяем placeholder-ы
# тензор, содержащий данные (gold, silver, bronze) для расчета
features = tf.placeholder(tf.int32, shape=[3], name='features')
# тензор, содержащий название страны
country = tf.placeholder(tf.string, name='country')
# операция расчета (в нашем случае суммирования тензора с данными)
total = tf.reduce_sum(features, name='total')
Далее определим новую операцию tf.Print(), которая будет суммировать и печатать общий результат сложения всех медалей (features).
printerop = tf.Print(total, [country, features, total], name='printer')
Что происходит, когда мы используем printerop? Эта переменная ссылается на функцию, которая регистрирует текущие значения, переданные ей во втором параметре (в данном случае список [country, features, total]) и возвращает их сумму, применяя к этому списку операцию total. Далее мы открываем сеанс для расчетов графа, открываем файл для чтения и передаем строки из файла функции printerop строка за строкой. Обратите внимание, что чтение файла выполняется исключительно средствами Python во время расчетов в сеансе.
line_count = 0
with tf.Session() as sess:
sess.run( tf.global_variables_initializer())
while True:
line = buf.readline().strip()
if len(line) == 0: break
if line_count == 0: # пропустим заголовок cvs файла
line_count += 1
continue
# Читаем данные для расчета, используя python, в переменную TensorFlow с именем features
country_name, code, gold, silver, bronze, total = line.strip().split(",")
gold = int(gold)
silver = int(silver)
bronze = int(bronze)
# Вызываем функцию Print, которая делает всю работу
total = sess.run(printerop, feed_dict={features: [gold, silver, bronze], country:country_name})
print(country_name, total)
line_count += 1
Результат исполнения этого кода будет выглядеть следующим образом:
Внутри цикла мы читаем файла файл построчно, разделяем каждую строку на элементы до каждой запятой, преобразуем значения в целые числа и затем передаем данные в файл feed_dict в качестве значений для placeholder-а.
При каждом вызове printerop в лог TensorFlow будет попадать строка вида, содержащая лог операции:
I tensorflow/core/kernels/logging_ops.cc:79] [\"France\"][10 18 14][42]
Результат же самой операции будет печататься на стандартный поток вывода функцией print (country_name, total), которая печатает текущее имя страны из Python переменной и результат работы printerop (сумма золотых, серебряных и бронзовых медалей).
Работа с данными в TensorFlow подобным образом является хорошей практикой: создайте placeholder-ы, в цикле загружайте немного данных в память, вычисляйте нужные вам значения и переходите к новой порции данными.
Чтение csv файлов в Tensorflow
TensorFlow поддерживает и непосредственное считывание данных в тензоры, однако работать с CSV форматом далеко не всегда удобно и приятно. Тем не менее, т.к. это довольно частый сценарий, давайте рассмотрим один из множества способ сделать это.
Суть подхода заключается в том, чтобы определить список имен файлов, из которых необходимо прочитать данные, затем создать функцию для чтения, которая будет позже вызываться в процессе работы сессии. Внутри функции для чтения нужно определить переменные, которые заменяются фактическими значениями, когда они выполняются на этапе выполнения графика.
def file_reader_func(filename_queue):
reader = tf.TextLineReader(skip_header_lines=1)
_, csv_row = reader.read(filename_queue)
record_defaults = [[""], [""], [0], [0], [0], [0]]
country, code, gold, silver, bronze, total = tf.decode_csv(csv_row, record_defaults=record_defaults)
features = tf.pack([gold, silver, bronze])
return features, country
Функция file_reader_func здесь принимает объект очереди, а не обычный список Python, поэтому нам нужно создать его перед тем, как передавать его в нашу функцию:
filename_queue = tf.train.string_input_producer(filenames, num_epochs=1, shuffle=False)
example, country = file_reader_func(filename_queue)
Результатом вызова функции file_reader_func будут значения каждой отдельной строки из нашего набора данных. Далее, т.к. файлов в наборе данных может быть несколько, нам потребуется координатор Coordinator , задачей которого будет переключение между файлами набора данных при чтении каждый раз, когда будут оцениваться значения переменных example и label.
with tf.Session() as sess:
tf.global_variables_initializer().run()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
while True:
try:
example_data, country_name = sess.run([example, country])
print(example_data, country_name)
except tf.errors.OutOfRangeError:
break
Цикл while будет обходить данные до тех пор, пока у нас не останется данных и не возникнет исключение OutOfRangeError.
При помощи этого кода мы теперь можем получить по одной строки из нашего набора данных и загружать их прямо в наш граф для последующей обработки. Существуют и другие функции для получения порций данных и их перемешивания (см. описание функций tf.train.string_input_producer и tf.train.shuffle_batch).