cifar10資料集的讀取Python/Tensorflow
阿新 • • 發佈:2018-12-31
以github上yscbm的程式碼為例進行講解,程式碼連結:https://github.com/yscbm/tensorflow/blob/master/common/extract_cifar10.py
首先匯入必要的模組
<pre><code>
import gzip
import numpy as np
import os
import tensorflow as tf
</pre></code>
我們定義一些變數,因為針對的是cifar10資料集,所以變數的值都是固定的,為什麼定義這些變數呢,因為變數的名字可以很直觀的告訴我們這個數字的代表什麼,試想如果程式碼裡面全是些數字,我們會不會看糊塗了呢,我們知道cifar10資料集下載下來你會發現有data_batch_1.bin,data_batch_2.bin....data_batch_5.bin五個作為訓練,test_batch.bin作為測試,每一個檔案都是10000張圖片,因此50000張用於訓練,10000張用於測試
<pre><code>
LABEL_SIZE = 1
IMAGE_SIZE = 32
NUM_CHANNELS = 3
PIXEL_DEPTH = 255
NUM_CLASSES = 10
TRAIN_NUM = 10000
TRAIN_NUMS = 50000
TEST_NUM = 10000
</pre></code>
接著我們定義提取資料的函式
<pre><code>
def extract_data(filenames):
#驗證檔案是否存在
for f in filenames:
if not tf.gfile.Exists(f):
raise ValueError('Failed to find file: ' + f)
#讀取資料
labels = None
images = None
for f in filenames:
bytestream=open(f,'rb')
#讀取資料,首先將資料集中的資料讀取進來作為buf
buf = bytestream.read(TRAIN_NUM * (IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS+LABEL_SIZE))
#把資料流轉化為np的陣列,為什麼要轉化為np陣列呢,因為array陣列只支援一維操作,為了滿足我們的操作需求,我們利用np.frombuffer()將buf轉化為numpy陣列現在data的shape為(30730000,),3073是3*1024+1得到的,3個channel(r,g,b),每個channel有1024=32*32個資訊,再加上 1 個label
data = np.frombuffer(buf, dtype=np.uint8)
#改變資料格式,將shape從原來的(30730000,)——>為(10000,3073)
data = data.reshape(TRAIN_NUM,LABEL_SIZE+IMAGE_SIZE* IMAGE_SIZE* NUM_CHANNELS)
#分割陣列,分割陣列,np.hsplit是在水平方向上,將陣列分解為label_size的一部分和剩餘部分兩個陣列,在這裡label_size=1,也就是把標籤label給作為一個數組單獨切分出來如果你對np.split還不太瞭解,可以自行查閱一下,此時label_images的shape應該是這樣的[array([.......]) , array([.......................])]
labels_images = np.hsplit(data, [LABEL_SIZE])
label = labels_images[0].reshape(TRAIN_NUM)#此時labels_images[0]就是我們上面切分陣列得到的第一個陣列,在這裡就是label陣列,這時的shape為array([[3] , [6] , [4] , ....... ,[7]]),我們把它reshape()一下變為了array([3 , 6 , ........ ,7])
image = labels_images[1].reshape(TRAIN_NUM,IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)#此時labels_image[1]就是我們上面切分陣列的剩餘部分,也就是圖片部分我們把它reshape()為(10000,32,32,3)
if labels == None:
labels = label
images = image
else:
#合併陣列,不能用加法
labels = np.concatenate((labels,label))
images = np.concatenate((images,image))
images = (images - (PIXEL_DEPTH / 2.0)) / PIXEL_DEPTH
return labels,images
</pre></code>
定義提取訓練資料函式
<pre><code>
def extract_train_data(files_dir):
#獲得訓練資料
filenames = [os.path.join(files_dir, 'data_batch_%d.bin' % i) for i in xrange(1, 6)]
return extract_data(filenames)
</pre></code>
定義提取測試資料函式
<pre><code>
def extract_test_data(files_dir):
#獲得測試資料
filenames = [os.path.join(files_dir, 'test_batch.bin'),]
return extract_data(filenames)
</pre></code>
把稠密資料label[1,5...]變為[[0,1,0,0...],[...]...]
<pre><code>
def dense_to_one_hot(labels_dense, num_classes):
#資料數量,np.shape[0]返回行數,對於一維資料返回的是元素個數,如果讀取了5個檔案的所有訓練資料,那麼現在的num_labels的值應該是50000
num_labels = labels_dense.shape[0]
#生成[0,1,2...]*10,[0,10,20...],之所以這樣子是每隔10個數定義一次值,比如第0個,第11個,第22個......的值都賦值為1
index_offset = np.arange(num_labels) * num_classes
#初始化np的二維陣列,一個全0,shape為(50000,10)的陣列
labels_one_hot = np.zeros((num_labels, num_classes))
#相對應位置賦值變為[[0,1,0,0...],[...]...],np.flat將labels_one_hot砸平為1維
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
</pre></code>
定義cifar10資料集類
<pre><code>
class Cifar10DataSet(object):
"""docstring for Cifar10DataSet"""
def __init__(self,data_dir):
super(Cifar10DataSet, self).__init__()
self.train_labels,self.train_images = extract_train_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
self.test_labels,self.test_images = extract_test_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
print self.train_labels.size
self.train_labels = dense_to_one_hot(self.train_labels,NUM_CLASSES)
self.test_labels = dense_to_one_hot(self.test_labels,NUM_CLASSES)
#epoch完成次數
self.epochs_completed = 0
#當前批次在epoch中進行的進度
self.index_in_epoch = 0
def next_train_batch(self,batch_size):
#起始位置
start = self.index_in_epoch
self.index_in_epoch += batch_size
#print "self.index_in_epoch: ",self.index_in_epoch
#完成了一次epoch
if self.index_in_epoch > TRAIN_NUMS:
#epoch完成次數加1,50000張全部訓練完一次,那麼沒有資料用了怎麼辦,採取的辦法就是將原來的資料集打亂順序再用
self.epochs_completed += 1
#print "self.epochs_completed: ",self.epochs_completed
#打亂資料順序,隨機性
perm = np.arange(TRAIN_NUMS)
np.random.shuffle(perm)
self.train_images = self.train_images[perm]
self.train_labels = self.train_labels[perm]
start = 0
self.index_in_epoch = batch_size
#條件不成立會報錯
assert batch_size <= TRAIN_NUMS
end = self.index_in_epoch
#print "start,end: ",start,end
return self.train_images[start:end], self.train_labels[start:end]
def test_data(self):
return self.test_images,self.test_labels
</pre></code>
<pre><code>
def main():
cc = Cifar10DataSet('../data/')
cc.next_train_batch(100)
if __name__ == '__main__':
main()
</pre></code>
以上就是我對cifar10資料集讀取的理解,cifar10資料集的介紹參考 http://blog.csdn.net/garfielder007/article/details/51480844
本文作為自己的筆記
首先匯入必要的模組
<pre><code>
import gzip
import numpy as np
import os
import tensorflow as tf
</pre></code>
我們定義一些變數,因為針對的是cifar10資料集,所以變數的值都是固定的,為什麼定義這些變數呢,因為變數的名字可以很直觀的告訴我們這個數字的代表什麼,試想如果程式碼裡面全是些數字,我們會不會看糊塗了呢,我們知道cifar10資料集下載下來你會發現有data_batch_1.bin,data_batch_2.bin....data_batch_5.bin五個作為訓練,test_batch.bin作為測試,每一個檔案都是10000張圖片,因此50000張用於訓練,10000張用於測試
<pre><code>
LABEL_SIZE = 1
IMAGE_SIZE = 32
NUM_CHANNELS = 3
PIXEL_DEPTH = 255
NUM_CLASSES = 10
TRAIN_NUM = 10000
TRAIN_NUMS = 50000
TEST_NUM = 10000
</pre></code>
接著我們定義提取資料的函式
<pre><code>
def extract_data(filenames):
#驗證檔案是否存在
for f in filenames:
if not tf.gfile.Exists(f):
raise ValueError('Failed to find file: ' + f)
#讀取資料
labels = None
images = None
for f in filenames:
bytestream=open(f,'rb')
#讀取資料,首先將資料集中的資料讀取進來作為buf
buf = bytestream.read(TRAIN_NUM * (IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS+LABEL_SIZE))
#把資料流轉化為np的陣列,為什麼要轉化為np陣列呢,因為array陣列只支援一維操作,為了滿足我們的操作需求,我們利用np.frombuffer()將buf轉化為numpy陣列現在data的shape為(30730000,),3073是3*1024+1得到的,3個channel(r,g,b),每個channel有1024=32*32個資訊,再加上 1 個label
data = np.frombuffer(buf, dtype=np.uint8)
#改變資料格式,將shape從原來的(30730000,)——>為(10000,3073)
data = data.reshape(TRAIN_NUM,LABEL_SIZE+IMAGE_SIZE* IMAGE_SIZE* NUM_CHANNELS)
#分割陣列,分割陣列,np.hsplit是在水平方向上,將陣列分解為label_size的一部分和剩餘部分兩個陣列,在這裡label_size=1,也就是把標籤label給作為一個數組單獨切分出來如果你對np.split還不太瞭解,可以自行查閱一下,此時label_images的shape應該是這樣的[array([.......]) , array([.......................])]
labels_images = np.hsplit(data, [LABEL_SIZE])
label = labels_images[0].reshape(TRAIN_NUM)#此時labels_images[0]就是我們上面切分陣列得到的第一個陣列,在這裡就是label陣列,這時的shape為array([[3] , [6] , [4] , ....... ,[7]]),我們把它reshape()一下變為了array([3 , 6 , ........ ,7])
image = labels_images[1].reshape(TRAIN_NUM,IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)#此時labels_image[1]就是我們上面切分陣列的剩餘部分,也就是圖片部分我們把它reshape()為(10000,32,32,3)
if labels == None:
labels = label
images = image
else:
#合併陣列,不能用加法
labels = np.concatenate((labels,label))
images = np.concatenate((images,image))
images = (images - (PIXEL_DEPTH / 2.0)) / PIXEL_DEPTH
return labels,images
</pre></code>
定義提取訓練資料函式
<pre><code>
def extract_train_data(files_dir):
#獲得訓練資料
filenames = [os.path.join(files_dir, 'data_batch_%d.bin' % i) for i in xrange(1, 6)]
return extract_data(filenames)
</pre></code>
定義提取測試資料函式
<pre><code>
def extract_test_data(files_dir):
#獲得測試資料
filenames = [os.path.join(files_dir, 'test_batch.bin'),]
return extract_data(filenames)
</pre></code>
把稠密資料label[1,5...]變為[[0,1,0,0...],[...]...]
<pre><code>
def dense_to_one_hot(labels_dense, num_classes):
#資料數量,np.shape[0]返回行數,對於一維資料返回的是元素個數,如果讀取了5個檔案的所有訓練資料,那麼現在的num_labels的值應該是50000
num_labels = labels_dense.shape[0]
#生成[0,1,2...]*10,[0,10,20...],之所以這樣子是每隔10個數定義一次值,比如第0個,第11個,第22個......的值都賦值為1
index_offset = np.arange(num_labels) * num_classes
#初始化np的二維陣列,一個全0,shape為(50000,10)的陣列
labels_one_hot = np.zeros((num_labels, num_classes))
#相對應位置賦值變為[[0,1,0,0...],[...]...],np.flat將labels_one_hot砸平為1維
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
</pre></code>
定義cifar10資料集類
<pre><code>
class Cifar10DataSet(object):
"""docstring for Cifar10DataSet"""
def __init__(self,data_dir):
super(Cifar10DataSet, self).__init__()
self.train_labels,self.train_images = extract_train_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
self.test_labels,self.test_images = extract_test_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
print self.train_labels.size
self.train_labels = dense_to_one_hot(self.train_labels,NUM_CLASSES)
self.test_labels = dense_to_one_hot(self.test_labels,NUM_CLASSES)
#epoch完成次數
self.epochs_completed = 0
#當前批次在epoch中進行的進度
self.index_in_epoch = 0
def next_train_batch(self,batch_size):
#起始位置
start = self.index_in_epoch
self.index_in_epoch += batch_size
#print "self.index_in_epoch: ",self.index_in_epoch
#完成了一次epoch
if self.index_in_epoch > TRAIN_NUMS:
#epoch完成次數加1,50000張全部訓練完一次,那麼沒有資料用了怎麼辦,採取的辦法就是將原來的資料集打亂順序再用
self.epochs_completed += 1
#print "self.epochs_completed: ",self.epochs_completed
#打亂資料順序,隨機性
perm = np.arange(TRAIN_NUMS)
np.random.shuffle(perm)
self.train_images = self.train_images[perm]
self.train_labels = self.train_labels[perm]
start = 0
self.index_in_epoch = batch_size
#條件不成立會報錯
assert batch_size <= TRAIN_NUMS
end = self.index_in_epoch
#print "start,end: ",start,end
return self.train_images[start:end], self.train_labels[start:end]
def test_data(self):
return self.test_images,self.test_labels
</pre></code>
<pre><code>
def main():
cc = Cifar10DataSet('../data/')
cc.next_train_batch(100)
if __name__ == '__main__':
main()
</pre></code>
LABEL_SIZE = 1
IMAGE_SIZE = 32
NUM_CHANNELS = 3
PIXEL_DEPTH = 255
NUM_CLASSES = 10
TRAIN_NUM = 10000
TRAIN_NUMS = 50000
TEST_NUM = 10000
</pre></code>
接著我們定義提取資料的函式
<pre><code>
def extract_data(filenames):
#驗證檔案是否存在
for f in filenames:
if not tf.gfile.Exists(f):
raise ValueError('Failed to find file: ' + f)
#讀取資料
labels = None
images = None
for f in filenames:
bytestream=open(f,'rb')
#讀取資料,首先將資料集中的資料讀取進來作為buf
buf = bytestream.read(TRAIN_NUM * (IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS+LABEL_SIZE))
#把資料流轉化為np的陣列,為什麼要轉化為np陣列呢,因為array陣列只支援一維操作,為了滿足我們的操作需求,我們利用np.frombuffer()將buf轉化為numpy陣列現在data的shape為(30730000,),3073是3*1024+1得到的,3個channel(r,g,b),每個channel有1024=32*32個資訊,再加上 1 個label
data = np.frombuffer(buf, dtype=np.uint8)
#改變資料格式,將shape從原來的(30730000,)——>為(10000,3073)
data = data.reshape(TRAIN_NUM,LABEL_SIZE+IMAGE_SIZE* IMAGE_SIZE* NUM_CHANNELS)
#分割陣列,分割陣列,np.hsplit是在水平方向上,將陣列分解為label_size的一部分和剩餘部分兩個陣列,在這裡label_size=1,也就是把標籤label給作為一個數組單獨切分出來如果你對np.split還不太瞭解,可以自行查閱一下,此時label_images的shape應該是這樣的[array([.......]) , array([.......................])]
labels_images = np.hsplit(data, [LABEL_SIZE])
label = labels_images[0].reshape(TRAIN_NUM)#此時labels_images[0]就是我們上面切分陣列得到的第一個陣列,在這裡就是label陣列,這時的shape為array([[3] , [6] , [4] , ....... ,[7]]),我們把它reshape()一下變為了array([3 , 6 , ........ ,7])
image = labels_images[1].reshape(TRAIN_NUM,IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)#此時labels_image[1]就是我們上面切分陣列的剩餘部分,也就是圖片部分我們把它reshape()為(10000,32,32,3)
if labels == None:
labels = label
images = image
else:
#合併陣列,不能用加法
labels = np.concatenate((labels,label))
images = np.concatenate((images,image))
images = (images - (PIXEL_DEPTH / 2.0)) / PIXEL_DEPTH
return labels,images
</pre></code>
定義提取訓練資料函式
<pre><code>
def extract_train_data(files_dir):
#獲得訓練資料
filenames = [os.path.join(files_dir, 'data_batch_%d.bin' % i) for i in xrange(1, 6)]
return extract_data(filenames)
</pre></code>
定義提取測試資料函式
<pre><code>
def extract_test_data(files_dir):
#獲得測試資料
filenames = [os.path.join(files_dir, 'test_batch.bin'),]
return extract_data(filenames)
</pre></code>
把稠密資料label[1,5...]變為[[0,1,0,0...],[...]...]
<pre><code>
def dense_to_one_hot(labels_dense, num_classes):
#資料數量,np.shape[0]返回行數,對於一維資料返回的是元素個數,如果讀取了5個檔案的所有訓練資料,那麼現在的num_labels的值應該是50000
num_labels = labels_dense.shape[0]
#生成[0,1,2...]*10,[0,10,20...],之所以這樣子是每隔10個數定義一次值,比如第0個,第11個,第22個......的值都賦值為1
index_offset = np.arange(num_labels) * num_classes
#初始化np的二維陣列,一個全0,shape為(50000,10)的陣列
labels_one_hot = np.zeros((num_labels, num_classes))
#相對應位置賦值變為[[0,1,0,0...],[...]...],np.flat將labels_one_hot砸平為1維
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
</pre></code>
定義cifar10資料集類
<pre><code>
class Cifar10DataSet(object):
"""docstring for Cifar10DataSet"""
def __init__(self,data_dir):
super(Cifar10DataSet, self).__init__()
self.train_labels,self.train_images = extract_train_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
self.test_labels,self.test_images = extract_test_data(os.path.join(data_dir,'cifar10/cifar-10-batches-bin'))
print self.train_labels.size
self.train_labels = dense_to_one_hot(self.train_labels,NUM_CLASSES)
self.test_labels = dense_to_one_hot(self.test_labels,NUM_CLASSES)
#epoch完成次數
self.epochs_completed = 0
#當前批次在epoch中進行的進度
self.index_in_epoch = 0
def next_train_batch(self,batch_size):
#起始位置
start = self.index_in_epoch
self.index_in_epoch += batch_size
#print "self.index_in_epoch: ",self.index_in_epoch
#完成了一次epoch
if self.index_in_epoch > TRAIN_NUMS:
#epoch完成次數加1,50000張全部訓練完一次,那麼沒有資料用了怎麼辦,採取的辦法就是將原來的資料集打亂順序再用
self.epochs_completed += 1
#print "self.epochs_completed: ",self.epochs_completed
#打亂資料順序,隨機性
perm = np.arange(TRAIN_NUMS)
np.random.shuffle(perm)
self.train_images = self.train_images[perm]
self.train_labels = self.train_labels[perm]
start = 0
self.index_in_epoch = batch_size
#條件不成立會報錯
assert batch_size <= TRAIN_NUMS
end = self.index_in_epoch
#print "start,end: ",start,end
return self.train_images[start:end], self.train_labels[start:end]
def test_data(self):
return self.test_images,self.test_labels
</pre></code>
<pre><code>
def main():
cc = Cifar10DataSet('../data/')
cc.next_train_batch(100)
if __name__ == '__main__':
main()
</pre></code>
以上就是我對cifar10資料集讀取的理解,cifar10資料集的介紹參考 http://blog.csdn.net/garfielder007/article/details/51480844
本文作為自己的筆記