天天看點

[基于tensorflow的人臉檢測] 基于神經網絡的人臉檢測5——神經網絡的搭建

1.神經網絡的基本組成部分

2.tensorflow實作神經網絡的架構搭建

3.兩個經典的神經網絡執行個體

正文:

1.神經網絡的基本組成部分

一個典型的卷積神經網絡一般由全連接配接層、卷積層和池化層組成。

  • 全連接配接層是層與層之間所有神經元節點都兩兩互相連接配接,是以重要的參數隻有兩個,輸入節點個數和輸出節點個數。
  • 卷積層的層與層之間的神經元節點是采用部分連接配接的方式,采用塊狀的連接配接方式(這個塊狀叫過濾器),其需要定義的參數有
    • 輸入以及輸入的深度
    • 過濾器尺寸
    • 輸出深度(過濾器深度)
    • 過濾的移動步長
  • 池化層的連接配接方式與卷積層的連接配接方式一樣,由于池化層不改變輸入的深度(輸出和輸入的深度是一樣的),是以需要指定的參數是過濾器尺寸和過濾器移動步長。另外根據計算方式的不同,常用的池化層有最大池化和平均池化兩種。

2.tensorflow實作神經網絡的架構搭建

tensorflow對神經網絡的實作有很好的函數支援,下面是實作上面的三種網絡層結構的代碼。

import tensorflow as tf

def fc(input_, input_deep, out_deep, name): #全連接配接層
    """參數->輸入、輸入深度、輸出深度、該層的變量名"""
    with tf.compat.v1.variable_scope(name):
        weight = tf.Variable( #權重
            tf.random.truncated_normal([input_deep, out_deep], stddev=0.05),
            name="weights")
        bias = tf.Variable( #偏置
            tf.constant(0.1, dtype=tf.float32, shape=[out_deep]), 
            name="bias")
        net = tf.nn.relu(tf.add(tf.matmul(input_, weight), bias)) #乘加 激活
        
    return net
  
def conv(input_, input_deep, output_deep, ksize, stride, name):#卷積層
    """參數->輸入、輸入深度、輸出深度、過濾器尺寸、過濾器移動步長、該層的變量名"""
    with tf.compat.v1.variable_scope(name):
        conv_weights = tf.compat.v1.get_variable( #權重
            'weight', [ksize, ksize, input_deep, output_deep],
            initializer = tf.truncated_normal_initializer(stddev=0.1))
        conv_biases = tf.compat.v1.get_variable( #偏置
            'biases', [output_deep], initializer = tf.constant_initializer(0.0))

        conv = tf.nn.conv2d( #卷積
            input_, conv_weights, strides=[1,stride,stride,1], padding='SAME')
        relu = tf.nn.relu(tf.nn.bias_add(conv, conv_biases)) #激活
        
    return relu

def maxpool(input_, ksize, stride, name): #最大池化層
    """參數->輸入、過濾器尺寸、過濾器移動步長、該層的變量名"""
    with tf.name_scope(name):
        pool = tf.nn.max_pool2d(input_, ksize=[1,ksize,ksize,1], strides=[1,stride,stride,1],
                                padding='VALID') #最大池化
        
    return pool
           

在卷積和池化時還需要指定填充方式(padding),填充是利用0填充輸入矩陣,進而使得輸出矩陣的大小不變。padding參數的表示如下。

padding = ‘VALID’ #不使用零填充

padding = ‘SAME’ #使用零填充

填充的方式不同,計算輸出矩陣的尺寸也不同。下面是兩種方式的計算方法,其中 ⌈ ⌉ \lceil\rceil ⌈⌉ 表示向上取整。

padding = ‘VALID’ :

輸 出 的 高 = ⌈ 輸 入 的 高 − 過 濾 器 的 高 + 1 過 濾 器 移 動 步 長 ⌉ 輸出的高 = \lceil \frac{輸入的高-過濾器的高+1}{過濾器移動步長}\rceil 輸出的高=⌈過濾器移動步長輸入的高−過濾器的高+1​⌉

輸 出 的 寬 = ⌈ 輸 入 的 寬 − 過 濾 器 的 寬 + 1 過 濾 器 移 動 步 長 ⌉ 輸出的寬 = \lceil \frac{輸入的寬-過濾器的寬+1}{過濾器移動步長}\rceil 輸出的寬=⌈過濾器移動步長輸入的寬−過濾器的寬+1​⌉

輸 出 的 深 度 = 過 濾 器 深 度 輸出的深度 = 過濾器深度 輸出的深度=過濾器深度

padding = ‘SAME’:

輸 出 的 高 = ⌈ 輸 入 的 高 過 濾 器 移 動 步 長 ⌉ 輸出的高 = \lceil \frac{輸入的高}{過濾器移動步長}\rceil 輸出的高=⌈過濾器移動步長輸入的高​⌉

輸 出 的 寬 = ⌈ 輸 入 的 寬 過 濾 器 移 動 步 長 ⌉ 輸出的寬 = \lceil \frac{輸入的寬}{過濾器移動步長}\rceil 輸出的寬=⌈過濾器移動步長輸入的寬​⌉

輸 出 的 深 度 = 過 濾 器 深 度 輸出的深度 = 過濾器深度 輸出的深度=過濾器深度

3.兩個經典的神經網絡執行個體

  1. Alexnet神經網絡

    下圖為Alexnet的神經網絡結構圖。

    [基于tensorflow的人臉檢測] 基于神經網絡的人臉檢測5——神經網絡的搭建
    (圖檔來源于百度百科) 下面是代碼實作:
    def alexnet(input_):
        """alexnet網絡結構"""
        conv1 = conv(input_, 3, 96, 11, 4,'layer1_conv1')
        #3為輸入到神經網絡的次元
        
        lrn1 = tf.nn.lrn(conv1,4,bias=1,alpha=1e-3/9,beta=0.75,name="layer2_lrn1")
        #局部響應歸一化
        
        pool1 = maxpool(lrn1, 3, 2,'layer3_pool1')
        
        conv2 = conv(pool1, 96, 256, 5, 1,'layer4_conv2')
    
        lrn2 = tf.nn.lrn(conv2,4,bias=1,alpha=1e-3/9,beta=0.75,name="layer5_lrn2")
    
        pool2 = maxpool(lrn2, 3, 2,'layer6_pool2')
    
        conv3 = conv(pool2, 256, 384, 3, 1,'layer7_conv3')
    
        conv4 = conv(conv3, 384, 384, 3, 1,'layer8_conv4')
    
        conv5 = conv(conv4, 384, 256, 3, 1,'layer9_conv5')
    
        pool3 = maxpool(conv5, 3, 2,'layer10_pool3')
    
        pool_shape = pool3.get_shape().as_list()
        #計算向量長度 長x寬x高(第二、三、四次元,第一維為batch個數)
        nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
        #通過函數變成向量
        reshaped = tf.reshape(pool3, [pool_shape[0], nodes])
        
        fc1 = fc(reshaped, nodes, 4096, 'layer11_fc1')
        
        fc2 = fc(fc1, 4096, 4096, 'layer12_fc2')
        
        fc3 = fc(fc2, 4096, 2, 'layer13_fc3' )
    
        return fc3
               

神經網絡的輸出的次元應該等于分類的個數,在人臉檢測中,神經網絡用于判定輸入的圖檔是否為人臉,是一個二分類任務,是以在最後一層的輸出次元中應該是2。

​ 2.vgg神經網絡

下表為vgg的神經網絡結構圖,以表格C列的vgg-16為例搭建神經網絡,其中卷積層的過濾器移動步長為1,池化層過濾器的移動步長為2。

[基于tensorflow的人臉檢測] 基于神經網絡的人臉檢測5——神經網絡的搭建

(圖檔來源于百度百科)

vgg16代碼實作:

def vgg_16(input_):
    """vgg16網絡結構"""
    conv1 = conv(input_, 3, 64, 3, 1,'layer1_conv1')
    #3為輸入到神經網絡的次元
    
    conv2 = conv(conv1, 64, 64, 3, 1,'layer2_conv2')
    
    pool1 = maxpool(conv2, 3, 2,'layer3_pool1')
    
    conv3 = conv(pool1, 64, 128, 3, 1,'layer4_conv3')
    
    conv4 = conv(conv3, 128, 128, 3, 1,'layer5_conv4')
    
    pool2 = maxpool(conv4, 3, 2,'layer6_pool2')

    conv5 = conv(pool2, 128, 256, 3, 1,'layer7_conv5')

    conv6 = conv(conv5, 256, 256, 3, 1,'layer8_conv6')

    conv7 = conv(conv6, 256, 256, 1, 1,'layer9_conv7')

    pool3 = maxpool(conv7, 3, 2,'layer10_pool3')
    
    conv8 = conv(pool3, 256, 512, 3, 1,'layer11_conv8')

    conv9 = conv(conv8, 512, 512, 3, 1,'layer12_conv9')

    conv10 = conv(conv9, 512, 512, 1, 1,'layer13_conv10')

    pool4 = maxpool(conv10, 3, 2,'layer14_pool4')
    
    conv11 = conv(pool4, 512, 512, 3, 1,'layer15_conv11')

    conv12 = conv(conv11, 512, 512, 3, 1,'layer16_conv12')

    conv13 = conv(conv12, 512, 512, 1, 1,'layer17_conv13')

    pool5 = maxpool(conv13, 3, 2,'layer18_pool5')
    

    pool_shape = pool5.get_shape().as_list()
    #計算向量長度 長x寬x高(第二、三、四次元,第一維為batch個數)
    nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
    #通過函數變成向量
    reshaped = tf.reshape(pool5, [pool_shape[0], nodes])
    
    fc1 = fc(reshaped, nodes, 4096, 'layer19_fc1')
    
    fc2 = fc(fc1, 4096, 4096, 'layer20_fc2')
    
    fc3 = fc(fc2, 4096, 2, 'layer21_fc3' )
    
    soft = tf.nn.softmax(fc3)

    return soft
           

搭建完成網絡之後,可以利用圖檔進行測試,輸入一張圖檔,檢視通過神經網絡後的輸出次元。下面是測試vgg16神經網絡的代碼以及結果展示。

import tensorflow as tf
import cv2
import numpy as np
path = r"C:\Users\user\Desktop\lena.jpg"
tf.compat.v1.reset_default_graph() #先清空計算圖
image = cv2.imread(path, 1)
image_data = tf.image.convert_image_dtype(image,dtype=tf.float32)
with tf.compat.v1.Session() as sess:
    image = sess.run(image_data)
    image = cv2.resize(image,(224,224))
    reshape_xs=np.reshape(image,(1,224,224,3))
    y = vgg_16(reshape_xs)
    print(y)
#輸出結果為
#Tensor("Softmax:0", shape=(1, 2), dtype=float32)
           

結語:

如果對你有幫助,就給我一個贊吧,如何有問題,可以在評論區進行讨論。

上一篇:[基于tensorflow的人臉檢測] 基于神經網絡的人臉檢測4——資料集的标簽生成

下一篇:[基于tensorflow的人臉檢測] 基于神經網絡的人臉檢6——資料的存儲與加載

繼續閱讀