网络结构

1.全连接网络

缺点:
如果一个图像的尺寸是(28,28,1)。使用全连接的网络结构,即,网络中的神经与与相邻层上的每个神经元均连接,那就意味着我们的网络有28 * 28 =784个神经元,hidden层采用了15个神经元,那么简单计算一下,我们需要的参数个数(w和b)就有:7841510+15+10=117625个,这个参数太多了,随便进行一次反向传播计算量都是巨大的,从计算资源和调参的角度都不建议用传统的神经网络。(参数计算:图片是由像素点组成的,用矩阵表示的,2828的矩阵,肯定是没法直接放到神经元里的,我们得把它“拍平”,变成一个2828=784 的一列向量,这一列向量和隐含层的15个神经元连接,就有78415=11760个权重w,隐含层和最后的输出层的10个神经元连接,就有1176010=117600个权重w,再加上隐含层的偏置项15个和输出层的偏置项10个,就是:117625个参数了)

生成全连接网络模型,并输入自定义图片验证
参考:https://github.com/niektemme/tensorflow-mnist-predict/find/master

a.py(全连接模型训练):

a.py(全连接模型训练)

import tensorflow.examples.tutorials.mnist.input_data as input_data
input_data = input_data.read_data_sets("MNIST/data",one_hot=True)
import tensorflow as tf
import matplotlib.pyplot as plt
import cv2

class Net:
    def __init__(self):
        self.x = tf.placeholder(dtype=tf.float32, shape=[None, 784])
        self.y = tf.placeholder(dtype=tf.float32, shape=[None, 10])
        self.w1 = tf.Variable(tf.truncated_normal(shape=[784, 512], stddev=tf.sqrt(1/512),dtype=tf.float32))
        self.b1 = tf.Variable(tf.zeros([512]))

        self.w2 = tf.Variable(tf.truncated_normal(shape=[512, 256], stddev=tf.sqrt(1 / 256), dtype=tf.float32))
        self.b2 = tf.Variable(tf.zeros([256]))

        self.w3 = tf.Variable(tf.truncated_normal(shape=[256, 128], stddev=tf.sqrt(1 / 128), dtype=tf.float32))
        self.b3 = tf.Variable(tf.zeros([128]))

        self.w4 = tf.Variable(tf.truncated_normal(shape=[128, 64], stddev=tf.sqrt(1 / 64), dtype=tf.float32))
        self.b4 = tf.Variable(tf.zeros([64]))

        self.w5 = tf.Variable(tf.truncated_normal(shape=[64, 10], stddev=tf.sqrt(1 / 10), dtype=tf.float32))
        self.b5 = tf.Variable(tf.zeros([10]))

    def forward(self):
        self.y1 = tf.sigmoid(tf.matmul(self.x, self.w1)+self.b1)
        self.y2 = tf.sigmoid(tf.matmul(self.y1, self.w2) + self.b2)
        self.y3 = tf.sigmoid(tf.matmul(self.y2, self.w3) + self.b3)
        self.y4 = tf.sigmoid(tf.matmul(self.y3, self.w4) + self.b4)
        self.y5 = tf.sigmoid(tf.matmul(self.y4, self.w5) + self.b5)

    def backward(self):
        self.loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y, logits=self.y5))
        self.optimizer = tf.train.AdamOptimizer().minimize(self.loss)


if __name__ == "__main__":

    net = Net()
    net.forward()
    net.backward()
    init = tf.global_variables_initializer()
    # a = []
    # b = []
    # plt.ion()


    with tf.Session() as sess:

        sess.run(init)

        saver = tf.train.Saver()
        saver.save(sess, "save/data.ckpt")

        for i in range(5000):
            # if i in range(200):
            s1, s2 = input_data.train.next_batch(100)
            loss, optimizer,y_5 = sess.run([net.loss, net.optimizer,net.y5], feed_dict={net.x: s1, net.y: s2})
        # print(sess.run(tf.argmax(y5[0]),feed_dict={net.x:(1,a)}))

            if i%200 == 0:
                print(sess.run(tf.argmax(s2[0])),"------------->",sess.run(tf.argmax(y_5[0])))

                # print("****{}".format(j), loss, "****")
                # j = j + 1
            if i%500 == 0:
                predict = tf.equal(tf.argmax(net.y, 1), tf.argmax(net.y5, 1))
                # print("jdjjdjdjdjd",predict,"djkdfjegjiergreg")
                accuracy = tf.reduce_mean(tf.cast(predict, dtype=tf.float32))
                print(sess.run(accuracy,feed_dict={net.x:input_data.train.images,net.y:input_data.train.labels}))
            # a.append(i)
            # b.append(loss)
            # plt.clf()
            # plt.plot(a,b)
            # plt.pause(0.01)
b.py (输入数字图片,进行识别)


# import modules
import sys
import tensorflow as tf
from PIL import Image, ImageFilter
import a

def predictint(imvalue):
    """
    This function returns the predicted integer.
    The input is the pixel values from the imageprepare() function.
    """

    # Define the model (same as when creating the model file)
    net = a.Net()
    net.forward()
    net.backward()

    init_op = tf.global_variables_initializer()
    saver = tf.train.Saver()

    """
    Load the model.ckpt file
    file is stored in the same directory as this python script is started
    Use the model to predict the integer. Integer is returend as list.
    Based on the documentatoin at
    https://www.tensorflow.org/versions/master/how_tos/variables/index.html
    """
    with tf.Session() as sess:
        sess.run(init_op)
        saver.restore(sess, "save/data.ckpt")
        # print ("Model restored.")

        prediction = tf.argmax(net.y5, 1)

        # return prediction.eval(feed_dict={net.x:[imvalue]}, session=sess)
        return sess.run(prediction,feed_dict={net.x: [imvalue]})

def imageprepare(argv):
    """
    This function returns the pixel values.
    The imput is a png file location.
    """
    im = Image.open(argv).convert('L')
    width = float(im.size[0])
    height = float(im.size[1])
    newImage = Image.new('L', (28, 28), 255)  # creates white canvas of 28x28 pixels

    if width > height:  # check which dimension is bigger
        # Width is bigger. Width becomes 20 pixels.
        nheight = int(round((20.0 / width * height), 0))  # resize height according to ratio width
        if (nheight == 0):  # rare case but minimum is 1 pixel
            nheight = 1
        # resize and sharpen
        img = im.resize((20, nheight), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wtop = int(round(((28 - nheight) / 2), 0))  # caculate horizontal pozition
        newImage.paste(img, (4, wtop))  # paste resized image on white canvas
    else:
        # Height is bigger. Heigth becomes 20 pixels.
        nwidth = int(round((20.0 / height * width), 0))  # resize width according to ratio height
        if (nwidth == 0):  # rare case but minimum is 1 pixel
            nwidth = 1
        # resize and sharpen
        img = im.resize((nwidth, 20), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wleft = int(round(((28 - nwidth) / 2), 0))  # caculate vertical pozition
        newImage.paste(img, (wleft, 4))  # paste resized image on white canvas

    # newImage.save("sample.png")

    tv = list(newImage.getdata())  # get pixel values


    # normalize pixels to 0 and 1. 0 is pure white, 1 is pure black.
    tva = [(255 - x) * 1.0 / 255.0 for x in tv]
    print(tva)
    return tva
    # print(tva)



if __name__ == "__main__":
    """
    Main function.
    """
    imvalue = imageprepare("9.png")#1/2/3/6/7
    predint = predictint(imvalue)
    print(predint[0])  # first value in list

2.MTCNN网络

论文题目《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》

MTCNN提出了一种Multi-task的人脸检测框架,将人脸检测和人脸特征点检测同时进行。论文使用3个CNN级联的方式。他的思想是多任务级联

重点:
(1)由于RNet是一个全卷积网络,所以当作Inference的时候输入数据可以是任意大小的图片。这样网络最后的输出就不是一个11大小的特征图了,而是一个HW大小的特征网格。该特征网格每个网格的坐标表示对应一个回归框的位置信息,如下图所示:

其中右面是PNet网络生成的特征图,左边是原始图片中对应的回归框坐标。原始图片中回归框坐标需要经过反向运算,计算方式如下,其中cellSize=12,是因为1212的图片进去后变成11,;stride=2是因为几层卷积中只有一个stride为2

x1= (stride*1)/scale,
y1= (stride*1)/scale,
x2= ((stride*1)+cellSize)/scale
y2= ((stride*1)+cellSize)/scale

(2)
①做图片的金字塔:顶端金字塔最小应该大于12 * 12

② 将每个金字塔的图片输入到P网络(在人脸的地方会有大量的框,),进而输出所有框的置信度定义一个置信度:大于此值为人脸(因为是初选,置信度定义不易过大,):得到5个通道的特征图:第一个通道代表置信度:凡是大于0.7的留下来然后。反算回去:IDX(特征图的索引)*步长=进入P网络图的尺寸,然后除以原图的比例,得到建议框(为正方形),另外四个通道为位置的偏移:XX * / W = X关(偏移)得到原框X.然后通过非大值抑制,将多余的框去掉,(不在建议框做NMS的原因是因为建议框往往是个正方形,框的位置往往会过大,会过滤的不该过滤的信息)

③将信息输入到网络(图片大小固定:24 * 24):由于得到的原框大小可能为长方形,所以需要PIL等工具在原图上接一个正方形,然后在等比例缩放,得到的24×24的人脸不会变形。然后重新确定位置的偏移,得到新的框,再做NMS

③ 将信息输入到ø网络(图片大小固定为48×48)

(3)
建立图像金字塔:
他的做法非常简单就是将原图尺寸反复乘以缩放因子,直到达到最小的尺寸为止,这样做的目的是不断缩放图片,以便得到更多的boundingbox。

(4)
将那些坐标的值大于或者小于原图尺寸的候选框的坐标值修改为对应原图位置的边界坐标,如图所示:
在这里插入图片描述

框架
算法流程
在这里插入图片描述
当给定一张照片的时候,将其缩放到不同尺度形成图像金字塔,以达到尺度不变。

Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。

Stage 2:使用N-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。

Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。

CNN结构

本文使用三个CNN,结构如图:
在这里插入图片描述
P-NET
在这里插入图片描述
该训练网络的输入是一个 12×12 大小的图片,所以训练前需要生成 PNet 网络的训练数据。训练数据可以通过和 Guarantee True Box 的 IOU 的计算生成一系列的 bounding box。可以通过滑动窗口或者随机采样的方法获取训练数据,训练数据分为三种正样本,负样本,中间样本。其中正阳本是生成的滑动窗口和 Guarantee True Box 的 IOU 大于 0.65,负样本是 IOU 小于 0.3,中间样本是 IOU 大于 0.4 小于 0.65。

然后把 bounding box resize 成 12×12 大小的图片,转换成 12×12×3 的结构,生成 PNet 网络的训练数据。训练数据通过 10 个 3×3×3 的卷积核(101010特征图),2×2 的 Max Pooling(stride=2)操作,一个卷积核有一个特征图,生成 10 个 5×5 的特征图。接着特征图作为输入,通过 16 个 3×3×10 的卷积核,卷积核深度要和输入通道相同,生成 16 个 3×3 的特征图。接着通过 32 个 3×3×16 的卷积核,生成 32 个 1×1 的特征图。

最后针对 32 个 1×1 的特征图,可以通过 2 个 1×1×32 的卷积核,生成 2 个 1×1 的特征图用于分类;4 个 1×1×32 的卷积核,生成 4 个 1×1 的特征图用于回归框判断;10 个 1×1×32 的卷积核,生成 10 个 1×1 的特征图用于人脸轮廓点的判断。

RNet:
在这里插入图片描述
模型输入为 24×24 大小的图片,通过 28 个 3×3×3 的卷积核(24-3+1=22即28个2222的特征图)和 3×3(stride=2)的 max pooling 后生成 28 个 11×11(步长为2时,如果输入是偶数时:n/步长即22/2=11,如果输 入时奇数时:(n-1)/步长) 的特征图;通过 48 个 3×3×28 的卷积核(48个11-3+1即99的特征图)和 3×3(stride=2)的 max pooling 后生成 48 个 4×4 ((9-1)/2)的特征图;通过 64 个 2×2×48 的卷积核后,生成 64 个 3×3 的特征图;把 3×3×64 的特征图转换为 128 大小的全连接层;对回归框分类问题转换为大小为 2 的全连接层;对 bounding box 的位置回归问题,转换为大小为 4 的全连接层;对人脸轮廓关键点转换为大小为 10 的全连接层。

ONet:
ONet 是 MTCNN 中的最后一个网络,用于做网络的最后输出。ONet 的训练数据生成类似于 RNet,检测数据为图片经过 PNet 和 RNet 网络后,检测出来的 bounding boxes,包括正样本,负样本和中间样本。ONet 的模型结构如下所示:
在这里插入图片描述
模型输入是一个 48×48×3 大小的图片,通过 32 个 3×3×3 的卷积核和 3×3(stride=2)的 max pooling 后转换为 32 个 23×23 的特征图;通过 64 个 3×3×32 的卷积核和 3×3(stride=2)的 max pooling 后转换为 64 个 10×10 的特征图;通过 64 个 3×3×64 的卷积核和 3×3(stride=2)的 max pooling 后转换为 64 个 4×4 的特征图;通过 128 个 2×2×64 的卷积核转换为 128 个 3×3 的特征图;通过全链接操作转换为 256 大小的全链接层;最好生成大小为 2 的回归框分类特征;大小为 4 的回归框位置的回归特征;大小为 10 的人脸轮廓位置回归特征。

3.CNN网络

卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层、全连接层组成,即INPUT(输入层)-CONV(卷积层)-RELU(激活函数)-POOL(池化层)-FC(全连接层)
1.卷积层多通道计算
卷积核除了长宽这两个参数之外还有通道数这个参数,首先需要明确的是单个卷积核的通道数要等于图像的通道数,一般图像是RGB模式的话,卷积核的大小为hw3。

卷积过程中,输入层有多少个通道,卷积核就要有多少个通道,但是卷积核的数量是任意的,卷积核的数量决定了卷积后 featuremap 的数量即通道数。

卷积过程的最后一步要包括生成 feature,将 各个通道对应坐标的值相加就生成了 feature。

在这里插入图片描述
一般卷积核不止一个,对于多个卷积核的情况也不复杂,直接对每个卷积核进行单个卷积核的操作,然后把它们拼在一起就行了,如图所示:

整个层都共享使用卷积核即共享权重
在这里插入图片描述
2.池化层
池化层(pooling)的作用主要是降低维度,通过对卷积后的结果进行降采样来降低维度,分为最大池化和平均池化两类。
3.全连接层
经过卷积,relu后得到3x3x5的输出。那它是怎么样把3x3x5的输出,转换成1x4096的形式?
在这里插入图片描述
很简单,可以理解为在中间做了一个卷积。
在这里插入图片描述
从上图我们可以看出,我们用一个3x3x5的filter 去卷积激活函数的输出,得到的结果就是一个fully connected layer 的一个神经元的输出,这个输出就是一个值。因为我们有4096个神经元。我们实际就是用一个3x3x5x4096的卷积层去卷积激活函数的输出。

说明:
为什么卷积核有效?

为什么使用卷积核计算后分类效果要由于普通的神经网络呢?
  通过第一个卷积核计算后的feature_map是一个三维数据,在第三列的绝对值最大,说明原始图片上对应的地方有一条垂直方向的特征,即像素数值变化较大;而通过第二个卷积核计算后,第三列的数值为0,第二行的数值绝对值最大,说明原始图片上对应的地方有一条水平方向的特征。

仔细思考一下,这个时候,我们设计的两个卷积核分别能够提取,或者说检测出原始图片的特定的特征。此时我们其实就可以把卷积核就理解为特征提取器啊!现在就明白了,为什么我们只需要把图片数据灌进去,设计好卷积核的尺寸、数量和滑动的步长就可以让自动提取出图片的某些特征,从而达到分类的效果啊!

注:
1.此处的卷积运算是两个卷积核大小的矩阵的内积运算,不是矩阵乘法。即相同位置的数字相乘再相加求和。不要弄混淆了。

2.卷积核的公式有很多,这只是最简单的一种。我们所说的卷积核在数字信号处理里也叫滤波器,那滤波器的种类就多了,均值滤波器,高斯滤波器,拉普拉斯滤波器等等,不过,不管是什么滤波器,都只是一种数学运算,无非就是计算更复杂一点。

3.每一层的卷积核大小和个数可以自己定义,不过一般情况下,根据实验得到的经验来看,会在越靠近输入层的卷积层设定少量的卷积核,越往后,卷积层设定的卷积核数目就越多。具体原因大家可以先思考一下,小结里会解释原因。

为什么采用Max Pooling?

从计算方式来看,算是最简单的一种了,取max即可,但是这也引发一个思考,为什么需要Max Pooling,意义在哪里?如果我们只取最大值,那其他的值被舍弃难道就没有影响吗?不会损失这部分信息吗?如果认为这些信息是可损失的,那么是否意味着我们在进行卷积操作后仍然产生了一些不必要的冗余信息呢?

其实从上文分析卷积核为什么有效的原因来看,每一个卷积核可以看做一个特征提取器,不同的卷积核负责提取不同的特征,我们例子中设计的第一个卷积核能够提取出“垂直”方向的特征,第二个卷积核能够提取出“水平”方向的特征,那么我们对其进行Max Pooling操作后,提取出的是真正能够识别特征的数值,其余被舍弃的数值,对于我提取特定的特征并没有特别大的帮助。那么在进行后续计算使,减小了feature map的尺寸,从而减少参数,达到减小计算量,缺不损失效果的情况。

不过并不是所有情况Max Pooling的效果都很好,有时候有些周边信息也会对某个特定特征的识别产生一定效果,那么这个时候舍弃这部分“不重要”的信息,就不划算了。所以具体情况得具体分析,如果加了Max Pooling后效果反而变差了,不如把卷积后不加Max Pooling的结果与卷积后加了Max Pooling的结果输出对比一下,看看Max Pooling是否对卷积核提取特征起了反效果。

小结:
  
  这一节我们介绍了最基本的卷积神经网络的基本层的定义,计算方式和起的作用。有几个小问题可以供大家思考一下:

1.卷积核的尺寸必须为正方形吗?可以为长方形吗?如果是长方形应该怎么计算?

2.卷积核的个数如何确定?每一层的卷积核的个数都是相同的吗?

3.步长的向右和向下移动的幅度必须是一样的吗?

如果对上面的讲解真的弄懂了的话,其实这几个问题并不难回答。下面给出我的想法,可以作为参考:

1.卷积核的尺寸不一定非得为正方形。长方形也可以,只不过通常情况下为正方形。如果要设置为长方形,那么首先得保证这层的输出形状是整数,不能是小数。如果你的图像是边长为 28 的正方形。那么卷积层的输出就满足 [ (28 - kernel_size)/ stride ] + 1 ,这个数值得是整数才行,否则没有物理意义。譬如,你算得一个边长为 3.6 的 feature map 是没有物理意义的。 pooling 层同理。FC 层的输出形状总是满足整数,其唯一的要求就是整个训练过程中 FC 层的输入得是定长的。如果你的图像不是正方形。那么在制作数据时,可以缩放到统一大小(非正方形),再使用非正方形的 kernel_size 来使得卷积层的输出依然是整数。总之,撇开网络结果设定的好坏不谈,其本质上就是在做算术应用题:如何使得各层的输出是整数。

2.由经验确定。通常情况下,靠近输入的卷积层,譬如第一层卷积层,会找出一些共性的特征,如手写数字识别中第一层我们设定卷积核个数为5个,一般是找出诸如"横线"、“竖线”、“斜线”等共性特征,我们称之为basic feature,经过max pooling后,在第二层卷积层,设定卷积核个数为20个,可以找出一些相对复杂的特征,如“横折”、“左半圆”、“右半圆”等特征,越往后,卷积核设定的数目越多,越能体现label的特征就越细致,就越容易分类出来,打个比方,如果你想分类出“0”的数字,你看到这个特征,能推测是什么数字呢?只有越往后,检测识别的特征越多,试过能识别这几个特征,那么我就能够确定这个数字是“0”。

3.有stride_w和stride_h,后者表示的就是上下步长。如果用stride,则表示stride_h=stride_w=stride。

CNN 中 1x1 卷积核的作用:
1、增加网络的深度:

其实,这涉及到感受野的问题,我们知道卷积核越大,它生成的 featuremap 上单个节点的感受野就越大,随着网络深度的增加,越靠后的 featuremap 上的节点感受野也越大。因此特征也越来越抽象。

但有的时候,我们想在不增加感受野的情况下,让网络加深,为的就是引入更多的非线性。

而 1x1 卷积核,恰巧可以办到。

我们知道,卷积后生成图片的尺寸受卷积核的大小和跨度影响,但如果卷积核是 1x1 ,跨度也是 1,那么生成后的图像大小就并没有变化。

但通常一个卷积过程包括一个激活函数,比如 Sigmoid 和 Relu。

所以,在输入不发生尺寸的变化下,却引入了更多的非线性,这将增强神经网络的表达能力。

2.升维或者是降维

卷积后的的 featuremap 通道数是与卷积核的个数相同的

所以,如果输入图片通道是 3,卷积核的数量是 6 ,那么生成的 feature map 通道就是 6,这就是升维,如果卷积核的数量是 1,那么生成的 feature map 只有 1 个通道,这就是降维度。

值得注意的是,所有尺寸的卷积核都可以达到这样的目的。

那为什么要用 1x1 呢

原因就是数据量的大小,我们知道在训练的时候,卷积核里面的值就是要训练的权重,3x3 的尺寸是 1x1 所需要内存的 9 倍,其它的类似。所以,有时根据实际情况只想单纯的去提升或者降低 feature map 的通道,1x1 无疑是一个值得考虑的选项。

4.facenet

有关博客:https://www.cnblogs.com/zyly/p/9703614.html
谷歌人脸检测算法,发表于 CVPR 2015,利用相同人脸在不同角度等姿态的照片下有高内聚性,不同人脸有低耦合性,提出使用 cnn + triplet mining 方法,在 LFW 数据集上准确度达到 99.63%,在 youtube 人脸数据集上准确度 95.12%,比以往准确度提升了将近 30%。

方法
通过 CNN 将人脸映射到欧式空间的特征向量上,计算不同图片人脸特征的距离,通过相同个体的人脸的距离,总是小于不同个体的人脸这一先验知识训练网络。
测试时只需要计算人脸特征,然后计算距离使用阈值即可判定两张人脸照片是否属于相同的个体。

直接学习图像到欧式空间上点的映射,两张图像所对应的特征的欧式空间上的点的距离直接对应着两个图像是否相似。

图像的类内距离明显的小于类间距离,阈值大约为1.1左右。

实现
Facenet的结构如下图:

前面就是一个传统的卷积神经网络,然后在求L2范数之前进行归一化,就建立了这个嵌入空间,最后损失函数。

如上图所示
batch :是指输入的人脸图像样本,这里的样本是已经经过人脸检测找到人脸并裁剪到固定尺寸(例如160x160)的图片样本。
Deep architecture:指的是采用一种深入学习架构例如imagenet历年冠军网络中的ZF,googlenet等。
L2 :是指特征归一化(使其特征的||f(x)||2=1,这里是2次方的意思。这样所有图像的特征都会被映射到一个超球面上)
Embeddings: 就是前面经过深度学习网络,L2归一化后生成的特征向量(这个特征向量就代表了输入的一张样本图片)
riplet Loss: 就是有三张图片输入的Loss(之前的都是Double Loss或者 是 SingleLoss)。直接学习特征间的可分性:相同身份之间的特征距离要尽可能的小,而不同身份之间的特征距离要尽可能的大。

先导入模型参数
然后导入两张图片,分别获取其经过模型后得到的128维特征向量
最后计算两个向量的欧氏距离

注意:
1.对图片使用 CNN 网络提取特征向量。

  1. 1.存在特征向量的维度选择问题,维度约小计算越快,但是太小的话很难区分不同图片;维度越大越容易区分不同图片,但是太大训练模型不易收敛,且测试时计算慢,占用空间大。作者实验证明
    128 维的特征能够较好的平衡这个问题。

  2. 2.CNN 模型的选择,高精度的模型往往参数多,计算量大。移动设备上最好使用体积小,精度略低的模型;服务器上可以使用高精度,高计算量的模型。

  3. 3.另外一点embeding这层实现方式就是linear,这点在论文上找了一会儿才找到,通过模型训练收敛得到一个合适的线性欧式向量提取器。

2.使用三元损失函数。
之前的工作有人使用的是二元损失函数,二元损失函数的目标是把相同个体的人脸特征映射到空间中的相同点,而三元损失函数目标是映射到相同的区域,使得类内距离小于类间距离。

一 MTCNN算法结构

MTCNN算法是一种基于深度学习的人脸检测和人脸对齐方法,它可以同时完成人脸检测和人脸对齐的任务,相比于传统的算法,它的性能更好,检测速度更快。
一 MTCNN算法结构
MTCNN算法是一种基于深度学习的人脸检测和人脸对齐方法,它可以同时完成人脸检测和人脸对齐的任务,相比于传统的算法,它的性能更好,检测速度更快。

MTCNN算法包含三个子网络:Proposal Network(P-Net)、Refine Network(R-Net)、Output Network(O-Net),这三个网络对人脸的处理依次从粗到细。

在使用这三个子网络之前,需要使用图像金字塔将原始图像缩放到不同的尺度,然后将不同尺度的图像送入这三个子网络中进行训练,目的是为了可以检测到不同大小的人脸,从而实现多尺度目标检测。

4.siamese network孪生网络

对于两个不同的输入,运行相同的卷积神经网络,然后比较它们,这一般叫做 Siamese network。
在这里插入图片描述
在这里插入图片描述

5.facenet

通过 CNN 将人脸映射到欧式空间的特征向量上,计算不同图片人脸特征的距离,通过相同个体的人脸的距离,总是小于不同个体的人脸这一先验知识训练网络。
测试时只需要计算人脸特征,然后计算距离使用阈值即可判定两张人脸照片是否属于相同的个体。

在这里插入图片描述
对图片使用 CNN 网络提取特征向量。
存在特征向量的维度选择问题,维度约小计算越快,但是太小的话很难区分不同图片;维度越大越容易区分不同图片,但是太大训练模型不易收敛,且测试时计算慢,占用空间大。作者实验证明 128 维的特征能够较好的平衡这个问题。
CNN 模型的选择,高精度的模型往往参数多,计算量大。移动设备上最好使用体积小,精度略低的模型;服务器上可以使用高精度,高计算量的模型。
另外一点embeding这层实现方式就是linear,这点在论文上找了一会儿才找到,通过模型训练收敛得到一个合适的线性欧式向量提取器。

使用三元损失函数。
之前的工作有人使用的是二元损失函数,二元损失函数的目标是把相同个体的人脸特征映射到空间中的相同点,而三元损失函数目标是映射到相同的区域,使得类内距离小于类间距离。
最终的损失函数为:
在这里插入图片描述
可以看到上面的公式中需要三个输入人像,如何选择这一个三元组训练呢?为了保证训练收敛速度,我们就选择距离最远的相同人像,和距离最近的不同人像来训练好了。于是作者在每个 mini-batch 中进行上述选择。
卷积网络。选择模型是常见的问题,作者针对 ZF/GoogLeNet 做了不同的测试。
最终验证。通过计算不同图片的特征向量的距离,使用阈值后得到结果。

FaceNet的center-loss和SoftMax简介(比较简略):https://7n.w3cschool.cn/attachments/image/20180109/1515464523236480.png
https://blog.csdn.net/Eclipsesy/article/details/78909799

FaceNet models:
The folder “20170511-185253” stores the model trained by CASIA-WebFace dataset. The folder “20170512-110547” stores the model trained by MS-Celeb-1M dataset.

FaceNet pre-trained模型以及FaceNet源码使用方法和讲解:
https://blog.csdn.net/MrCharles/article/details/80360461

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值