1. 程式人生 > >Tensorflow之構建自己的圖片資料集

Tensorflow之構建自己的圖片資料集

用了這麼久的tensorflow,例子跑了N多便,基本流程是清楚了。但是自己獨立做一個小例子各種問題都來了。如自己圖片資料集怎麼做?說句老實話,tensorflow真是煩,管方文件教程上老拿MNIST和cifar_10這種做好的資料集說事,對於我們這些初學者,完全不知道圖片該如何輸入。今天給大家分享我的Tensorflow製作資料集的學習歷程。 
流程是:製作資料集—讀取資料集—-加入佇列 
先貼完整的程式碼:

#encoding=utf-8
import os
import tensorflow as tf
from PIL import Image

cwd = os.getcwd()

classes = {'test'
,'test1','test2'} #製作二進位制資料 def create_record(): writer = tf.python_io.TFRecordWriter("train.tfrecords") for index, name in enumerate(classes): class_path = cwd +"/"+ name+"/" for img_name in os.listdir(class_path): img_path = class_path + img_name img = Image.open(img_path) img = img.resize((64
, 64)) img_raw = img.tobytes() #將圖片轉化為原生bytes print index,img_raw example = tf.train.Example( features=tf.train.Features(feature={ "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[index])), 'img_raw'
: tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])) })) writer.write(example.SerializeToString()) writer.close() data = create_record() #讀取二進位制資料 def read_and_decode(filename): # 建立檔案佇列,不限讀取的數量 filename_queue = tf.train.string_input_producer([filename]) # create a reader from file queue reader = tf.TFRecordReader() # reader從檔案佇列中讀入一個序列化的樣本 _, serialized_example = reader.read(filename_queue) # get feature from serialized example # 解析符號化的樣本 features = tf.parse_single_example( serialized_example, features={ 'label': tf.FixedLenFeature([], tf.int64), 'img_raw': tf.FixedLenFeature([], tf.string) } ) label = features['label'] img = features['img_raw'] img = tf.decode_raw(img, tf.uint8) img = tf.reshape(img, [64, 64, 3]) img = tf.cast(img, tf.float32) * (1. / 255) - 0.5 label = tf.cast(label, tf.int32) return img, label if __name__ == '__main__': if 0: data = create_record("train.tfrecords") else: img, label = read_and_decode("train.tfrecords") print "tengxing",img,label #使用shuffle_batch可以隨機打亂輸入 next_batch挨著往下取 # shuffle_batch才能實現[img,label]的同步,也即特徵和label的同步,不然可能輸入的特徵和label不匹配 # 比如只有這樣使用,才能使img和label一一對應,每次提取一個image和對應的label # shuffle_batch返回的值就是RandomShuffleQueue.dequeue_many()的結果 # Shuffle_batch構建了一個RandomShuffleQueue,並不斷地把單個的[img,label],送入佇列中 img_batch, label_batch = tf.train.shuffle_batch([img, label], batch_size=4, capacity=2000, min_after_dequeue=1000) # 初始化所有的op init = tf.initialize_all_variables() with tf.Session() as sess: sess.run(init) # 啟動佇列 threads = tf.train.start_queue_runners(sess=sess) for i in range(5): print img_batch.shape,label_batch val, l = sess.run([img_batch, label_batch]) # l = to_categorical(l, 12) print(val.shape, l)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

製作資料集

#製作二進位制資料
def create_record():
    cwd = os.getcwd()
    classes = {'1','2','3'}
    writer = tf.python_io.TFRecordWriter("train.tfrecords")
    for index, name in enumerate(classes):
        class_path = cwd +"/"+ name+"/"
        for img_name in os.listdir(class_path):
            img_path = class_path + img_name
            img = Image.open(img_path)
            img = img.resize((28, 28))
            img_raw = img.tobytes() #將圖片轉化為原生bytes
            #print index,img_raw
            example = tf.train.Example(
                features=tf.train.Features(
                    feature={
                        "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[index])),
                        'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
                    }
                )
            )
            writer.write(example.SerializeToString())
    writer.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

TFRecords檔案包含了tf.train.Example 協議記憶體塊(protocol buffer)(協議記憶體塊包含了欄位 Features)。我們可以寫一段程式碼獲取你的資料, 將資料填入到Example協議記憶體塊(protocol buffer),將協議記憶體塊序列化為一個字串, 並且通過tf.python_io.TFRecordWriter 寫入到TFRecords檔案。

讀取資料集

#讀取二進位制資料
def read_and_decode(filename):
    # 建立檔案佇列,不限讀取的數量
    filename_queue = tf.train.string_input_producer([filename])
    # create a reader from file queue
    reader = tf.TFRecordReader()
    # reader從檔案佇列中讀入一個序列化的樣本
    _, serialized_example = reader.read(filename_queue)
    # get feature from serialized example
    # 解析符號化的樣本
    features = tf.parse_single_example(
        serialized_example,
        features={
            'label': tf.FixedLenFeature([], tf.int64),
            'img_raw': tf.FixedLenFeature([], tf.string)
        }
    )
    label = features['label']
    img = features['img_raw']
    img = tf.decode_raw(img, tf.uint8)
    img = tf.reshape(img, [64, 64, 3])
    img = tf.cast(img, tf.float32) * (1. / 255) - 0.5
    label = tf.cast(label, tf.int32)
    return img, label
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

一個Example中包含Features,Features裡包含Feature(這裡沒s)的字典。最後,Feature裡包含有一個 FloatList, 或者ByteList,或者Int64List

加入佇列

with tf.Session() as sess:
            sess.run(init)
            # 啟動佇列
            threads = tf.train.start_queue_runners(sess=sess)
            for i in range(5):
                print img_batch.shape,label_batch
                val, l = sess.run([img_batch, label_batch])
                # l = to_categorical(l, 12)
                print(val.shape, l)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這樣就可以的到和tensorflow官方的二進位制資料集了, 
注意:

  • 啟動佇列那條code不要忘記,不然卡死
  • 使用的時候記得使用val和l,不然會報型別錯誤:TypeError: The value of a feed cannot be a tf.Tensor object. Acceptable feed values include Python scalars, strings, lists, or numpy ndarrays.
  • 算交叉熵時候:cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits,labels)算交叉熵 
    最後評估的時候用tf.nn.in_top_k(logits,labels,1)選logits最大的數的索引和label比較
  • cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))算交叉熵,所以label必須轉成one-hot向量

2017-11-12