人脸识别算法的小改进

Deeplearning.ai课程中第4门卷积神经网络里, 第4周的作业是做一个人脸识别的小应用.

这门课的作业设计都有些问题. 因为需要的数据量很大, 需要的算力也很高, 所以不大可能让学生从头做一个深度神经网络然后训练出结果. 所以作业基本是两头的, 一头是教如何建立这个深度神经网络, 一头是教如何应用这个建好的网络, 中间的部分就一笔带过说我们已经帮各位训练好了, 大家load就行了.

原有的人脸识别算法:

人脸识别的算法是所谓one-shot的方式, 不是直接去分类, 而是判断两个图片是否是属于统一类的, 或着说, 就是计算两个图片之间的距离.

人脸的照片(96*96像素)先经过一个深度神经网络编码器, 输出一个128位的编码.

FRmodel = faceRecoModel(input_shape=(3, 96, 96))
load_weights_from_FaceNet(FRmodel)

这个编码器是已经训练好的. 需要的话可以从这里下载到, (具体是那个文件我还没弄清楚. )

有了编码器, 就可以把任意人脸的照片进行编码, 例如:

database["danielle"] = img_to_encoding("images/danielle.png", FRmodel)

然后就是计算待测图片和目标图片编码的欧式距离. 一句话而已, 但属于作业内容, 我不能写出来.

算出距离以后, 跟一个阈值(! yu4 zhi2 !)比较一下, 如果距离小于阈值就认为两个图片是一个人的, 于是就"识别"了.

Andrew Ng老师给出的应用样例是百度的门禁. 人走过去, 照相, 与ID记录中保存的照片对比, 距离小于阈值, 放行.

原算法的问题

交付的时候编码器应该是已经完成的, 阈值也就是一个单一的数, 估计也是写死的. 所以这个人脸识别的应用在交付给用户应用的时候是固定的. 当然这也无可厚非, 毕竟大多数软件是这样的.

但神经网络毕竟得到的是个概率, 阈值也是人为设定的, 有可能出现一直把老板和扫地僧搞混的情况. 或者类似apple FaceID里的问题, 也许亲缘系数很近的亲属是可以互相解锁的. (10岁男儿解锁其母的FaceID, wired报道, 网易报道 )

(写到这的时候我意识到自己不小心开源了一个可以赚钱的算法, 算了, 开了就开了吧. 好像丢了一大笔钱 )

  • 理论上, 可以把编码器重新训练一遍, 比如把老板, 亲属, 扫地僧的照片加入到训练集里再重新修炼.
  • 理论上, 用户也可以调整阈值, 提高或者降低特异性敏感性.

但实际上, 显然让用户重新训练这么大而深的网络不现实, 没有数据集也没有那么强的算力. 调整阈值也可能会造成其他的连带问题.

综上, 赋予用户后期调整的能力很重要.

并联网络

之前的神经网络, 全连接也好, 卷积神经网络也好, 都是串联的, 一层接着一层, 直到ResNet出现, 在两层网络之间增加了短路的通道. 所谓短路, 就是直接把上一层的计算结果送到后面去. 被短路的几层网络只是负责训练"残差".

类似的思想也可以用在这里. 分两条路径:

  • 代数函数路径
def dist_path(x1,x2,threshold):
    d = tf.norm((x1-x2),axis=-1)
    # output=1-Activation('sigmoid')(d-threshold)
    output = 0.5 - (tf.sign(d-threshold))/2
    return output

这条路径上, 还是使用欧式距离来计算两个输入图片x1,x2之间的距离, 然后跟阈值比较. 如果想二值输出, 就用符号函数sign, 如果想得到连续输出就用一下sigmoid.

这条路径就是原来的计算方式, 参数都是写死的.

  • 修正神经网络

在这条路径之外, 我又并联了一条神经网络路径, 所用的神经网络其实要求并不高, 一是大部分的feature已经被编码器模型提取好了, 二是代数路径其实效果已经不错, 只需要微调一下. 所以并不一定需要多复杂的网络.

def tinker_path(x1,x2): 
    X=tf.concat([x1,x2],axis=-1)
    X = Dense(128, activation='relu', 
              kernel_initializer = 
              RandomNormal(mean=0.0, stddev=0.05))(X)
    X = Dense(128, activation='relu', 
              kernel_initializer = 
              RandomNormal(mean=0.0, stddev=0.05))(X)
    X = Dense(1, activation='tanh', 
              kernel_initializer = 
              RandomNormal(mean=0.0, stddev=0.05))(X)
    return X

这里仅使用了一个简单的全连接网络示意, 实际中可能比这个层次稍微多一点, 但我觉得没必要太深. 卷积网络可以考虑, 而且可以考虑把输入的两份编码数据交叉排布成一个类似图片的东西.

由于并联上去的神经网络是为了修正误差用的, 所以通常来说它的输出值应该很小, 不影响主路径的结果. 所以我在初始化的时候使用的随机初始值是很集中于0附近的. 把标准差stddev改得很小.

  • 合并网络

将代数函数路径和修正神经网络并联在一起. 所谓并联就是将两个网络进行加权平均.

def face_tinker(x1,x2,threshold,alpha=[0.7,  0.3]):
    paths=[dist_path(x1,x2,threshold), tinker_path(x1,x2)]
    X=Add()([ a*path for (a,path) in zip(alpha,paths)])
    return X

主要的是代数函数路径, 给的权重应当高一点, 次要的是修正神经网络路径, 给的权重可以低一些, 但是修正神经网络要真的能够改变输出才行, 如果是[0.9, 0.1]这样的加权平均就没什么意义了.

完整的代码在github上

后续

我对tensorflow还不是很熟练, 还应当补充上loss, 训练之类的.

实际使用中如果两个人总是搞混, 可以把各自的照片多拍一些, 固定编码器的参数, 只去训练修正神经网络, 哪怕过拟合了也没什么关系, 毕竟是小范围使用, 不必太过追求泛化.

唉, 丢了一大笔钱.

并联网络推广

在已知代数函数上并联一个神经网络进行修正的模式很有意思.

现有的知识中其实已经有大量的线性拟合或者简单的非线性拟合工具, 比如计算人工晶体度数的SRK公式, 但是这些公式面对特殊问题的时候还是会出问题, 比如遇到高度近视或者准分子激光手术后的患者.

完全抛弃原有的公式, 使用深度神经网络重做一个算法当然可以, 但这需要大量的数据堆砌, 好像人们以前的经验也就浪费了.

如果在已知代数函数的基础上并联一个神经网络, 用神经网络来修正原有函数, 就好像Taylor展开那样, 一点一点近似, 近似到够用就可以了.

也许对数据集的大小, 对训练神经网络所需要的算力, 要求都会减低一些吧.

不过, 我估计肯定有很多人尝试过了, 而且失败了不少. 通常觉得自己有个新想法的时候, 只是因为文献阅读得不够多.

EOF( )

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 大数据预测 (豆瓣)https://book.douban.com/subject/25841481/ 大数据预测...
    葡萄喃喃呓语阅读 298评论 0 1
  • 什么是ctags呢?wiki上是这样解释的: Ctags是一个用于从程序源代码树产生索引文件(或tag文件),从而...
    tailang阅读 1,715评论 0 2
  • 一个人, 此刻在等公交, 累到不想说话, 四十五度抬头仰望天空, 想找个答案, 想找个继续前行的理由, 但是天空不...
    吃货哆啦阅读 231评论 0 0
  • 文/邵桂香 一 山间旷野无人, 夕阳老树远村。 幸有几根电杆, 努力撑起黄昏。 二 秋风真是厉害, 无手拿着水彩...
    邵桂香阅读 407评论 0 3
  • 涅槃之阳,晨曦升,夕暮落,轮回之循,不换不变。不弋不迟,生亦在此,死亦在此,破红尘,唯汝沧澜。
    游吟pote阅读 74评论 0 0