深度學習(5)——多線程輸入數據處理框架

目錄

摘要:

1. 隊列與多線程

2. 輸入文件隊列

3.組合訓練數據

4.輸入數據處理框架

4.1 一個完整的tensorflow處理輸入數據


摘要:

圖像處理中出現的亮度、對比度等對圖像的影響很大,對圖像進行預處理可以使得神經網絡模型儘可能小的被無關因素影響,但複雜的預處理過程可能導致訓練效率下降。爲了減小預處理對訓練速度的影響,就需要用到多線程處理輸入數據。

1. 隊列與多線程

修改隊列狀態的操作:Enqueue、EnqueueMany和Dequeue

tensorflow提供了兩種隊列,除了FIFOQueue,還有RandomShuffleQueue,後者會將隊列的元素打亂,每次出隊列得到的是從當前隊列所有元素種隨機一個

# -*- coding: utf-8 -*-
import tensorflow as tf

#創建一個先進先出隊列,指定隊列中最多可以保存兩個元素,並指定類型
q=tf.FIFOQueue(2,"int32")

init=q.enqueue_many(([0,10],))

#使用dequeue將隊列的第一個元素出隊列,這個元素保存在變量x中
x=q.dequeue()

y=x+1

#重回隊列
q_inc=q.enqueue([y])

with tf.Session() as sess:
	init.run()
	for _ in range(5):
		v,_=sess.run([x,q_inc])
		print(v)

tensorflow中用來完成多線程協同功能的tf.Coordinator(Coordinator有協調者的意思)和tf.QueueRunner。

tf.Coordinator主要用於協同多個線程一起停止,並提供了should_stop\request_stop\join三個函數。

import tensorflow as tf
import numpy as np
import threading
import time

def MyLoop(coord,worker_id):
	while not coord.should_stop():
		if np.random.rand()<0.1:
			print("stoping from id:%d\n"%worker_id)
		else:
			print("working on id:%d\n"%worker_id)
		time.sleep(1)
		
coord=tf.train.Coordinator()
threads=[threading.Thread(target=MyLoop,args=(coord,i,)) for i in range(5)]
for t in threads:t.start()
coord.join(threads)

tf.QueueRunner主要用來啓動多個線程來操作同一個隊列

import tensorflow as tf

#定義隊列及其操作。
queue = tf.FIFOQueue(100,"float")
enqueue_op = queue.enqueue([tf.random_normal([1])])
qr = tf.train.QueueRunner(queue, [enqueue_op] * 5)
tf.train.add_queue_runner(qr)
#定義出隊操作
out_tensor = queue.dequeue()

#啓動線程
with tf.Session() as sess:
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    for _ in range(3): print (sess.run(out_tensor)[0])
    coord.request_stop()
    coord.join(threads)

2. 輸入文件隊列

note:Tensorflow提供了一種統一的格式來存儲數據,TFRecord

#獲取文件列表
files=tf.train.match_filenames_once("/path/to/data.tfrecords-*")
#通過tf.train.string_input_producer函數創建輸入隊列
filename_queue=tf.train.string_input_producer(files,shuffle=False)

reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
      serialized_example,
      features={
          'i': tf.FixedLenFeature([], tf.int64),
          'j': tf.FixedLenFeature([], tf.int64),
      })
with tf.Session() as sess:
    sess.run([tf.global_variables_initializer(), tf.local_variables_initializer()])
    print (sess.run(files))
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    for i in range(6):
        print (sess.run([features['i'], features['j']]))
    coord.request_stop()
    coord.join(threads)

3.組合訓練數據

# 組合訓練數據
example, label = features['i'], features['j']
batch_size = 2
capacity = 1000 + 3 * batch_size
#使用tf.train.batch來組合樣例,batch給出樣例個數,capacity給出隊列的最大容量
example_batch, label_batch = tf.train.batch([example, label], batch_size=batch_size, capacity=capacity)

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    tf.local_variables_initializer().run()
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    for i in range(3):
        cur_example_batch, cur_label_batch = sess.run([example_batch, label_batch])
        print cur_example_batch, cur_label_batch
    coord.request_stop()
    coord.join(threads)

 

4.輸入數據處理框架

4.1 一個完整的tensorflow處理輸入數據

# -*- coding: utf-8 -*-
"""
# 輸入數據,使用生成的訓練和測試數據。
"""
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np

# 定義函數轉化變量類型。
def _int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def _bytes_feature(value):
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

# 將數據轉化爲tf.train.Example格式。
def _make_example(pixels, label, image):
    image_raw = image.tostring()
    example = tf.train.Example(features=tf.train.Features(feature={
        'pixels': _int64_feature(pixels),
        'label': _int64_feature(np.argmax(label)),
        'image_raw': _bytes_feature(image_raw)
    }))
    return example

# 讀取mnist訓練數據。
mnist = input_data.read_data_sets("../../datasets/MNIST_data",dtype=tf.uint8, one_hot=True)
images = mnist.train.images
labels = mnist.train.labels
pixels = images.shape[1]
num_examples = mnist.train.num_examples

# 輸出包含訓練數據的TFRecord文件。
with tf.python_io.TFRecordWriter("output.tfrecords") as writer:
    for index in range(num_examples):
        example = _make_example(pixels, labels[index], images[index])
        writer.write(example.SerializeToString())
print("TFRecord訓練文件已保存。")

# 讀取mnist測試數據。
images_test = mnist.test.images
labels_test = mnist.test.labels
pixels_test = images_test.shape[1]
num_examples_test = mnist.test.num_examples

# 輸出包含測試數據的TFRecord文件。
with tf.python_io.TFRecordWriter("output_test.tfrecords") as writer:
    for index in range(num_examples_test):
        example = _make_example(
            pixels_test, labels_test[index], images_test[index])
        writer.write(example.SerializeToString())
print("TFRecord測試文件已保存。")

train_files = tf.train.match_filenames_once("output.tfrecords")
test_files = tf.train.match_filenames_once("output_test.tfrecords")

"""
# 定義解析一個TFRecord的方法。
"""
def parser(record):
    features = tf.parse_single_example(
        record,
        features={
            'image_raw':tf.FixedLenFeature([],tf.string),
            'pixels':tf.FixedLenFeature([],tf.int64),
            'label':tf.FixedLenFeature([],tf.int64)
        })
    decoded_images = tf.decode_raw(features['image_raw'],tf.uint8)
    retyped_images = tf.cast(decoded_images, tf.float32)
    images = tf.reshape(retyped_images, [784])
    labels = tf.cast(features['label'],tf.int32)
    #pixels = tf.cast(features['pixels'],tf.int32)
    return images, labels
"""
# 定義訓練數據集
"""
image_size = 299          # 定義神經網絡輸入層圖片的大小。
batch_size = 100          # 定義組合數據batch的大小。
shuffle_buffer = 10000   # 定義隨機打亂數據時buffer的大小。

# 定義讀取訓練數據的數據集。
dataset = tf.data.TFRecordDataset(train_files)
dataset = dataset.map(parser)

# 對數據進行shuffle和batching操作。這裏省略了對圖像做隨機調整的預處理步驟。
dataset = dataset.shuffle(shuffle_buffer).batch(batch_size)

# 重複NUM_EPOCHS個epoch。
NUM_EPOCHS = 10
dataset = dataset.repeat(NUM_EPOCHS)

# 定義數據集迭代器。
iterator = dataset.make_initializable_iterator()
image_batch, label_batch = iterator.get_next()

"""
# 定義神經網絡的結構以及優化過程。
"""
def inference(input_tensor, weights1, biases1, weights2, biases2):
    layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)
    return tf.matmul(layer1, weights2) + biases2

INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500
REGULARAZTION_RATE = 0.0001   
TRAINING_STEPS = 5000        

weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))

weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))

y = inference(image_batch, weights1, biases1, weights2, biases2)
    
# 計算交叉熵及其平均值
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=label_batch)
cross_entropy_mean = tf.reduce_mean(cross_entropy)
    
# 損失函數的計算
regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)
regularaztion = regularizer(weights1) + regularizer(weights2)
loss = cross_entropy_mean + regularaztion

# 優化損失函數
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)


"""
# 定義測試用的Dataset。
"""
test_dataset = tf.data.TFRecordDataset(test_files)
test_dataset = test_dataset.map(parser)
test_dataset = test_dataset.batch(batch_size)

# 定義測試數據上的迭代器。
test_iterator = test_dataset.make_initializable_iterator()
test_image_batch, test_label_batch = test_iterator.get_next()

# 定義測試數據上的預測結果。
test_logit = inference(test_image_batch, weights1, biases1, weights2, biases2)
predictions = tf.argmax(test_logit, axis=-1, output_type=tf.int32)
 
# 聲明會話並運行神經網絡的優化過程。
with tf.Session() as sess:  
    # 初始化變量。
    sess.run((tf.global_variables_initializer(),
              tf.local_variables_initializer()))
    
    # 初始化訓練數據的迭代器。
    sess.run(iterator.initializer)
    
    # 循環進行訓練,直到數據集完成輸入、拋出OutOfRangeError錯誤。
    while True:
        try:
            sess.run(train_step)
        except tf.errors.OutOfRangeError:
            break

    test_results = []
    test_labels = []
    # 初始化測試數據的迭代器。
    sess.run(test_iterator.initializer)
    # 獲取預測結果。
    while True:
        try:
            pred, label = sess.run([predictions, test_label_batch])
            test_results.extend(pred)
            test_labels.extend(label)
        except tf.errors.OutOfRangeError:
            break

# 計算準確率
correct = [float(y == y_) for (y, y_) in zip (test_results, test_labels)]
accuracy = sum(correct) / len(correct)
print("Test accuracy is:", accuracy)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章