cascade down_Cascaded CNN 方法寻找人脸关键点

Cascaded CNN 方法寻找人脸关键点

论文笔记

阅读论文

第一阶段阅读论文,大约两天大体阅读完论文 Deep Convolutional Network Cascade for Facial Point Detection。感觉还是比较缺乏论文阅读经验,但是比以前快了很多。主要阅读论文 intro、method 和 modeling。作者的思维比较奇特,把损失函数放在 experiment 部分,我找了好久没找到。

编写代码

寻找同学帮助,发现代码变化太快,旧经验有些跟不上。尝试瞎猫撞死耗子的策略,瞎写,显然不能成功,浪费 4+ 天时间。

静下心,阅读 Caffe 框架代码,C++ 不熟悉,读 C++ 代码没经验。硬着头皮读,不得法,痛苦,事倍功半;晚上,脑子突然灵光一闪,读继承关系和头文件(因为 C 的头文件只是函数声明,而宏定义可以临时找),有效,思路清晰。一天时间写完代码。

NaN 和收敛失败

计算结果 J(theta) 是 NaN,天!各种 Debug,找了 3+ 天,代码中没发现和数值相关的 BUG。也许是数值计算方法的问题?不能,这是框架写的代码。后来发是学习率调太大。之前已经调小过,无效,没想到还要继续调小。

再次验证,收敛失败。这是什么原因?后来发现是 loss 的设计存在问题,没有做 normalization。细节在这里。收敛成功。

算法效果验证

最直接的方法当然是输出坐标点,可惜一点都不直观。写了一堆代码用来在图上做各种标记,代码混乱成翔(后来抽取到 我的 github)。从输出来看,总体位置还算靠谱,但是效果并不好,虽然还没量化,但是我知道肯定不好,不用算了。

我天真的觉得是 overfit 了。在 train set 做个测试,underfit。

突然想到会不会是 BUG 导致所有输出都是一样的?检查了输出的坐标,虽然比较相近,但是确实是不同的,所以应该不是 BUG。这说明,没有提取到足够的 inter-face 特征?这个地方要想想。

单点验证

其实我没有完全按照论文实现。论文结构太复杂,存在 3 个级联,第一个级联有 3 个网络做平均。作者的说法是第一个级联最重要,所以我只实现了第一个级联的其中一个网络。有可能没有完全按照结构设计导致的问题?

另外一个思路是,用一个 kernel 去扫描 5 个不同的面部特征真的靠谱么?我也许试试五个 kernel?一时间没有思路为何 underfit。先做一个 left eye 试试吧。我快速 10000 轮迭代做出个 model,输出一百个图像来人力比较,第一印象是单点的确比多点要准确。看一下损失:

左眼坐标网络损失:I0920 16:27:52.355422 11912 solver.cpp:294] Iteration 10000, Testing net (#0)

I0920 16:27:52.606781 11912 solver.cpp:343] Test net output #0: loss = 0.00317065 (* 1 = 0.00317065 loss)

脸部坐标网络损失:I0920 16:19:16.628931 48513 solver.cpp:294] Iteration 10000, Testing net (#0)

I0920 16:19:16.885615 48513 solver.cpp:343] Test net output #0: loss = 0.0263838 (* 1 = 0.0263838 loss)

从数据来看,确实只做一个坐标效果会比较好。

重读论文

我想我一定是弄错论文某些细节了,我决定重新读一遍这篇论文。重新阅读论文过程中,我产生了新的想法。

之前的 network 只有一个 kernel,而作者提出的方案是 locally weight-sharing,开始的时候不甚明了,直接忽略了。我看了 Convolutional Neural Networks 突然想通了 weight-sharing 指的是什么意思。Convolutional layers consist of a rectangular grid of neurons. It requires that the previous layer also be a rectangular grid of neurons. Each neuron takes inputs from a rectangular section of the previous layer; the weights for this rectangular section are the same for each neuron in the convolutional layer. Thus, the convolutional layer is just an image convolution of the previous layer, where the weights specify the convolution filter.

Fully-Connected layer 的输入和输出的尺寸都是固定的,每一个神经元对应一个输出。根据 Andrew NG 的 UFLDL,我产生了这种观念:卷积层只有一个神经元,这个神经元就是 kernel,是 weight 的矩阵。我突然发觉这种观念可能有问题。

我现在的理解是这样的,不知道有没有错。一般看到,kernel 只有一个,而 convolution layer 的输入是没有大小限制的,而输出也固定,根据图像大小产生不同大小的 feature map。如果换个角度看,convolution layer 是一个 (N−m+1)×(N−m+1) 个 m×m 的 kernel 的神经元,每个神经元对应着自己的感受域,产生一个输出:如果这样定义,convolution layer 也是输入输出大小固定的。而 weight-sharing 也很好理解了,就是这 (N−m+1)×(N−m+1) 个 kernel 现在变成了同一个,他们 share weight。而文章提出的方法就是,不再使用整个 feature map 做 weight-sharing,用同一个 kernel,而是分区域使用不同的 kernel。

输入区域似乎也和我想的不一样,原文的 input range 是脸部区域 + 一个百分比...,我觉得我当时没看到是不是不太合适....

看完我大概是怎么一个思路:先修改输入区域;

实现 locally weight-sharing 看看效果;

进一步提高再实现 cascaded 结构,这是后话。

调整输入范围

根据上次阅读论文的想法,先测试左眼的检测,进行数据清洗,只截取左眼。结果发现,虽然输出的 cost 变小了,但是看图片依然是 underfit。

进行 64 样本的测试,发现依旧是 underfit,这实在诡异,难道是 Bug?那么测试 1 样本试试,还是不准。输出预测值和坐标试试....咦,数据绩小,所以几乎完美重合,那么打印怎么会有那么巨大的位置错误,这只能解释为我的程序哪里写错了。

理理思路,程序的逻辑大概是:

Created with Raphaël 2.1.2Create DBLE DataLayerCNNLE Feature Extract

很可能是某个数值忘记加减,导致的偏移。检查输出值后发现,输出的训练坐标和预测坐标是几乎相同的。这就说明:训练数据生成错了

训练图像框错了

测试后发现,确实是自己 normalize 监督信号的时候把监督信号弄错了。在选取 sub-region 时候并不需要 normalize 坐标,只有 resize 才需要,大脑故障了。调整后发现,无论是损失函数,还是肉眼观察结果,比起之前大大靠谱,非常好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

了解一下HTTP1.1 Pipelining技术

为什么谈HTTP1.1 Pipelining呢?主要问题根源还是来源于Beetlex参加了techempower的测试。先看一下以下两项测试的结果:以上分别是.net平台的Json和Plaintext的测试结果,其实Plaintext最高能跑700多万RPS已经完全超了对网络IO读写损耗的认知&a…

springboot2 多线程写入数据_解决SpringBoot项目使用多线程处理任务时无法通过@Autowired注入bean问题...

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":7,"count":7}]},"card":[{"des":"EDAS 是一个应用托管和微服务管理的PaaS平台…

算法题目——子序列和问题(poj-3061)(尺取法)

题目链接:POJ-3061 题意:给定一个序列,使得其和大于或等于S,求最短的子序列长度。 问题分析: 1.首先序列都是正整数,当子序列和大于等于S时,已经没有必要再将右端点继续向右移动。因为再向右移动,序列的长度一定会大于此时的长度 2.所以,当子序列和小于S时,右端点向…

读书 | 数字化转型的道与术(下)

【数字化转型】| 作者 / Edison Zhou这是EdisonTalk的第313篇学习总结 最近在阅读钟华老师的新作《数字化转型的道与术》,记录和总结了一些学习笔记和感想,整理成文分享与你,本文为下半部分,希望能对也在参与数字化转型的各位童鞋…

算法题目——读书知识点统计问题(POJ-3320)(尺取法)

题目链接:poj-3320 问题:杰西卡是一个非常可爱的女孩,受到许多男孩的追捧。最近她有个问题。期末考试快到了,但她几乎没花什么时间。如果她想通过考试,她必须掌握一本厚厚的教科书中包含的所有思想。那本教科书的作者和其他作者一样,对这些观点极为挑剔,因此有些观点被…

aop springboot 传入参数_Springboot添加AOP打印请求参数

1. 引入依赖org.springframework.bootspring-boot-starter-aop2. 写切面切面类需要加Aspect和Component注解package com.test.demo.aspect;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.Pro…

GraphQL:面对复杂类型

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进&#xff0c…

算法与数据结构——并查集

文章推荐:【算法与数据结构】—— 并查集 例子: 数据结构——最小生成树之克鲁斯卡尔算法(Kruskal) 1.2 并查集思想(重点) 我们可以把每个连通分量看成一个集合,该集合包含了连通分量的所有点。而具体的连通方式无关紧要,好比集合中的元素没有先后顺序之分,只有“属于”…

eclipse 输入卡顿_7个小技巧,解决eclipse卡顿问题

eclipse作为开发工具,每天都要使用,你肯定遇到过eclipse卡到想哭的时刻,严重影响开发效率啊!如果内存条不要钱,那就加内存吧!一个不够加两个!当然这都是玩笑话,如果不花钱也能解决问…

为什么建议学生积极参与开源项目?

喜欢就关注我们吧!“ 你参与过开源项目吗?” 随着开源技术对信息产业的积极影响进一步扩大,越来越多的面试官将是否参与开源项目作为考核开发者能力的一项基本指标。对于求职者来说,参与开源能为简历增色不少 ,增加赢得…

mysql 左连接 怎么走索引_数据库索引、左连接、右连接、等值连接

在MySQL中,主要有四种类型的索引,分别为:B-Tree索引,Hash索引,Fulltext索引(MyISAM 表)和R-Tree索引,本文讲的是B-Tree索引。一、Mysql索引主要有两种结构:BTree索引和Hash索引(a) Innodb存储引…

微服务技术栈及分享计划

前言上一篇对微服的演变、优缺点进行了概述,对于业务复杂项目,微服务算是比较合适的解决方案;对于咱们开发者来说,有好的解决方案肯定要跟进学习,但不能盲目追崇流行技术,目的还是为了解决问题。这里就把As…

PAT乙级题目——1002写出这个数

问题分析:1.数据比较大,并且输入数据时没有停顿,所有使用字符串来存储数据 string str""; cin>>str;2.使用字符串数组来存储每个数字的拼音 string S[10]{"ling","yi","er","san"…

northstar机器人编程_《机器人构建实战》——导读

前言机器人构建实战机器人是21世纪发展最为迅速、应用前景最为广阔的科学技术领域之一。机器人技术综合运用了基础科学和应用工程技术的最新成果,是一个国家科技发展水平和国民经济现代化、信息化的重要标志,是世界强国重点发展的高技术之一。近年来&…

Linux性能挖潜的隐藏招数:内核CPU亲和性参数调整

作者:李彬,赵雪枫,金融科技工程师,架构师社区特邀作者!应用服务性能调优,是每个系统投产前都需要关注的问题,系统及软件层面的调优方法均有大量文章介绍,但在所有招数使出后&#xf…

PAT乙级——1001害死人不偿命的(3n+1)猜想(太简单)

#include<iostream> using namespace std;int main(){int n;int ans0;//记录走过的步数 cin>>n;while(n!1){if(n%20){ans;nn/2;}else{ans;n(3*n1)/2;}}cout<<ans;return 0; }

c4d如何把文字贴在物体表面_C4D在简模上整体和局部贴贴图的方法

引&#xff1a;可能常常碰到一个问题&#xff0c;有了一个模型一个简单的模型&#xff0c;也有了基本材质&#xff0c;想在这个材质上面加点文字内容&#xff0c;比方说一个盒子外面的简单的标签&#xff0c;或者其它&#xff0c;当然你可以用C4D模块中的3D Paint画&#xff0c…

好的重构方法才能摆脱“屎山”

大家好&#xff0c;我是Z哥。最近在整理一些项目&#xff0c;所以相关的文章写的多了些。之前的相关文章有《聊聊单元测试》&#xff0c;感兴趣的话可以点击文末链接去阅读。这次整理项目的时候&#xff0c;做了比较多的codereview和重构。好久没做这么高强度了重构了&#xff…

python中log1p用法_python中logging模块的基本用法

1、logging模块可以跟踪代码的运行记录事件&#xff0c;log信息共内置了5个层级——调试(debug)、信息(info)、警告(warning)、错误(error)、严重错误(critical)2、logging模块用处&#xff1a;控制信息层级&#xff0c;仅记录需要的信息&#xff1b;控制显示或者保存日志信息的…

在 Asp.Net Core 中使用 worker services

ASP.Net Core 3.0 Preview 3 新增了一个 worker services&#xff0c;那什么是 worker services 呢&#xff1f;它如同 windows服务 或者 Linux守护进程 一样的后台服务&#xff0c;在 Visual Studio 中提供了一个专门创建 worker services 的模板&#xff0c;如下图&#xff…