TeX、LaTeX、XeLaTeX

TeX

TeX:由Donald Knuth开发的高质量排版系统

  • TeX的范畴包括标记语法(命令)、具体实现(引擎),在不同 场合含义不同,类似语言、编译器

  • 初版TeX包含300左右命令,随后Donald添加Plain TeX扩展包 定义了600左右常用宏命令

  • TeX中将标记关键字称为命令,其实关键字确实类似命令,可能 系统对应命令、语言对应关键字

TeX宏包

  • *.cls类文件:定义文档结构
  • *.sty包/样式文件:提供类未包括的任何东西
    • 对类文件功能的补充:提供从属于类文件的功能
    • 对类文件功能的修改:改变类文件的风格

基础排版宏包

  • LaTeX:Leslie Lamport设计的更高层次、更抽象的排版格式

    • 包含以TeX命令为基础的一系列高层、抽象宏命令,包括 \section\usepackage
    • 用户可以使用模板而不必决定具体排版、打印,使用更加 方便
    • 是学界事实上的标准排版格式
  • ConTeXt:Pragma-ADE公司设计的文档制造格式

    • 为TeX提供对先进打印特性的易用接口
    • 生成的编译文件更美观,适合专业印刷行业使用
  • TeXinfo:FSF(Free Software Foundation)设计的格式

    • 是Linux系统的标准文档系统

中文排版宏包

  • xeCJK:在XeTeX引擎下处理中日韩文字断行、标点调整、字体 选择的基础性宏包

    • 基础从CCT、CJK以来的标点禁则、标点压缩、NFSS字体补丁
    • 实际上仅对简体中文处理机制比较完全
    • XeTeX本身已经能够大概处理中文文档的排版,但在某些 细节部分仍然可以改进
    • 类似的宏包还有:zhspacing、xCJK、xCCT
  • CTeX:提供了编写中文文档时常用的宏命令

其他宏包

  • AMS-TeX/AMS-LaTeX:AMS(American Mathematical Society) 设计的格式
    • 提供了额外的数学字体、多行数学表述排版

TeX引擎

  • pdfTex:将TeX文本编译输出为pdf格式的引擎实现

    • 最初TeX/LaTeX实现将TeX编译为DVI格式,然后方便转换为 PostScript文件用于打印
    • 而pdf格式超越PostScript格式成为更流行的预打印格式
    • 因此事实上,现在LaTeX发行版中包含4个部分:TeX、 pdfTeX、LaTeX、pdfLaTeX
  • XeTeX:扩展了TeX的字符、字体支持的引擎实现

    • 最初TeX/LaTeX仅仅支持英语数字、字母
    • XeTeX提供了对Unicode字符和TrueType/OpenType字体的 直接支持
  • LuaTeX:将TeX扩展为更sensible的编程语言的实现

TeX发行版

TeX Live

TeX Live:TUG(TeX User Group)发布、维护的TeX系统

  • TeX Live包含
    • 与TeX系统相关的各种程序
      • pdfTeX
      • XeTeX
      • LuaTeX
    • 编辑查看工具
      • DVIOUT DVI Viewer
      • PS View
      • TeXworks
    • 常用宏包
      • LaTeX
    • 常用字体
    • 多个语言支持

MiKTeX

MiKTeX:Christian Schenk开发的在MSWin下运行文字处理系统

CTeX

CTeX:CTeX学会开发,将MiKTeX及常用应用封装

  • 集成WinEdt编辑器
  • 强化了对中文的处理

Todo.txt

Todo.txt格式

  • todo.txt格式使用纯文本存储、表示任务
  • 存储任务的文本文件中每行表示一项task
  • todo.txt类清单管理应用因此一般具备如下特点
    • 待完成任务、已完成任务分为两个文件分别存储
    • 可以自由修改任务存储文件以修改任务内容

基本要素

todotxt_format_description

  • 任务结构:各部分之间使用空格分隔

    • x:任务完成标识符
    • 优先级:([A-Z])
    • 完成日期、创建日期:Y-m-d格式
    • 任务描述:任务主体部分
  • 任务描述部分可以包含各种类型的tag,tag格式上可以放在任务 任何部分,但习惯上放在末尾

    • project+标识
    • context@标识
    • [key]:[value]:metadata键值对,key表示键值对含义 (中间一般不用空格分隔,便于处理)
  • 常用特殊metadata键值对
    • 时间戳:t:Y-m-d
    • 截至日期:due:Y-m-d

Todo.txt工具

todo.txt-cli

todo.txt-cli:基于shell脚本管理todo.txt文件

  • 只提供基本todo.txt功能,可以通过自行添加脚本插件方式扩展

    • 插件文件即普通可执行脚本文件,todo.sh会将命令参数 传递给相应脚本文件
    • todo.sh [action]将直接调用相应action名称脚本 (可建立同名文件夹、文件管理,同名文件夹文件被调用)
  • 使用两个文件分别存储待完成任务、已完成任务

    • 待完成任务文件中可以自行x标记完成,然后使用命令 归档至已完成任务文件中

topydo

topydo:基本python脚本管理todo.txt文件

  • 提供了cli、prompt、column三种模式
  • 原生支持以下标签
    • due、start日期
    • 管理任务之间依赖管理
    • 重复任务

在线最优化

Truncated Gradient

L1正则化法

L1正则化

  • $\lambda$:正则化项参数
  • $sgn$:符号函数
  • $g^{(t)}=\nabla_w L(w^{(t)}, Z^{(t)})$:损失函数对参数梯度
  • L1正则化项在0处不可导,每次迭代使用次梯度计算正则项梯度
  • OGD中每次根据观测到的一个样本进行权重更新 (所以后面正则项次梯度只考虑非0处???)

简单截断法

简单截断法:以$k$为窗口,当$t/k$非整数时,使用标准SGD迭代, 否则如下更新权重

  • $w^{(t)}$:模型参数
  • $g^{(t)}$:损失函数对模型参数梯度
  • $T_0$:截断函数
  • $\theta$:控制参数稀疏性

截断梯度法

截断梯度法:以$k$为窗口,当$t/k$非整数时,使用标准SGD迭代, 否则如下更新权重

  • $\lambda, \theta$:控制参数$w$稀疏性
  • 对简单截断的改进,避免在实际(OgD)中参数因训练不足过小 而被错误截断,造成特征丢失

    truncated_gradient_compared_with_l1

Forward-Backward Spliting

FOBOS:前向后向切分,权重更新方式为proximal method如下

L1-FOBOS

L1-FOBOS:即令$Phi(w)=\lambda |w|_1$,则根据可加性如下

  • $V=[v_1, v_2, \cdots, v_N]:=w^{(t.5)}$:为方便
  • $\tilde \lambda := \eta^{t.5} \lambda$:为方便
  • $\eta^{t.5}$:学习率,常取 $\eta^{(t)} \in \theta(\frac 1 {\sqrt t})$
  • 则对$w_i$求次梯度、分类讨论,解得

    • 可以理解为:到当前样本为止,维度权重小于阈值 $\eta^{(t.5)} \lambda$)时,认为该维度不够重要, 权重置为0

    • 可视为$k=1, \theta=\infty$的Tg算法

  • 另外,显然有$w_i^{(t+1)} v_i \geq 0$

    • 考虑$w_i^{(t+1)}$使得目标函数最小,带入$w=0$则得

Regularized Dual Averaging

RDA算法:正则对偶平均算法,权重更新方式为 包含[增广]正则项的最速下降

  • 目标函数包括三个部分

    • $\frac 1 t \sum_{r=1}^t g^{(r)} w$:包含之前所有梯度 均值
    • $\Phi(w)$:正则项
    • $\frac {\beta^{(t)}} t h(w)$:额外正则项,严格凸,且 不影响稀疏性
  • 相较于TG、FOBOS是从另一方面求解在线最优化,更有效地提升 特征权重稀疏性

L1 RDA

L1 RDA:令$\Phi(w) := \lambda |w|_1$, 再设$h(w) := |w|_2^2$,根据可加性则有

  • $\lambda > 0, \gamma > 0$
  • $\bar gi^{(t)} = \frac 1 t \sum{r=1}^t g_i^{(r)}$
  • 对$w_i$求次梯度、置零、求解得

    • 可以理解为:某维度梯度累计均值绝对值$|bar g_i^{(t)}$ 小于阈值$\lambda$时,对应权重被置零、产生稀疏性
  • 相较于L1-FOBOS的截断

    • 截断阈值为常数,更加激进、容易产生稀疏性
    • 截断判断对象为梯度累加均值,避免由于训练不足而产生 截断
    • 只需条件$\lambda$参数,容易权衡精度、稀疏性

Follow the Regularized Leader

FTRL:综合考虑L1-RDA、L1-FOBOS

L1-FOBOS、L1-RDA变换

  • 将L1-FOBOS类似近端算法收敛证明中展开、去除无关项、放缩, 得到类似L1-RDA目标函数

  • 将L1-RDA目标函数整体整体放缩,得到

    • $g^{(1:t)} := \sum_{r=1}^t g^{(r)}$
  • FTRL综合考虑L1-FOBOS、L1-RDA,得到目标函数

    • 使用累加梯度更新,避免因训练不充分错误截断
    • 包含L1-FOBOS、L1-RDA全部正则化项

求解

  • 将FTRL中最后一项拆分、去除无关项

  • 则同样根据可加性,对各分量求次梯度、置零、求解得

  • 其中学习率$\eta$为类似Adagrad优化器的学习率,但包括可学习 参数$\alpha, \beta$

损失函数理论

参数估计

  • 矩估计:建立参数和总体矩的关系,求解参数

    • 除非参数本身即为样本矩,否则基本无应用价值
    • 应用场合
      • 均值:对应二次损失 $\arg\min{\mu} \sum{i=1}^N (x_i - \mu)^2$
      • 方差:对应二次损失?
  • 极大似然估计:极大化似然函数,求解概率上最合理参数

    • 需知道(假设)总体 概率分布形式
    • 似然函数形式复杂,求解困难
      • 往往无法直接给出参数的解析解,只能求数值解
    • 应用场合
      • 估计回归参数:对数损失 $\mathop{\arg\min}{\beta} \sum{i=1}^N lnP(y_i|x_i, \beta)$
  • 损失函数估计:极小化损失函数,求解损失最小的参数

    • 最泛用的参数求解方法
      • 适合求解有大量参数的待求解的问题
      • 往往通过迭代方式逐步求解
    • 特别的
      • 线性回归使用 MSE 作为损失函数时,也被称为最小二乘估计
      • 极大似然估计同对数损失函数
  • 参数估计都可以找到合适损失函数,通过迭代求解损失最小化

随机模拟估计参数

  • 需要设计随机模拟实验估计参数
  • 应用场合
    • 蒙特卡洛类似算法:随机化损失

迭代求解参数

  • 损失函数定义不同

    • 包含样本量数量不同
    • 惩罚项设置不同
  • 异步更新参数

    • 同时求解参数数量:全部、部分、单个
    • 参数升维
  • 更新方向

    • 梯度
    • 海瑟矩阵
    • 次梯度
  • 更新方式

    • 叠加惯性
    • 动态学习率

Loss Models

模型(目标函数)在样本整体的损失:度量模型整体预测效果

  • 代表模型在整体上的性质,有不同的设计形式
  • 可以用于 设计学习策略、评价模型

    • 风险函数
    • 评价函数
  • 有时在算法中也会使用整体损失

Expected Risk / Expected Loss / Generalization Loss

期望风险(函数):损失函数 $L(Y, f(X))$(随机变量)期望

  • $P(X, Y)$:随机变量 $(X, Y)$ 遵循的联合分布,未知
  • 风险函数值度量模型预测错误程度

    • 反映了学习方法的泛化能力
    • 评价标准(监督学习目标)就应该是选择期望风险最小
  • 联合分布未知,所以才需要学习,否则可以直接计算条件分布概率,而计算期望损失需要知道联合分布,因此监督学习是一个病态问题

Empirical Risk / Empirical Loss

经验风险:模型关于给定训练数据集的平均损失

  • $\theta$:模型参数
  • $D_i$:样本损失权重,常为 $\frac 1 N$,在 Boosting 框架中不同
  • 经验风险损失是模型 $f(x)$ 的函数

    • 训练时,模型是模型参数的函数
    • 即其为模型参数函数
  • 根据大数定律,样本量容量 $N$ 趋于无穷时,$R{emp}(f)$ 趋于 $R{exp}(f)$

    • 但是现实中训练样本数目有限、很小
    • 利用经验风险估计期望常常并不理想,需要对经验风险进行矫正
  • 例子

    • maximum probability estimation:极大似然估计
      • 模型:条件概率分布(贝叶斯生成模型、逻辑回归)
      • 损失函数:对数损失函数

Structual Risk / Structual Loss

结构风险:在经验风险上加上表示 模型复杂度regularizerpenalty term

  • $J(f)$:模型复杂度,定义在假设空间$F$上的泛函
  • $\lambda$:权衡经验风险、模型复杂度的系数
  • 结构风险最小化
    • 添加 regularization(正则化),调节损失函数(目标函数)
  • 模型复杂度 $J(f)$ 表示对复杂模型的惩罚:模型 $f$ 越复杂,复杂项 $J(f)$ 越大
  • 案例
    • maximum posterior probability estimation:最大后验概率估计
      • 损失函数:对数损失函数
      • 模型复杂度:模型先验概率对数后取负
      • 先验概率对应模型复杂度,先验概率越小,复杂度越大
    • 岭回归:平方损失 + $L2$ 正则化 $\mathop{\arg\min}{\beta} \sum_{i=1}^N (y_i - f(x_i, \beta))^2 + |\beta|$
    • LASSO:平方损失 + $L1$ 正则化 $\mathop{\arg\min}{\beta} \sum_{i=1}^N (y_i - f(x_i, \beta))^2 + |\beta|_1$

Generalization Ability

泛化能力:方法学习到的模型对未知数据的预测能力,是学习方法本质、重要的性质

  • 测试误差衡量学习方法的泛化能力不可靠,其依赖于测试集,而测试集有限
  • 学习方法的泛化能力往往是通过研究泛化误差的概率上界进行

Generalization Error Bound

泛化误差上界:泛化误差的 概率 上界

  • 是样本容量函数,样本容量增加时,泛化上界趋于 0
  • 是假设空间容量函数,假设空间容量越大,模型越难学习,泛化误差上界越大

泛化误差

  • 根据 Hoeffding 不等式,泛化误差满足

    • $H$:假设空间
    • $N$:样本数量
    • $E(h) := R_{exp}(h)$
    • $\hat E(h) := R_{emp}(h)$
  • 证明如下:

  • 对任意 $\epsilon$,随样本数量 $m$ 增大, $|E(h) - \hat E(h)| \leq \epsilon$ 概率增大,可以使用经验误差近似泛化误差

二分类泛化误差上界

  • Hoeffding 不等式

  • 则 $\forall h \in H$,有

    则令 $\sigma = |H| exp(-2N\epsilon^2)$,则至少以概率 $1-\sigma$ 满足如下,即得到泛化误差上界

Probably Approximate Correct 可学习

PAC 可学习:在短时间内利用少量(多项式级别)样本能够找到假设 $h^{‘}$,满足

  • 即需要假设满足两个 PAC 辨识条件

    • 近似条件:泛化误差 $E(h^{‘})$ 足够小
    • 可能正确:满足近似条件概率足够大
  • 同等条件下

    • 模型越复杂,泛化误差越大
    • 满足条件的样本数量越大,模型泛化误差越小
  • PAC 学习理论关心能否从假设空间 $H$ 中学习到好的假设 $h$

    • 由以上泛化误差可得,取 $\sigma = 2|H|e^{-2N\epsilon^2}$,则样本量满足 $N = \frac {ln \frac {2|H|} \sigma} {2 \epsilon^2}$ 时,模型是 PAC 可学习的

Regularization

正则化:(向目标函数)添加额外信息以求解病态问题、避免过拟合

  • 常应用在机器学习、逆问题求解

    • 对模型(目标函数)复杂度惩罚
    • 提高学习模型的泛化能力、避免过拟合
    • 学习简单模型:稀疏模型、引入组结构
  • 有多种用途

    • 最小二乘也可以看作是简单的正则化
    • 岭回归中的 $\mathcal{l_2}$ 范数

模型复杂度

模型复杂度:经常作为正则化项添加作为额外信息添加的,衡量模型复杂度方式有很多种

  • 函数光滑限制

    • 多项式最高次数
  • 向量空间范数

    • $\mathcal{L_0} - norm$:参数个数
    • $\mathcal{L_1} - norm$:参数绝对值和
    • $\mathcal{L_2}$- norm$:参数平方和

$\mathcal{L_0} - norm$

  • $\mathcal{l_0} - norm$ 特点
    • 稀疏化约束
    • 解 $\mathcal{L_0}$ 范数正则化是 NP-hard 问题

$\mathcal{L_1} - norm$

  • $\mathcal{L_1} - norm$ 特点

    • $\mathcal{L_1}$ 范数可以通过凸松弛得到 $\mathcal{L_0}$ 的近似解
    • 有时候出现解不唯一的情况
    • $\mathcal{L_1}$ 范数凸但不严格可导,可以使用依赖次梯度的方法求解极小化问题
  • 应用

    • LASSO
  • 求解

    • Proximal Method
    • LARS

$\mathcal{L_2} - norm$

  • $\mathcal{L_2} - norm$ 特点
    • 凸且严格可导,极小化问题有解析解

$\mathcal{L_1 + L_2}$

  • $\mathcal{L_1 + L_2}$ 特点

    • 有组效应,相关变量权重倾向于相同
  • 应用

    • Elastic Net

稀疏解产生

稀疏解:待估参数系数在某些分量上为 0

$\mathcal{L_1} - norm$ 稀疏解的产生

  • $\mathcal{L_1}$ 范数在参数满足 一定条件 情况下,能对 平方损失 产生稀疏效果
  • 在 $[-1,1]$ 内 $y=|x|$ 导数大于 $y=x^2$(除 0 点)

    • 则特征在 0 点附近内变动时,为了取到极小值,参数必须始终为 0
    • 高阶项在 0 点附近增加速度较慢,所以 $\mathcal{L_1} - norm$ 能产生稀疏解是很广泛的
    • $mathcal{L_1} - norm$ 前系数(权重)越大,能够容许高阶项增加的幅度越大,即压缩能力越强
  • 在 0 附近导数 “不小”,即导数在 0 点非 0

    • 对多项式正则化项
      • $\mathcal{L_1} - norm$ 项对稀疏化解起决定性作用
      • 其他项对稀疏解无帮助
    • 对“非多项式”正则化项
      • $e^{|x|}-1$、$ln(|x|+1)$ 等在0点泰勒展开同样得到 $\mathcal{L_1} - norm$ 项
      • 但是此类正则化项难以计算数值,不常用

$\mathcal{L_1} - norm$ 稀疏解推广

  • 正负差异化:在正负设置权重不同的 $\mathcal{L_1}$,赋予在正负不同的压缩能力,甚至某侧完全不压缩

  • 分段函数压缩:即只要保证在 0 点附近包含 $\mathcal{L_1}$ 用于产生稀疏解,远离 0 处可以设计为常数等不影响精确解的值

    • Smoothly Clipped Absolute Deviation

    • Derivate of SCAD

    • Minimax Concave Penalty

  • 分指标:对不同指标动态设置 $\mathcal{L_0}$ 系数

    • Adaptive Lasso:$\lambda \sum_J w_jx_j$

稀疏本质

稀疏本质:极值、不光滑,即导数符号突然变化

  • 若某约束项导数符号突然变化、其余项在该点处导数为 0,为保证仍然取得极小值,解会聚集(极小)、疏远(极大)该点(类似坡的陡峭程度)

    • 即此类不光滑点会抑制解的变化,不光滑程度即导数变化幅度越大,抑制解变化能力越强,即吸引、排斥解能力越强
    • 容易构造压缩至任意点的约束项
    • 特殊的,不光滑点为 0 时,即得到稀疏解
  • 可以设置的多个极小不光滑点,使得解都在不连续集合中

    • 可以使用三角函数、锯齿函数等构造,但此类约束项要起效果,必然会使得目标函数非凸
      • 但是多变量场合,每个变量实际解只会在某个候选解附近,其邻域内仍然是凸的
      • 且锯齿函数这样的突变非凸可能和凸函数具有相当的优秀性质
    • 当这些点均为整数时,这似乎可以近似求解 整数规划

Early Stopping

Early Stopping:提前终止(训练)

  • Early Stopping 也可以被视为是 regularizing on time
    • 迭代式训练随着迭代次数增加,往往会有学习复杂模型的倾向
    • 对时间施加正则化,可以减小模型复杂度、提高泛化能力

TensorFlow资源管理

Resources

tf.placeholder

placeholder:占位符,执行时通过feed_dict参数设置值

1
2
3
4
5
tf.placeholder(
dtype,
shape=None,
name=None
)
  • shape:并不必须,但最好设置参数方便debug
  • 需要导入数据给placeholder,可能影响程序速度
  • 方便用户替换图中值

tf.data.DataSet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class tf.data.DataSet:
def __init__(self)

# 从tensor slice创建`Dataset`
def from_tensor_slices(self,
?data=(?features, ?labels)
):
pass

# 从生成器创建`Dataset`
def from_generator(self,
gen,
output_types,
output_shapes
):
pass

# 迭代数据集一次,无需初始化
def make_one_shot_iterator(self):
pass

# 迭代数据集任意次,每轮迭代需要初始化
def make_initializable_iterator(self):
pass

# shuffle数据集
def shuffle(self, ?seed:int):
pass

# 重复复制数据集
def repeat(self, ?times:int):
pass

# 将数据集划分为batch
def batch(self, batch_size:int):
pass

def map(self, func:callable):
pass
  • 创建只能迭代一轮的迭代器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    iterator = dataset.make_one_shot_iterator()
    # 这里`X`、`Y`也是OPs,在执行时候才返回Tensor
    X, Y = iterator.get_next()

    with tf.Session() as sess:
    print(sess.run([X, Y]))
    print(sess.run([X, Y]))
    print(sess.run([X, Y]))
    # 每次不同的值
  • 创建可以多次初始化的迭代器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    iterator = data.make_initializable_iterator()
    with tf.Session() as sess:
    for _ in range(100):
    # 每轮重新初始化迭代器,重新使用
    sess.run(iterator.initializer)
    total_loss = 0
    try:
    while True:
    sess.run([optimizer])
    # 手动处理迭代器消耗完毕
    except tf.error.OutOfRangeError:
    pass
  • tf.datatf.placeholder适合场景对比

    • tf.data速度更快、适合处理多数据源
    • tf.placeholder更pythonic、原型开发迭代速度快

读取文件数据

可以从多个文件中读取数据

1
2
3
4
5
6
 # 文件每行为一个entry
class tf.data.TextLineDataset(filenames):
# 文件中entry定长
class tf.data.FixedLengthRecordDataset(filenames):
# 文件为tfrecord格式
class tf.data.TFRecordDataset(filenames):

tf.data.Iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class tf.data.Iterator:
# 获取下组迭代数据
def get_next():
pass

# 根据dtype、shape创建迭代器
@classmethod
def from_structure(self,
?dtype: type,
?shape: [int]/(int)
):
pass

# 从数据中初始化迭代器
def make_initializer(self,
?dataset: tf.data.Dataset
):
pass

TensorFlow Python IO接口

TFRecord

TFRecord格式:序列化的tf.train.Example protbuf对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class tf.python_io.TFRecordWriter:
def __init__(self,
?fileanme: str,
options: tf.python_io.TFRecordOptions,
name=None
):
pass

class tf.python_io.TFRecordReader:
def __init__(self,
options: tf.python_io.TFRecordOptions,
name=None
):
pass

def read(self):
pass

### Feature/Features

```python
class tf.train.Features:
def __init__(self,
feature: {str: tf.train.Feature}
):
pass

class tf.train.Feature:
def __init__(self,
int64_list: tf.train.Int64List,
float64_list: tf.train.Float64List,
)

示例

  • 转换、写入TFRecord

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 创建写入文件
    writer = tf.python_io.TFRecord(out_file)
    shape, binary_image = get_image_binary(image_file)
    # 创建Features对象
    featurs = tf.train.Features(
    feature = {
    "label": tf.train.Feature(int64_list=tf.train.Int64List(label)),
    "shape": tf.train.Feature(bytes_list=tf.train.BytesList(shape)),
    "image": tf.train.Feature(bytes_list=tf.train.BytesList(binary_image))
    }
    )
    # 创建包含以上特征的示例对象
    sample = tf.train.Example(features=Features)
    # 写入文件
    writer.write(sample.SerializeToString())
    writer.close()
  • 读取TFRecord

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    dataset = tf.data.TFRecordDataset(tfrecord_files)
    dataset = dataset.map(_parse_function)
    def _parse_function(tf_record_serialized):
    features = {
    "labels": tf.FixedLenFeature([], tf.int64),
    "shape": tf.FixedLenFeature([], tf.string),
    "image": tf.FixedLenFeature([], tf.string)
    }
    parsed_features = tf.parse_single_example(tfrecord_serialized, features)
    return parsed_features["label"], parsed_features["shape"],
    parsed_features["image"]

其他函数

TensorFlow控制算符

控制OPs

Neural Network Building Blocks

tf.softmax

tf.Sigmod

tf.ReLU

tf.Convolution2D

tf.MaxPool

Checkpointing

tf.Save

tf.Restore

Queue and Synchronization

tf.Enqueue

tf.Dequeue

tf.MutexAcquire

tf.MutexRelease

Control Flow

tf.count_up_to

tf.cond

predTrue,执行true_fn,否则执行false_fn

1
2
3
4
5
tf.cond(
pred,
true_fn=None,
false_fn =None,
)

tf.case

tf.while_loop

tf.group

tf.Merge

tf.Switch

tf.Enter

tf.Leave

tf.NextIteration

TensorFlow操作符

Tensor

张量:n-dimensional array,类型化的多维数组

  • TF使用Tensor表示所有的数据
  • Tensor包含一个静态类型rank、一个shape
  • TF会将python原生类型转换为相应的Tensor
    • 0-d tensor:scalar
    • 1-d tensor:vector,1d-array
    • 2-d tensor:matrix,2d-array

Data Type

  • TF被设计为和numpy可以无缝结合

    • TF的变量类型基于numpy变量类型:tf.int32==np.int32
    • bool、numeric等大部分类型可以不加转换的使用TF、np 变量类型
    • TF、np中string类型不完全一样,但TF仍然可以从numpy 中导入string数组,但是不能在numpy中指定类型
  • 但尽量使用TF变量类型

    • python原生类型:没有细分类型,TF需要推断类型
    • numpy类型:numpy不兼容GPU,也不能自动计算衍生类型
数据类型 说明
tf.float16 16-bit half-precision floating-point
tf.float32 32-bit single-presicion floating-point
tf.float64 64-bit double-presicion floating-point
tf.bfloat16 16-bit truncated floating-point
tf.complex64 64-bit single-presicion complex
tf.complex128 128-bit double-presicion complex
tf.int8 8-bit signed integer
tf.uint8 8-bit unsigned integer
tf.int16
tf.uint16
tf.int32
tf.int64
tf.bool
tf.string
tf.qint8 quantized 8-bit signed integer
tf.quint8
tf.qint16
tf.quint16
tf.qint32
tf.resource handle to a mutable resource

Constant OPs

tf.constant

1
2
3
4
5
6
7
def constant(
value,
dtype=none,
shape=none,
name="Const",
verify_shape=False
)

同值常量OPs

  • zeros:类似np中相应函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # `np.zeros`
    def tf.zeros(
    shape,
    dtype=tf.float32,
    name=None
    )

    # `np.zores_like`
    def tf.zeros_like(
    input_tensor,
    dtype=None,
    name=None,
    optimizeTrue
    )
    • 若没有指明dtype,根据input_tensor确定其中值
      • 对数值型为0.0
      • 对bool型为False
      • 对字符串为b''
  • ones:类似np中相应函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# `np.ones`
def tf.ones(
shape,
dtype=tf.float32,
name=None
)

# `np.ones_like`
def tf.ones_like(
input_tensor,
dtype=None,
name=None,
optimize=True
)
- 若没有指明`dtype`,根据`input_tensor`确定 - 对数值型为`0.0` - 对bool型为`True` - 对字符串报错
  • fill:以value填充dims给定形状

    1
    2
    3
    4
    5
    6
    # `np.fill`
    def tf.fill(
    dims,
    value,
    name=None
    )

列表常量OPs

  • tensor列表不能直接for语句等迭代
  • tf.lin_spacestartstop直接均分为num部分

    1
    2
    3
    4
    5
    6
    7
    # `np.linspace`
    def lin_space(
    start,
    stop,
    num,
    name=None
    )
  • tf.rangestartstop间等间隔delta取值

    1
    2
    3
    4
    5
    6
    7
    8
    # `np.arange`
    def tf.range(
    start,
    limit=None,
    delta=1,
    dtype=None,
    name="range"
    )

随机常量OPs

  • seed:设置随机数种子

    1
    2
    3
    # np.random.seed
    def tf.set_random_seed(seed):
    pass
  • random:随机生成函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    def tf.random_normal()
    def tf.truncated_normal(
    ?avg=0/int/(int),
    stddev=1.0/float,
    seed=None/int,
    name=None
    ):
    pass

    def tf.random_uniform(
    shape(1d-arr),
    minval=0,
    maxval=None,
    dtype=tf.float32,
    seed=None/int,
    name=None/str
    ):
    pass

    def tf.random_crop()

    def tf.multinomial()

    def tf.random_gamma()
  • shuffle

    1
    def tf.random_shuffle()

运算OPs

元素OPs

四则运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

def add(x, y, name=None)
def subtract(x, y, name=None)
def sub(x, y, name=None)
def multiply(x, y, name=None)
def mul(x, y, name=None)
# 加、减、乘

def floordiv(x, y, name=None)
def floor_div(x, y, name=None)
def div(x, y, name=None)
def truncatediv(x, y, name=None)
# 地板除

def divide(x, y, name=None)
def truediv(x, y, name=None)
# 浮点除

def realdiv(x, y, name=None)
# 实数除法,只能用于实数?

def add_n(input, name=None)
# `input`:list-like,元素shapetype相同
# 累加`input`中元素的值

逻辑运算

1
2
3
def greater()
def less()
def equal()

数学函数

1
2
3
4
5
6
7
8
9
10
11
def exp()
def log()
def square()
def round()
def sqrt()
def rsqrt()
def pow()
def abs()
def negative()
def sign()
def reciprocal() # 倒数

列表运算OPs

1
2
3
4
5
6
def tf.Concat()
def tf.Slice()
def tf.Split()
def tf.Rank()
def tf.Shape()
def tf.Shuffle()

矩阵OPs

1
2
3
4
def tf.MatMul()
def tf.MatrixInverse()
def tf.MatrixDeterminant()
def tf.tensordot() # 矩阵点乘

梯度OPs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def tf.gradients(				# 求`y`对`[xs]`个元素偏导
ys: tf.OPs,
xs: tf.OPs/[tf.OPs],
grad_ys=None,
name=None
)
def tf.stop_gradient(
input,
name=None
)
def clip_by_value(
t,
clip_value_min,
clip_value_max,
name=None
)
def tf.clip_by_norm(
t,
clip_norm,
axes=None,
name=None
)

Variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Variable:
def __init__(self,
init_value=None,
trainable=True,
collections=None,
validata_shape=True,
caching_device=None,
name=None,
variable_def=None,
dtype=None,
expected_shape=None,
import_scope=None,
constraint=None
)

# 初始化变量
# `sess.run`其即初始化变量
def intializer(self):
pass

# 读取变量值
def value(self):
pass

# 获取变量初始化值,其他变量调用、声明依赖该变量
def initilized_value(self):
pass

# 计算、获取变量值,类似`sess.run(OP)`
def eval(self):
pass

# 给变量赋值
# `assgin`内部有初始化Variable,所以有时可以不用初始化
def assign(self):
pass
#`assgin_add`等依赖于原始值,不会初始化变量
def assign_add(self, ?dec)
def assign_divide(self, ?dec)
  • Variable是包含很多方法的类

    • 其中方法OPs和一般的OP一样,也需要在Session中执行 才能生效
    • Variable必须在会话中初始化后,才能使用
    • 会话维护自身独立Variable副本,不相互影响
  • Variable和图分开存储,甚至是存储在独立参数服务器上

    • 存储大量数据也不会拖慢图载入速度
    • 通常用于存储训练过程中weight、bias、维护图执行过程 中状态信息
  • constants是常数OPs

    • 存储在图中:每次载入图会同时被载入,过大的constants 会使得载入图非常慢
    • 所以最好只对原生类型使用constants

Variable创建

tf.get_variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def get_variable(
name,
shape=None,
dtype=None,
initializer=None,
regularizer=None,
trainable=True,
collections=None,
caching_device=None,
partitioner=None,
validate_shape=True,
use_resource=None,
custom_getter=None,
constraint=None
)
  • 此封装工厂方法相较于直接通过tf.Variable更好
    • 若变量已设置,可通过变量名获取变量,方便变量共享
    • 可以提供更多的参数定制变量值
1
2
3
4
5
6
7
8
9
10
11
	# `tf.Variable`创建变量
s = tf.Variable(2, name="scalar")
m = tf.Variable([[0,1], [2,3]], name="matrix")
w = tf.Variable(tf.zeros([784, 10]))
# `tf.get_variable`创建、获取变量
s = tf.get_variable("scalar", initializer=tf.constant(2))
m = tf.get_variable("matrix", initializer=tf.constant([[0,1], [2,3]])
W = tf.get_variable("big_matrix",
shape=(784, 10),
initializer=tf.zeros_initializer()
)

Variable初始化

1
2
3
4
5
6
7
with tf.Session() as sess:
# 初始化所有Variables
sess.run(tf.global_variable_initialier())
# 初始化变量子集
sess.run(tf.variable_initializer([s, m])
# 初始化指定单个变量
sess.run(s.initializer)
  • 若某Variable依赖其他Variable,需要使用 initialized_value指明依赖,确保依赖线性初始化

    1
    2
    3
    W = tr.Variable(tf.truncated_normal([700, 100])
    # 指明依赖,保证依赖线性初始化
    U = tf.Variable(W.initialized_value() * 2)

TensorFlow 持久化

Session Checkpoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class tf.train.Saver:
def __init__(self,
var_list=None/list/dict,
reshape=False,
sharded=False,
max_to_keep=5,
keep_checkpoint_every_n_hours=10000.0,
name=None,
restore_sequentially=False,
saver_def=None,
builder=None,
defer_build=False,
allow_empty=False,
write_version=tf.train.SaverDef.V2,
pad_step_number=False,
save_relative_paths=False,
filename=None
):
self.last_checkpoints
  • 用途:保存Session中变量(张量值),将变量名映射至张量值

  • 参数

    • var_list:待保存、恢复变量,缺省所有
      • 变量需在tf.train.Saver实例化前创建
    • reshape:允许恢复并重新设定张量形状
    • sharded:碎片化保存至多个设备
    • max_to_keep:最多保存checkpoint数目
    • keep_checkpoint_every_n_hours:checkpoint有效时间
    • restore_sequentially:各设备中顺序恢复变量,可以 减少内存消耗
  • 成员

    • last_checkpoints:最近保存checkpoints

保存Session

1
2
3
4
5
6
7
8
9
10
def Saver.save(self,
sess,
save_path,
global_step=None/str,
latest_filename=None("checkpoint")/str,
meta_graph_suffix="meta",
write_meta_graph=True,
write_state=True
) -> str(path):
pass
  • 用途:保存Session,要求变量已初始化

  • 参数

    • global_step:添加至save_path以区别不同步骤
    • latest_filename:checkpoint文件名
    • meta_graph_suffix:MetaGraphDef文件名后缀

恢复Session

1
2
def Saver.restore(sess, save_path(str)):
pass
  • 用途:从save_path指明的路径中恢复模型
  • 模型路径可以通过Saver.last_checkpoints属性、 tf.train.get_checkpoint_state()函数获得

tf.train.get_checkpoint_state

1
2
3
4
5
def tf.train.get_checkpoint_state(
checkpoint_dir(str),
latest_filename=None
):
pass
  • 用途:获取指定checkpoint目录下checkpoint状态
    • 需要图结构已经建好、Session开启
    • 恢复模型得到的变量无需初始化
1
2
3
ckpt = tf.train.get_checkpoint_state(checkpoint_dir)
saver.restore(ckpt.model_checkpoint_path)
saver.restore(ckpt.all_model_checkpoint_paths[-1])

Graph Saver

tf.train.write_graph

1
2
3
4
5
6
def tf.train.write_graph(
graph_or_graph_def: tf.Graph,
logdir: str,
name: str,
as_text=True
)
  • 用途:存储图至文件中

  • 参数

    • as_text:以ASCII方式写入文件

Summary Saver

tf.summary.FileWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class tf.summary.FileWriter:
def __init__(self,
?path=str,
graph=tf.Graph
)

# 添加summary记录
def add_summary(self,
summary: OP,
global_step
):
pass

# 关闭`log`记录
def close(self):
pass
  • 用途:创建FileWriter对象用于记录log

    • 存储图到文件夹中,文件名由TF自行生成
    • 可通过TensorBoard组件查看生成的event log文件
  • 说明

    • 一般在图定义完成后、Session执行前创建FileWriter 对象,Session结束后关闭

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 # 创建自定义summary
with tf.name_scope("summaries"):
tf.summary.scalar("loss", self.loss)
tf.summary.scalar("accuracy", self.accuracy)
tf.summary.histogram("histogram loss", self.loss)
summary_op = tf.summary.merge_all()

saver = tf.train.Saver()

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 从checkpoint中恢复Session
ckpt = tf.train.get_check_state(os.path.dirname("checkpoint_dir"))
if ckpt and ckpt.model_check_path:
saver.restore(sess, ckpt.mode_checkpoint_path)

# summary存储图
writer = tf.summary.FileWriter("./graphs", sess.graph)
for index in range(10000):
loas_batch, _, summary = session.run([loss, optimizer, summary_op])
writer.add_summary(summary, global_step=index)

if (index + 1) % 1000 = 0:
saver.save(sess, "checkpoint_dir", index)

# 关闭`FileWriter`,生成event log文件
write.close()