书籍详情
动手打造深度学习框架
作者:李伟 著
出版社:人民邮电出版社
出版时间:2022-04-01
ISBN:9787115570123
定价:¥89.90
购买这本书可以去
内容简介
本书基于 C++编写,旨在带领读者动手打造出一个深度学习框架。本书首先介绍 C++模板元编程的基础技术,然后在此基础上剖析深度学习框架的内部结构,逐一实现深度学习框架中的各个组件和功能,包括基本数据结构、运算与表达模板、基本层、复合层、循环层、求值与优化等,最终打造出一个深度学习框架。本书将深度学习框架与 C++模板元编程有机结合,更利于读者学习和掌握使用 C++开发大型项目的方法。本书适合对 C++有一定了解,希望深入了解深度学习框架内部实现细节,以及提升 C++程序设计水平的读者阅读。
作者简介
李伟,毕业于清华大学,曾负责百度公司自然语言处理部深度学习机器翻译系统线上预测部分的开发与维护,目前就职于微软。主要研究方向为 C++,拥有 10 余年相关开发经验,对 C++ 模板元编程与编译期计算有着浓厚的兴趣。喜欢尝试新技术。著有《C++ 模板元编程实战》。
目录
第 1 部分 元编程基础技术
第 1 章 元编程基本方法 2
1.1 元函数与 type_traits 2
1.1.1 元函数简介 2
1.1.2 类型元函数 3
1.1.3 各式各样的元函数 5
1.1.4 type_traits 6
1.1.5 元函数与宏 6
1.1.6 本书中元函数的命名方式 7
1.2 模板型模板参数与容器模板 7
1.2.1 模板作为元函数的输入 8
1.2.2 模板作为元函数的输出 .8
1.2.3 容器模板 9
1.3 从元函数到元对象 10
1.3.1 元对象与元数据域 11
1.3.2 元方法 12
1.4 顺序、分支与循环代码的编写 13
1.4.1 顺序执行的代码 13
1.4.2 分支执行的代码 14
1.4.3 循环执行的代码 21
1.4.4 小心:实例化爆炸与编译崩溃 27
1.4.5 分支选择与短路逻辑 29
1.5 奇特的递归模板式 30
1.6 小结 32
1.7 练习 32
第 2 章 元数据结构与算法 34
2.1 基本数据结构与算法 34
2.1.1 数据结构的表示方法 34
2.1.2 基本算法 36
2.1.3 算法的复杂度 38
2.2 基于包展开与折叠表达式的优化 41
2.2.1 基于包展开的优化 41
2.2.2 基于折叠表达式的优化 42
2.3 基于操作合并的优化 43
2.4 基于函数重载的索引算法 46
2.4.1 分摊复杂度 46
2.4.2 容器的重载结构映射 46
2.4.3 构造重载结构 47
2.4.4 索引元函数 48
2.4.5 允许重复键 48
2.4.6 集合与顺序表的索引操作 51
2.5 顺序表的索引算法 52
2.5.1 构造索引序列 52
2.5.2 索引顺序表的元函数 54
2.6 小结 55
2.7 练习 56
第 3 章 异类词典与 policy 模板 57
3.1 具名参数简介 57
3.2 异类词典 59
3.2.1 模块的使用方式 59
3.2.2 键的表示 61
3.2.3 异类词典的实现 63
3.2.4 VarTypeDict 的性能简析 69
3.2.5 将 std::tuple 作为缓存 70
3.3 policy 模板 70
3.3.1 policy 介绍 71
3.3.2 定义 policy 与 policy 对象(模板) 73
3.3.3 使用 policy 76
3.3.4 背景知识-支配与虚继承 78
3.3.5 policy 对象与 policy 支配结构 79
3.3.6 policy 选择元函数 80
3.3.7 使用宏简化 policy 对象的声明 85
3.3.8 特殊的 policy 类型 86
3.3.9 其他与 policy 相关的元函数 89
3.4 小结 89
3.5 练习 90
第 2 部分 深度学习框架
第 4 章 深度学习概述 92
4.1 深度学习简介 92
4.1.1 从机器学习到深度学习 93
4.1.2 各式各样的人工神经网络 94
4.1.3 深度学习系统的组织与训练 96
4.2 本书所实现的框架--MetaNN 98
4.2.1 从矩阵运算工具到深度学习框架 98
4.2.2 MetaNN 概述 99
4.2.3 本书将要讨论的内容 101
4.3 小结 104
第 5 章 类型体系与基本数据类型 105
5.1 设计理念 106
5.1.1 编译期的职责划分 106
5.1.2 使用类型体系管理不同的数据类型 106
5.1.3 支持不同的计算设备与计算单元 107
5.1.4 存储空间的分配与维护 107
5.1.5 浅拷贝与写操作检测 110
5.1.6 底层接口扩展 112
5.1.7 类型转换与求值 113
5.1.8 数据接口规范 114
5.2 类型体系 114
5.2.1 类型体系概述 114
5.2.2 迭代器分类体系 116
5.2.3 将标签作为模板参数 117
5.2.4 MetaNN 的类型体系 119
5.2.5 类别标签与数据类型的关联 120
5.2.6 与类型体系相关的元函数 121
5.3 Shape 类与形状信息 123
5.3.1 模板定义与基本操作 124
5.3.2 索引与偏移量的变换 125
5.3.3 维度为 0 时的特化 127
5.3.4 Shape 的模板推导 127
5.4 Tensor 类模板 128
5.4.1 模板定义 128
5.4.2 底层访问接口 131
5.4.3 模板特化与类型别名 132
5.4.4 主体类型的相关元函数 133
5.5 TrivialTensor 134
5.6 MetaNN 所提供的其他数据类型 135
5.7 DynamicData 135
5.7.1 基类模板 DynamicBase 136
5.7.2 派生类模板DynamicWrapper 137
5.7.3 使用 DynamicData 封装指针行为 138
5.7.4 辅助函数与辅助元函数 139
5.7.5 DynamicData 与动态类型体系 139
5.8 小结 140
5.9 练习 141
第 6 章 运算与表达式模板 143
6.1 表达式模板概述 143
6.2 MetaNN 运算模板的设计思想 145
6.2.1 Add 类模板的问题 145
6.2.2 运算模板的行为分析 146
6.3 辅助元函数与辅助类模板 150
6.3.1 IsValidOper 150
6.3.2 辅助类模板 OperElementType_/ OperDeviceType_ 150
6.3.3 辅助类模板 OperCateCal 151
6.3.4 辅助类模板 OperAuxParams 152
6.3.5 辅助类模板 OperShapeInfo 153
6.3.6 辅助类模板 OperSeq_ 155
6.4 运算模板的框架 155
6.5 运算实现示例 157
6.5.1 Sigmoid 运算 157
6.5.2 加法运算 159
6.5.3 点乘运算 163
6.6 其他运算 167
6.6.1 四则运算 168
6.6.2 Slice 运算 168
6.6.3 Permute 运算及其相关运算 169
6.6.4 ReduceSum 运算 170
6.6.5 非线性变换与相应的梯度计算 170
6.7 运算的折中与局限性 171
6.7.1 运算的折中 171
6.7.2 运算的局限性 171
6.8 小结 172
6.9 练习 172
第 7 章 基本层 174
7.1 层的设计理念 174
7.1.1 概述 174
7.1.2 层对象的构造 176
7.1.3 参数的初始化与加载 178
7.1.4 正向传播 178
7.1.5 存储中间结果 180
7.1.6 反向传播 182
7.1.7 输出梯度的形状检测 183
7.1.8 更新参数 183
7.1.9 导出参数 184
7.1.10 层的中性检测 184
7.2 层的辅助逻辑 184
7.2.1 初始化模块 184
7.2.2 接口相关辅助逻辑 192
7.2.3 GradPolicy 195
7.2.4 MakeInferLayer 与MakeTrainLayer 196
7.2.5 通用操作函数 197
7.2.6 其他辅助逻辑 198
7.3 层的具体实现 201
7.3.1 AddLayer 202
7.3.2 MultiplyLayer 206
7.3.3 ParamSourceLayer 208
7.4 小结 214
7.5 练习 214
第 8 章 复合层 215
8.1 复合层的接口与设计理念 216
8.1.1 基本结构 216
8.1.2 结构描述语法 217
8.1.3 policy 的继承 218
8.1.4 policy 的修正 219
8.1.5 输入类型映射表的推导 219
8.1.6 复合层的构造函数 220
8.1.7 一个完整的复合层构造示例 220
8.2 policy 继承与修正逻辑的实现 222
8.2.1 policy 继承逻辑的实现 222
8.2.2 policy 修正逻辑的实现 225
8.3 ComposeTopology 的实现 225
8.3.1 功能简述 225
8.3.2 拓扑排序算法概述 226
8.3.3 ComposeTopology 包含的主要步骤 227
8.3.4 结构描述子句与其划分 227
8.3.5 结构合法性检查 229
8.3.6 拓扑排序的实现 230
8.3.7 子层实例化元函数 233
8.4 ComposeKernel 的实现 239
8.4.1 类模板的声明 239
8.4.2 子层对象管理 240
8.4.3 参数初始化、参数获取、参数梯度收集与中性检测 242
8.4.4 正向传播 244
8.4.5 反向传播 248
8.5 复合层实现示例 250
8.6 小结 251
8.7 练习 252
第 9 章 循环层 253
9.1 设计理念 253
9.1.1 子层的容器接口 253
9.1.2 确定序列所在维度 254
9.1.3 正向传播与反向传播 255
9.2 循环层的实现 256
9.2.1 主体框架 256
9.2.2 (元)数据域 256
9.2.3 KernelGenerator_的实现 257
9.2.4 ShapeDictHelper 259
9.2.5 构造函数、参数初始化等接口 260
9.2.6 正向传播 261
9.2.7 反向传播 263
9.3 循环层应用示例 265
9.3.1 以 AddLayer 作为内核的循环层 265
9.3.2 GRU 266
9.4 小结 268
9.5 练习 268
第 10 章 求值与优化 269
10.1 MetaNN 的求值模型 270
10.1.1 运算的层次结构 270
10.1.2 求值子系统的类划分 271
10.2 基本求值逻辑 280
10.2.1 主体类型的求值接口 280
10.2.2 非主体基本数据类型的求值 281
10.2.3 运算模板的求值 284
10.2.4 DynamicData 与求值 286
10.3 求值过程的优化 287
10.3.1 避免重复计算 287
10.3.2 针对运算特性的优化 289
10.3.3 同类计算合并 290
10.3.4 多运算协同优化 291
10.4 小结 297
10.5 练习 298
后记 299
第 1 章 元编程基本方法 2
1.1 元函数与 type_traits 2
1.1.1 元函数简介 2
1.1.2 类型元函数 3
1.1.3 各式各样的元函数 5
1.1.4 type_traits 6
1.1.5 元函数与宏 6
1.1.6 本书中元函数的命名方式 7
1.2 模板型模板参数与容器模板 7
1.2.1 模板作为元函数的输入 8
1.2.2 模板作为元函数的输出 .8
1.2.3 容器模板 9
1.3 从元函数到元对象 10
1.3.1 元对象与元数据域 11
1.3.2 元方法 12
1.4 顺序、分支与循环代码的编写 13
1.4.1 顺序执行的代码 13
1.4.2 分支执行的代码 14
1.4.3 循环执行的代码 21
1.4.4 小心:实例化爆炸与编译崩溃 27
1.4.5 分支选择与短路逻辑 29
1.5 奇特的递归模板式 30
1.6 小结 32
1.7 练习 32
第 2 章 元数据结构与算法 34
2.1 基本数据结构与算法 34
2.1.1 数据结构的表示方法 34
2.1.2 基本算法 36
2.1.3 算法的复杂度 38
2.2 基于包展开与折叠表达式的优化 41
2.2.1 基于包展开的优化 41
2.2.2 基于折叠表达式的优化 42
2.3 基于操作合并的优化 43
2.4 基于函数重载的索引算法 46
2.4.1 分摊复杂度 46
2.4.2 容器的重载结构映射 46
2.4.3 构造重载结构 47
2.4.4 索引元函数 48
2.4.5 允许重复键 48
2.4.6 集合与顺序表的索引操作 51
2.5 顺序表的索引算法 52
2.5.1 构造索引序列 52
2.5.2 索引顺序表的元函数 54
2.6 小结 55
2.7 练习 56
第 3 章 异类词典与 policy 模板 57
3.1 具名参数简介 57
3.2 异类词典 59
3.2.1 模块的使用方式 59
3.2.2 键的表示 61
3.2.3 异类词典的实现 63
3.2.4 VarTypeDict 的性能简析 69
3.2.5 将 std::tuple 作为缓存 70
3.3 policy 模板 70
3.3.1 policy 介绍 71
3.3.2 定义 policy 与 policy 对象(模板) 73
3.3.3 使用 policy 76
3.3.4 背景知识-支配与虚继承 78
3.3.5 policy 对象与 policy 支配结构 79
3.3.6 policy 选择元函数 80
3.3.7 使用宏简化 policy 对象的声明 85
3.3.8 特殊的 policy 类型 86
3.3.9 其他与 policy 相关的元函数 89
3.4 小结 89
3.5 练习 90
第 2 部分 深度学习框架
第 4 章 深度学习概述 92
4.1 深度学习简介 92
4.1.1 从机器学习到深度学习 93
4.1.2 各式各样的人工神经网络 94
4.1.3 深度学习系统的组织与训练 96
4.2 本书所实现的框架--MetaNN 98
4.2.1 从矩阵运算工具到深度学习框架 98
4.2.2 MetaNN 概述 99
4.2.3 本书将要讨论的内容 101
4.3 小结 104
第 5 章 类型体系与基本数据类型 105
5.1 设计理念 106
5.1.1 编译期的职责划分 106
5.1.2 使用类型体系管理不同的数据类型 106
5.1.3 支持不同的计算设备与计算单元 107
5.1.4 存储空间的分配与维护 107
5.1.5 浅拷贝与写操作检测 110
5.1.6 底层接口扩展 112
5.1.7 类型转换与求值 113
5.1.8 数据接口规范 114
5.2 类型体系 114
5.2.1 类型体系概述 114
5.2.2 迭代器分类体系 116
5.2.3 将标签作为模板参数 117
5.2.4 MetaNN 的类型体系 119
5.2.5 类别标签与数据类型的关联 120
5.2.6 与类型体系相关的元函数 121
5.3 Shape 类与形状信息 123
5.3.1 模板定义与基本操作 124
5.3.2 索引与偏移量的变换 125
5.3.3 维度为 0 时的特化 127
5.3.4 Shape 的模板推导 127
5.4 Tensor 类模板 128
5.4.1 模板定义 128
5.4.2 底层访问接口 131
5.4.3 模板特化与类型别名 132
5.4.4 主体类型的相关元函数 133
5.5 TrivialTensor 134
5.6 MetaNN 所提供的其他数据类型 135
5.7 DynamicData 135
5.7.1 基类模板 DynamicBase 136
5.7.2 派生类模板DynamicWrapper 137
5.7.3 使用 DynamicData 封装指针行为 138
5.7.4 辅助函数与辅助元函数 139
5.7.5 DynamicData 与动态类型体系 139
5.8 小结 140
5.9 练习 141
第 6 章 运算与表达式模板 143
6.1 表达式模板概述 143
6.2 MetaNN 运算模板的设计思想 145
6.2.1 Add 类模板的问题 145
6.2.2 运算模板的行为分析 146
6.3 辅助元函数与辅助类模板 150
6.3.1 IsValidOper 150
6.3.2 辅助类模板 OperElementType_/ OperDeviceType_ 150
6.3.3 辅助类模板 OperCateCal 151
6.3.4 辅助类模板 OperAuxParams 152
6.3.5 辅助类模板 OperShapeInfo 153
6.3.6 辅助类模板 OperSeq_ 155
6.4 运算模板的框架 155
6.5 运算实现示例 157
6.5.1 Sigmoid 运算 157
6.5.2 加法运算 159
6.5.3 点乘运算 163
6.6 其他运算 167
6.6.1 四则运算 168
6.6.2 Slice 运算 168
6.6.3 Permute 运算及其相关运算 169
6.6.4 ReduceSum 运算 170
6.6.5 非线性变换与相应的梯度计算 170
6.7 运算的折中与局限性 171
6.7.1 运算的折中 171
6.7.2 运算的局限性 171
6.8 小结 172
6.9 练习 172
第 7 章 基本层 174
7.1 层的设计理念 174
7.1.1 概述 174
7.1.2 层对象的构造 176
7.1.3 参数的初始化与加载 178
7.1.4 正向传播 178
7.1.5 存储中间结果 180
7.1.6 反向传播 182
7.1.7 输出梯度的形状检测 183
7.1.8 更新参数 183
7.1.9 导出参数 184
7.1.10 层的中性检测 184
7.2 层的辅助逻辑 184
7.2.1 初始化模块 184
7.2.2 接口相关辅助逻辑 192
7.2.3 GradPolicy 195
7.2.4 MakeInferLayer 与MakeTrainLayer 196
7.2.5 通用操作函数 197
7.2.6 其他辅助逻辑 198
7.3 层的具体实现 201
7.3.1 AddLayer 202
7.3.2 MultiplyLayer 206
7.3.3 ParamSourceLayer 208
7.4 小结 214
7.5 练习 214
第 8 章 复合层 215
8.1 复合层的接口与设计理念 216
8.1.1 基本结构 216
8.1.2 结构描述语法 217
8.1.3 policy 的继承 218
8.1.4 policy 的修正 219
8.1.5 输入类型映射表的推导 219
8.1.6 复合层的构造函数 220
8.1.7 一个完整的复合层构造示例 220
8.2 policy 继承与修正逻辑的实现 222
8.2.1 policy 继承逻辑的实现 222
8.2.2 policy 修正逻辑的实现 225
8.3 ComposeTopology 的实现 225
8.3.1 功能简述 225
8.3.2 拓扑排序算法概述 226
8.3.3 ComposeTopology 包含的主要步骤 227
8.3.4 结构描述子句与其划分 227
8.3.5 结构合法性检查 229
8.3.6 拓扑排序的实现 230
8.3.7 子层实例化元函数 233
8.4 ComposeKernel 的实现 239
8.4.1 类模板的声明 239
8.4.2 子层对象管理 240
8.4.3 参数初始化、参数获取、参数梯度收集与中性检测 242
8.4.4 正向传播 244
8.4.5 反向传播 248
8.5 复合层实现示例 250
8.6 小结 251
8.7 练习 252
第 9 章 循环层 253
9.1 设计理念 253
9.1.1 子层的容器接口 253
9.1.2 确定序列所在维度 254
9.1.3 正向传播与反向传播 255
9.2 循环层的实现 256
9.2.1 主体框架 256
9.2.2 (元)数据域 256
9.2.3 KernelGenerator_的实现 257
9.2.4 ShapeDictHelper 259
9.2.5 构造函数、参数初始化等接口 260
9.2.6 正向传播 261
9.2.7 反向传播 263
9.3 循环层应用示例 265
9.3.1 以 AddLayer 作为内核的循环层 265
9.3.2 GRU 266
9.4 小结 268
9.5 练习 268
第 10 章 求值与优化 269
10.1 MetaNN 的求值模型 270
10.1.1 运算的层次结构 270
10.1.2 求值子系统的类划分 271
10.2 基本求值逻辑 280
10.2.1 主体类型的求值接口 280
10.2.2 非主体基本数据类型的求值 281
10.2.3 运算模板的求值 284
10.2.4 DynamicData 与求值 286
10.3 求值过程的优化 287
10.3.1 避免重复计算 287
10.3.2 针对运算特性的优化 289
10.3.3 同类计算合并 290
10.3.4 多运算协同优化 291
10.4 小结 297
10.5 练习 298
后记 299
猜您喜欢