Mô hình NMT của tôi có 2 lớp, 512 đơn vị ẩn. Tôi đào tạo với độ dài câu tối đa = 50, kích thước lô = 32 và xem tốc độ tương tự giữa feed_dict và hàng đợi, khoảng 2400-2500 từ mục tiêu mỗi giây (tôi sử dụng chỉ số này cho tốc độ dựa trên số paper) này.
Tôi tìm thấy feed_dict rất trực quan và dễ sử dụng. Hàng đợi là khó khăn. Sử dụng hàng đợi, bạn phải:
1/Chuyển đổi dữ liệu của bạn thành tfrecords. Tôi thực sự gotta google một chút để hiểu làm thế nào để chuyển đổi dữ liệu seq2seq của tôi để tfrecords bởi vì các tài liệu không phải là rất hữu ích.
2/Giải mã dữ liệu của bạn từ tfrecords. Bạn sẽ tìm thấy các chức năng được sử dụng để tạo ra tfrecords và giải mã nó không trực quan phù hợp. Ví dụ: nếu mỗi ví dụ đào tạo của tôi có 3 chuỗi (chỉ 3 danh sách số nguyên) src_input, trg_input, trg_target
và tôi cũng muốn ghi lại độ dài của src_input
(một số phần tử của nó có thể là PADDING, vì vậy đừng tính), dưới đây là cách để tạo tfrecord từ mỗi ví dụ:
def _make_example(src_input, src_seq_length, trg_input, trg_seq_length, trg_target, target_weight):
context = tf.train.Features(
feature={
'src_seq_length': int64_feature(src_seq_length)
})
feature_lists = tf.train.FeatureLists(
feature_list={
'src_input': int64_featurelist(src_input),
'trg_input': int64_featurelist(trg_input),
'trg_target': int64_featurelist(trg_target)
})
return tf.train.SequenceExample(context=context, feature_lists=feature_lists)
Và dưới đây là cách để giải mã nó:
def _read_and_decode(filename_queue):
reader = tf.TFRecordReader(options=self.tfrecord_option)
_, serialized_ex = reader.read(filename_queue)
context_features = {
'src_seq_length': tf.FixedLenFeature([], dtype=tf.int64)
}
sequence_features = {
'src_input': tf.FixedLenSequenceFeature([], dtype=tf.int64),
'trg_input': tf.FixedLenSequenceFeature([], dtype=tf.int64),
'trg_target': tf.FixedLenSequenceFeature([], dtype=tf.int64)
}
context, sequences = tf.parse_single_sequence_example(
serialized_ex,
context_features=context_features,
sequence_features=sequence_features)
src_seq_length = tf.cast(context['src_seq_length'], tf.int32)
src_input = tf.cast(sequences['src_input'], tf.int32)
trg_input = tf.cast(sequences['trg_input'], tf.int32)
trg_target = tf.cast(sequences['trg_target'], tf.int32)
return src_input, src_seq_length, trg_input, trg_target
Và để tạo ra mỗi tính năng tfrecord/featurelist:
def int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def int64_featurelist(l):
feature = [tf.train.Feature(int64_list=tf.train.Int64List(value=[x])) for x in l]
return tf.train.FeatureList(feature=feature)
3/Thiết lập tàu/dev. Tôi tin rằng đó là một thực tế phổ biến để định kỳ đào tạo mô hình của bạn trong một thời gian, sau đó đánh giá về bộ dev, sau đó lặp lại. Tôi không biết làm thế nào để làm điều này với hàng đợi. Với feed_dict, bạn chỉ cần xây dựng hai biểu đồ có thông số được chia sẻ trong cùng một phiên, một cho đào tạo và một cho dev. Khi bạn đánh giá trên bộ dev, chỉ cần nạp dữ liệu dev vào biểu đồ dev, đó là nó.Nhưng đối với hàng đợi, đầu ra từ hàng đợi là một phần của chính đồ thị. Để chạy hàng đợi, bạn phải bắt đầu hàng đợi, tạo một điều phối viên, sử dụng điều phối viên này để quản lý hàng đợi. Khi nó được thực hiện, hàng đợi là gần !!! Hiện tại, tôi không biết cách viết mã của mình tốt nhất để phù hợp với thiết lập tàu/dev với hàng đợi ngoại trừ việc mở phiên mới, tạo biểu đồ mới cho mỗi lần tôi đánh giá. Cùng một vấn đề được nêu ra here và bạn có thể google cho các câu hỏi tương tự trên Stackoverflow.
Tuy nhiên, nhiều người cho rằng hàng đợi nhanh hơn feed_dict. Đoán của tôi là hàng đợi có lợi nếu bạn đào tạo theo cách phân tán. Nhưng đối với tôi, tôi thường tập luyện chỉ trên 1 GPU và cho tới giờ tôi vẫn không ấn tượng với hàng đợi. Vâng, chỉ là tôi đoán.
Phần một trong hướng dẫn đó cung cấp thêm một số hướng dẫn về thời điểm sử dụng hàng đợi: https://indico.io/blog/tensorflow-data-inputs-part1-placeholders-protobufs-queues/ –