簡單影象分類與識別CNN,Tensorflow,Cifar10(吳恩達Deep Learning)
阿新 • • 發佈:2018-12-30
簡介
因最近在學習深度學習,看了網易雲課堂吳恩達的深度學習工程師和李巨集毅的機器學習的課程,對卷積神經網路還是不是很理解。自己在網上搜教程,深度學習的入門程式《MNIST手寫數字識別》,照著寫了一遍跑了一遍。於是在網上下載了cifar資料集, 隨便搭建了一個卷積神經網路, 僅供娛樂, 不追求過高表現, 展示一遍學習深度學習的心路歷程,優點是及其簡單,比tensorflow官方給出的cifar10識別程式碼簡單。
CIFAR資料集
Cifar10資料集下載連結,找到python版本的下載即可,大小170M左右。
簡要介紹該資料集:
- 50000張訓練集圖片,10000張測試集圖片
- 每張圖片為32*32*3 = 3072個畫素值,32*32、32*32、32*32位RGB不同通道
- 檔案解壓後有5個data_batch和1個test_batch,每個有1萬張資料,如下圖:
卷積神經網路(LeNet-5)
網上視訊+論文+其它教程,自行去了解觀看,我自己按照LeNet-5結構隨便隨性搭的CNN,未使用太多優化,也未考慮效率或者其它問題。大致思路是輸入、卷積、池化、再卷積、再池化、拉伸、接入全連線網路、輸出、訓練。
程式碼
程式碼簡潔清晰,因博主也沒用過多久python,簡單勿嫌棄。
import tensorflow as tf
import numpy, pickle
# import matplotlib.pyplot as plt
# 1.處理輸入
# cifar10中訓練batch儲存格式為字典,其中
# data:10000個32*32*3影象,labels:0-9數字表示10個類別,filenames:10000個影象名稱,batch_label為batch序號
# 輸出為X(10000, 3072), Y(10000, 10)
def load_cifar_10_data_batch(filename):
file = open(filename, 'rb')
datadictionary = pickle.load(file, encoding='latin1')
X = datadictionary['data'] # X.shape = (1000, 3072)
Y = datadictionary['labels']
# filenames = datadictionary['filenames']
# batch_label = datadictionary['batch_label']
# X = X.reshape(10000, 3, 32, 32).transpose(0, 2 ,3 ,1).astype('float')
Y_temp = numpy.array(Y)
return X, Y
path = '/home/wanglei/wl/vscode/deeplearning'
X_train, Y_train = load_cifar_10_data_batch(path + '/cifar-10-batches-py/data_batch_1')
X_test, Y_test = load_cifar_10_data_batch(path + '/cifar-10-batches-py/test_batch')
# 2.構造網路所需的函式
# 2.1 引數w初始化, tf.random_normal為根據shape產生隨機分佈,均值標準差自定, shape=[height, width, channels, filters]
def weights(shape):
return tf.Variable(tf.random_normal(shape=shape, mean=0, stddev=0.1))
# 2.2 引數b初始化, tf.constant為根據shape產生常量
def biases(shape):
return tf.Variable(tf.constant(0.1, shape=shape))
# 2.3 卷積函式, x=[m, height, width, channels], m為待訓練集數量
def conv2d(x, W):
return tf.nn.conv2d(input=x, filter=W, strides=[1,1,1,1], padding='SAME', use_cudnn_on_gpu=True)
# 2.4 池化函式, 池化其實也相當於一次卷積, 比較特殊的卷積
def max_pool(x):
return tf.nn.max_pool(value=x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# 2.5 計算準確率, 根據測試集
def compute_accuracy(x_test, y_test):
global predict_function
predict_test = sess.run(predict_function, feed_dict={xs:x_test})
# 比較預測值與測試集最大值下標是否相同, 返回相同個數
y_test_one_hot = tf.one_hot(y_test, depth = 10)
correct_num = tf.equal(tf.argmax(predict_test, 1), tf.argmax(y_test_one_hot, 1))
# 計算均值即為精確率, 並轉格式float32
accuracy = tf.reduce_mean(tf.cast(correct_num, tf.float32))
return sess.run(accuracy, feed_dict={xs:x_test, ys:y_test})
# 3.定義輸入, xs為訓練集輸入m*3072矩陣, ys為訓練集labelsm*1矩陣
xs = tf.placeholder(tf.float32, [None, 32*32*3])/255
ys = tf.placeholder(tf.int32, [None])
# 4. 構造網路
# x0為輸入m*32*32*3, 影象數量m, 大小32*32, channels為3
x0 = tf.transpose(tf.reshape(xs, [-1, 3, 32, 32]), perm=[0, 2, 3, 1])
# 4.1 構建卷積層, 卷積、池化、再卷積、再池化、最後拉伸
W_conv1 = weights([5, 5, 3, 20])
b_conv1 = biases([20])
a_conv1 = conv2d(x0, W_conv1) + b_conv1
z_conv1 = tf.nn.relu(a_conv1)
h_conv1 = max_pool(z_conv1)
W_conv2 = weights([5, 5, 20, 50])
b_conv2 = biases([50])
a_conv2 = conv2d(h_conv1, W_conv2) + b_conv2
z_conv2 = tf.nn.relu(a_conv2)
h_conv2 = max_pool(z_conv2)
# x_conv0為卷積池化後拉伸的輸入m*(8*8*35=2240), 影象數量m, 輸入為2240
x_conv0 = tf.reshape(h_conv2, [-1, 8*8*50])
# 4.2 接入fully connected networks, 網路各層單元數為2240, 1024, 10
W_fc1 = weights([8*8*50, 1024])
b_fc1 = biases([1024])
a_fc1 = tf.matmul(x_conv0, W_fc1) + b_fc1
z_fc1 = tf.nn.sigmoid(a_fc1)
W_fc2 = weights([1024, 10])
b_fc2 = biases([10])
a_fc2 = tf.matmul(z_fc1, W_fc2) + b_fc2
# z_fc2 = tf.nn.relu(a_fc2)
# 4.3 預測函式與代價函式, 採用最簡單的
predict_function = a_fc2
ys_one_hot = tf.one_hot(ys, depth = 10)
# cost_function = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(predict_function), reduction_indices=[1]))
cost_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=ys_one_hot, logits=predict_function))
# 4.4 梯度下降, 使cost_function值最小
train_step = tf.train.GradientDescentOptimizer(1e-4).minimize(cost_function)
# train_step = tf.train.AdamOptimizer(1e-3).minimize(cost_function)
# 5. 訓練並影象化表示
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
for i in range(20):
for t in range(0, 10000-32, 32):
iter = t // 32
xs_batch, ys_batch = X_train[t:t+32], Y_train[t:t+32]
sess.run(train_step, feed_dict={xs:xs_batch, ys:ys_batch})
if iter % 10 == 0:
cost = sess.run(cost_function, feed_dict={xs: xs_batch, ys: ys_batch})
accuracy = compute_accuracy(X_test[:10000], Y_test[:10000])
print("iters:%s, cost:%s, accuracy:%s" % (iter, cost, accuracy))
# saver.save(sess, '/Users/wanglei/Downloads/test/model.ckpt')
sess.close()
實驗結果
因自己的破電腦原因,用了1000個訓練集都TM很慢,效果當然不是很好,精確率10%(殘缺),MMP,跑了幾個小時還沒跑完。實驗室一同學替我跑了下,10000個訓練集差不多達到27%左右精確率,50000個訓練完,達到68.9%精確率。
總結
不是為了展現多優美的模型,多高深的架構或者多好的表現。僅僅是為了學習卷積神經網路,而且是讓我能簡單的學習,麻雀雖小,五臟俱全,不想思考太深的網路,由淺入深、登堂入室才是王道。如果是為了追求極高的準確率,可以去tensorflow官網下關於cifar10的原始碼,然後研讀,再研究出更好的,調參優化等等。嗯,這是博主關於cnn的第二個自己練手的例子。
深度學習心路歷程
- 看視訊,從吳恩達的Machine Learning到Deep Learning, 穿插著李巨集毅的機器學習
- 程式設計,跟著網上視訊課程做作業和網上找教程案例,吳恩達的機器學習課的作業挺不錯,簡單便於理解。
- 看論文,然而了了,進度太慢,需要耐心。
我最開始從開視訊開始,看了好久,然後苦於沒有任何思路去練習,最後找了一個框架tensorflow進行簡單的學習,MNIST手寫數字,然後再找到cifar10資料集進行簡單的識別分類。由簡入深,慢慢來。