TensorFlow載入資料的方式
阿新 • • 發佈:2018-11-09
tensorflow作為符號程式設計框架,需要先構建資料流圖,再讀取資料,然後再進行訓練。tensorflow提供了以下三種方式來載入資料:
- 預載入資料(preloaded data):在tensorflow圖中定義常量或變數來儲存所有資料
- 填充資料(feeding):Python產生資料,再把資料填充到後端
- 從檔案中讀取資料(reading from file):通過佇列管理器從檔案中讀取資料
下面將詳細介紹這三種載入資料的方法以及它們之間的優缺點
一、預載入資料
下面是一個使用TensorFlow來預載入資料進行手寫數字的識別
1、以constant的方式進行預載入
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data from tensorflow.examples.tutorials.mnist import mnist import time class Config(object): #設定訓練集存放的路徑 train_dir = "data/MNIST_data" #是否是fake_data進行單元測試 fake_data = False #設定batch_size的大小 batch_size = 100 #設定學習率的大小 learning_rate = 0.01 #設定迭代的輪數 num_epochs = 2 #第一層隱藏層的層數 hidden1 = 128 #第二層隱藏層的層數 hidden2 = 128 #設定每多少次迭代輸出一次結果 print_step = 100 #多少次儲存一次模型 save_checkpoint_step = 1000 #設定模型的儲存路徑 save_model_path = "model/" #設定tensorboard的儲存目錄 save_tensorboard_path = "log/" #神經網路的配置設定 config = Config() ''' 訓練模型 ''' def run_training(): #獲取資料 data_set = input_data.read_data_sets(config.train_dir) #設定預設的圖 with tf.Graph().as_default(): with tf.name_scope("input"): #使用cpu載入資料 input_images = tf.constant(data_set.train.images) input_labels = tf.constant(data_set.train.labels) image,label = tf.train.slice_input_producer([input_images,input_labels], num_epochs=config.num_epochs) #轉換標籤的型別 label = tf.cast(label,tf.int32) #獲取一個批量資料 images,labels = tf.train.batch([image,label],batch_size=config.batch_size) #構建一個計算圖建立預測模型 logits = mnist.inference(images,config.hidden1,config.hidden2) #計算損失值 loss = mnist.loss(logits,labels) #開始訓練,使用梯度下降演算法 train_op = mnist.training(loss,config.learning_rate) #計算預測的準確率 eval_correct = mnist.evaluation(logits,labels) #構建tensorboard summary_op = tf.summary.merge_all() #儲存模型 saver = tf.train.Saver() init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) #建立會話 sess = tf.Session() #初始化變數 sess.run(init_op) #儲存計算圖 summary_writer = tf.summary.FileWriter(config.save_tensorboard_path,sess.graph) #開啟入隊執行緒 coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess,coord=coord) #開始訓練 try: step = 0 #檢查是否關閉執行緒 while not coord.should_stop(): #記錄開始時間 start_time = time.time() #獲取該次迭代的損失值 _,loss_value = sess.run([train_op,loss]) #計算本次迭代所耗費時間 duration = time.time() - start_time if step % config.print_step == 0: print("step:%d,loss:%.3f,consum time:%.3f sec"%(step,loss_value,duration)) summary_str = sess.run(summary_op) summary_writer.add_summary(summary_str,step) #儲存模型 if(step+1)%config.save_checkpoint_step == 0: saver.save(sess,config.save_model_path,global_step=step) step += 1 except tf.errors.OutOfRangeError: saver.save(sess,config.save_model_path,global_step=step) finally: #停止執行緒 coord.request_stop() #等待執行緒結束 coord.join(threads) sess.close() if __name__ == "__main__": run_training()
2、以variable的方式載入資料
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data from tensorflow.examples.tutorials.mnist import mnist import time ''' 網路引數設定 ''' class Config(object): #設定訓練集存放的路徑 train_dir = "data/MNIST_data" #是否是fake_data進行單元測試 fake_data = False #設定batch_size的大小 batch_size = 100 #設定學習率的大小 learning_rate = 0.01 #設定迭代的輪數 num_epochs = 2 #第一層隱藏層的層數 hidden1 = 128 #第二層隱藏層的層數 hidden2 = 128 #設定每多少次迭代輸出一次結果 print_step = 100 #多少次儲存一次模型 save_checkpoint_step = 1000 #設定模型的儲存路徑 save_model_path = "model/" #設定tensorboard的儲存目錄 save_tensorboard_path = "log/" #神經網路的配置設定 config = Config() def run_training(): #載入資料集 data_sets = input_data.read_data_sets(config.train_dir,config.fake_data) #設定預設計算圖 with tf.Graph().as_default(): with tf.name_scope("input"): images_initializer = tf.placeholder(dtype=data_sets.train.images.dtype, shape=data_sets.train.images.shape) labels_initializer = tf.placeholder(dtype=data_sets.train.labels.dtype, shape=data_sets.train.labels.shape) input_images = tf.Variable(images_initializer,trainable=False,collections=[]) input_labels = tf.Variable(labels_initializer,trainable=False,collections=[]) image,label = tf.train.slice_input_producer([input_images,input_labels],num_epochs=config.num_epochs) label = tf.cast(label,tf.int32) images,labels = tf.train.batch([image,label],batch_size=config.batch_size) #構建訓練網路 logits = mnist.inference(images,config.hidden1,config.hidden2) #計算損失值 loss = mnist.loss(logits,labels) #使用優化演算法最小化損失函式 train_op = mnist.training(loss,config.learning_rate) #計算準確率 eval_correct = mnist.evaluation(logits,labels) #儲存tensorboard summary_op = tf.summary.merge_all() #儲存模型 saver = tf.train.Saver() init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) #建立會話 sess = tf.Session() #初始化變數 sess.run(init_op) sess.run(input_images.initializer,feed_dict={images_initializer:data_sets.train.images}) sess.run(input_labels.initializer,feed_dict={labels_initializer:data_sets.train.labels}) #儲存tensorboard summary_writer = tf.summary.FileWriter(config.save_tensorboard_path,sess.graph) #啟動入隊執行緒 coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess,coord=coord) #開始訓練 try: step = 0 while not coord.should_stop(): start_time = time.time() _,loss_value = sess.run([train_op,loss]) #計算時間間隔 duration = time.time() - start_time if step % config.print_step == 0: print("step:%s,loss:%.3f,consume time:%.3f sec"%(step,loss_value,duration)) #寫入tensorboard中 summary_str = sess.run(summary_op) summary_writer.add_summary(summary_str,step) #儲存模型 if (step+1)%config.save_checkpoint_step == 0: saver.save(sess,config.save_model_path,global_step=step) step += 1 except tf.errors.OutOfRangeError: saver.save(sess,config.train_dir,global_step=step) finally: #通知執行緒退出 coord.request_stop() #等待執行緒關閉 coord.join(threads) sess.close() if __name__ == "__main__": run_training()
通過預載入的方式載入資料的缺點在於,將資料直接嵌入到資料流圖中,當訓練資料較大時,很消耗記憶體。
二、填充資料
填充資料是使用sess.run()中的feed_dict引數,將Python產生的資料填充給後端。
import tensorflow as tf
if __name__ == "__main__":
#定義輸入資料
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
#定義操作
c = tf.add(a,b)
#python產生資料
x1 = [1.0,2.0,3.0]
x2 = [5.0,6.0,7.0]
#建立會話
with tf.Session() as sess:
print(sess.run(c,feed_dict={a:x1,b:x2}))
填充資料也存在資料量大、消耗記憶體等缺點,並資料型別轉換等中間環節也增加了不少的記憶體開銷。這時候最好採用最後一種載入資料的方式,先在圖中定義好檔案讀取的方法,通過TensorFlow從檔案中讀取資料,再解碼成為訓練資料。
三、從檔案讀取資料
從檔案中讀取資料,主要分為兩個步驟:
1、將樣本寫入到TFRecords二進位制檔案中
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets import mnist
import os
#設定TFRecords檔案儲存路徑目錄
TFRecords_dir = "tfRecords/"
#設定data的存放目錄
data_dir = "data/MNIST_data"
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]))
'''
將資料轉換為TFRecords檔案
'''
def convert_to(data_sets,name):
images = data_sets.images
labels = data_sets.labels
num_examples = data_sets.num_examples
if images.shape[0] != num_examples:
return ValueError("images size %d does not match label size %d."
%(images.shape[0],num_examples))
#獲取圖片的高
rows = images.shape[1]
#獲取圖片的寬
cols = images.shape[2]
#獲取圖片的深度
depth = images.shape[3]
#獲取TFRecords檔案的儲存路徑
save_TFRecords_path = os.path.join(TFRecords_dir,name+".tfrecords")
#將資料儲存成tfrecords檔案
with tf.python_io.TFRecordWriter(save_TFRecords_path) as writer:
for index in range(num_examples):
#將圖片資料轉換為字串
image_raw = images[index].tostring()
#將資料寫入協議緩衝區中,將圖片的寬、高、通道數、標籤編碼成為int64
#將圖片資料編碼成為二進位制
example = tf.train.Example(
features=tf.train.Features(
feature={
"height":_int64_feature(rows),
"width":_int64_feature(cols),
"depth":_int64_feature(depth),
"label":_int64_feature(int(labels[index])),
"image_raw":_bytes_feature(image_raw)
}))
#將協議緩衝區資料轉為字串寫入檔案
writer.write(example.SerializeToString())
if __name__ == "__main__":
#獲取資料
data_sets = mnist.read_data_sets(data_dir,dtype=tf.uint8,reshape=False,validation_size=5000)
#將訓練集轉換成為tfrecords檔案
convert_to(data_sets.train,"train")
#將驗證集儲存為tfrecords檔案
convert_to(data_sets.validation,"validation")
#將測試集儲存為tfrecords檔案
convert_to(data_sets.test,"test")
2、再從佇列中讀取解碼成為可以進行訓練的資料
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import mnist
import os,time
#設定TFRecords檔案的存放路徑
train_tfrecords_path = "tfRecords/train.tfrecords"
test_tfrecords_path = "tfRecords/test.tfrecords"
validation_tfrecords_path = "tfRecords/validation.tfrecords"
'''
讀取TFRecords檔案並解碼
'''
def decode(serialized_example):
features = tf.parse_single_example(
serialized_example,
features={
'image_raw': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64),
})
image = tf.decode_raw(features['image_raw'], tf.uint8)
image.set_shape((mnist.IMAGE_PIXELS))
label = tf.cast(features['label'], tf.int32)
return image, label
def augment(image, label):
return image, label
'''
歸一化圖片的畫素
'''
def normalize(image, label):
#將圖片畫素值從[0,255]轉換成為[-0.5,0.5]
image = tf.cast(image, tf.float32) * (1. / 255) - 0.5
return image, label
'''
讀取資料
'''
def inputs(tfrecords_path,batch_size,num_epochs):
if not num_epochs:
num_epochs = None
with tf.name_scope("input"):
#讀取tfrecords檔案
dataset = tf.data.TFRecordDataset(tfrecords_path)
#tfrecords資料解碼
dataset = dataset.map(decode)
dataset = dataset.map(augment)
dataset = dataset.map(normalize)
#打亂資料的順序
dataset = dataset.shuffle(1000 + 3 * batch_size)
dataset = dataset.repeat(num_epochs)
dataset = dataset.batch(batch_size)
iterator = dataset.make_one_shot_iterator()
return iterator.get_next()
'''
網路引數設定
'''
class Config(object):
#設定訓練集存放的路徑
train_dir = "data/MNIST_data"
#是否是fake_data進行單元測試
fake_data = False
#設定batch_size的大小
batch_size = 100
#設定學習率的大小
learning_rate = 0.01
#設定迭代的輪數
num_epochs = 2
#第一層隱藏層的層數
hidden1 = 128
#第二層隱藏層的層數
hidden2 = 128
#設定每多少次迭代輸出一次結果
print_step = 100
#多少次儲存一次模型
save_checkpoint_step = 1000
#設定模型的儲存路徑
save_model_path = "model/"
#設定tensorboard的儲存目錄
save_tensorboard_path = "log/"
#神經網路的配置設定
config = Config()
def run_training():
with tf.Graph().as_default():
image_batch,label_batch = inputs(train_tfrecords_path,batch_size=config.batch_size,num_epochs=config.num_epochs)
logits = mnist.inference(image_batch,config.hidden1,config.hidden2)
loss = mnist.loss(logits,label_batch)
train_op = mnist.training(loss,config.learning_rate)
init_op = tf.group(tf.global_variables_initializer(),
tf.local_variables_initializer())
with tf.Session() as sess:
sess.run(init_op)
try:
step = 0
while True:
start_time = time.time()
_,loss_value = sess.run([train_op,loss])
duration_time = time.time() - start_time
if step % config.print_step == 0:
print("step:%s,loss:%.3f,consume time:%.3f sec"%(step,loss_value,duration_time))
step += 1
except tf.errors.OutOfRangeError:
print("Done training for %d epchos,%d steps."%(config.num_epochs,step))
if __name__ == "__main__":
run_training()