1. 程式人生 > >CNN卷積神經網路應用於人臉識別(詳細流程+程式碼實現)和相應的超引數解釋

CNN卷積神經網路應用於人臉識別(詳細流程+程式碼實現)和相應的超引數解釋

DeepLearning tutorial(5)CNN卷積神經網路應用於人臉識別(詳細流程+程式碼實現)

@author:wepon

本文主要講解將CNN應用於人臉識別的流程,程式基於Python+numpy+theano+PIL開發,採用類似LeNet5的CNN模型,應用於olivettifaces人臉資料庫,實現人臉識別的功能,模型的誤差降到了5%以下。本程式只是個人學習過程的一個toy implement,樣本很小,模型隨時都會過擬合。

但是,本文意在理清程式開發CNN模型的具體步驟,特別是針對影象識別,從拿到影象資料庫,到實現一個針對這個影象資料庫的CNN模型,我覺得本文對這些流程的實現具有參考意義。

《本文目錄》

一、olivettifaces人臉資料庫介紹

二、CNN的基本“構件”(LogisticRegression、HiddenLayer、LeNetConvPoolLayer)

三、組建CNN模型,設定優化演算法,應用於Olivetti Faces進行人臉識別

四、訓練結果以及引數設定的討論

五、利用訓練好的引數初始化模型

六、一些需要說明的

一、olivettifaces人臉資料庫介紹

由40個人的400張圖片構成,即每個人的人臉圖片為10張。每張圖片的灰度級為8位,每個畫素的灰度大小位於0-255之間,每張圖片大小為64×64。如下圖,這個圖片大小是1190*942,一共有20*20張人臉,故每張人臉大小是(1190/20)*(942/20)即57*47=2679:


本文所用的訓練資料就是這張圖片,400個樣本,40個類別,乍一看樣本好像比較小,用CNN效果會好嗎?先別下結論,請往下看。

要執行CNN演算法,這張圖片必須先轉化為陣列(或者說矩陣),這個用到python的影象庫PIL,幾行程式碼就可以搞定,具體的方法我之前剛好寫過一篇文章,也是用這張圖,考慮到文章冗長,就不復制過來了,連結在此:《利用Python PIL、cPickle讀取和儲存影象資料庫》

訓練機器學習演算法,我們一般將原始資料分成訓練資料(training_set)、驗證資料(validation_set)、測試資料(testing_set)。本程式將training_set、validation_set、testing_set分別設定為320、40、40個樣本。它們的label為0~39,對應40個不同的人。這部分的程式碼如下:

  1. """ 
  2. 載入影象資料的函式,dataset_path即影象olivettifaces的路徑 
  3. 載入olivettifaces後,劃分為train_data,valid_data,test_data三個資料集 
  4. 函式返回train_data,valid_data,test_data以及對應的label 
  5. """
  6. def load_data(dataset_path):  
  7.     img = Image.open(dataset_path)  
  8.     img_ndarray = numpy.asarray(img, dtype='float64')/256
  9.     faces=numpy.empty((400,2679))  
  10.     for row in range(20):  
  11.        for column in range(20):  
  12.         faces[row*20+column]=numpy.ndarray.flatten(img_ndarray [row*57:(row+1)*57,column*47:(column+1)*47])  
  13.     label=numpy.empty(400)  
  14.     for i in range(40):  
  15.     label[i*10:i*10+10]=i  
  16.     label=label.astype(numpy.int)  
  17.     #分成訓練集、驗證集、測試集,大小如下
  18.     train_data=numpy.empty((320,2679))  
  19.     train_label=numpy.empty(320)  
  20.     valid_data=numpy.empty((40,2679))  
  21.     valid_label=numpy.empty(40)  
  22.     test_data=numpy.empty((40,2679))  
  23.     test_label=numpy.empty(40)  
  24.     for i in range(40):  
  25.     train_data[i*8:i*8+8]=faces[i*10:i*10+8]  
  26.     train_label[i*8:i*8+8]=label[i*10:i*10+8]  
  27.     valid_data[i]=faces[i*10+8]  
  28.     valid_label[i]=label[i*10+8]  
  29.     test_data[i]=faces[i*10+9]  
  30.     test_label[i]=label[i*10+9]  
  31.     #將資料集定義成shared型別,才能將資料複製進GPU,利用GPU加速程式。
  32.     def shared_dataset(data_x, data_y, borrow=True):  
  33.         shared_x = theano.shared(numpy.asarray(data_x,  
  34.                                                dtype=theano.config.floatX),  
  35.                                  borrow=borrow)  
  36.         shared_y = theano.shared(numpy.asarray(data_y,  
  37.                                                dtype=theano.config.floatX),  
  38.                                  borrow=borrow)  
  39.         return shared_x, T.cast(shared_y, 'int32')  
  40.     train_set_x, train_set_y = shared_dataset(train_data,train_label)  
  41.     valid_set_x, valid_set_y = shared_dataset(valid_data,valid_label)  
  42.     test_set_x, test_set_y = shared_dataset(test_data,test_label)  
  43.     rval = [(train_set_x, train_set_y), (valid_set_x, valid_set_y),  
  44.             (test_set_x, test_set_y)]  
  45.     return rval  

二、CNN的基本“構件”(LogisticRegression、HiddenLayer、LeNetConvPoolLayer)

卷積神經網路(CNN)的基本結構就是輸入層、卷積層(conv)、子取樣層(pooling)、全連線層、輸出層(分類器)。  卷積層+子取樣層一般都會有若干個,本程式實現的CNN模型參考LeNet5,有兩個“卷積+子取樣層”LeNetConvPoolLayer。全連線層相當於MLP(多層感知機)中的隱含層HiddenLayer。輸出層即分類器,一般採用softmax迴歸(也有人直接叫邏輯迴歸,其實就是多類別的logistics regression),本程式也直接用LogisticRegression表示。 總結起來,要組建CNN模型,必須先定義LeNetConvPoolLayer、HiddenLayer、LogisticRegression這三種layer,這一點在我上一篇文章介紹CNN演算法時講得很詳細,包括程式碼註解,因為太冗長,這裡給出連結:《DeepLearning tutorial(4)CNN卷積神經網路原理簡介+程式碼詳解》

程式碼太長,就不貼具體的了,只給出框架,具體可以下載我的程式碼看看:

  1. #分類器,即CNN最後一層,採用邏輯迴歸(softmax)
  2. class LogisticRegression(object):  
  3.     def __init__(self, input, n_in, n_out):  
  4.         self.W = ....  
  5.         self.b = ....  
  6.         self.p_y_given_x = ...  
  7.         self.y_pred = ...  
  8.         self.params = ...  
  9.     def negative_log_likelihood(self, y):  
  10.     def errors(self, y):  
  11. #全連線層,分類器前一層
  12. class HiddenLayer(object):  
  13.     def __init__(self, rng, input, n_in, n_out, W=None, b=None,activation=T.tanh):  
  14.         self.input = input  
  15.         self.W = ...  
  16.         self.b = ...  
  17.         lin_output = ...  
  18.         self.params = [self.W, self.b]  
  19. #卷積+取樣層(conv+maxpooling)
  20. class LeNetConvPoolLayer(object):  
  21.     def __init__(self, rng, input, filter_shape, image_shape, poolsize=(22)):  
  22.         self.input = input  
  23.         self.W = ...  
  24.         self.b = ...  
  25.         # 卷積
  26.         conv_out = ...  
  27.         # 子取樣
  28.         pooled_out =...  
  29.         self.output = ...  
  30.         self.params = [self.W, self.b]  

三、組建CNN模型,設定優化演算法,應用於Olivetti Faces進行人臉識別

上面定義好了CNN的幾個基本“構件”,現在我們使用這些構件來組建CNN模型,本程式的CNN模型參考LeNet5,具體為:input+layer0(LeNetConvPoolLayer)+layer1(LeNetConvPoolLayer)+layer2(HiddenLayer)+layer3(LogisticRegression)

這是一個串聯結構,程式碼也很好寫,直接用第二部分定義好的各種layer去組建就行了,上一layer的輸出接下一layer的輸入,具體可以看看程式碼evaluate_olivettifaces函式中的“建立CNN模型”部分。

CNN模型組建好了,就剩下用優化演算法求解了,優化演算法採用批量隨機梯度下降演算法(MSGD),所以要先定義MSGD的一些要素,主要包括:代價函式,訓練、驗證、測試model、引數更新規則(即梯度下降)。這部分的程式碼在evaluate_olivettifaces函式中的“定義優化演算法的一些基本要素”部分。

優化演算法的基本要素也定義好了,接下來就要運用人臉影象資料集來訓練這個模型了,訓練過程有訓練步數(n_epoch)的設定,每個epoch會遍歷所有的訓練資料(training_set),本程式中也就是320個人臉圖。還有迭代次數iter,一次迭代遍歷一個batch裡的所有樣本,具體為多少要看所設定的batch_size。關於引數的設定我在下面會討論。這一部分的程式碼在evaluate_olivettifaces函式中的“訓練CNN階段”部分。

程式碼很長,只貼框架,具體可以下載我的程式碼看看:

  1. def evaluate_olivettifaces(learning_rate=0.05, n_epochs=200,  
  2.                     dataset='olivettifaces.gif',  
  3.                     nkerns=[510], batch_size=40):     
  4.     #隨機數生成器,用於初始化引數....
  5.     #載入資料.....
  6.     #計算各資料集的batch個數....
  7.     #定義幾個變數,x代表人臉資料,作為layer0的輸入......
  8.     ######################
  9.     #建立CNN模型:
  10.     #input+layer0(LeNetConvPoolLayer)+layer1(LeNetConvPoolLayer)+layer2(HiddenLayer)+layer3(LogisticRegression)
  11.     ######################
  12.     ...  
  13.     ....  
  14.     ......  
  15.     #########################
  16.     # 定義優化演算法的一些基本要素:代價函式,訓練、驗證、測試model、引數更新規則(即梯度下降)
  17.     #########################
  18.     ...  
  19.     ....  
  20.     ......  
  21.     #########################
  22.     # 訓練CNN階段,尋找最優的引數。
  23.     ########################
  24.     ...  
  25.     .....  
  26.     .......  


另外,值得一提的是,在訓練CNN階段,我們必須定時地儲存模型的引數,這是在訓練機器學習演算法時一個經常會做的事情,這一部分的詳細介紹我之前寫過一篇文章《DeepLearning tutorial(2)機器學習演算法在訓練過程中儲存引數》。簡單來說,我們要儲存CNN模型中layer0、layer1、layer2、layer3的引數,所以在“訓練CNN階段”這部分下面,有一句程式碼:

  1. save_params(layer0.params,layer1.params,layer2.params,layer3.params)  

這個函式具體定義為:

  1. #儲存訓練引數的函式
  2. def save_params(param1,param2,param3,param4):    
  3.         import cPickle    
  4.         write_file = open('params.pkl''wb')     
  5.         cPickle.dump(param1, write_file, -1)  
  6.         cPickle.dump(param2, write_file, -1)  
  7.         cPickle.dump(param3, write_file, -1)  
  8.         cPickle.dump(param4, write_file, -1)  
  9. 相關推薦

    CNN神經網路應用人臉識別詳細流程+程式碼實現)相應引數解釋

    DeepLearning tutorial(5)CNN卷積神經網路應用於人臉識別(詳細流程+程式碼實現) @author:wepon 本文主要講解將CNN應用於人臉識別的流程,程式基於Python+numpy+theano+PIL開發,採用類似LeNet5的

    用keras小試CNN神經網路應用人臉識別

    Keras是一個簡約,高度模組化的神經網路庫。採用Python / Theano開發。 使用Keras如果你需要一個深度學習庫: 可以很容易和快速實現原型(通過總模組化,極簡主義,和可擴充套件性)同時支援卷積網路(vision)和複發性的網路(序列資料)。以及兩者的組合。

    神經網路FCN詳解(附帶Tensorflow詳解程式碼實現)

    一.導論 在影象語義分割領域,困擾了電腦科學家很多年的一個問題則是我們如何才能將我們感興趣的物件和不感興趣的物件分別分割開來呢?比如我們有一隻小貓的圖片,怎樣才能夠通過計算機自己對影象進行識別達到將小貓和圖片當中的背景互相分割開來的效果呢?如下圖所示:      而在2015年

    Keras學習四)——CNN神經網路

    本文主要介紹使用keras實現CNN對手寫資料集進行分類。 示例程式碼: import numpy as np from keras.datasets import mnist from keras.utils import np_utils from keras.models impo

    CNN神經網路簡單實現模型

    這是基於Mnist手寫識別的資料訓練的一個簡單的CNN卷積神經網路,可以直接在網上下載訓練資料集,但是經常會出現連線不到伺服器的提示,所以我下到本地進行資料的載入,下面程式碼的資料載入有問題,所以自己找了一些程式碼整出來了這個資料載入的辦法,連結為:https://blog.csdn.net/lxi

    【深度學習】Tensorflow——CNN 神經網路 2

    轉自https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/5-05-CNN3/ 目錄 圖片處理  建立卷積層  建立全連線層  選優化方法  完整程式碼

    【深度學習】Tensorflow——CNN 神經網路 1

    轉自https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/5-04-CNN2/ 這一次我們會說道 CNN 程式碼中怎麼定義 Convolutional 的層和怎樣進行 pooling. 基於上一次卷積神經網路的介

    TensorFlow之CNN神經網路實現

    下載MNIST資料集(28*28,輸入維度為784) import tensorflow as tf #下載MNIST資料集(28*28,輸入維度為784) from tensorflow.examples.tutorials.mnist import input_data mnist =

    DeepLearning tutorial4)CNN神經網路原理簡介+程式碼詳解

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    Python CNN神經網路程式碼實現

    1 # -*- coding: utf-8 -*- 2 """ 3 Created on Wed Nov 21 17:32:28 2018 4 5 @author: zhen 6 """ 7 8 import tensorflow as tf 9 from tensorflow.e

    TensorFlow實現CNN神經網路對手寫數字集mnist的模型訓練

    mnist手寫數字集相當於是TensorFlow應用中的Helloworld。 在學習了TensorFlow的卷積神經網路應用之後,今天就分步解析一下其應用過程  一、mnist手寫數字資料集         MN

    CNN神經網路入門整合

    這是一篇關於CNN入門知識的部落格,基本手法是抄、刪、改、查,就算是自己的一個筆記吧,以後忘了多看看。   1.邊界檢測示例 假如你有一張如下的影象,你想讓計算機搞清楚影象上有什麼物體,你可以做的事情是檢測影象的垂直邊緣和水平邊緣。   卷積計算可以得

    CNN-神經網路

    開局一張圖 資料輸入層 去均值:把輸入資料各個維度都中心化到0             注意只是在訓練資料上,測試集上減去的是訓練集上的均值,不要再求測試集的均值。 歸一化:幅度歸一到同一範圍。             在實際操作中不用,因為RGB天生就是0-2

    吳恩達deeplearning之CNN神經網路入門

    1.邊界檢測示例 假如你有一張如下的影象,你想讓計算機搞清楚影象上有什麼物體,你可以做的事情是檢測影象的垂直邊緣和水平邊緣。  如下是一個6*6的灰度影象,構造一個3*3的矩陣,在卷積神經網路中通常稱之為filter,對這個6*6的影象進行卷積運算,以左上角的-5計算為例  3*1+

    詳細解釋CNN神經網路各層的引數連線個數的計算

    積神經網路是一個多層的神經網路,每層由多個二維平面組成,而每個平面由多個獨立神經元組成。        圖:卷積神經網路的概念示範:輸入影象通過和三個可訓練的濾波器和可加偏置進行卷積,濾波過程如圖一,卷積後在C1層產生三個特徵對映圖,然後特徵對映圖中每組的四個畫素再進行

    CNN神經網路原理的直觀理解

    哈哈?偶然在知乎上翻到了我旭神對CNN原理的通俗易懂的解釋,看完以後簡直醍醐灌頂呢。 下面上頭像!! 哼,趕緊記錄一下加強一下理解! 轉自知乎我旭神 如果學過數字影象處理,對於卷積核的作用應該不陌生,比如你做一個最簡單的方向濾波器,那就是一個二維卷積核,這個

    CNN神經網路

    1、MLP和CNN的區別 MLP喪失了二維影象資訊,必須轉成向量 2、將全連線層轉換為區域性連線層 stride和填充:stride步長,對於超出範圍的區域,可以刪除或者填充預設值,根據需要選擇(pandding分別對應valid和same) 3、卷積層的

    python神經網路案例——CNN神經網路實現mnist手寫體識別

    全棧工程師開發手冊 (作者:欒鵬) 載入樣本資料集 首先我們要有手寫體的資料集檔案 我們實現一個MNIST.py檔案,專門用來讀取手寫體檔案中的資料。 # -*- coding: UTF-8 -*- # 獲取手寫資料。

    CNN神經網路基礎

    轉自:http://www.sohu.com/a/138403426_470008 卷積神經網路基礎 神經網路 先借用 CNTK 的一個例子,來看看如何使用神經網路來進行分類。如果想根據一個人的年齡和年收入,對他的政治傾向進行分類(保守派,居中和自由派),怎麼做呢?

    CNN神經網路學習筆記1:背景介紹

         Convolutional Neural Network 卷積神經網路是基於人工神經網路提出的。人工神經網路模擬人的神經系統,由一定數量的神經元構成。在一個監督學習問題中,有一組訓練資料(xi,yi),x是樣本,y是label,把它們輸入人工神經網路,