使用神经网络进行命名实体识别(二值词窗分类)
根据上下文窗口 建立词向量 通过一个神经网络层,通过一个逻辑分类器,得到这个概率是属于特定实体词的预测概率。 另一个分类器来比较说明 这个词是哪个实体类型(比较概率)
手工实现梯度下降
基础知识
雅可比矩阵:梯度的推广
给定一个具有
m
m
m 输出和
n
n
n 输入的函数:
f
(
x
)
=
[
f
1
(
x
1
,
x
2
,
.
.
.
,
x
n
)
,
.
.
.
,
f
m
(
x
1
,
x
2
,
.
.
.
,
x
n
)
]
\boldsymbol{f}(\boldsymbol{x})=[f_1(x_1,x_2,...,x_n),...,f_m(x_1,x_2,...,x_n)]
f(x)=[f1(x1,x2,...,xn),...,fm(x1,x2,...,xn)]它的雅可比矩阵是一个
m
×
n
m\times n
m×n 偏导数矩阵:
∂
f
∂
x
=
[
∂
f
1
∂
x
1
…
∂
f
1
∂
x
n
⋮
⋱
⋮
∂
f
m
∂
x
1
…
∂
f
m
∂
x
n
]
(
∂
f
∂
x
)
i
j
=
∂
f
i
∂
x
j
\dfrac{\partial\boldsymbol{f}}{\partial\boldsymbol{x}}=\begin{bmatrix}\frac{\partial f_1}{\partial x_1}&\dots&\frac{\partial f_1}{\partial x_n}\\\vdots&\ddots&\vdots\\\frac{\partial f_m}{\partial x_1}&\dots&\frac{\partial f_m}{\partial x_n}\end{bmatrix} \color{red}{\boxed{\left(\frac{\partial f}{\partial x}\right)_{ij}=\frac{\partial f_i}{\partial x_j}}}
∂x∂f=
∂x1∂f1⋮∂x1∂fm…⋱…∂xn∂f1⋮∂xn∂fm
(∂x∂f)ij=∂xj∂fi
链式法则
对于一变量函数的复合:乘导数
z
=
3
y
y
=
x
2
d
z
d
x
=
d
z
d
y
d
y
d
x
=
(
3
)
(
2
x
)
=
6
x
\begin{aligned} &z=3y \\ &y=x^{2} \\ &\begin{aligned}\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}=(3)(2x)=6x\end{aligned} \end{aligned}
z=3yy=x2dxdz=dydzdxdy=(3)(2x)=6x对于同时多个变量:乘以雅可比行列式
h
=
f
(
z
)
z
=
W
x
+
b
∂
h
∂
x
=
∂
h
∂
z
∂
z
∂
x
=
.
.
.
\begin{aligned} &\boldsymbol{h}=f(\boldsymbol{z}) \\ &z=\boldsymbol{W}\boldsymbol{x}+\boldsymbol{b} \\ &\begin{aligned}\frac{\partial\boldsymbol{h}}{\partial\boldsymbol{x}}=\frac{\partial\boldsymbol{h}}{\partial\boldsymbol{z}}\frac{\partial\boldsymbol{z}}{\partial\boldsymbol{x}}=...\end{aligned} \end{aligned}
h=f(z)z=Wx+b∂x∂h=∂z∂h∂x∂z=...
雅可比行列式示例:逐元素激活函数
h
=
f
(
z
)
,
∂
h
∂
z
是什么
?
h
,
z
∈
R
n
\boldsymbol{h}= f( \boldsymbol{z}) ,\ \, \frac {\partial\boldsymbol{h}}{\partial\boldsymbol{z}}是什么? \ \ \ \ \ \ \ \ h,z\in\mathbb{R}^n
h=f(z), ∂z∂h是什么? h,z∈Rn
h
i
=
f
(
z
i
)
h_i=f(z_i)
hi=f(zi)
(
∂
h
∂
z
)
i
j
=
∂
h
i
∂
z
j
=
∂
∂
z
j
f
(
z
i
)
雅可比行列式的定义
=
{
f
′
(
z
i
)
if
i
=
j
0
if otherwise
常规的一个变量的导数
\begin{aligned} \left(\frac{\partial\boldsymbol{h}}{\partial\boldsymbol{z}}\right)_{ij}& =\frac{\partial h_{i}}{\partial z_{j}}=\frac{\partial}{\partial z_{j}}f(z_{i}) \ \ \ \ \ \ 雅可比行列式的定义 \\ &=\begin{cases}f'(z_i)\quad\text{if }i=j\\0\quad \text{if otherwise}\end{cases} \ \ \ \ \ 常规的一个变量的导数 \end{aligned}
(∂z∂h)ij=∂zj∂hi=∂zj∂f(zi) 雅可比行列式的定义={f′(zi)if i=j0if otherwise 常规的一个变量的导数
∂
h
∂
z
=
(
f
′
(
z
1
)
0
⋱
0
f
′
(
z
n
)
)
=
diag
(
f
′
(
z
)
)
\left.\frac{\partial\boldsymbol{h}}{\partial\boldsymbol{z}}=\left(\begin{array}{ccc}f'(z_1)&&0\\&\ddots&\\0&&f'(z_n)\end{array}\right.\right)=\operatorname{diag}(\boldsymbol{f'}(\boldsymbol{z}))
∂z∂h=
f′(z1)0⋱0f′(zn)
=diag(f′(z))
其他雅可比行列式
∂
∂
x
(
W
x
+
b
)
=
W
∂
∂
b
(
W
x
+
b
)
=
I
(单位矩阵)
∂
∂
u
(
u
T
h
)
=
h
T
\begin{aligned} &\begin{aligned}\frac{\partial}{\partial\boldsymbol{x}}(\boldsymbol{W}\boldsymbol{x}+\boldsymbol{b})=\boldsymbol{W}\end{aligned} \\ &\begin{aligned}\frac{\partial}{\partial\boldsymbol{b}}(\boldsymbol{W}\boldsymbol{x}+\boldsymbol{b})&=\boldsymbol{I}&\text{(单位矩阵)}\end{aligned} \\ &\begin{aligned}\frac{\partial}{\partial\boldsymbol{u}}(\boldsymbol{u}^T\boldsymbol{h})=\boldsymbol{h}^T\end{aligned} \end{aligned}
∂x∂(Wx+b)=W∂b∂(Wx+b)=I(单位矩阵)∂u∂(uTh)=hT
回到神经网络
怎么计算
∂
s
∂
b
\frac{\partial s}{\partial b}
∂b∂s?
把等式拆解成简单的几个分块 应用链式法则写下雅各比表达式
怎么计算
∂
s
∂
w
\frac{\partial s}{\partial w}
∂w∂s?
δ
\delta
δ 是局部误差符号,是固定的。
关于矩阵的导数:输出形状
雅可比公式表达:
如果有一个函数
y
=
f
(
x
)
,其中
x
是一个向量,
y
是一个向量,
则雅可比矩阵
J
的元素
J
i
j
表示
y
i
对
x
j
的偏导数。
雅可比公式表达:\\ 如果有一个函数 y = f(x),其中 x 是一个向量,y 是一个向量,\\ 则雅可比矩阵\ J\ 的元素\ J_{ij}\ 表示\ y_i\ 对\ x_j\ 的偏导数。
雅可比公式表达:如果有一个函数y=f(x),其中x是一个向量,y是一个向量,则雅可比矩阵 J 的元素 Jij 表示 yi 对 xj 的偏导数。
W
∈
R
n
×
m
W\in\mathbb{R}^{n\times m}
W∈Rn×m ,
∂
s
∂
W
\frac{\partial s}{\partial W}
∂W∂s 的形状是:
“ 给定一个具有
m
m
m 输出和
n
n
n 输入的函数,它的雅可比矩阵是一个
m
×
n
m\times n
m×n 偏导数矩阵。”1个输出,
n
×
m
n\times m
n×m 个输入,得到的应该是
1
×
n
m
1\times nm
1×nm 的雅可比矩阵?一个很长的低向量
问题: 这样不方便更新参数
θ
n
e
w
=
θ
o
l
d
−
α
∇
θ
J
(
θ
)
\theta^{new}=\theta^{old}-\alpha\nabla_\theta J(\theta)
θnew=θold−α∇θJ(θ),都应该是
n
×
m
n\times m
n×m解决: 脱离数学,使用形状约定:导数的矩阵形状等于参数的矩阵形状
∂
s
∂
W
\frac{\partial s}{\partial W}
∂W∂s 的形状是
n
×
m
n\times m
n×m
[
∂
s
∂
W
11
⋯
∂
s
∂
W
1
m
⋮
⋱
⋮
∂
s
∂
W
n
1
⋯
∂
s
∂
W
n
m
]
\left.\left[\begin{matrix}\frac{\partial s}{\partial W_{11}}&\cdots&\frac{\partial s}{\partial W_{1m}}\\\vdots&\ddots&\vdots\\\frac{\partial s}{\partial W_{n1}}&\cdots&\frac{\partial s}{\partial W_{nm}}\end{matrix}\right.\right]
∂W11∂s⋮∂Wn1∂s⋯⋱⋯∂W1m∂s⋮∂Wnm∂s
b
∈
R
n
×
1
b\in\mathbb{R}^{n\times 1}
b∈Rn×1 ,
∂
s
∂
b
\frac{\partial s}{\partial b}
∂b∂s 的形状是:
∂
s
∂
b
=
h
T
∘
f
′
(
z
)
\frac{\partial s}{\partial\boldsymbol{b}}=\boldsymbol{h}^T\circ f^{\prime}(z)
∂b∂s=hT∘f′(z) 是行向量但是习惯上 梯度应该是一个列向量 因为
b
b
b 是一个列向量
雅可比矩阵形式(这使得链式法则很容易,对计算微积分很有意义) 和 形状约定(这使得SGD很容易实现)之间的分歧。
解决:两个选择
尽量使用雅可比矩阵形式(不完全使用),最后按照形状约定进行整形
最后转置
∂
s
∂
b
\frac{\partial s}{\partial b}
∂b∂s 使导数成为列向量(而不是按照雅各比矩阵形式的行向量),通过
δ
T
\delta^T
δT 来实现,这样始终遵循形状约定。 一直遵循形状约定
查看维度,找出何时转置 和/或 重新排序项。
关于矩阵的导数(按照雅各比矩阵形式)
∂
s
∂
W
=
δ
∂
z
∂
W
\quad\frac{\partial s}{\partial W}=\boldsymbol{\delta}\frac{\partial z}{\partial W}
∂W∂s=δ∂W∂z
δ
\delta
δ 将出现在我们的答案中。 另一项应该是
x
x
x ,因为
z
=
W
x
+
b
z=Wx+b
z=Wx+b
∂
s
∂
b
=
δ
∂
z
∂
b
\quad\frac{\partial s}{\partial b}=\boldsymbol{\delta}\frac{\partial z}{\partial b}
∂b∂s=δ∂b∂z
δ
\delta
δ 将出现在我们的答案中。 另一项应该是
1
1
1 ,因为
z
=
W
x
+
b
z=Wx+b
z=Wx+b
这表明
∂
s
∂
W
=
δ
T
x
T
\frac{\partial s}{\partial W}=\boldsymbol{\delta}^T\boldsymbol{x}^T
∂W∂s=δTxT
∂
s
∂
b
=
δ
T
\frac{\partial s}{\partial b}=\boldsymbol{\delta}^T
∂b∂s=δT
δ
\delta
δ 是 z 处的局部误差信号 x 是本地输入信号
总结
反向传播
求导,使用链式法则
构建计算图
前向传播阶段
神经网络的基本附加元素是 发回梯度,告诉我们怎么更新模型的参数,使得模型在 获得损失函数后进行学习(最小化损失)。
反向传播阶段 反向传播:单个节点 反向传播:多个节点 一个例子 反向传播最后的结果体现 改变输入对输出的影响,上涨/减少这个变量的多少倍
开始计算
就像前面手动计算梯度下降那样
在一般的计算图中进行反向传播计算的流程
现在的深度学习神经网络框架(Tensorflow, PyTorch, etc…)可以自动做反向传播,但是主要让层/节点编写器手动计算局部导数。我们需要为图中的特定节点或层添加内容。
反向传播的具体实现
class ComputationalGraph(object):
#.....
def forward(inputs):
# 1.[pass inputs to input gates...]
# 2. forward the computational graph:
# 根据节点在计算图中的依赖关系对节点进行拓扑排序
for gate in self .graph.nodes_topologically_sorted():
gate.forward()
return loss # the final gate in the graph outputs the loss
def backward():
# 反转图的拓扑排序
for gate in reversed(self.graph.nodes_topologically_sorted()):
gate.backward() # little piece of backprop (chain rule applied)
return inputs_gradients
手动实现前向/后向API
总结
反向传播:下游梯度 = 上游梯度 * 局部梯度前向传播计算出当前参数的值,然后进行反向传播以计算出损失的梯度(当前参数的损失)。现在的深度学习神经网络框架(Tensorflow, PyTorch, etc…)可以自动做反向传播,我们不用知道具体是怎么操作的,就像我们使用gcc来编译c代码,但是我们不需要具体知道gcc是怎么操作的。
相关链接
发表评论