\parinterval 本章默认使用行向量,如$\mathbf a=(a_1, a_2, a_3)$,$\mathbf a $对应的列向量记为$\mathbf a^{\rm T}$。
\parinterval{\small\sffamily\bfseries{矩阵}}\index{矩阵}(Matrix)\index{Matrix}:矩阵是一个按照长方阵列排列的实数集合,最早来自于方程组的系数及常数所构成的方阵。在计算机领域,通常将矩阵看作二维数组。这里用粗体的符号$\mathbf a $表示一个矩阵,如果该矩阵有$ m $行$ n $列,那么有$\mathbf a\in R^{m\times n}$。这里,用不加粗的符号来表示矩阵中的元素,其中每个元素都被一个行索引和一个列索引所确定。例如,$ a_{ij}$表示第$ i $行、第$ j $列的矩阵元素。如下,公式\ref{eq:5-3}中$\mathbf a $定义了一个2行2列的矩阵。
\parinterval{\small\sffamily\bfseries{矩阵}}\index{矩阵}(Matrix)\index{Matrix}:矩阵是一个按照长方阵列排列的实数集合,最早来自于方程组的系数及常数所构成的方阵。在计算机领域,通常将矩阵看作二维数组。这里用粗体的符号$\mathbf a $表示一个矩阵,如果该矩阵有$ m $行$ n $列,那么有$\mathbf a\in R^{m\times n}$。这里,用不加粗的符号来表示矩阵中的元素,其中每个元素都被一个行索引和一个列索引所确定。例如,$ a_{ij}$表示第$ i $行、第$ j $列的矩阵元素。如下,公式\ref{eq:9-3}中$\mathbf a $定义了一个2行2列的矩阵。
\parinterval 矩阵加法又被称作{\small\sffamily\bfseries{按元素加法}}\index{按元素加法}(Element-wise Addition)\index{Element-wise Addition}。它是指两个矩阵把其相对应元素加在一起的运算,通常的矩阵加法被定义在两个形状相同的矩阵上。两个$ m\times n $矩阵$\mathbf a $和$\mathbf b $的和,标记为$\mathbf a +\mathbf b $,它也是个$ m\times n $矩阵,其内的各元素为其相对应元素相加后的值。如果矩阵$\mathbf c =\mathbf a +\mathbf b $,则$ c_{ij}= a_{ij}+ b_{ij}$。公式\ref{eq:5-4}展示了矩阵之间进行加法的计算过程。
\parinterval 矩阵加法又被称作{\small\sffamily\bfseries{按元素加法}}\index{按元素加法}(Element-wise Addition)\index{Element-wise Addition}。它是指两个矩阵把其相对应元素加在一起的运算,通常的矩阵加法被定义在两个形状相同的矩阵上。两个$ m\times n $矩阵$\mathbf a $和$\mathbf b $的和,标记为$\mathbf a +\mathbf b $,它也是个$ m\times n $矩阵,其内的各元素为其相对应元素相加后的值。如果矩阵$\mathbf c =\mathbf a +\mathbf b $,则$ c_{ij}= a_{ij}+ b_{ij}$。公式\ref{eq:9-4}展示了矩阵之间进行加法的计算过程。
\begin{eqnarray}
\begin{pmatrix}
1 & 3\\
...
...
@@ -293,7 +293,7 @@
8 & 5\\
3 & 3
\end{pmatrix}
\label{eq:5-4}
\label{eq:9-4}
\end{eqnarray}
\parinterval 矩阵加法满足以下运算规律:
...
...
@@ -323,7 +323,7 @@
6 & 4 & 14\\
10 & 16 & 2
\end{pmatrix}
\label{eq:5-5}
\label{eq:9-5}
\end{eqnarray}
\parinterval 矩阵的数乘满足以下运算规律,其中$ k $和$ l $是实数,$\mathbf a $和$\mathbf b $是形状相同的矩阵:
...
...
@@ -347,10 +347,10 @@
\parinterval 矩阵乘法是矩阵运算中最重要的操作之一,为了与矩阵点乘区分,通常也把矩阵乘法叫做矩阵叉乘。假设$\mathbf a $为$ m\times p $的矩阵,$\mathbf b $为$ p\times n $的矩阵,对$\mathbf a $和$\mathbf b $作矩阵乘法的结果是一个$ m\times n $的矩阵$\mathbf c $,其中矩阵$\mathbf c $中第$ i $行、第$ j $列的元素可以表示为:
\parinterval{\small\sffamily\bfseries{线性映射}}\index{线性映射}( Linear Mapping)\index{Linear Mapping}或{\small\sffamily\bfseries{线性变换}}\index{线性变换}(Linear Transformation)\index{Linear Transformation}是从一个向量空间V到另一个向量空间W的映射函数$ f:v\rightarrow w$,且该映射函数保持加法运算和数量乘法运算,即对于空间V中任何两个向量$\mathbf u $ 和$\mathbf v $以及任何标量$ c $,有:
\parinterval 利用矩阵$\mathbf a\in R^{m\times n}$,可以实现两个有限维欧氏空间的映射函数$f:R^n\rightarrow R^m$。例如$ n $维列向量$\mathbf x ^{\rm T}$与$ m\times n $的矩阵$\mathbf a $,向量$\mathbf x ^{\rm T}$左乘矩阵$\mathbf a $,可将向量$\mathbf x ^{\rm T}$映射为$ m $列向量。如下是一个具体的例子,
\parinterval 同样,人工神经元是人工神经网络的基本单元。在人们的想象中,人工神经元应该与生物神经元类似。但事实上,二者在形态上是有明显差别的。如图\ref{fig:9-4} 是一个典型的人工神经元,其本质是一个形似$ y=f(\mathbf x\cdot\mathbf w+b)$的函数。显而易见,一个神经元主要由$\mathbf x $,$\mathbf w $,$ b $,$ f $四个部分构成。其中$\mathbf x $是一个形如$(x_0,x_1,\dots,x_n)$ 的实数向量,在一个神经元中担任``输入''的角色。$\mathbf w $是一个权重矩阵,其中的每一个元素都对应着一个输入和一个输出,代表着``某输入对某输出的贡献程度'',通常也被理解为神经元连接的{\small\sffamily\bfseries{权重}}\index{权重}(weight)\index{weight}。$ b $被称作偏置,是一个实数。$ f $被称作激活函数,用于对输入向量各项加权和后进行某种变换。可见,一个人工神经元的功能是将输入向量与权重矩阵右乘(做内积)后,加上偏置量,经过一个激活函数得到一个标量结果。
\parinterval 同样,人工神经元是人工神经网络的基本单元。在人们的想象中,人工神经元应该与生物神经元类似。但事实上,二者在形态上是有明显差别的。如图\ref{fig:9-4} 是一个典型的人工神经元,其本质是一个形似$ y=f(\mathbf x\cdot\mathbf w+b)$的函数。显而易见,一个神经元主要由$\mathbf x $,$\mathbf w $,$ b $,$ f $四个部分构成。其中$\mathbf x $是一个形如$(x_0,x_1,\dots,x_n)$ 的实数向量,在一个神经元中担任``输入''的角色。$\mathbf w $是一个权重矩阵,其中的每一个元素都对应着一个输入和一个输出,代表着``某输入对某输出的贡献程度'',通常也被理解为神经元连接的{\small\sffamily\bfseries{权重}}\index{权重}(Weight)\index{Weight}。$ b $被称作偏置,是一个实数。$ f $被称作激活函数,用于对输入向量各项加权和后进行某种变换。可见,一个人工神经元的功能是将输入向量与权重矩阵右乘(做内积)后,加上偏置量,经过一个激活函数得到一个标量结果。
\parinterval 张量乘以矩阵是怎样计算呢?可以先回忆一下\ref{sec:5.2.1}节的线性代数的知识。假设$\mathbf a $为$ m\times p $的矩阵,$\mathbf b $为$ p\times n $的矩阵,对$\mathbf a $和$\mathbf b $ 作矩阵乘积的结果是一个$ m\times n $的矩阵$\mathbf c $,其中矩阵$\mathbf c $中第$ i $行、第$ j $列的元素可以表示为:
\parinterval 将矩阵乘法扩展到高阶张量中:一个张量$\mathbf x $若要与矩阵$\mathbf w $做矩阵乘法,则$\mathbf x $的最后一维度需要与$\mathbf w $的行数大小相等,即:若张量$\mathbf x $的形状为$\cdot\times n $,$\mathbf w $须为$ n\times\cdot$的矩阵。如下是一个例子:
\noindent 其中,张量$\mathbf x $沿第1阶所在的方向与矩阵$\mathbf w $进行矩阵运算(张量$\mathbf x $第1阶的每个维度都可以看做一个$4\times4$的矩阵)。图\ref{fig:9-27}演示了这个计算过程。张量$\mathbf x $中编号为\ding{172}的子张量(可看作矩阵)与矩阵$\mathbf w $进行矩阵乘法,其结果对应张量$\mathbf s $中编号为\ding{172}的子张量。这个过程会循环四次,因为有四个这样的矩阵(子张量)。最终,图\ref{fig:9-27}给出了结果张量的形式($4\times4\times2$)。
\noindent 其中,$\Delta\mathbf w $表示参数的一个很小的变化值。式\ref{eq:5-33}也被称作导数的双边定义。如果一个函数是初等函数,可以用求导法则来求得其导函数。如果不知道函数导数的解析式,则必须利用数值方法来求解该函数在某个点上的导数,这种方法就是数值微分。
\noindent 其中,$\Delta\mathbf w $表示参数的一个很小的变化值。式\ref{eq:9-33}也被称作导数的双边定义。如果一个函数是初等函数,可以用求导法则来求得其导函数。如果不知道函数导数的解析式,则必须利用数值方法来求解该函数在某个点上的导数,这种方法就是数值微分。
\parinterval 数值微分根据导数的原始定义完成,根据公式可知,要得到损失函数在某个参数状态$\mathbf w $下的梯度,可以将$\mathbf w $增大或减小一点($\Delta\mathbf w $),例如,取$\Delta\mathbf w=0.0001$,之后观测损失函数的变化与$\Delta\mathbf w $的比值。$\Delta\mathbf w $的取值越小计算的结果越接近导数的真实值,但是对计算的精度要求越高。
\parinterval 这里新出现了变量$ z $,它保存了以前的所有梯度值的平方和,在更新参数时,通过乘以$\frac{1}{\sqrt{z_t}}$ ,就可以调整学习的尺度。这意味着,变动较大(被大幅度更新)的参数的学习率将变小。也就是说,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。
\parinterval$ w_{i-3}$、 $ w_{i-2}$ 、$ w_{i-1}$为该语言模型的输入(绿色方框),输入为每个词的One-hot向量表示(维度大小与词表大小一致),每个One-hot向量仅一维为1,其余为0,比如:$(0,0,1,\dots,0)$ 表示词表中第三个单词。之后把One-hot向量乘以一个矩阵$\mathbf C $得到单词的分布式表示(紫色方框)。令$ w_i $为第$ i $个词的One-hot表示,$\mathbf e_i $为第$ i $个词的分布式表示,有:
\begin{eqnarray}
\mathbf e_i&=&w_i\mathbf C
\label{eq:5-60}
\label{eq:9-60}
\end{eqnarray}
\noindent 这里的$\mathbf C $可以被理解为一个查询表,根据$ w_i $中为1的那一维,在$\mathbf C $中索引到相应的行进行输出(结果是一个行向量)。通常,把$\mathbf e_i$这种单词的实数向量表示称为{\small\bfnew{词嵌入}}\index{词嵌入}(Word Embedding\index{Word Embedding}),把$\mathbf C $称为词嵌入矩阵。
\noindent 这里的$\mathbf C $可以被理解为一个查询表,根据$ w_i $中为1的那一维,在$\mathbf C $中索引到相应的行进行输出(结果是一个行向量)。通常,把$\mathbf e_i$这种单词的实数向量表示称为词嵌入,把$\mathbf C $称为词嵌入矩阵。
\noindent 这里,输出$\mathbf y $是词表$V$上的一个分布,来表示${\rm P}(w_i|w_{i-1},w_{i-2},w_{i-3})$。$\mathbf U $、$\mathbf H $和$\mathbf d $是模型的参数。这样,对于给定的$w_i$可以用$\mathbf y(i)$得到其概率,其中$\mathbf y(i)$表示向量$\mathbf y$的第$i$维。
\noindent 其中,$\mathbf h_t $表示$ t $时刻循环单元的输出,$\mathbf h_{t-1}$表示$ t-1$时刻循环单元的输出,$\mathbf U $和$\mathbf W $是模型的参数。可以看出,循环单元的结构其实很简单,只是一个对$\mathbf h_{t-1}$和$\mathbf x_t $的线性变换再加上一个Tanh函数。通过读入上一时刻的输出,当前时刻可以访问以前的历史信息。这个过程可以循环执行,这样就完成了对所有历史信息的建模。$\mathbf h_t $可以被看作是序列在$ t $时刻的一种表示,也可以被看作是网络的一个隐藏层。进一步,$\mathbf h_t $可以被送入输出层,得到$ t $时刻的输出: