1. 程式人生 > >Cifar-10影象分類任務

Cifar-10影象分類任務

Cifar-10資料集

Cifar-10資料集是由10類32*32的彩色圖片組成的資料集,一共有60000張圖片,每類包含6000張圖片。其中50000張是訓練集,1000張是測試集。

1. 獲取每個batch檔案中的字典資訊

import pickle
def unpickle(file):
	fo = open(file,'rb')
	dick = pickle.load(fo,encoding='latin1')
	fo.close()
	return dick

在字典結構中,每一張圖片是以被展開的形式儲存,即一張32*32*3的圖片被展開成3072長度的list,每一個數據的格式為unit8,前1024為紅色通道,中間1024為綠色通道,後1024為藍色通道。

2.影象預處理。對資料進行標準化操作,按照一定比例進行縮放,使其落入一個特定的區域,便於操作處理。提高了處理速度。

import numpy as np
def clean(data):
	imgs = data.reshape(data.shape[0],3,32,32)
	grayscale_imgs = imgs.mean(1)
	cropped_imgs = grayscale_imgs[:,4:28,4:28]
	img_data = cropped_imgs.reshape(data.shape[0],-1)
	img_size = np.shape(img_data)[1]
	means = np.mean(img_data,axis=1)
	meansT = means.reshape(len(means),1)
	stds = np.std(img_data,axis=1)
	stdsT = stds.reshape(len(stds),1)
	adj_stds = np.maximum(stdsT,1.0/np.sqrt(img_size))
	normalized = (img_data - meansT) / adj_stds
	return normalized

mean(axis)函式:求平均值。對m*n的矩陣來說

axis=0:壓縮行,對各列求平均值,返回1*n矩陣。

axis=1:壓縮列,對各行求平均值,返回m*1矩陣。

axis不設定值,對m*n個數求平均值,返回一個實數。

reshape()函式:改變陣列的形狀。

reshape((2,4)):變為一個二維陣列;reshape((2,2,2)):變為一個三維陣列

當有一個引數為-1時,會根據另一個引數的維度計算陣列的另外一個shape屬性值。

如reshape(data.shape[0],-1):行為data.shape[0]行,列自動算出。data.shape[0]:data第一維的長度。

3.影象資料讀取

def read_data(directory):
	names = unpickle('{}/batches.meta'.format(directory))['label_names']
	
	print('dede')
	print('names',names)
	print('dede')
	
	data,labels = [],[]
	#一個batch一個batch的去讀取batch資料
	for i in range(1,6):
		filename = '{}/data_batch_{}'.format(directory,i)
		batch_data = unpickle(filename)
		#拼加操作
		if len(data) > 0:
			data = np.vstack((data,batch_data['data']))
			labels = np.hstack((labels,batch_data['labels']))
		else:
			data = batch_data['data']
			labels = batch_data['labels']
			
	print('haha')		
	print(np.shape(data),np.shape(labels))	#輸出data和labels的長度
	print('haha')	
	
	data = clean(data)
	data = data.astype(np.float32)
	return names,data,labels

 下圖為names的值,圖片集中的分類

  可以看出,data和labels的資料型別為ndarray,batch_data的資料型別為字典型別。

hstack(a,b,c,d):水平把陣列堆疊起來

vstack(a,b,c,d):豎直把陣列堆疊起來

4.顯示資料

import matplotlib.pyplot as plt
import random
random.seed(1)	

#把資料讀取進來
names,data,labels = read_data('D://hh/cifar-10-batches-py')

def show_some_examples(names,data,labels):
	plt.figure()
	#繪製一個子圖 4*4結構
	rows,cols = 4,4
	random_idxs = random.sample(range(len(data)),rows * cols)
	for i in range(rows*cols):
		plt.subplot(rows,cols,i+1)
		j = random_idxs[i]
		plt.title(names[labels[j]])
		img = np.reshape(data[j,:],(24,24))
		plt.imshow(img,cmap='Greys_r')
		plt.axis('off')
	plt.tight_layout()
	plt.savefig('cifar_examples,png')
	
show_some_examples(names,data,labels)	
print('stop1')	

繪製的圖

5.經過卷積後的結果

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

names,data,labels = read_data('D://hh/cifar-10-batches-py')	

def show_conv_results(data,filename = None):
	plt.figure()
	#子圖 4行8列  每一個子圖都是其中的一個特徵圖
	rows,cols = 4,8		
	for i in range(np.shape(data)[3]):
		img = data[0,:,:,i]		#分別取當前的每一個特徵圖
		plt.subplot(rows,cols,i+1)
		plt.imshow(img,cmap='Greys_r',interpolation='none')
		plt.axis('off')
	if filename:
		plt.savefig(filename)
	else:
		plt.show()
print('stop2')	
#權重引數
def show_weights(W,filename=None):
	plt.figure()
	rows,cols = 4,8
	for i in range(np.shape(W)[3]):
		img = W[:,:,0,i]
		plt.subplot(rows,cols,i+1)
		plt.imshow(img,cmap='Greys_r',interpolation='none')
		plt.axis('off')
	if filename:
		plt.savefig(filename)
	else:
		plt.show()

#顯示
raw_data = data[4,:]		
raw_img = np.reshape(raw_data,(24,24))
plt.figure()
plt.imshow(raw_img,cmap='Greys_r')
plt.show()

 6.引數設定

x = tf.reshape(raw_data,shape=[-1,24,24,1])
W = tf.Variable(tf.random_normal([5,5,1,32])) 	#輸入為1 輸出為32
b = tf.Variable(tf.random_normal([32]))

7.卷積操作

conv = tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')	#卷積
conv_with_b = tf.nn.bias_add(conv,b)		#卷積後加偏置項
conv_out = tf.nn.relu(conv_with_b)		#啟用函式

k = 2
maxpool = tf.nn.max_pool(conv_out,ksize=[1,k,k,1],strides=[1,k,k,1], padding='SAME')

8.檢視中間結果

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer()) 
	
	W_val = sess.run(W)
	print('weight:')
	show_weights(W_val)
	
	#開始卷積
	conv_val = sess.run(conv)
	print("convolution results:")
	print(np.shape(conv_val))
	show_conv_results(conv_val)
	
	#relu
	conv_out_val = sess.run(conv_out)
	print("convolution with blas and relu:")
	print(np.shape(conv_out_val))
	show_conv_results(conv_out_val)
	
	#池化
	maxpool_val = sess.run(maxpool)
	print("maxpool after all the convolutions:")
	print(np.shape(maxpool_val))
	show_conv_results(maxpool_val)

 weight:

 卷積:

relu:

  最大池化:

9.構建網路模型

x = tf.placeholder(tf.float32,[None,24*24])	
y = tf.placeholder(tf.float32,[None,len(names)])
W1 = tf.Variable(tf.random_normal([5,5,1,64]))
b1 = tf.Variable(tf.random_normal([64]))
W2 = tf.Variable(tf.random_normal([5,5,64,64]))
b2 = tf.Variable(tf.random_normal([64]))
W3 = tf.Variable(tf.random_normal([6*6*64,1024]))
b3 = tf.Variable(tf.random_normal([1024]))
W_out = tf.Variable(tf.random_normal([1024,len(names)]))
b_out = tf.Variable(tf.random_normal([len(names)]))

10.卷積池化操作函式

def conv_layer(x,W,b):
	conv = tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
	conv_with_b = tf.nn.bias_add(conv,b)
	conv_out = tf.nn.relu(conv_with_b)
	return conv_out
	
def maxpool_layer(conv,k=2):
	return tf.nn.max_pool(conv,ksize=[1,k,k,1],strides=[1,k,k,1],padding='SAME')

11.把引數組合到一起

def model():
	x_reshapes = tf.reshape(x,shape=[-1,24,24,1])
	#卷積層
	conv_out1 = conv_layer(x_reshapes,W1,b1)
	#池化層
	maxpool_out1 = maxpool_layer(conv_out1)
	#提出了LRN層(區域性響應層),對區域性神經元的活動建立競爭機制,使得其中響應比較大的值變得相對更大,並抑制其他反饋比較小的神經元,
	#增強了模型的泛化能力,使表達能力增強
	norm1 = tf.nn.lrn(maxpool_out1,4,bias=1.0,alpha=0.001/9.0,beta=0.75)
	#第二次卷積池化
	conv_out2 = conv_layer(norm1,W2,b2)
	norm2 = tf.nn.lrn(conv_out2,4,bias=1.0,alpha=0.01/9.0,beta=0.75)
	maxpool_out2 = maxpool_layer(norm2)
	
	maxpool_reshaped = tf.reshape(maxpool_out2,[-1,W3.get_shape().as_list()[0]])
	local = tf.add(tf.matmul(maxpool_reshaped,W3),b3)
	local_out = tf.nn.relu(local)
	
	out = tf.add(tf.matmul(local_out,W_out),b_out)
	return out

12. 指定學習率和 損失函式

learning_rate = 0.001
model_op = model()
cost = tf.reduce_mean(
	tf.nn.softmax_cross_entropy_with_logits(logits=model_op,labels=y)
)	
train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

correct_pred = tf.equal(tf.argmax(model_op,1),tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred,tf.float32))

13.迭代

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	#把標籤轉換成10個概率
	onehot_labels = tf.one_hot(labels,len(names),axis=-1)
	onehot_vals = sess.run(onehot_labels)
	batch_size = 64
	print('batch size',batch_size)
	for j in range(0,1000):
		avg_accuracy_val = 0
		batch_count = 0
		for i in range(0,len(data),batch_size):
			batch_data = data[i:i+batch_size,:]
			batch_onehot_vals = onehot_vals[i:i+batch_size,:]
			_,accuracy_val = sess.run([train_op,accuracy],feed_dict={x:batch_data,y:batch_onehot_vals})
			avg_accuracy_val += accuracy_val
			batch_count += 1
		avg_accuracy_val /= batch_count
		print('Epoch[],Avg accuracy []',format(j,avg_accuracy_val))
		
		print('Epoch [],Avg accuracy []',format(j,avg_accuracy_val))