没有合适的资源?快使用搜索试试~ 我知道了~
Project5-goodexamples-2021fall-by何泽安1
需积分: 0 0 下载量 4 浏览量
2022-08-03
18:28:28
上传
评论
收藏 4.89MB PDF 举报
温馨提示
试读
20页
Project5-goodexamples-2021fall-by何泽安1
资源详情
资源评论
资源推荐
CS205 · C/C++ Programming
Project 5: CNN Face Detector
何泽安 (He Zean)
12011323
Dec. 19, 2021
Contents
1 需求分析 1
2 代码实现 1
2.1 整体架构 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.2 Img & CnnExceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.3 CnnLayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.4 ImgInput . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.5 Conv3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.5.1 优化卷积:Im2Col+GEMM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.6 Pooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.7 FullConn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.8 class Sequential . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 测试样例及分析 14
3.1 正确性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2 准确性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 性能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4 困难及解决 17
4.1 内联函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 One more thing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5 总结 18
He Zean · 12011323 CS205 ◦ Project 5: CNN Face Detector 1 / 19
1 需求分析
在充分学习了面向对象编程的知识后,本次 project 设计了对模型的设计者和使用者都有友好的使用
体验的类,其具有健全的异常处理体系以及灵活的参数选择(如激活函数不限定为 Relu),在此基础上修
改模型结构和拓展本框架都极为方便。
本 project 也讨论了 CNN 在访存优化及并行计算方面的加速方案,另外,对于具体的模型(如提供的
SimpleCNNbyCPP),在损失一定代码通用性的条件下还可进一步的提速。
此外,提供了方便测试本模型效果的网站 http://172.18.24.39:8501 1 ,能直观展示结果并与官方 Python
实现进行对比。
2 代码实现
本次 CNN 代码分为两部分:第一部分用于体现面向对象程序设计思维,鲁棒性强,能方便的适配各
种结构的神经网络;而第二部分专门为 SimpleCNNbyCPP 的网络结构实现了性能提升,网络参数固定并
直接写入代码2
2.1 整体架构
核心代码架构(精简起见,仅展示头文件)
1需在校园网环境下访问。
2要实现通用的 CNN 需要考虑多种情况,且代码实现耗时多于特例化版本,考虑到时间关系,仅以此为例展示优化方案。
He Zean · 12011323 CS205 ◦ Project 5: CNN Face Detector 2 / 19
利用(纯)虚函数和类的继承,我们在 CnnLayer 类中定义了神经网络层需要支持的基本操作(类似于
Java 中实现某个 Interface),并体现了各种网络层的 is-a 关系;在类的实现中重写虚函数来完成具体操作。
各层的参数(若有)由各层各自保管,而 modules/Sequential 封装了网络的细节(保存了 CNN 中的
layers),提供了模型合法性检查和开箱即用的特性。
与 project 4 类似,我们使用 cnnexception 完善并归类了神经网络可能遇到的几种异常;imgdata 通过
在拷贝构造器和赋值运算符中管理引用计数器,大大减轻了网络层中内层管理的负担(由 SmartPtr 修改而
来,但本次在了解 channel 的作用后将其存为一维数组),也能有效避免忘记释放内存(通过了 project 4 中
的 debug_new 的内存泄露检测);extras 提供了计时器等辅助功能。
2.2 Img & CnnExceptions
1 class Img {
2 Data *m_data; /* { size_t width, height, channels; int ref_cnt; float *data; } */
3 public:
4 /* constructors, with try-catch-throw to avoid partial construction */
5 Img(const Img &rhs) { this->m_data = rhs.m_data; ++this->m_data->ref_cnt; }
6 ~Img() { try { if (--m_data->ref_cnt == 0) { delete m_data; } } catch (...) {} }
7 Img &operator=(const Img &rhs) {
8 if (this == &rhs || this->m_data == rhs.m_data) return *this;
9 if (--m_data->ref_cnt == 0) delete m_data;
10 m_data = rhs.m_data; ++m_data->ref_cnt;
11 return *this;
12 }
13 };
Project 4 中通过使用 initializer_list,实现了不定长传参,但这要求参数类型一致。而本次使用了展开
He Zean · 12011323 CS205 ◦ Project 5: CNN Face Detector 3 / 19
参数包的方式使传入信息更加灵活。
2.3 CnnLayer
1 class CnnLayer {
2 public:
3 virtual ~CnnLayer() = default;
4 virtual Img forward(const Img &img) const = 0;
5 virtual void summary(ostream &os, const vector<size_t> &input) const = 0;
6 virtual bool checkValid(vector<size_t> &last_opt) const = 0;
7 virtual vector<size_t> optSize(vector<size_t> &in_size) const = 0;
8 };
下面将以此为基类将用到的多种 layers 写为派生类,不同种类的 layers 间的行为有较大差异,但作为
layer 均需实现基类中规定的纯虚函数;显然,这里基类的析构函数无需有任何实际行为,但我们需要将其
指出是虚函数以便在 delete CnnLayer* 时能调用派生类的析构函数,避免内存泄露。
¬ forward 即 layer 向后计算。这里的 Img 与 project 4 中实现的 SmartPtr 类似,唯一的成员变量为一个
指向(保管了引用计数器的)struct Data 的指针,并在拷贝构造、赋值操作和析构函数中自动管理内存。
在此处,我们在函数内创建保存新结果的 Img 对象 <img_out>,此时其数据区引用计数为 1,通过拷贝构
造传出时,数据区引用首先短暂的变为 2,但函数内的栈内对象随即被析构,引用数重新变为 1。而原 Img
的引用数在函数内外均为 1,并在赋值操作时析构原有数据区。
summary, checkValid, & optSize 主要供 Module 调用。optSize 需要输入上一层输出尺寸并计算输出
尺寸,checkValid 检查该层是否能合法放入模型中(如上一层输出通道数为 16,则要求 Conv3D 的卷积核
深度一致)。
2.4 ImgInput
作为模型的第一层,负责接收各种图片并将其整形为预训练网络所期望的输入大小及通道3。并提供多
种“resize”方式4 ,仅在实际输入大小与输出大小不一致时使用。此外,考虑到 OpenCV 获取数据的较高
效手段是通过 ptr 一次获取一行,且获得的 NHWC 与后面所需的 NCHW 存储顺序差异较大,故仅尝试使
用 OpenMP 和循环展开的基本手段提速。
对于 SimpleCnnByCpp,这里直接使用 BGR 的顺序读入可以获取与 demo.py 一致的结果,能验证其余
部分代码的正确性;而转为 RGB 读入(可以通过 ¬ 使用 cv::COLOR_BGR2RGB 调整 79 行 for 循环写入
顺序实现,这里选择)则可获得更高的准确率。
3由于图片的伸缩(resize)和通道变换(cvtColor)涉及较多插值等数学内容(没学过啊),这里直接调用 OpenCV。
4时间关系,仅实现前两种,即强制变形和无伸缩变形。
剩余19页未读,继续阅读
神康不是狗
- 粉丝: 31
- 资源: 338
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0