Làm cách nào để * thực sự * đọc dữ liệu CSV trong TensorFlow?


83

Tôi còn khá mới mẻ với thế giới TensorFlow và khá bối rối trước cách bạn thực sự đọc dữ liệu CSV thành một ví dụ / bộ căng nhãn có thể sử dụng trong TensorFlow. Ví dụ từ hướng dẫn TensorFlow về cách đọc dữ liệu CSV khá phân mảnh và chỉ giúp bạn có được một phần cách để có thể đào tạo về dữ liệu CSV.

Đây là mã của tôi mà tôi đã ghép lại với nhau, dựa trên hướng dẫn 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")

Và đây là một ví dụ ngắn gọn từ tệp CSV mà tôi đang tải - dữ liệu khá cơ bản - 4 cột tính năng và 1 cột nhãn:

0,0,0,0,0
0,15,0,0,0
0,30,0,0,0
0,45,0,0,0

Tất cả những gì đoạn mã trên làm là in từng ví dụ từ tệp CSV, từng ví dụ một , mặc dù đẹp nhưng lại khá vô dụng cho việc đào tạo.

Điều tôi đang gặp khó khăn ở đây là cách bạn thực sự biến những ví dụ riêng lẻ đó, được tải từng cái một, thành một tập dữ liệu đào tạo. Ví dụ: đây là một cuốn sổ ghi chép tôi đang làm trong khóa học Học sâu của Udacity. Về cơ bản, tôi muốn lấy dữ liệu CSV mà tôi đang tải và chuyển nó vào một cái gì đó như train_datasettrain_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)

Tôi đã thử sử dụng tf.train.shuffle_batch, như thế này, nhưng nó chỉ bị treo một cách không thể giải thích được:

  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)

Tóm lại, đây là những câu hỏi của tôi:

  • Tôi còn thiếu gì về quy trình này?
    • Có vẻ như có một trực giác quan trọng nào đó mà tôi đang thiếu về cách xây dựng đường ống đầu vào đúng cách.
  • Có cách nào để tránh phải biết độ dài của tệp CSV không?
    • Có cảm giác khá không phù hợp khi phải biết số dòng bạn muốn xử lý ( for i in range(file_length)dòng mã ở trên)

Chỉnh sửa: Ngay sau khi Yaroslav chỉ ra rằng tôi có khả năng trộn lẫn các phần bắt buộc và xây dựng đồ thị ở đây, nó bắt đầu trở nên rõ ràng hơn. Tôi đã có thể tập hợp mã sau đây, mà tôi nghĩ gần giống với những gì thường làm khi đào tạo một mô hình từ CSV (không bao gồm bất kỳ mã đào tạo mô hình nào):

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) 

Tôi đã thử mã của bạn, nhưng không thể làm cho nó hoạt động. Có điều gì tôi đang thiếu mà bạn xác định? Cảm ơn. Tôi đã đăng một chủ đề ở đây để bạn có thể biết thêm chi tiết: stackoverflow.com/questions/40143019/…
Liên kết

Câu trả lời:


24

Tôi nghĩ rằng bạn đang trộn lẫn các phần bắt buộc và xây dựng đồ thị ở đây. Thao tác này tf.train.shuffle_batchtạo ra một nút hàng đợi mới và một nút duy nhất có thể được sử dụng để xử lý toàn bộ tập dữ liệu. Vì vậy, tôi nghĩ rằng bạn đang bị treo bởi vì bạn đã tạo một loạt các shuffle_batchhàng đợi trong vòng lặp for của mình và không bắt đầu các trình chạy hàng đợi cho chúng.

Việc sử dụng đường ống đầu vào bình thường trông như thế này:

  1. Thêm các nút thích shuffle_batchvào đường dẫn đầu vào
  2. (tùy chọn, để ngăn việc sửa đổi biểu đồ không chủ ý) hoàn thiện biểu đồ

--- kết thúc xây dựng đồ thị, bắt đầu lập trình mệnh lệnh -

  1. tf.start_queue_runners
  2. while(True): session.run()

Để có thể mở rộng hơn (để tránh Python GIL), bạn có thể tạo tất cả dữ liệu của mình bằng cách sử dụng đường ống TensorFlow. Tuy nhiên, nếu hiệu suất không quan trọng, bạn có thể kết nối một mảng numpy với một đường dẫn đầu vào bằng cách sử dụng slice_input_producer.Đây là một ví dụ với một số Printnút để xem điều gì đang xảy ra (thông báo Printsẽ được chuyển đến stdout khi nút được chạy)

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."

Bạn sẽ thấy một cái gì đó như thế này

[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
[[0 1]
 [2 3]]
[[4 5]
 [6 7]]
No more inputs.

Các số "8, 9" không có đầy đủ lô, vì vậy chúng không được sản xuất. Cũng tf.Printđược in sang sys.stdout, vì vậy chúng hiển thị riêng trong Terminal cho tôi.

Tái bút: kết nối tối thiểu batchvới hàng đợi được khởi tạo thủ công nằm trong vấn đề github 2193

Ngoài ra, với mục đích gỡ lỗi, bạn có thể muốn thiết lập timeouttrên phiên của mình để sổ ghi chép IPython của bạn không bị treo trên các hàng đợi trống. Tôi sử dụng chức năng trợ giúp này cho các phiên của mình

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

Ghi chú về khả năng mở rộng:

  1. tf.constantnội tuyến bản sao dữ liệu của bạn vào Biểu đồ. Có giới hạn cơ bản là 2GB về kích thước của định nghĩa Biểu đồ, vì vậy đó là giới hạn trên về kích thước dữ liệu
  2. Bạn có thể nhận được xung quanh giới hạn đó bằng cách sử dụng v=tf.Variablevà lưu dữ liệu vào đó bằng cách chạy v.assign_opvới một tf.placeholderbên cánh tay phải và ăn mảng NumPy để giữ chỗ ( feed_dict)
  3. Điều đó vẫn tạo ra hai bản sao dữ liệu, do đó, để tiết kiệm bộ nhớ, bạn có thể tạo phiên bản của riêng mình slice_input_producerđể hoạt động trên các mảng không rõ ràng và tải lên từng hàng một bằng cách sử dụngfeed_dict

2
À, vâng! Bạn hoàn toàn đúng - ngay khi bạn nói: "Tôi nghĩ bạn đang trộn lẫn các phần bắt buộc và xây dựng đồ thị ở đây", tôi bắt đầu thấy mình đã sai ở đâu. Tôi đã đăng một bản chỉnh sửa cho câu hỏi của mình bao gồm mã mới nhất mà tôi đã tổng hợp lại, điều này thực sự đưa tôi đến gần hơn với những gì tôi muốn - Tôi có thể đọc thành công dữ liệu CSV và kết hợp nó theo cách mà tôi có thể đào tạo mô hình.
Cướp

2
Tôi khuyên bạn nên cập nhật câu trả lời này để nó hoạt động với các phiên bản gần đây của TensorFlow: thay thế tf.slice_input_producer()bằng tf.train.slice_input_producer()(và tương tự cho một số chức năng khác). Và cũng thêm sess.run(tf.initialize_local_variables())sau sess.run(tf.initialize_all_variables()).
MiniQuark

Một số thay đổi khác cần thực hiện: pack()hiện tại stack(), và initialize_all_variables()nên được thay thế bằng global_variables_initializer()local_variables_initializer().
MiniQuark

Với tensorflow 1.0.1, bạn cần khởi tạo các biến cục bộ và toàn cục như tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()).run(). Bạn sẽ cần khởi tạo các biến cục bộ vì bạn đang sử dụng num_epochs và theo tài liệu "Lưu ý: nếu num_epochskhông None, hàm này tạo bộ đếm cục bộ epochs."
Bruno R. Cardoso

13

Hoặc bạn có thể thử điều này, mã tải tập dữ liệu Iris vào tensorflow bằng cách sử dụng gấu trúc và numpy và một đầu ra nơ-ron đơn giản được in trong phiên. Hy vọng nó sẽ giúp bạn hiểu cơ bản .... [Tôi đã không thêm cách của một nhãn giải mã nóng].

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)

Đây là bài học rất, nhưng nếu tôi hiểu đúng nó không hiển thị cách sử dụng các dữ liệu cho đào tạo ...
dividebyzero

vâng, tôi sẽ thêm chúng sớm ... Nó phải là tầm thường phải không .... tính toán sự mất mát, chạy anaway ưu tôi sẽ thêm chúng sớm
Nagarjun Gururaj

2
Xin chào chiabyzero, xin lỗi tôi đến muộn! Tôi tìm thấy một liên kết mà là thú vị và thực sự giúp giảm bớt các vấn đề tensorflow.org/tutorials/tflearn .... Ở đây bạn có thể tải các tập tin csv, đào tạo họ, thực hiện phân loại ...
Nagarjun Gururaj

@NagarjunGururaj Tôi có thể sử dụng tập dữ liệu được tạo bởi Contrib_learn trong quy trình tensorflow bình thường không?
Jay Wong,

tập dữ liệu nào? Ý bạn là Iris hay bất kỳ người nào khác?
Nagarjun Gururaj

2

Bạn có thể sử dụng API tf.data mới nhất:

dataset = tf.contrib.data.make_csv_dataset(filepath)
iterator = dataset.make_initializable_iterator()
columns = iterator.get_next()
with tf.Session() as sess:
   sess.run([iteator.initializer])

2

Nếu có ai đó đến đây để tìm kiếm một cách đơn giản để đọc các tệp CSV hoàn toàn lớn và bị phân mảnh trong API tf.estimator, vui lòng xem bên dưới mã của tôi

CSV_COLUMNS = ['ID','text','class']
LABEL_COLUMN = 'class'
DEFAULTS = [['x'],['no'],[0]]  #Default values

def read_dataset(filename, mode, batch_size = 512):
    def _input_fn(v_test=False):
#         def decode_csv(value_column):
#             columns = tf.decode_csv(value_column, record_defaults = DEFAULTS)
#             features = dict(zip(CSV_COLUMNS, columns))
#             label = features.pop(LABEL_COLUMN)
#             return add_engineered(features), label

        # Create list of files that match pattern
        file_list = tf.gfile.Glob(filename)

        # Create dataset from file list
        #dataset = tf.data.TextLineDataset(file_list).map(decode_csv)
        dataset = tf.contrib.data.make_csv_dataset(file_list,
                                                   batch_size=batch_size,
                                                   column_names=CSV_COLUMNS,
                                                   column_defaults=DEFAULTS,
                                                   label_name=LABEL_COLUMN)

        if mode == tf.estimator.ModeKeys.TRAIN:
            num_epochs = None # indefinitely
            dataset = dataset.shuffle(buffer_size = 10 * batch_size)
        else:
            num_epochs = 1 # end-of-input after this

        batch_features, batch_labels = dataset.make_one_shot_iterator().get_next()

        #Begins - Uncomment for testing only -----------------------------------------------------<
        if v_test == True:
            with tf.Session() as sess:
                print(sess.run(batch_features))
        #End - Uncomment for testing only -----------------------------------------------------<
        return add_engineered(batch_features), batch_labels
    return _input_fn

Ví dụ sử dụng trong TF.estimator:

train_spec = tf.estimator.TrainSpec(input_fn = read_dataset(
                                                filename = train_file,
                                                mode = tf.estimator.ModeKeys.TRAIN,
                                                batch_size = 128), 
                                      max_steps = num_train_steps)

0

2.0 Giải pháp tương thích : Câu trả lời này có thể được cung cấp bởi những người khác trong chuỗi trên nhưng tôi sẽ cung cấp các liên kết bổ sung sẽ giúp ích cho cộng đồng.

dataset = tf.data.experimental.make_csv_dataset(
      file_path,
      batch_size=5, # Artificially small to make examples easier to show.
      label_name=LABEL_COLUMN,
      na_value="?",
      num_epochs=1,
      ignore_errors=True, 
      **kwargs)

Để biết thêm thông tin, vui lòng tham khảo Hướng dẫn Tensorflow này .


1
Tôi thấy câu trả lời này (và hướng dẫn và tài liệu) hoàn toàn bực bội. Nó vẫn chỉ đạt được "một phần của cách có thể đào tạo trên dữ liệu CSV" theo lời của OP. Nó tạo ra một "tập dữ liệu" (nhưng kiểu gì - nó thậm chí là tf.data.Dataset? Tài liệu không rõ ràng) và có vẻ như tập dữ liệu là hướng cột chứ không phải hướng hàng. Hầu hết các mô hình cần hàng loạt hàng được chuyển cho họ để đào tạo - làm thế nào để đạt được bước này? Tôi đã hỏi câu hỏi này để tìm kiếm một ví dụ từ đầu đến cuối.
omatai

Vui lòng cung cấp ví dụ từ đầu đến cuối của make_csv_dataset thay vì chỉ đặt một tài liệu cấp độ trừu tượng!
DevLoverUmar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.