diff --git a/2017/01/16/buptroomreview/index.html b/2017/01/16/buptroomreview/index.html index 69afffab..65e61e7f 100644 --- a/2017/01/16/buptroomreview/index.html +++ b/2017/01/16/buptroomreview/index.html @@ -29,7 +29,7 @@ - + @@ -146,6 +146,11 @@

Thinkwee's Blog

Memory + + + + + diff --git a/2017/01/22/LinearAlgebra3/index.html b/2017/01/22/LinearAlgebra3/index.html index 5ee800c6..345e01e0 100644 --- a/2017/01/22/LinearAlgebra3/index.html +++ b/2017/01/22/LinearAlgebra3/index.html @@ -28,7 +28,7 @@ - + @@ -144,6 +144,11 @@

Thinkwee's Blog

Memory + + diff --git a/2017/01/23/numpycookbook/index.html b/2017/01/23/numpycookbook/index.html index efe46c51..a7a55051 100644 --- a/2017/01/23/numpycookbook/index.html +++ b/2017/01/23/numpycookbook/index.html @@ -28,10 +28,10 @@ - + - + @@ -146,6 +146,11 @@

Thinkwee's Blog

Memory + + @@ -353,8 +358,8 @@

+

投影矩阵

+

最小二乘法

+ -

傅里叶级数

+

第十六讲:正交矩阵和Gram-Schmidt正交化

+

正交矩阵

-

第二十二讲:对称矩阵及其正定性

-

对称矩阵

+

Gram-Schmidt正交化

-

正定性

- -]]> - - 数学 - - - math - linearalgebra - - - - Note for Linear Algebra 2 - /2017/01/21/LinearAlgebra2/ - -

第九讲:线性相关性、基、维数

-

线性相关性

-
    -
  • 背景知识:假设一个矩阵A,m<n,即未知数个数大于方程数,因此在零空间内除了零向量之外还有别的向量,最多m个主元,存在n-m个自由向量,整个方程存在非零解。
  • -
  • 什么条件下,\(x_1,x_2,x_3...x_n\)线性无关?存在一个系数不全为零的组合,使得线性相加结果为0,则为线性相关,反之为线性无关。
  • -
  • 如果向量组里存在一个零向量,则这个向量组不可能线性无关。
  • -
  • 假如在二维空间内随意画三个向量,则他们一定线性相关,为什么?由背景知识可得。
  • -
  • 对一个矩阵A,我们关心各列是否线性相关,如果零空间内存在非零向量,则各列相关。
  • -
  • 换一种方式解释:当\(v_1,v_2...v_n\)是A的各列,如果他们是无关的,那么A的零空间是怎样的?只有零向量。如果他们是相关的呢?那么零空间内除了零向量还存在一个非零向量。
  • -
  • 列向量无关时,所有的列向量都是主向量,秩为n。列向量相关时,秩小于n。
  • -
- -

生成空间、基

-
    -
  • \(v_1...,v_l\)生成了一个空间,是指这个空间包含这些向量的所有线性组合。

  • -
  • 向量空间的一组基是指一个向量组,这些向量有两个特性:他们线性无关、他们生成整个空间。

  • -
  • 举个栗子:求\(R^3\)的一组基,最容易想到的是 \[ -\begin{bmatrix} -1 \\ -0 \\ -0 \\ -\end{bmatrix} -, -\begin{bmatrix} -0 \\ -1 \\ -0 \\ -\end{bmatrix} -, +

  • 正交基就是A,B除以他们的长度\(q_1=\frac{A}{||A||}\)
  • +
  • 扩展到求三个向量,即A,B,C的情况,从上式我们已知A,B,同理,C需要c剪去在A和B上的投影分量 +\[ +C=c- \frac {A^Tc}{A^TA}A- \frac {B^Tc}{B^TB} B +\]
  • +
  • 由a,b组成列向量的矩阵A就通过施密特正交化变成了正交矩阵Q,用公式推导可以看出,Q的各列\(q_1,q_2,...\)\(a,b,....\)在同一列空间内,正交化可以写成 +\[ +A=QR \\ +\]
  • +
  • \[ \begin{bmatrix} -0 \\ -0 \\ -1 \\ -\end{bmatrix} -\]

  • -
  • 这是一组标准基,另一个栗子: \[ +a & b \\ +\end{bmatrix}= \begin{bmatrix} -1 \\ -1 \\ -2 \\ +q_1 & q_2 \\ \end{bmatrix} -, \begin{bmatrix} -2 \\ -2 \\ -5 \\ -\end{bmatrix} -\]

  • -
  • 显然无法构成一个空间,只要再取一个不在这两个向量构成的平面上的任意一个向量即可。

  • -
  • 如何检验他们是一组基?将他们作为列构成一个矩阵,矩阵必须可逆(因为此例中为方阵)。

  • -
  • 若只有例2中2个向量,他们无法构成三维空间的基,那么他们能构成什么空间的基呢?这两个向量所构成的平面。

  • -
  • 基不是唯一确定的,但所有的基都有共同点:基中向量的个数是相同的。

  • +q_1^Ta & q_1^Tb \\ +q_2^Ta & q_2^Tb \\ +\end{bmatrix} \\ +\] +
  • 其中,因为\(QQ^T=I\)
  • +
  • 所以\(R=Q^TA\)
  • +
  • \(q_2\)\(q_1\)正交,而\(q_1\)只是\(a\)的单位化,所以\(q_2^Ta=0\),即\(R\)是上三角矩阵
-

维数

+]]>
+ + 数学 + + + math + linearalgebra + +
+ + Note for Linear Algebra 3 + /2017/01/22/LinearAlgebra3/ + +

第十七讲:行列式及其性质

+

行列式

    -
  • 上面提到的所有基向量的个数相同,这个个数就是空间的维数。不是基向量的维数,而是基向量的个数
  • -
-

最后举个栗子

-

对矩阵A \[ -\begin{bmatrix} -1 & 2 & 3 &1 \\ -1 & 1 & 2 & 1 \\ -1 & 2 & 3 & 1 \\ -\end{bmatrix} -\] - 四列并不线性无关,可取第一列第二列为主列 - -2=A的秩=主列数=列空间维数 - 第一列和第二列构成列空间的一组基。 - -如果你知道列空间的维数,则确定了向量的个数,再满足线性无关,这些向量就可以构成一组基。 -- 零空间的维数是多少?在本例中零空间中的两个向量(特殊解)为: 矩阵A的行列式是与矩阵相关的一个数,记作\(detA或者|A|\) +

  • 行列式的性质
  • +
  • \(detI=1\)
  • +
  • 交换行,行列式的值的符号会相反
  • +
  • 一个置换矩阵的行列式是1或-1,取决于交换行次数的奇偶
  • +
  • 两行相等使得行列式为0(由性质二可以直接推出)
  • +
  • 矩阵消元不改变其行列式(证明见下)
  • +
  • 某一行为0,行列式为0(与0相乘等价于某一行为0,结果为0)
  • +
  • \(detA=0\)当且仅当A是奇异矩阵
  • +
  • \(det(A+B) \neq detA+detB \\ +detAB=(detA)(detB)\)
  • +
  • \(detA^{-1}detA=1\)
  • +
  • \(detA^2=(detA)^2\)
  • +
  • \(det2A=2^n detA\)
  • +
  • \(detA^T=detA\)(证明见下) +
  • +
  • 行列式按行是线性的,但行列式本身不是线性的 \[ -\begin{bmatrix} --1 \\ --1 \\ -1 \\ -0 \\ -\end{bmatrix} -, -\begin{bmatrix} --1 \\ -0 \\ -0 \\ -1 \\ -\end{bmatrix} -\] - -这两个特殊解是否构成了零空间的一组基?是的,零空间的维数就是自由变量的个数,即n-r,在本例中是4-2=2。

    -

    第十讲:四个基本子空间

    -
      -
    • 列空间C(A),零空间N(A),行空间C(\(A^T\)),左零空间N(\(A^T\))。
    • -
    • 分别处于\(R^m、R^n、R^n、R^m\)空间中
    • -
    • 列空间与行空间的维数都是秩r,零空间维数是n-r,左零空间维数是m-r
    • -
    • 列空间的基:主列,共r列。零空间的基:特殊解(自由列),共n-r个。行空间的基:最简形式R的非0行,共r行
    • -
    • 行变换是行向量的线性组合,因此A和R的行空间相同,列空间发生了变化
    • -
    • 为什么叫做左零空间? \[ -rref\begin{bmatrix} -A_{m*n} & I_{m*n} -\end{bmatrix}\rightarrow -\begin{bmatrix} -R_{m*n} & E_{m*n} -\end{bmatrix} \\ +\begin{vmatrix} +1 & 0 \\ +0 & 1 \\ +\end{vmatrix}=1 \\ +\begin{vmatrix} +0 & 1 \\ +1 & 0 \\ +\end{vmatrix}=-1 \\ +\begin{vmatrix} +ta & tb \\ +c & d \\ +\end{vmatrix}= +t\begin{vmatrix} +a & b \\ +c & d \\ +\end{vmatrix} \\ +\begin{vmatrix} +t+a & t+b \\ +c & d \\ +\end{vmatrix}= +\begin{vmatrix} +a & b \\ +c & d \\ +\end{vmatrix}+ +\begin{vmatrix} +t & t \\ +c & d \\ +\end{vmatrix} \]
    • -
    • 易得rref=E,即EA=R
    • -
    • 通过E可以计算左零空
    • -
    • 求左零空间即找一个产生零行向量的行组合
    • -
    • 左零空间的基就是R非0行对应的E行,共m-r行
    • +
    • 证明消元不改变行列式 \[ +\begin{vmatrix} +a & b \\ +c-la & d-lb \\ +\end{vmatrix}= +\begin{vmatrix} +a & b \\ +c & d \\ +\end{vmatrix}-l +\begin{vmatrix} +a & b \\ +a & b \\ +\end{vmatrix}= +\begin{vmatrix} +a & b \\ +c & d \\ +\end{vmatrix} +\]
    • +
    • 证明转置不改变行列式 \[ +A=LU \\ +\]
    • +
    • 即证 \(|U^TL^T|=|LU|\) \[ +|U^T||L^T|=|L||U| +\]
    • +
    • 以上四个矩阵都是三角矩阵,行列式等于对角线乘积,转置没有影响,所以相等
    • +
    +

    三角阵行列式

    +
      +
    • 对三角阵U的行列式,值为对角线上元素乘积(主元乘积)
    • +
    • 为什么三角阵其他元素不起作用?因为通过消元我们可以得到只有对角元素的矩阵,而消元不改变行列式
    • +
    • 为什么是对角线元素的乘积?因为可以消元后可以依次把对角元素提出来,即得到\(d_1d_2d_3...d_nI\),其中单位矩阵的行列式为1
    • +
    • 奇异矩阵行列式为0,存在全0行;可逆矩阵行列式不为0,能化成三角阵,行列式是三角矩阵对角元素乘积
    • +
    +

    A little more

    +
      +
    • 进行奇数次置换和偶数次置换得到的行列式肯定不一样(符号不同),这意味着进行奇数次置换和偶数次置换后的矩阵不会一样,即置换是严格区分奇偶的

    第十一讲:矩阵空间、秩1矩阵和小世界图

    -

    矩阵空间

    +id="第十八讲行列式公式和代数余子式">第十八讲:行列式公式和代数余子式 +

    行列式公式

      -
    • 可以看成向量空间,可以数乘,可以相加
    • -
    • \(3*3\)矩阵空间M为例,空间的一组基即9个矩阵,每个矩阵中只包含一个元素1,这是一组标准基,可得这个矩阵空间维数是9 -\[ -\begin{bmatrix} -1 & 0 & 0 \\ -0 & 0 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}, -\begin{bmatrix} -0 & 1 & 0 \\ -0 & 0 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}, -\begin{bmatrix} -0 & 0 & 1 \\ -0 & 0 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}..... +
    • 推导2*2行列式 \[ +\begin{vmatrix} +a & b \\ +c & d \\ +\end{vmatrix}= +\begin{vmatrix} +a & 0 \\ +c & d \\ +\end{vmatrix}+ +\begin{vmatrix} +0 & b \\ +c & d \\ +\end{vmatrix}= +\begin{vmatrix} +a & 0 \\ +c & 0 \\ +\end{vmatrix}+ +\begin{vmatrix} +a & 0 \\ +0 & d \\ +\end{vmatrix}+ +\begin{vmatrix} +0 & b \\ +c & 0 \\ +\end{vmatrix}+ +\begin{vmatrix} +0 & b \\ +0 & d \\ +\end{vmatrix} \\ +=0+ad-bc+0 +\] +我们可以发现这种方法是一次取一行,将这一行拆解(行列式按行是线性的),再提取出因子,通过行交换得到单位矩阵,通过性质一和性质二得到答案
    • +
    • 如果扩展到3*3矩阵,则第一行分解成三部分,每部分针对第二行又分解成三部分,所以最后得到27部分,其中不为0的部分是那些各行各列均有元素的矩阵。
    • +
    • 例如 \[ +\begin{vmatrix} +a & 0 & 0\\ +0 & 0 & b\\ +0 & c & 0\\ +\end{vmatrix} +\] 先提取出因子,得到\(abc\),交换第二行第三行得到单位矩阵,于是答案就是\(abc*detI=abc\),又因为进行了一次行交换,所以答案是负的,\(-abc\)
    • +
    • n*n的矩阵可以分成\(n!\)个部分,因为第一行分成n个部分,第二行不能重复,选择n-1行,一次重复,所以得到\(n!\)部分
    • +
    • 行列式公式就是这\(n!\)个部分加起来
    • +
    +

    代数余子式

    +
      +
    • \(det=a_{11}(a_{22}a_{33}-a_{23}a_{32})+a_{12}(....)+a_{13}(....)\)
    • +
    • 提取出一个因子,由剩余的因子即括号内的内容组成的就是余子式
    • +
    • 从矩阵上看,选择一个元素,它的代数余子式就是排除这个元素所在行和列剩下的矩阵的行列式
    • +
    • \(a_{ij}\)的代数余子式记作\(c_{ij}\)
    • +
    • 注意代数余子式的正负,与\(i+j\)的奇偶性有关,偶数取正,奇数取负,这里的符号是指代数余子式对应的子矩阵正常计算出行列式后前面的符号
    • +
    • \(detA=a_{11}C_{11}+a_{12}C_{12}+....+a_{1n}C_{1n}\)
    • +
    +

    第十九讲:克拉默法则,逆矩阵,体积

    +

    逆矩阵

    +
      +
    • 只有行列式不为0时,矩阵才是可逆的
    • +
    • 逆矩阵公式 \[ +A^{-1}=\frac{1}{detA}C^T +\] 其中\(C_{ij}\)\(A_{ij}\)的代数余子式
    • +
    • 证明:即证\(AC^T=(detA)I\) \[ \begin{bmatrix} -0 & 0 & 0 \\ -0 & 0 & 0 \\ -0 & 0 & 1 \\ +a_{11} & ... & a_{1n} \\ +a_{n1} & ... & a_{nn} \\ \end{bmatrix} -\]
    • -
    • 再来研究\(3*3\)矩阵空间中对称矩阵子空间S的维数,可以看到原空间基中9个矩阵,有3个矩阵属于对称矩阵子空间,另外还有上三角与下三角对称的三个矩阵,所以对称矩阵子空间的维数是6 -\[ -\begin{bmatrix} -1 & 0 & 0 \\ -0 & 0 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}, \begin{bmatrix} -0 & 0 & 0 \\ -0 & 1 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}, +c_{11} & ... & c_{n1} \\ +c_{1n} & ... & c_{nn} \\ +\end{bmatrix}= \begin{bmatrix} -0 & 0 & 0 \\ -0 & 0 & 0 \\ -0 & 0 & 1 \\ +detA & 0 & 0 \\ +0 & detA & 0 \\ +0 & 0 & detA \\ \end{bmatrix} -\] \[ +\] 对角线上都是行列式,因为\(det=a_{11}(a_{22}a_{33}-a_{23}a_{32})+a_{12}(....)+a_{13}(....)\) +其他位置都是0,因为行a乘以行b的代数余子式相当于求一个矩阵的行列式,这个矩阵行a与行b相等,行列式为0
    • +
    +

    克拉默法则

    +
      +
    • 解Ax=b \[ +Ax=b \\ +x=A^{-1}b \\ +x=\frac{1}{detA}C^Tb \\ +\\ +x_1=\frac{detB_1}{detA} \\ +x_3=\frac{detB_2}{detA} \\ +... \\ +\]
    • +
    • 克拉默法则即发现矩阵\(B_i\)就是矩阵\(A\)的第i列换成b,其余不变
    • +
    +

    体积

    +
      +
    • A的行列式可以代表一个体积,例如3*3矩阵的行列式代表一个三维空间内的体积
    • +
    • 矩阵的每一行代表一个盒子的一条边(从同一顶点连出的),行列式就是这个盒子的体积,行列式的正负代表左手或者右手系。
    • +
    • (1)单位矩阵对应单位立方体,体积为1
    • +
    • 对正交矩阵Q, \[ +QQ^T=I \\ +|QQ^T|=|I| \\ +|Q||Q^T|=1 \\ +{|Q|}^2=1 \\ +|Q|=1 \\ +\] +Q对应的盒子是单位矩阵对应的单位立方体在空间中旋转过一个角度
    • +
    • (3a)如果矩阵的某一行翻倍,即盒子一组边翻倍,体积也翻倍,从行列式角度可以把倍数提出来,因此行列式也是翻倍
    • +
    • (2)交换矩阵两行,盒子的体积不变
    • +
    • (3b)矩阵某一行拆分,盒子也相应切分为两部分
    • +
    • 以上,行列式的三条性质(1,2,3a,3b)均可以在体积上验证
    • +
    +

    第二十讲:特征值和特征向量

    +

    特征向量

    +
      +
    • 给定矩阵A,矩阵A可以看成一个函数,作用在一个向量x上,得到向量Ax
    • +
    • 当Ax平行于x时,即\(Ax=\lambda +x\),我们称\(x\)为特征向量,\(\lambda\)为特征值
    • +
    • 如果A是奇异矩阵,\(\lambda = +0\)是一个特征值
    • +
    +

    几个例子

    +
      +
    • 如果A是投影矩阵,可以发现它的特征向量就是投影平面上的任意向量,因为\(Ax\)即投影到平面上,平面上的所有向量投影后不变,自然平行,同时特征值就是1。如果向量垂直于平面,\(Ax=0\),特征值为0.因此投影矩阵A的特征向量就分以上两种情况,特征值为1或0.
    • +
    • 再举一例 \[ +A= \begin{bmatrix} -0 & 1 & 0 \\ -1 & 0 & 0 \\ -0 & 0 & 0 \\ -\end{bmatrix}, +0 & 1 \\ +1 & 0 \\ +\end{bmatrix} \\ +\lambda =1, x= \begin{bmatrix} -0 & 0 & 1 \\ -0 & 0 & 0 \\ -1 & 0 & 0 \\ -\end{bmatrix}, +1 \\ +1 \\ +\end{bmatrix} +Ax= \begin{bmatrix} -0 & 0 & 0 \\ -0 & 0 & 1 \\ -0 & 1 & 0 \\ +1 \\ +1 \\ +\end{bmatrix} \\ +\lambda =-1, x= +\begin{bmatrix} +-1 \\ +1 \\ \end{bmatrix} +Ax= +\begin{bmatrix} +1 \\ +-1 \\ +\end{bmatrix} \\ \]
    • -
    • 对于上三角矩阵子空间U,易得维数为6,且元空间的基包含了子空间的基
    • -
    • 接着再来研究\(S \bigcap U\) -,易得这个子空间即对角矩阵D,维度为3
    • -
    • 如果是$S U $呢?他们的并的基可以得到所有M的基,所以其维数是9
    • -
    • 整理一下可得 \[ -dim(S)=6,dim(U)=6,dim(S \bigcap U)=3,dim(S \bigcup U)=3 \\ -dim(S)+dim(U)=dim(S \bigcap U)+dim(S \bigcup U) \\ -\]
    • -
    • 再来举一个栗子,说明向量空间不一定有向量,比如下面这个基于微分方程的向量空间 -\[ -\frac{d^2y}{dx^2}+y=0 +
    • n*n矩阵有n个特征值
    • +
    • 特征值的和等于对角线元素和,这个和称为迹(trace),
    • +
    • 如何求解\(Ax=\lambda x\) \[ +(A-\lambda I)x=0 \\ \]
    • -
    • 他的几个解为 \[ -y=cos(x),y=sin(x) +
    • 可见方程有非零解,\((A-\lambda +I)\)必须是奇异的 即: \[ +det(A-\lambda I)=0 \\ \]
    • -
    • 完整解为
      -\[ -y=c_1cos(x)+c_2sin(x) +
    • \[ +If \qquad Ax=\lambda x \\ +Then \qquad (A+3I)x=(\lambda +3)x \\ \]
    • -
    • 即得到一个向量空间,基为2
    • -
    -

    秩1矩阵

    -
      -
    • 先写一个简单的秩1矩阵 \[ +
    • 因为加上单位矩阵,特征向量不变依然为x,特征值加上单位矩阵的系数即\((\lambda +3)\)
    • +
    • A+B的特征值不一定是A的特征值加上B的特征值,因为他们的特征向量不一定相同。同理AB的特征值也不一定是他们的特征值的乘积
    • +
    • 再举一例,对旋转矩阵Q \[ +Q= \begin{bmatrix} -1 & 4 & 5 \\ -2 & 8 & 10 \\ -\end{bmatrix}= +0 & -1 \\ +1 & 0 \\ +\end{bmatrix} \\ +trace=0=\lambda _1 +\lambda _2 \\ +det=1=\lambda _1 \lambda _2 \\ +\]
    • +
    • 但是可以看出 \(\lambda _1,\lambda +_2\)无实数解
    • +
    • 再看看更加糟糕的情况(矩阵更加不对称,更难得到实数解的特征值) \[ +A= \begin{bmatrix} -1 \\ -2 \\ -\end{bmatrix}* +3 & 1 \\ +0 & 3 \\ +\end{bmatrix} \\ +det(A-\lambda I)= +\begin{vmatrix} +3-\lambda & 1 \\ +0 & 3-\lambda \\ +\end{vmatrix} +==(3-\lambda )^2=0 \\ +\lambda _1=\lambda _2=3 \\ +x_1= \begin{bmatrix} -1 & 4 & 5 \\ +1 \\ +0 \\ \end{bmatrix} \]
    • -
    • 所有的秩1矩阵都可以表示为一列乘一行
    • -
    • 秩1矩阵就像积木,比如一个秩为4的矩阵可以由4个秩1矩阵构建而成
    • -
    • 再来看一个秩1矩阵的栗子,在四维空间中,设向量\(v=(v_1,v_2,v_3,v_4)\),集合\(S=\{v|v_1+v_2+v_3+v_4=0\}\),假如把S看成零空间,则相应的方程\(Av=0\)中的矩阵A为 +

      第二十一讲:对角化和A的幂

      +

      对角化

      +
        +
      • 假设A有n个线性无关特征向量,按列组成矩阵S,即特征向量矩阵

      • +
      • 以下所有关于矩阵对角化的讨论都在S可逆,即n个特征向量线性无关的前提下

      • +
      • \[ +AS=A[x_1,x_2...x_n]=[\lambda _1 x_1,....\lambda _n x_n] \\ +=[x_1,x_2,...x_n] +\begin{bmatrix} +\lambda _1 & 0 & ... & 0 \\ +0 & \lambda _2 & ... & 0 \\ +... & ... & ... & ... \\ +0 & 0 & 0 & \lambda _n \\ +\end{bmatrix} \\ +=S \Lambda \\ +\]

      • +
      • 假设S可逆,即n个特征向量无关,此时可以得到 \[ -A=\begin{bmatrix} -1 & 1 & 1 & 1 \\ -\end{bmatrix} -\]

      • -
      • 易得\(dimN(A)=n-r\),所以S的维数是\(4-1=3\),S的一组基为

      • +
      • \(\Lambda\)是对角矩阵,这里我们得到了除了\(A=LU\)\(A=QR\)之外的一种矩阵分解

      • +
      • \[ +if \qquad Ax=\lambda x \\ +A^2 x=\lambda AX=\lambda ^2 x \\ +A^2=S\Lambda S^{-1} S \Lambda S^{-1}=S \Lambda ^2 S^{-1} \\ +\]

      • +
      • 上面关于\(A^2\)的两式说明平方后特征向量不变,特征值平方,K次方同理

      • +
      • 特征值和特征向量帮助我们理解矩阵幂,当计算矩阵幂时,我们可以把矩阵分解成特征向量矩阵和对角阵相乘的形式,K个相乘两两可以抵消,如上式

      • +
      • 什么样的矩阵的幂趋向于0(稳定) \[ +A^K \rightarrow 0 \quad as \quad K \rightarrow \infty \\ +if \quad all |\lambda _i|<1 \\ +\]

      • +
      • 哪些矩阵可以对角化? 如果所有特征值不同,则A可以对角化

      • +
      • 如果矩阵A已经是对角阵,则\(\Lambda\)与A相同

      • +
      • 特征值重复的次数称为代数重度,对三角阵,如 \[ +A= \begin{bmatrix} --1 \\ -1 \\ -0 \\ -0 \\ -\end{bmatrix}, +2 & 1 \\ +0 & 2 \\ +\end{bmatrix} \\ +det(A-\lambda I)= +\begin{vmatrix} +2-\lambda & 1 \\ +0 & 2-\lambda \\ +\end{vmatrix}=0 \\ +\lambda =2 \\ +A-\lambda I= \begin{bmatrix} --1 \\ -0 \\ -1 \\ -0 \\ -\end{bmatrix}, +0 & 1 \\ +0 & 0 \\ +\end{bmatrix} \\ +\]

      • +
      • \(A-\lambda +I\),几何重数是1,而特征值的代数重度是2

      • +
      • 特征向量只有(1,0),因此对于三角阵,它不可以对角化,不存在两个线性无关的特征向量。

      • +
      +

      A的幂

      +
        +
      • 多数矩阵拥有互相线性无关的一组特征值,可以对角化。假如可以对角化,我们需要关注如何求解A的幂
      • +
      • \[ +give \quad u_0 \\ +u_{k+1}=Au_k \\ +u_k=A^ku_0 \\ +how \quad to \quad solve \quad u_k \\ +u_0=c_1x_1+c_2x_2+...+c_nx_n=SC \\ +Au_0=c_1 \lambda _1 x_1 + c_2 \lambda _2 x_2 +...+c_n \lambda _n x_n \\ +A^{100}u_0=c_1 \lambda _1^{100} x_1 + c_2 \lambda _2^{100} x_2 +...+c_n +\lambda _n^{100} x_n \\ +=S\Lambda ^{100} C \\ +=u_{100} \\ +\]
      • +
      • 因为n个特征向量互相不线性相关,因此它们可以作为一组基覆盖整个n维空间,自然\(u_0\)可以用特征向量的线性组合表示,C是线性系数向量。上式得出了矩阵幂的解法,接下来以斐波那契数列为例 +\[ +F_0=0 \\ +F_1=1 \\ +F_2=1 \\ +F_3=2 \\ +F_4=3 \\ +F_5=5 \\ +..... \\ +F_{100}=? \\ +\]
      • +
      • 斐波那契数列的增长速度有多快?由特征值决定,我们尝试构造向量,来找到斐波那契数列迭代的矩阵关系 +\[ +F_{k+2}=F_{k+1}+F_k \\ +F_{k+1}=F_{k+1} \\ +\]
      • +
      • 定义向量 \[ +u_k= \begin{bmatrix} --1 \\ -0 \\ -0 \\ -1 \\ +F_{k+1} \\ +F_k \\ +\end{bmatrix} \\ +\]
      • +
      • 利用这个向量可以将前两个等式写成矩阵形式 \[ +u_{k+1}= +\begin{bmatrix} +1 & 1 \\ +1 & 0 \\ \end{bmatrix} +u_k \\ +A= +\begin{bmatrix} +1 & 1 \\ +1 & 0 \\ +\end{bmatrix} \\ +\lambda =\frac {1 \pm \sqrt 5}2 \\ \]
      • -
      • 矩阵A的四个子空间:易得行空间和列空间的秩(维数)均为1,行空间\(C(A^T)=\{a,a,a,a\}​\),列空间\(C(A)=R^1​\),零空间\(N(A)​\)即S的基线性组合,\(N(A^T)={0}​\)
      • -
      • 整理一下 \[ -dim(N(A))+dim(C(A^T))=3+1=4=n \\ -dim(C(A))+dim(N(A^T))=1+0=1=m \\ +
      • 得到两个特征值,我们很容易得到特征向量
      • +
      • 回到斐波那契数列,斐波那契数列的增长速率由我们构造的"数列更新矩阵"的特征值决定,而且由\(A^{100}u_0=c_1 \lambda _1^100 x_1 + c_2 \lambda +_2^100 x_2 +...+c_n \lambda _n^100 +x_n\)可以看出增长率主要由由较大的特征值决定,因此\(F_{100}\)可以写成如下形式 \[ +F_{100} \approx c_1 {\frac {1 + \sqrt 5}2}^{100} \\ \]
      • +
      • 再有初始值有 \[ +u_0= +\begin{bmatrix} +F_1 \\ +F_0 \\ +\end{bmatrix}= +\begin{bmatrix} +1 \\ +0 \\ +\end{bmatrix} +=c_1x_1+c_2x_2 +\]
      • +
      • 其中\(x_1,x_2\)是两个特征向量,线性系数可求,代入公式可求\(F_{100}\)的近似值
      -

      小世界图

      -
        -
      • 仅仅引入了图的概念,为下一讲准备
      • -
      -

      第十二讲:图和网络

      -

      -
        -
      • 图的一些基础概念,略过
      • -
      -

      网络

      -
        -
      • 图的关联矩阵A,将列作为图的节点,行作为矩阵的边,起点为-1,终点为1,其余为0

      • -
      • 构成回路的几行线性相关,回路意味着相关

      • -
      • 关联矩阵A描述了图的拓扑结构

      • -
      • \(dimN(A^T)=m-r​\)

      • -
      • 假如图的节点是电势,\(Ax\)中x即电势,\(Ax=0\)得到一组电势差方程,零空间是一维的,\(A^Ty\)中y即边上的电流,电流与电势差的关系即欧姆定律,\(A^Ty=0\)得到基尔霍夫定律,零空间包含了基尔霍夫电流方程的两个解,从电路图上看即两个小回路

      • -
      • 树就是没有回路的图

      • -
      • 再来看看\(dimN(A^T)=m-r\)

      • -
      • \(dimN(A^T)\)=无关回路数
        -

      • -
      • \(m\)=边数

      • -
      • \(r=n-1\)=节点数-1 -(因为零空间是一维的)

      • -
      • 即:节点数-边数+回路数=1(欧拉公式)

      • -
      -

      总结

      -
        -
      • 将电势记为e,\(e=Ax\)

      • -
      • 电势差导致电流产生,\(y=Ce\)

      • -
      • 电流满足基尔霍夫电流方程,\(A^Ty=0\)

      • -
      • 将三个方程联立: \[ -A^TCAx=f -\] 这就是应用数学中最基本的平衡方程

      • -
      -

      第十三讲:正交向量与子空间

      -

      正交向量

      +

      总结

        -
      • 正交即垂直,意味着在n维空间内,这些向量的夹角是90度

      • -
      • \(x^Ty=0\),x与y正交,证明:

      • -
      • 若x与y正交,易得: \[ -{||x||}^2+{||y||}^2={||x+y||}^2 \\ -\]

      • -
      • 即: \[ -x^Tx+y^Ty={(x+y)}^T(x+y)=x^Tx+y^Ty+x^Ty+xy^T=2x^Ty \\ -\]

      • -
      • 即: \[ -x^Ty=0 \\ -\]

      • -
      • 子空间正交意味着一个子空间内的所有向量与另一个子空间内的每一个向量正交,显然,如果两个二维子空间在某一向量处相交,则这两个空间一定不正交

      • -
      • 若两个子空间正交,则他们一定不会相交于某一个非零向量,因为这个非零向量同时存在于两个子空间内,它不可能自己垂直于自己

      • -
      • 行空间正交于零空间,因为\(Ax=0\),即矩阵的每一行以及这些行的线性组合(行空间)与解向量(零空间)点乘都为0。这样就证明了图中左半部分

      • -
      • 图中右半部份,列空间和左零空间分别是矩阵A的转置矩阵的行空间和零空间,刚才的证明同样有效,因此列空间和左零空间正交,图中右半部份成立

      • -
      • 图中给出了n维空间和m维空间的正交子空间,n维空间的正交子空间:r维行空间和n-r维零空间。m维空间的正交子空间:r维列空间和m-r维左零空间。

      • +
      • 我们发现在A可逆的情况下,A可以分解成\(S\Lambda S^{-1}\)的形式
      • +
      • 这种形式有一个特点,方便求A的幂,即分解后可以看出A的幂的特征值单位矩阵是A的特征值单位矩阵的幂
      • +
      • 我们在求解斐波那契数列中尝试运用此特点,首先将数列的更新转换为矩阵形式
      • +
      • 求出矩阵的特征值,特征向量
      • +
      • 由A的幂的展开式可以看出A的幂主要由较大的特征值决定,因此\(F_{100}\)可以写成\(F_{100} \approx c_1 {(\frac {1 + \sqrt +5}2)}^{100}\)的形式
      • +
      • 由初始值\(F_0\)求出线性系数,代入上式,得到\(F_{100}\)的近似值
      • +
      • 以上是差分方程的一个例子,下一节将讨论微分方程
      -

      正交子空间

      +

      第二十二讲:微分方程和exp(At)

      +

      微分方程

        -
      • 例如三维空间,假如行空间是一维的,则零空间是二维的,行空间是一条直线,零空间是垂直于这个直线的平面,从几何上可以直观看出他们正交
      • -
      • 因为零空间是行空间的正交补集,所以零空间包含了所有正交于行空间的向量
      • -
      • 以上是所有关于解\(Ax=0\)的知识,如果要解不可解的方程,或者说求最优解,该怎么办呢?我们引入一个重要的矩阵\(A^TA\)
      • -
      • \(A^TA\)是一个\(n*n\)的方阵,而且对称
      • -
      • 坏方程转换为好方程,两边同乘\(A^T\)
      • -
      • \(A^TA\)不总是可逆,若可逆,则\(N(A^TA)=N(A)\),且他们的秩相同
      • -
      • \(A^TA\)可逆当且仅当零空间内只有零向量,即各列线性无关,下一讲将证明这些性质
      • -
      -

      第十四讲:子空间投影

      -

      投影

      -
        -
      • 在二维情况下讨论投影
      • -
      • 一个点b到另一条直线a的投影,即从这个点做垂直于a的垂线段交a于p点,p即b在a上的投影点,以p为终点的向量即投影p,垂线段即误差e,e=b-p
      • -
      • p在a的一维子空间里,是a的x倍,即p=xa
      • -
      • a垂直于e,即 \[ -a^T(b-xa)=0 \\ -xa^Ta=a^Tb \\ -x= \frac {a^Tb}{a^Ta} \\ -p=a\frac {a^Tb}{a^Ta} \\ -\]
      • -
      • 从式子中可以看到,若b翻倍,则投影翻倍,若a变化,则投影不变,因为分子分母抵消了
      • -
      -

      投影矩阵

      -
        -
      • 现在可以引入投影矩阵P的一维模式(projection matrix),\(p=Pb\),\(P= \frac -{aa^T}{a^Ta}\)
      • -
      • 用任意b乘投影矩阵,总会落在通过a的一条线上(即b在a上的投影p),所以投影矩阵的列空间是这条线,矩阵的秩为1
      • -
      • 投影矩阵的另外两条性质:
      • -
      • 对称,即\(P^T=P\)
      • -
      • 两次投影在相同的位置,即\(P^2=P\)
      • -
      -

      投影的意义

      -
        -
      • 下面在高维情况下讨论
      • -
      • 当方程数大于未知数个数时,经常无解,这时我们只能找出最接近的解
      • -
      • 如何找?将b微调,使得b在列空间中
      • -
      • 怎么微调?将b变成p,即列空间中最接近b的那一个,即转换求解\(Ax^{'}=p\),p时b在列空间上的投影
      • -
      • 现在我们要求\(x^{'}\),\(p=Ax^{'}\),误差向量\(e=b-Ax^{'}\),由投影定义可知e需要垂直于A的列空间
      • -
      • 综上可得 \[ -A^T(b-Ax^{'})=0 \\ +
      • 常系数线性方程的解是指数形式的,如果微分方程的解是指数形式,只需利用线代求出指数,系数,就可以求出解
      • +
      • 举个例子 \[ +\frac{du_1}{dt}=-u_1+2u_2 \\ +\frac{du_2}{dt}=u_1-2u_2 \\ +u(0)= +\begin{bmatrix} +1 \\ +0 \\ +\end{bmatrix} \\ \]
      • -
      • 由上式可以看出e在A的左零空间,与列空间正交。解上式可得 首先我们列出系数矩阵,并找出矩阵的特征值和特征向量 \[ -x^{'}=(A^TA)^{-1}A^Tb \\ -p=Ax^{'}=A(A^TA)^{-1}A^Tb \\ -\]
      • -
      • 即投影矩阵P的n维模式: \[ -A(A^TA)^{-1}A^T \\ +A= +\begin{bmatrix} +-1 & 2 \\ +1 & -2 \\ +\end{bmatrix} \]
      • -
      • 投影矩阵P的n维模式依然保留了1维模式的两个性质
      • -
      • 现在回到求最优解,最常见的一个例子是通过最小二乘法拟合一条直线
      • -
      • 已知三个点\(a_1,a_2,a_3\),找出一条直线拟合接近三个点,\(b=C+Da\)
      • -
      • 假如\(a_1=(1,1),a_2=(2,2),a_3=(3,2)\),则 易得\(\lambda=0\)是这个奇异矩阵的一个解,由迹可以看出第二个特征值是\(\lambda=-3\),并得到两个特征向量 \[ -C+D=1 \\ -C+2D=2 \\ -C+3D=2 \\ -\] 写成线代形式为: \[ +x_1= \begin{bmatrix} -1 & 1 \\ -1 & 2 \\ -1 & 3 \\ -\end{bmatrix} +2 \\ +1 \\ +\end{bmatrix} \\ +x_2= \begin{bmatrix} -C \\ -D \\ +1 \\ +-1 \\ \end{bmatrix} +\]
      • +
      • 微分方程解的通解形式将是 \[ +u(t)=c_1e^{\lambda _1 t}x_1+c_1e^{\lambda _2 t}x_2 +\]
      • +
      • 为什么? \[ +\frac{du}{dt} \\ +=c_1 \lambda _1 e^{\lambda _1 t}x_1 \\ +=A c_1 e^{\lambda _1 t}x_1 \\ +because \quad A x_1=\lambda _1 x_1 \\ +\]
      • +
      • 在差分方程\(u_{k+1}=Au_k\)当中,解的形式是\(c_1\lambda _1 ^k x_1+c_2 \lambda _2 ^k +x_2\)
      • +
      • 在微分方程\(\frac +{du}{dt}=Au\)当中,解的形式是\(u(t)=c_1e^{\lambda _1 t}x_1+c_1e^{\lambda _2 +t}x_2\)
      • +
      • \(c_1,c_2\)由初始值解出,即系数矩阵C乘特征向量矩阵S得到初始值
      • +
      • 可以看出t趋于无穷时,例子方程的解只剩下稳态部分,即\((\frac 23,\frac 13)\)
      • +
      • 什么时候解趋向于0?存在负数特征值,因为\(e^{\lambda t}\)需要趋向于0
      • +
      • 如果特征值是复数呢?虚数部分的模值是1,所以如果复数的实数部分是负数,解依然趋向于0
      • +
      • 什么时候存在稳态?特征值中只存在0和负数,就如上面的例子
      • +
      • 什么时候解无法收敛?任何特征值的实数部分大于0
      • +
      • 改变系数矩阵的符号,特征值也改变符号,稳态的解依然稳态,收敛的解就会变成发散
      • +
      • 如何从矩阵直接判断解是否收敛?即特征值的实数部分都小于0?
      • +
      • 矩阵的迹应该小于0,但对角线之和为0依然不一定收敛,如 \[ \begin{bmatrix} -1 \\ -2 \\ -2 \\ +-2 & 0 \\ +0 & 1 \\ \end{bmatrix} \]
      • -
      • 即Ax=b,方程数大于未知数个数,若两边乘以A转置,即求\(x^{'}\),这样就可以求出拟合直线。下一讲继续此例
      • +
      • 因此还需要另一个条件:行列式的值是特征值乘积,因此行列式的值应该大于0
      -

      第十五讲:投影矩阵和最小二乘法

      -

      投影矩阵

      +

      exp(At)

        -
      • 回顾,\(P=A(A^TA)^{-1}A^T\),\(Pb\)即b在A的列空间上的投影,现在考虑两种极端情况,b在列空间上和b正交于列空间: -b在列空间上:\(Pb=b\);证明:若b在列空间上,则可以表示为\(b=Ax\),在A各列线性无关的条件下,\((A^TA)\)可逆,代入\(P=A(A^TA)^{-1}A^T\)\(Pb=b\) b正交于列空间,\(Pb=0\);证明:若b正交于列空间则b在左零空间内,即\(A^Tb=0\),显然代入\(P=A(A^TA)^{-1}A^T\)\(Pb=0\)

      • -
      • p是b在列空间上的投影,因为列空间正交于左零空间,自然e就是b在左零空间上的投影,如图: -\[ -b=p+e \\ -p=Pb \\ -\]

      • -
      • 所以 \[ -e=(I-P)b \\ -\]

      • -
      • 所以左零空间的投影矩阵为\((I-P)\)

      • +
      • 是否可以把解表示成\(S,\Lambda\)的形式
      • +
      • 矩阵A表示\(u_1,u_2\)耦合,首先我们需要将u对角化,解耦
      • +
      • \[ +\frac{du}{dt} = Au \\ +set \quad u=Sv \\ +S \frac{dv}{dt} = ASv \\ +\frac{dv}{dt}=S^{-1}ASv=\Lambda v \\ +v(t)=e^{\Lambda t}v(0) \\ +u(t)=Se^{\Lambda t}S^{-1}u(0) \\ +\]
      -

      最小二乘法

      +

      第二十一讲:马尔科夫矩阵;傅立叶级数

      +

      马尔科夫矩阵

        -
      • 回到上一讲的例子,找到一条最优直线接近三个点,最小化误差,如图

      • -
      • 设直线为\(y=C+Dt\),代入三个点坐标得到一个方程组 -\[ -C+D=1 \\ -C+2D=2 \\ -C+3D=2 \\ +

      • 一个典型的马尔科夫矩阵 \[ +\begin{bmatrix} +0.1 & 0.01 & 0.3 \\ +0.2 & 0.99 & 0.3 \\ +0.7 & 0 & 0.4 \\ +\end{bmatrix} \]

      • -
      • 此方程组无解但是存在最优价,从代数角度看:

        每一个元素大于等于0,每一列之和为1,马尔科夫矩阵的幂都是马尔科夫矩阵

      • +
      • \(\lambda=1\)是一个特征值,其余的特征值的绝对值都小于1

      • +
      • 在上一讲中我们谈到矩阵的幂可以分解为 \[ -||e||^2=(C+D-1)^2+(C+2D-2)^2+(C+3D-2)^2 \\ +u_k=A^ku_0=c_1\lambda _1 ^kx_1+c_2\lambda _2 ^kx_2+..... \]

      • -
      • 分别对C和D求偏导为0,得到方程组: \[ -\begin{cases} -3C+6D=5\\ -6C+14D=11\\ -\end{cases} +

      • 当A是马尔科夫矩阵时,只有一个特征值为1,其余特征值小于1,随着k的变大,小于1的特征值所在项趋向于0,只保留特征值为1的那一项,同时对应的特征向量的元素都大于0

      • +
      • 当每一列和为1时,必然存在一个特征值\(\lambda =1\)

      • +
      • 证明: \[ +A-I= +\begin{bmatrix} +-0.9 & 0.01 & 0.3 \\ +0.2 & -0.01 & 0.3 \\ +0.7 & 0 & -0.6 \\ +\end{bmatrix} \]

      • -
      • 写成矩阵形式,这里的\(C,D\)仅仅存在一个形式,他们无解,要解出\(C,D\)是将其作为拟合直线,即b被替换为投影p时的\(C,D\)\[ -Ax=b \\ +

      • 若1是一个特征值,则\(A-I\)应该是奇异的,可以看到\(A-I\)每一列和为0,即说明行向量线性相关,即矩阵奇异,同时全1向量在左零空间。

      • +
      • 对于马尔科夫矩阵A,我们研究\(u_{k+1}=Au_k\)

      • +
      • 一个例子,u是麻省和加州的人数,A是人口流动矩阵 \[ \begin{bmatrix} -1 & 1 \\ -1 & 2 \\ -1 & 3 \\ +u_{cal} \\ +u_{mass} \\ +\end{bmatrix}_{t=k+1} += +\begin{bmatrix} +0.9 & 0.2 \\ +0.1 & 0.8 \\ \end{bmatrix} \begin{bmatrix} -C \\ -D \\ -\end{bmatrix}= +u_{cal} \\ +u_{mass} \\ +\end{bmatrix}_{t=k} +\]

      • +
      • 可以看到每一年(k)80%的人留在麻省,20%的人前往加州,加州那边也有10%移居麻省

      • +
      • 对马尔科夫矩阵A \[ +\begin{bmatrix} +0.9 & 0.2 \\ +0.1 & 0.8 \\ +\end{bmatrix} \\ +\lambda _1 =1 \\ +\lambda _2 =0.7 \\ +\]

      • +
      • 对特征值为1的项,容易求出特征向量为\((2,1)\),对特征值为0.7的项,特征向量为(-1,1)

      • +
      • 得到我们要研究的公式 \[ +u_k=c_1*1^k* \begin{bmatrix} -1 \\ -2 \\ 2 \\ +1 \\ +\end{bmatrix} ++c_2*(0.7)^k* +\begin{bmatrix} +-1 \\ +1 \\ \end{bmatrix} \]

      • -
      • A满足各列线性无关,b不在A的列空间里,现在我们想最小化误差\(e=Ax-b\),怎么量化误差?求其长度的平方\(||e||^2\),在图中即y轴方向上点到拟合直线的距离的平方和。这些点\(b_1,b_2,b_3\)的误差线段\(e_1,e_2,e_3\)与拟合直线交于\(p_1,p_2,p_3\),当将三个b点用三个p点取代时,方程组有解。

      • -
      • 现在要解出\(x^{'},p\),已知\(p=Ax^{'}=A(A^TA)^{-1}A^Tb\)\(Ax=b\),两边同乘\(A^T\)联立有 \[ -A^TAx^{'}=A^Tb -\]

      • -
      • 代入数值可得 \[ -\begin{cases} -3C+6D=5\\ -6C+14D=11\\ -\end{cases} -\]

      • -
      • 与代数求偏导数结果一样,之后可以解出\(C,D\),也就得到了拟合直线

      • -
      • 回顾一下上面两幅图,一张解释了\(b,p,e\)的关系,另一张用\(C,D\)确定了拟合直线,由\(C,D\)确定的列组合就是向量p

      • -
      • 如果A的各列线性无关,则\(A^TA\)是可逆的,这时最小二乘法使用的前提,证明: -如果矩阵可逆,则它的零空间仅为零向量,即\(A^TAx=0\)中x必须是零向量 \[ -A^TAx=0 \\ -x^TA^TAx=0 \\ -(Ax)^T(Ax)=0 \\ -Ax=0 \\ -\]

      • -
      • 又因为A各列线性无关,所以 \[ -x=0 -\]

      • -
      • 即证

      • -
      • 对于处理相互垂直的单位向量,我们引入标准正交向量组,这个矩阵的各列是标准正交而且是单位向量组,下一讲将介绍更多关于标准正交向量组的内容

      • +
      • 假设一开始加州有0人,麻省有1000人,即\(u_0\),代入公式可以得到\(c_1,c_2\),可以看到很多年之后,加州和麻省的人数将稳定,各占1000人中的三分之一和三分之二。

      • +
      • 行向量为和为1是另外一种定义马尔科夫矩阵的方式

      -

      第十六讲:正交矩阵和Gram-Schmidt正交化

      -

      正交矩阵

      +

      傅里叶级数

        -
      • 已知一组正交向量集 \[ -q_i^Tq_j= -\begin{cases} -0 \quad if \quad i \neq j \\ -1 \quad if \quad i=j \\ -\end{cases} -\] \[ -Q= -\begin{bmatrix} -q_1 & q_2 & ... & q_n \\ -\end{bmatrix} \\ -Q^TQ=I \\ -\]
      • -
      • 所以,对有标准正交列的方阵,\(Q^TQ=I\),\(Q^T=Q^{-1}\),即正交矩阵,例如 先讨论带有标准正交基的投影问题
      • +
      • 假设\(q_1....q_n\)是一组标准正交基,任何向量\(v\)都是这组基的线性组合
      • +
      • 现在我们要求出线性组合系数\(x_1....x_n\) \(v=x_1q_1+x_2q_2+...x_nq_n\) +一种方法是将\(v\)\(q_i\)做内积,逐一求出系数 \[ -Q=\begin{bmatrix} -cos \theta & -sin \theta \\ -sin \theta & cos \theta \\ -\end{bmatrix}or -\frac {1}{\sqrt 2} +q_1^Tv=x_1q_1^Tq_1+0+0+0....+0=x_1 \\ +\]
      • +
      • 写成矩阵形式 \[ \begin{bmatrix} -1 & 1 \\ -1 & -1 \\ +q_1 & q_2 & ... & q_n \\ \end{bmatrix} +\begin{bmatrix} +x_1 \\ +x_2 \\ +... \\ +x_n \\ +\end{bmatrix}= +v \\ +Qx=v \\ +x=Q^{-1}v=Q^Tv \\ \]
      • -
      • Q不一定是方阵。Q的各列将是列空间的标准正交基
      • -
      • 对Q,投影到Q的列空间的投影矩阵P是什么?\(P=Q(Q^TQ)^{-1}Q^T=QQ^T\)
      • -
      -

      Gram-Schmidt正交化

      -
        -
      • 给定两个不正交的向量a和b,我们希望从a,b中得到两个正交向量A,B,可设A=a,则B就是b投影到A上的误差向量e: -\[ -B=e=b-\frac{A^Tb}{A^TA}A -\]
      • -
      • 正交基就是A,B除以他们的长度\(q_1=\frac{A}{||A||}\)
      • -
      • 扩展到求三个向量,即A,B,C的情况,从上式我们已知A,B,同理,C需要c剪去在A和B上的投影分量 -\[ -C=c- \frac {A^Tc}{A^TA}A- \frac {B^Tc}{B^TB} B +
      • 现在讨论傅里叶级数
      • +
      • 我们希望将函数分解 \[ +f(x)=a_0+a_1cosx+b_1sinx+a_2cos2x+b_2cos2x+....... \]
      • -
      • 由a,b组成列向量的矩阵A就通过施密特正交化变成了正交矩阵Q,用公式推导可以看出,Q的各列\(q_1,q_2,...\)\(a,b,....\)在同一列空间内,正交化可以写成 -\[ -A=QR \\ +
      • 关键是,在这种分解中,\(coskx,sinkx\)构成一组函数空间的无穷正交基,即这些函数内积为0(向量的内积是离散的值累加,函数的内积是连续的值积分)。
      • +
      • 如何求出傅里叶系数?
      • +
      • 利用之前的向量例子来求
      • +
      • \(f(x)\)逐一与正交基元素内积,得到这个正交基元素对应的系数乘\(\pi\),例如 \[ +\int _0 ^{2\pi} f(x)cosx dx=0+ a_1 \int _0^{2\pi}(cosx)^2dx+0+0...+0=\pi +a_1 \\ \]
      • -
      • \[ -\begin{bmatrix} -a & b \\ -\end{bmatrix}= -\begin{bmatrix} -q_1 & q_2 \\ -\end{bmatrix} -\begin{bmatrix} -q_1^Ta & q_1^Tb \\ -q_2^Ta & q_2^Tb \\ -\end{bmatrix} \\ +
      +

      第二十二讲:对称矩阵及其正定性

      +

      对称矩阵

      +
        +
      • 对称矩阵的特征值是实数,不重复的特征值对应的特征向量互相正交
      • +
      • 对一般矩阵\(A=S\Lambda +S^{-1}\),S为特征向量矩阵
      • +
      • 对对称矩阵\(A=Q\Lambda Q^{-1}=Q\Lambda +Q^T\),Q为标准正交的特征向量矩阵
      • +
      • 为什么特征值都是实数?
      • +
      • \(Ax=\lambda +x\)对左右同时取共轭,因为我们现在只考虑实数矩阵A,\(Ax^{*}=\lambda ^{*} x^{*}\)
      • +
      • \(\lambda\)和它的共轭都是特征值,现在再对等式两边取转置,$x{* +T}AT=x^{* T} ^{* T} $
      • +
      • 上式中\(A=A^T\),且两边同乘以\(x\),与\(x^{* +T}A\lambda x^{* T}x\)对比可得\(\lambda +^{*}=\lambda\),即特征值是实数
      • +
      • 可见,对于复数矩阵,需要\(A=A^{* +T}\)才满足对称
      • +
      • 对于对称矩阵 \[ +A=Q\Lambda Q^{-1}=Q\Lambda Q^T \\ +=\lambda _1 q_1 q_1^T+\lambda _2 q_2 q_2^T+.... \\ \]
      • -
      • 其中,因为\(QQ^T=I\)
      • -
      • 所以\(R=Q^TA\)
      • -
      • \(q_2\)\(q_1\)正交,而\(q_1\)只是\(a\)的单位化,所以\(q_2^Ta=0\),即\(R\)是上三角矩阵
      • +
      • 所以每一个对称矩阵都是一些互相垂直的投影矩阵的组合
      • +
      • 对于对称矩阵,正主元的个数等于正特征值的个数,且主元的乘积等于特征值的乘积等于矩阵的行列式
      • +
      +

      正定性

      +
        +
      • 正定矩阵都是对称矩阵,是对称矩阵的一个子类,其所有特征值为正数,所有主元为正数,所有的子行列式都是正数
      • +
      • 特征值的符号与稳定性有关
      • +
      • 主元、行列式、特征值三位一体,线性代数将其统一
      ]]> @@ -3189,48 +3189,307 @@ J(w) = MSE_{train} + \lambda w^T w - NLP Basics - /2018/03/07/NLPBasic/ - 记录入门NLP中seq2seq模型时学习到的一些深度学习基础知识。

      - + Paper Reading 1 + /2018/03/07/PaperReading/ + +
    • attention开山作(机器翻译)
    • +
    • Luong attention,全局与局部注意力、
    • +
    • attention开山作(自动文摘)
    • +
    • 生成式摘要技巧集合:LVT,开关网络,层次注意力
    • +
    • 对话系统,端到端的层次RNN
    • +
    • 微博摘要,补充micropoints
    • +
    • disan,有向的transformer,注意力掩码
    • +
    • 注意力抽取器
    • +
    • 基于强化学习的生成式摘要
    • +
    • w2v,负采样
    • +
    -i0I5WV.jpg - +i0o00J.jpg +
    -

    前馈神经网络相关

    +

    Neural +Machine Translation By Jointly Learning To Align And Translate

      -
    • 数据维数很高时,样本空间容量可能远大于训练样本数目,导致维数灾难。
    • -
    • 激活函数.用于表示神经网络中的非线性变换,没有激活函数而只有权重矩阵的话神经网络是线性变换的组合,依然是线性变换。利用非线性变换能提取出方便进行线性变换的特征,避免维数灾难(?)。
    • -
    • Softmax和sigmoid的意义:具有最大熵,方便求导,万能近似定理(具有挤压性质)
    • -
    • 隐藏层可使用激活函数ReLU,即整流线性,缺陷是不能使用梯度学习使函数激活为0的样本,因此发展了三种扩展: +
    • 发布于2015.5(ICLR2015),作者Dzmitry Bahdanau。
    • +
    • 编码器解码器模型,翻译任务。
    • +
    • 其中双向GRU做编码器。编码隐藏层向量由双向连接而成。
    • +
    • 生成每一个单词时有不同的表示。
    • +
    • 权重由所有步编码隐藏层向量和前一步的解码隐藏层向量决定。
    • +
    • 对所有步编码隐藏层向量加权生成表示。 i0oB79.png
    • +
    +

    Effective +Approaches to Attention-based Neural Machine Translation

    +
      +
    • 发布于2015.8,作者(Minh-Thang +Luong)使用RNN编码器解码器模型,翻译任务。
    • +
    • 其中解码时是将包含注意力的表示和目标单词对应的解码隐藏层向量连接再经激活函数生成注意力向量: \[ -g(z,\alpha)_i = max(0,z_i) + \alpha _i min(0,z_i) -\] 绝对值整流:右边系数为-1 渗漏整流:右边系数固定为一个较小值 -参数化整流:系数放到模型中学习
    • +h_t = tanh(W_c[c_t;h_t]) +\] 之后注意力向量过softmax生成概率分布。
    -

    反向传播

    +

    全局注意力

      -
    • 反向传播将输出的偏差通过梯度计算出参数的更新值,从输出层往输入层一层一层更新参数,传播的是上一层用到的梯度,利用向量的微积分链式法则。 -每一层更新量=本层Jacobian矩阵*上一层梯度。
    • -
    • 神经网络中的反向传播: i0IIzT.png -初始化梯度表 最后一层输出对输出求梯度,因此初始值为1 -从后往前循环,本层的梯度表是本层Jacobian矩阵和上一层梯度表相乘(即链式求导)。 -本层使用上一层的梯度表进行计算,并存储,避免链式法则中的多次重复计算。
    • +
    • 文章先介绍全局注意力模型,即对全部编码隐藏层信息进行注意力加权生成表示,这样会导致对齐向量长度不定(对齐向量对输入信息加权,长度和输入句子的单词数相同).上文中Dzmitry +Bahdanau提出的模型即全局注意力模型。本文中的全局注意力模型更为一般化:未使用双向RNN拼接输入向量而是普通的RNN;直接用当前步解码隐藏层向量计算权重,而不是前一步,避免了复杂计算。 +
    • +
    • 之后引入了两种Effective +Approaches,即局部注意力和input-feeding。
    -

    RNN循环神经网络

    -

    RNN

    +

    局部注意力

      -
    • 特点:所有的隐藏层共享参数,将隐藏层作为状态变量,方便参数化。
    • -
    • 用双曲正切作为隐藏层激活函数
    • -
    • 输入x,x过权重矩阵经隐藏层激活后得到h,h过权重矩阵输出o,代价L,o经输出激活后得到y
    • -
    • 基本结构(展开和非展开): i0I7yF.png
    • -
    • 几种变式:
    • -
    • 每一个时间步均有输出,隐藏层之间有循环连接: i0ITQU.png
    • -
    • 每一个时间步均有输出,输出与隐藏层之间有循环连接: i0IqeJ.png
    • +
    • 局部注意力:不使用全部输入信息,而是对每一个输出的单词先生成一个对齐位置,然后只对对齐位置附近窗内的输入信息注意力加权生成表示。文章给出了两种种生成对齐位置的方式:
    • +
    • 单调对齐:简单的将第i输出单词的对齐位置设为i,显然在文摘中这种方式不可取。
    • +
    • 预测对齐:训练对齐位置。 \[ +p_t = S \cdots sigmoid(v_p^T tanh(W_ph_t)) \\ +\] 其中\(h_t\)是第t个生成单词的隐藏层向量 \(W_p\)\(v_p\)都是需要训练的权重 +S是输入单词长度,与sigmoid相乘就得到输入句中任意位置
    • +
    • 另外为了使得对齐位置的权重最大,先以对齐位置为期望、半窗长为标准差生成高斯分布,再以此为基础生成权重。 +\[ +a_t(s) = align(h_t,h_s)exp(-\frac{(s-p_t)^2}{2\sigma ^2}) +\]
    • +
    +

    Input-feeding

    +
      +
    • Input-feeding:生成对齐时还需要依赖过去的对齐,实际实现是将上一步的注意力向量作为下一步解码隐藏层的feed,好处在于模型可以完全了解之前的对齐决策,而且在水平层次和垂直层次上创造了一个非常深的网络。
    • +
    • 实验结果表明使用预测对齐的局部注意力模型表现最好。 i0oyfx.png
    • +
    +

    A +Neural Attention Model for Abstractive Sentence Summarization

    +
      +
    • 发布于2015.9,作者Alexander M. +Rush,解码器编码器模型,文摘任务。
    • +
    • 提出了一种注意力编码器,使用普通的NNLM解码器。
    • +
    • 未使用RNN,直接用词向量。
    • +
    • 使用全部输入信息,局部输出信息(yc)构建注意力权重。
    • +
    • 直接对平滑化的输入句子的词向量矩阵加权而不是RNN隐藏层向量。
    • +
    • 模型如下图:
    • +
    +

    Abstractive +Text Summarization using Sequence-to-sequence RNNs and Beyond

    +
      +
    • 发布于2016.8,作者Ramesh +Nallapati。编码器解码器模型,使用RNN,注意力,文摘任务。
    • +
    • 基于Dzmitry +Bahdanau的机器翻译模型(双向GRU编码,单向GRU解码)进行改进。
    • +
    • 改进包括LVT(large vocabulary trick)、Feature-rich +encoder、switching generator-pointer、分层注意力。
    • +
    +

    LVT

    +
      +
    • 减少解码器的softmax层大小,加速计算,加速收敛。实际实现是在每一个mini-batch中解码器的词典只限于本batch内的输入文本,而且把之前batch内解码词典中最频繁的单词加入之后batch的解码词典(直至达到一个上限)。
    • +
    +

    Feature-rich Encoder

    +
      +
    • 不使用简单的只表示语义距离的词向量,而是构建包含了实体信息等多种语义特征,分别构成向量并拼接起来形成新的词向量 +
    • +
    +

    Switching Generator-pointer

    +
      +
    • 解决罕见词,额外词问题。解码器的词典是固定的,如果测试文本中包含词典外的单词该如何解决。其提供的解决方案是给解码器加上一个开关,开关打开时就普通的使用自己词典生成,开关关上时,就产生一个指针指向输入文本中的一个单词,并将其复制入文摘。 +) Switching generator/pointer model +开关为G时就用传统方法生成文摘 开关为P时就从输入中拷贝单词到文摘中
    • +
    +

    分层注意力

    +
      +
    • 传统的注意力是指关注句子中的关键词位置,分层还包括上一层,即文本中的关键句位置。使用两层双向RNN分别在词层次和句层次捕捉注意力。注意力机制同时运行在两个层次之上,词层次的注意力权重会被句层次的注意力权重重新加权调整。 +
    • +
    +

    Recurrent Neural +Network Regularization

    +
      +
    • 本文介绍了如何在循环神经网络中使用dropout来防止过拟合
    • +
    • Dropout是指在深度神经网络当中,在每次训练时随机丢掉某些隐藏层的某些节点,测试时不丢弃节点但是将节点输出乘以丢弃概率。这种方法可以有效解决深度学习费时且容易过拟合的问题。
    • +
    • 对于dropout的理解有两种,1:它强迫一个神经单元,和随机挑选出来的其他神经单元共同工作,达到好的效果。消除减弱了神经元节点间的联合适应性,增强了泛化能力。2:它相当于创造了一些噪声数据,增加了训练数据的稀疏性,增加了特征的区分度。
    • +
    • 在RNN中不能直接按时间步丢弃隐藏层节点,因为这样会丢失RNN所需要的长期依赖信息,引入很大的噪声破坏了学习过程。
    • +
    • 作者提出的是按层丢弃节点,即使用多层RNN结构,即便丢失了一层中的某一时间步的节点,其他层的相同时间步的节点也能传递过来,不破坏序列的长期依赖信息
    • +
    • 效果如图:
    • +
    +

    Building +End-To-End Dialogue Systems Using Generative Hierarchical Neural Network +Models

    +
      +
    • 本文介绍了使用完全数据驱动的分层RNN端到端模型来构建non-goal-driven的自然语言对话系统。
    • +
    • 训练数据是从电影字幕中提取的triples,即两个对话人按A-B-A的顺序完成三次表达。
    • +
    • 分层的结构不是简单的增加RNN隐藏层层数,而是分别在词水平和句水平构建两个RNN,如下图。 +i0TC90.png +三段式对话包含在两个词水平RNN端到端系统中 +中间生成的句表示又作为更高层次即句水平RNN的隐藏层向量
    • +
    • 文章中使用了bootstrapping的技巧,即用一些预先训练好的数据作为模型的初始值。例如用w2v在大语料库中训练好词嵌入矩阵的初始值。本文中甚至将整个模型都预训练好了,原理是使用QA系统的二段式对话大语料库预训练整个模型,第三段设为空。在实际训练中,先预训练词嵌入完成词嵌入的初始化,然后预训练整个模型4个epoch,最后固定词嵌入不变接着预训练整个模型到最佳值。
    • +
    • 系统是给定三段式对话中的前两段推测出第三段。Evaluation使用两种标准:word +perplexity衡量语法准确度,word classification error衡量语义准确度
    • +
    • 论文最后总结了一种不好的现象出现的原因。在最大后验概率输出时经常出现一些通常的回答,例如”i +don’t know”或者”i’m +sorry”。作者认为原因有三种:1:数据太少。因为对话系统是有内在歧义性和多模态性的,大规模数据才能训练出较好的结果。2:标点符号和代词在对话中占有很大比例,但是系统很难区分不同上下文环境中标点符号和代词的意义。3:对话一般很简短,因此infer时一个triple可以提供的信息太少。区分度不够。因此设计自然语言神经模型时应尽量区分语义和语法结构。作者还发现,如果不用最大后验概率而是随机输出时不会出现此问题,且infer出来的句子一般能保持话题,出现一个与话题相关的特殊词。
    • +
    +

    News Event +Summarization Complemented by Micropoints

    +
      +
    • 这是来自北大的一篇论文,使用微博上的数据,其工作是给定从传统新闻中提取出的文摘,在相同主题的微博博文中构造出一些micropoints来补充文摘,实验证明这种补充的文摘能在ROUGE中取得更好分数。
    • +
    • 文章的阐述重点在于提取micropoints而不是如何将micropoints整合进原始文摘。
    • +
    • 这个团队之前提出了两种工具:用于提取新闻关键词的一种文本聚类模型CDW;用于将一段博文分割成各自拥有相对完整含义的片段(几句话)的Snippet +Growth Model。
    • +
    • Micropoints生成的主要步骤:筛选博文、将博文按主题分类、将博文分割成片段、从同一主题的博文片段中挑选一些组成micropoints、对micropoints进行筛选。
    • +
    • 筛选博文考虑两个指标:相关性和差异性,既要与原新闻文摘主题相关,又不能太重复而导致冗余。作者使用CDW提取原新闻多个角度的关键词,并将博文与这些关键词计算cos相似度,以筛选多个具有相关性的博文。另外作者利用Joint +Topic Modeling(Joint topic modeling for event summarization across news +and social media +streams)计算博文和文摘的差异性。将计算出的两个指标取调和平均作为总体筛选的指标。
    • +
    • 将博文按主题分类:受限使用LDA得到p(topic|tweet),再利用此条件概率为每一个博文构造向量v(t) += (p(topic 1 |t), p(topic 2 |t), ..., p(topic n +|t)),最后使用DBSCAN完成主题聚类。
    • +
    • 使用团队之前提出的Snippet Growth +Model将博文分成片段,大致方法是先取一个句子,然后计算其他句子与这个句子之间的文本相似度、距离度量、影响度量来决定是否将其他句子加入这个句子所在的片段当中。
    • +
    • 现在已经得到了按主题分类的一堆片段,之后需要在一个主题的片段中挑一些最能代表本主题的片段出来。其方法是挑选到同主题其他片段平均距离最小的前几个片段。因为句子不太长,作者将一个片段用词袋表示,词袋中装了组成本片段中所有句子的所有词,用词向量表示。距离用KL散度衡量。如果新挑出来的片段与已挑片段距离太近则放弃,以保证挑选出来的片段依然具有差异性。
    • +
    • 得到这些片段将组成micropoints,但是在补充进文摘之前还要进行筛选。作者提出了三个指标:信息量,流行度,简洁性。信息量即补充进文摘之后文摘获得信息熵增益,信息量越大越好;流行度用原博文评论数来衡量,越流行的博文越不容易极端,用流行度来防止极端、三观不正的博文被补充进文摘。流行度越大越好;简洁性用补充的部分和原文摘的长度比来描述,越小表示补充的越简洁,不会喧宾夺主。此时问题就化成在给定简洁性要求下,每一个片段能带来信息量和流行度的收益,同时耗费一定的简洁性,选择片段使收益最大,即离散的有限制条件的最优化问题,可以抽象为0-1背包问题,用动态规划解决。作者还设置了阈值,使用分段函数:当流行度大于阈值时,信息增益对于收益的贡献会更大。这样设置是为了保证不会因为出现流行度和信息增益一方很大而另一方几乎没有的片段被加入文摘。
    • +
    +

    DiSAN: +Directional Self-Attention Network for RNN/CNN-Free Language +Understanding

    +
      +
    • 更新,作者后来又推出了fast +disan,貌似是改了注意力的计算,细节待补充
    • +
    • 作者提出了一种有向自注意网络,不依赖RNN或者CNN结构也能很好的完成NLP问题中的编码任务。
    • +
    • 作者认为现有的编码器中,使用RNN能很好的捕捉序列的顺序信息但是慢;使用纯注意力机制(就如同A +Neural Attention Model for Abstractive Sentence +Summarization中不使用RNN而是直接对词向量序列进行注意力加权)虽然能利用现有的分布式或者并行式计算框架加速运算,却丢失了序列的顺序信息。因此作者提出了一种能捕捉序列顺序信息的纯注意力编码器结构,结合了两者的优点。
    • +
    • 作者首先提出了三种注意力概念:多维度注意力,自注意力,有向注意力。
    • +
    • 传统的注意力是对一个句子中各个单词加权,权值是标量。而多维度注意力中权值是向量,维度和词向量维度相同。使用多维度的理由在于这样是对每一个词的每一个特征进行注意力加权,词向量本身具有一词多义性,传统的对整个词向量进行加权的注意力机制对同一个词在不同上下文环境中的情况不能很好区分,多维度是对词向量的每一个分量加权,它可以给能表示当前上下文环境的特征更多的注意力权重。我的理解是对词向量的分量进行注意力加权,这样相当于同一个词在不同的上下文环境中有略微不同的表示,可以用来区分。下图是传统注意力与多维度注意力的区别。 +i0ojBQ.png +右边是多维度注意力 +可以看到注意力权重变成了向量,与输入词向量维度数相同
    • +
    • 一般的注意力权重是编码输入和一个解码输出作为参数生成,权重与当前输出有关。自注意力与解码端无关,要么用本句子中的每一个词替代解码输出,要么用整个输入句子替代解码输出。前者与多维度结合形成token2token注意力,后者与多维度结合形成source2token。
    • +
    • 有向注意力即在生成token2token注意力时根据需要添加一个掩码矩阵,矩阵元素为0或者负无穷。矩阵可以为上三角或者下三角,代表两个方向的掩码,例如从i到j是0,从j到i是负无穷,则在token2token中词之间的注意力就有了方向,不正确方向的注意力过softmax之后会降到0,而正确方向的注意力不受影响。掩码矩阵还有第三种,无对角线矩阵,即对角线上的值为负无穷,这样token2token中一个单词对自己不会产生注意力。有向注意力如下图: +
    • +
    • 最后有向自注意网络的构成利用了以上三种注意力,首先上下三角两种掩码搭配多维度token2token可以产生前向后向两个自注意力向量,类似blstm,然后将向量连接,过一个多维度source2token产生最终的编码输出。作者测试了这种编码能在自然语言推测和情感分析任务中达到最佳水平,也可以作为其他模型的一部分在其他任务中使用。
    • +
    +

    Neural +Summarization by Extracting Sentences and Words

    +
      +
    • 本文是使用了完全数据驱动的模型来完成抽取式文摘。其模型结构由一个分层文本编码器和一个注意力机制抽取器构成。
    • +
    • 与生成式注意力机制文摘不同的地方在于:使用CNN而不是w2v构建词嵌入;注意力用来直接抽取词而不是加权生成中间表示。
    • +
    • 因为本文是用数据驱动的抽取式文摘,所以需要大量的抽取式文摘训练数据,这样的训练数据很少,作者提出了制造词水平和句水平的抽取式训练数据的方法:对于句抽取,作者的思路是将生成式文摘转换成抽取式文摘,首先获得生成式文摘,然后将原文中每一句与生成式文摘对比以决定是否应该抽取出来,对比的指标包括句子在文档中的位置,一元语法和二元语法重叠性,出现的命名实体数量等等;对于词抽取,同样也是对比生成式文摘和原文中词的词义重叠程度来决定该词是否应该抽取出来。对于那些生成式文摘中出现而原文中没有的词,作者的解决方案是用原文中词嵌入距离相近的词替代形成训练数据。
    • +
    • 编码时,用CNN形成词嵌入,将句子表示为词嵌入序列,再用RNN形成文档层次上的编码(一个句子为一个时间步输入)。
    • +
    • 句抽取时,与生成式不同,抽取的RNN输出依赖是上一个抽取生成的句子乘以一个置信系数,这个置信系数代表上一个句子有多大可能被抽取出来。
    • +
    • 与生成式一样,train和infer存在差异,前期抽取infer出现的问题会在后期越滚越大。为了解决这个问题,作者使用了一种“课程学习策略”:训练刚开始置信水平不能准确预测,就设为1,之后随着训练进行逐渐将置信水平恢复成训练出来的值。
    • +
    • 与句抽取相比,词抽取更加贴近生成式算法,可以看成是词典受限的词水平上的生成式文摘。
    • +
    • 抽取式文摘在处理稀疏词汇和命名实体上有优势,可以让模型检查这些词汇或实体的上下文、句中相对位置等来降低注意力权重,减少这类词影响。
    • +
    • 抽取式要解决的一个问题是决定抽取数量。作者取抽取置信水平最高的三句作为文摘。另一个问题是每一个batch的词典一般是不同的。作者采用了一种负采样的解决方案。
    • +
    +

    A DEEP +REINFORCED MODEL FOR ABSTRACTIVE SUMMARIZATION

    +
      +
    • 使用强化学习来优化当前的端到端生成式文摘模型 i0TicT.png
    • +
    • 解决长文摘生成和重复短语问题
    • +
    • 强化学习需要外界给予模型反馈,这里作者使用人工对生成的文摘进行评价并反馈给模型,使得模型可以生成可读性更好的文摘
    • +
    • 模型的改进主要在两点:在编码端和解码端分别加入了内注意力,其中编码端是之前提出过的,本文主要引入解码端的内注意力机制;提出了一种新的目标函数,结合了交叉熵损失和来自强化学习的奖励
    • +
    • 编码解码两端的内注意力是从两个方面解决重复短语问题,因为重复问题在长文本生成文摘中相比短文本更加严重。
    • +
    • 编码端加入内注意力是认为重复来自于在解码各个时间步对输入长文本的注意力分布不均匀,没用充分利用长文本,在解码各个时间步可能注意力的分布都相似,导致生成重复语段。因此作者在模型中对过去已经获得高注意力权重的输入位置给予惩罚,保证输入文本的各个部分充分利用。引入惩罚的方式是在新的某一解码时间步,某一编码输入位置的注意力权重是本次产生的注意力权重除以之前所有时间步注意力权重之和,这样如果过去的产生了大的注意力权重,则新产生的注意力权重会变小。
    • +
    • 解码端加入内注意力是认为重复还来源于解码端本身的隐藏状态重复。作者认为解码时依赖的解码端信息应该不止包含上一时间步的解码端隐藏层状态,而是过去所有时间步的隐藏层状态并给予注意力加权,因此在解码端引入了类似的内注意力机制和惩罚机制。
    • +
    • 在这个端到端模型中注意力并不是沟通编码端和解码端的方式,而是独立在两端,仅依赖于编码/解码端之前的状态和当前状态产生,因此是内注意力(自注意力)。
    • +
    • 在搭建端到端模型时作者还采用了一些其他前人提出过的技巧,例如使用复制指针和开关解决稀疏词问题,编码解码共享词嵌入矩阵,另外还特别提出了一个小技巧:基于观察,一般文摘中不会出现重复的三词短语,因此在解码端束搜索中若出现了重复的三词短语就剪枝。
    • +
    • 之后作者分析了静态的监督学习在文摘评价标准中常常取不到理想结果的两个原因:一是exposure +bias,即模型在训练时是接触到了正确的输出(ground +truth),但是在infer时是没有正确输出做矫正的,因此如果infer时错了一个词,之后错误会越积越大;二是文摘生成本身不是静态的,没有标准答案,而好的文摘有许多种可能(文摘评价标准中一般考虑了这些可能),但使用最大似然目标函数的静态的学习方法扼杀了这些可能。
    • +
    • 因此作者在监督学习之外为文摘任务引入了policy +learning,一种策略搜索强化学习方式。在强化学习中模型不是以生成与标签最相似的输出为目标,而是以最大化某一种指标为目标。在这里作者借鉴了图像标注任务中的一种强化学习算法:self-critical +policy gradient training algorithm: \[ +L_{rl} = (r(y)-r(y^s))\sum _{t=1}^n log p(y_t^s | y_1^s,...,y_{t-1}^s,x) +\] r是人工评价奖励函数 +两个r函数的参数:前者是最大化输出概率得到的基准句子,后者是根据每一步输出条件概率分布采样得到的句子 +目标是最小化这个L目标函数,假如采样的句子得到的人工奖励比基准句子多,则这个最小化目标函数等价于最大化采样句子的条件概率(前面的两个r函数计算之后为负号)
    • +
    • 之后作者将监督学习和强化学习的两种目标函数结合起来:
    • +
    +

    Distributed +Representations of Words and Phrases and their Compositionality

    +
      +
    • 介绍了w2v的负采样版本。
    • +
    • 以短语为基本单位训练而不是单词,这样能够更好的表示一些idiomatic +phrase。
    • +
    • 用nce(噪声对比估计)替代分层softmax,nce近似最大化softmax的对数概率,在w2v中只关心学到好的表示,因此用简化版的nce,负采样,用下式替代输出的条件概率: +\[ +p(w_O | w_I) = \frac {exp(v_{w_O}^T v_{w_I})}{\sum _{w=1}^W +exp(v_{w_O}^T v_{w_I})} +\] 被替换成 $$ log (v_{w_O}^T v_{w_I}) + {i=1}^k E{w_i +P_n(w)} [log (v_{w_O}^T v_{w_I})]
    • +
    • 每次在softmax输出层只激活目标label和k个噪声label(即非目标label),即对每一个单词,有k+1个样本,1个正样本,k个采样得到的负样本,进行logistic回归分类,上式即logistics回归的似然函数,其中Pn是噪声的概率分布。
    • +
    • 对常见词进行降采样,因为常见词的向量表示容易稳定,再训练几百万次也不会发生大的改变,因此每一次对词的训练以一定概率跳过:
    • +
    • 这样训练出来的skip-gram模型具有很好的加法语义合成性(两个向量的逐分量相加),即俄国+河与伏尔加河相近,因为向量与输出层的概率对数相关,两个向量相加与两个上下文的乘积相关,这种乘积相当于逻辑与:高概率乘高概率为高概率,其余为低概率。因此具有这种简单的算术语义合成性。
    • +
    +]]> + + 机器学习 + + + abstractive summarization + math + machine learning + theory + nlp + + + + NLP Basics + /2018/03/07/NLPBasic/ + 记录入门NLP中seq2seq模型时学习到的一些深度学习基础知识。

    + +
    +i0I5WV.jpg + +
    +

    前馈神经网络相关

    +
      +
    • 数据维数很高时,样本空间容量可能远大于训练样本数目,导致维数灾难。
    • +
    • 激活函数.用于表示神经网络中的非线性变换,没有激活函数而只有权重矩阵的话神经网络是线性变换的组合,依然是线性变换。利用非线性变换能提取出方便进行线性变换的特征,避免维数灾难(?)。
    • +
    • Softmax和sigmoid的意义:具有最大熵,方便求导,万能近似定理(具有挤压性质)
    • +
    • 隐藏层可使用激活函数ReLU,即整流线性,缺陷是不能使用梯度学习使函数激活为0的样本,因此发展了三种扩展: +\[ +g(z,\alpha)_i = max(0,z_i) + \alpha _i min(0,z_i) +\] 绝对值整流:右边系数为-1 渗漏整流:右边系数固定为一个较小值 +参数化整流:系数放到模型中学习
    • +
    +

    反向传播

    +
      +
    • 反向传播将输出的偏差通过梯度计算出参数的更新值,从输出层往输入层一层一层更新参数,传播的是上一层用到的梯度,利用向量的微积分链式法则。 +每一层更新量=本层Jacobian矩阵*上一层梯度。
    • +
    • 神经网络中的反向传播: i0IIzT.png +初始化梯度表 最后一层输出对输出求梯度,因此初始值为1 +从后往前循环,本层的梯度表是本层Jacobian矩阵和上一层梯度表相乘(即链式求导)。 +本层使用上一层的梯度表进行计算,并存储,避免链式法则中的多次重复计算。
    • +
    +

    RNN循环神经网络

    +

    RNN

    +
      +
    • 特点:所有的隐藏层共享参数,将隐藏层作为状态变量,方便参数化。
    • +
    • 用双曲正切作为隐藏层激活函数
    • +
    • 输入x,x过权重矩阵经隐藏层激活后得到h,h过权重矩阵输出o,代价L,o经输出激活后得到y
    • +
    • 基本结构(展开和非展开): i0I7yF.png
    • +
    • 几种变式:
    • +
    • 每一个时间步均有输出,隐藏层之间有循环连接: i0ITQU.png
    • +
    • 每一个时间步均有输出,输出与隐藏层之间有循环连接: i0IqeJ.png
    • 读取整个序列后产生单个输出: i0oCOe.png
    • 普通的前向传播,softmax处理输出,负对数似然作为损失函数,通过时间反向传播代价过大。 @@ -3319,9 +3578,9 @@ href="https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid=2650720050&i 自然语言处理 - machine learning - math abstractive summarization + math + machine learning theory nlp @@ -3591,10 +3850,10 @@ Encoding for Abstractive Sentence Summarization 机器学习 - machine learning - math abstractive summarization - theory + math + machine learning + theory nlp @@ -3737,9 +3996,9 @@ W_Z = UV^{\frac 12} \\ 机器学习 - machine learning - math abstractive summarization + math + machine learning theory nlp @@ -3890,279 +4149,214 @@ Machine Learning from Disaster

      - Outstanding Papers Reading (ACL 2019) - /2019/07/28/acl2019/ - ACL 2019获奖论文选读。 - 利用oracle来做句子级别的teacher forcing - -speaker commitment - 适用于摘要的一套评价指标框架,结合了多个指标 - -Zero-Shot Entity Linking

      - + Summarization-Related Papers Reading (ACL/NAACL 2019) + /2019/08/15/acl2019-summarization/ + ACL/NAACL 2019 自动摘要相关论文选读 - DPPs 相似度度量改进 - +STRASS:抽取式摘要的反向传播 - 先翻译再生成摘要 - 阅读理解+自动摘要 - +BiSET:Retrieve + Fast Rerank + Selective Encoding + Template Based +

      Bridging -the Gap between Training and Inference for Neural Machine -Translation

      -

      Background

      +id="improving-the-similarity-measure-of-determinantal-point-processes-for-extractive-multi-document-summarization">Improving +the Similarity Measure of Determinantal Point Processes for Extractive +Multi-Document Summarization
        -
      • 最佳长论文,这个方向就很吸引人,属于很常见,大家都知道但都选择无视,或者找不出优雅有效解法的问题。
      • -
      • 本文试图解决所有seq2seq都会遇到的问题,训练与推理的不一致,即exposure -bias。
      • -
      • exposure -bias是解码时产生的偏差。正常来讲,我们生成一句话,是从左往右逐字生成,怎么个逐字?模型生成一个字,然后这个字接着输入解码器解码出下一个字,也就是解码出每一个字时使用的上文是之前解码出的句子片段。但是这样训练收敛很慢,容易导致错误的累积。想想模型一开始本来就难以生成正确的字,现在还要基于这个错误的字生成接下来的字,那就是错上加错了。因此一般训练时,都需要使用teacher -forcing的方法:forcing模型在生成每一个字的时候,依靠的是训练数据中正确的上文,也就是不管已经生成的字,只管前提正确的情况下去生成正确的字。但是这种技巧只能用于训练,测试的时候没有ground -truth来teacher forcing。
      • -
      • 这个问题说大不大,说小不小,之前做summarization也会遇到这个问题,导致训练的反应很好,但是测试效果差,或者出现难以解释的偏差。如今的seq2seq在编码端已经取得了长足的进步,CNN和Transformer等特征抽取器已经摆脱了单向的抽取方式,但是无论什么模型,在解码端,都得老老实实从左往右生成,都避免不了exposure -bias。
      • -
      • 对于翻译,exposure -bias还和另一个问题打包影响了翻译的质量:逐字计算的交叉熵损失。模型需要学习到在正确的位置生成正确的词,这个双重正确的标准对于翻译来说太过苛刻,模型难以学到灵活的翻译关系,也就是over -correction.
      • -
      • 现有的解决exposure bias以及word-level CrossEntrophy -Loss的方法有哪些? +
      • 这和我们组其他人做的很像,用DPPs处理抽取式文摘
      • +
      • 在上文的文摘指标论文中也提到了,搞文摘,尤其是抽取式文摘,就是三个词,qd,qd,还是qd!
          -
        • 在生成词的时候,有时用ground -truth,有时用自己的预测的输出,采样中庸一下,即scheduled sampling
        • -
        • 使用预训练模型,做Masked Seq2seq pretraining
        • -
        • 使用句子级别的损失函数,目标是整个句子的分数最高,而不是逐字贪心,这里包括了各种各样的优化指标以及强化学习的方法,例如mixed -incremental cross-entrophy reinforce
        • -
        • 其中预训练是比较新的方法,其余两类方法早在2015年就已经提出,作者也把自己的方法与他们的方法做了对比
        • +
        • q:quality,哪个句子重要,需要被抽出来作为文摘。这一步是特征的构造
        • +
        • d:diversity,抽取出来的句子之间不能冗余,不能老抽一样的句子。重要的一样的句子多了,也就变得不重要了。这一步是抽样方法的构造
      • -
      -

      Methods

      -
        -
      • 本文想要解决以上两个问题,粗看思路还是和以前一样:通过从ground truth -和 predicted -results中采样来中和偏差,以及使用句子级别的优化指标来放宽损失的约束。
      • -
      • 具体怎么采样?作者给出的方法如下图(这不就是scheduled -sampling的图吗。。。。): e26fV1.png -
          -
        • 先选出oracle -word,即模型预测的词:注意,这里用模型预测的词其实不太准确,因为模型预测的词是确定的,是decoder解码出词典概率分布取最大得到的(不考虑束搜索的话),然而这里的oracle应该表述为not -ground -truth,即非真实词。假如我们直接用预测的词,那就会错上加错;假如我们用ground -truth,那就会有exposure -bias。因此作者取了个折中,不同于之前概率上的折中(可能取预测词可能取ground -truth),还做了选词上的优化,不是简单的拿预测出的词作为oracle,具体而言: +
        • DPPs(Determinantal Point +Processes)就是一种抽样方法,保证抽出来的句子重要(根据特征计算好的重要性数值),而且不重复。本文作者就是思路非常清晰:我要改进抽取式文摘中的DPPs,怎么改进?DPPs依赖句子之间的相似度来避免抽重复的句子,那我就改进不管DPPs怎么改,直接改相似度的计算,所以问题就换到了一个非常成熟的领域:语义相似度计算。
        • +
        • 接下来就随便套网络来做语义相似度计算就行了。作者比较新潮,用了胶囊网络,这个网络本来是提出用于解决计算机视觉中物体的位置相对变化问题的,作者认为可以将其泛化到提取底层语义特征的空间与方位信息,这里我对胶囊网络及其在NLP的应用不太了解,但是就作者给出的对比实验来说,改进其实也就1个点,而整个DPP相比之前最好系统(2009)也就好2个点,感觉还是有点刻意为之。
        • +
        • 另外作者给出的网络是真的复杂,不是原理复杂,而是用了很多组件,包括:
            -
          • 假如直接取decoder预测概率最大的词作为Oracle,那就是普通的scheduled -sampling。
          • -
          • 然而作者使用Gumbel-Max正则化方法对预测概率分布调整,引入两个参数:一个由01均匀分布变量\(u\)计算得来的Gumbel noise \(\eta\);以及一个温度变量\(\gamma\)。假设原始概率分布为\(o\),则调整后的概率分布\(P\)\[ -\eta = - \log ( - \log u) \\ -\overline{o} _{j-1} = (o_{j-1} + \eta) / \gamma \\ -\overline{P} _{j-1} = softmax(\overline{o} _{j-1}) \\ -y_{j-1}^{\text {oracle -}}=y_{j-1}^{\mathrm{WO}}=\operatorname{argmax}\left(\tilde{P}_{j-1}\right) -\\ -\]
          • -
          • 这个加入噪音的过程只影响选择 oracle,而不影响模型的损失。增加Gumbel -noise的操作可以使得argmax操作等效于依据softmax的概率进行采样操作,使得softmax得到的概率分布有意义,而不是单纯取最大。这里只是用了Gumbel-Max(式子里那个softmax其实不需要)。Gumbel的另一个更为常见的应用是Gumbel-Softmax,用于在假设隐变量分布为category -distribution时实现重参数化(reparameterization),相比普通的softmax,Gumbel-Softmax的效果等价于用softmax计算出了一系列样本,这些样本是按照原始softmax概率依概率采样得到。
          • +
          • 三四五六七大小卷积核的CNN用于提取底层特征
          • +
          • 胶囊网络提取高层特征,用到了近年来的参数共享和路由等技巧
          • +
          • 还是用了one-hot向量,即一个词是否存在在某一个句子里
          • +
          • 各种特征的融合,包括内积,绝对差,再和所有独立的特征全部拼接到一起,预测两个句子的相似度
          • +
          • 而且相似度还只是一部分目标,另外作者还用了LSTM来重构两个句子,将重构损失加入最终的总损失 +
        • -
        • 这是单词级别的oracle选择,还可以做句子级别的选择,具体做法是 +
        • 粗看图片绝对以为这是一篇CV的work
        • +
        • 作者好歹是把最近能用的技巧都用上了,做了一个集大成的网络,可能学术上看没那么简洁优美,但是就工业上来说很多这样的网络集成操作就是很work
        • +
        • 另外虽然是抽取式摘要,但作者的工作是完全监督,因此还需要构造数据集
            -
          • 先用单词级别的方法,加上beam search,选出几个候选句
          • -
          • 通过BLEU,ROUGE等指标选出最好的句子,将这个句子的每一个词作为oracle
          • -
          • 显然这里有一个问题,就是得保证beam search出的oracle句子和ground -truth的句子长度一致,作者引入了force -decoding,当解码出的句子还不够ground -truth长度时,假如解码出了EOS,就排除EOS,取剩下的概率最大前k个单词做beam -search;假如长度已经够了,但是还没解码出EOS,就强制设置为EOS并结束解码
          • -
        • -
        • 再计算概率,决定是用oracle还是ground truth:和scheduled -sampling一样,也是要设置动态采样概率,刚开始训练的时候多用ground -truth,然后慢慢提高oracle的比例,作者给出的概率设置为: \[ -p = \frac{\mu}{\mu + exp(e / \mu)} -\]
        • +
        • 从生成式摘要数据集中构造有监督抽取式摘要数据集
        • +
        • 从生成式摘要数据集中构造有监督句子相似度计算据集
        • +
        • 这种构造也一定程度上限制了其泛化能力
      • -
      • 结果当然是比naive RNN and -Transformer要好,BLEU能有2个点的提升。作者也做了大量实验来测试超参数的影响。很简单很work,尤其是引入句子层级优化的方法简单明了,比一堆目标函数的改动要直观的多。
      • +
      • 作者的出发点其实非常好:因为传统的相似度停留在词的粒度,没有深入到语义特征,因此构造网络提取特征的方向没错,只不过稍显复杂,而且由于仅仅改进了抽取式文摘中某一种抽样方法的相似度计算中的句子特征提取部分,对整体的影响并没有特别大,最后的结果虽然吊打了很多传统方法,但是相比传统最佳方法并没有提高多少,相比纯DPPs更是只有1个点左右的提高。

      Do -you know that Florence is packed with visitors? Evaluating -state-of-the-art models of speaker commitment

      +id="strass-a-light-and-effective-method-for-extractive-summarization-based-on-sentence-embeddings">STRASS: +A Light and Effective Method for Extractive Summarization Based on +Sentence Embeddings +

      - +又是一篇用监督方法做抽取式文摘的,从标题就可以大致猜出来内容,基于embedding,还要light +and effective,那最简单的目标就是把摘要的embedding和gold +embedding保持一致。 - +困难的地方在于这是抽取式的,是离散的,因此需要一个流程把抽取、embedding、比较打分三个部分统一起来,软化使其可导,可以端到端训练,作者给出的是四个步骤: +- 将文档embedding映射到比较空间 - 抽句子组成摘要 - +去近似抽出的摘要的embedding - 和gold summary的embedding比较 - +首先给定一篇文档,直接用sent2vec获得doc +embedding和文档里每一句的sentence embedding - +之后只用一层全连接作为映射函数f(d),这里作者给出了第一个假设:抽取的摘要句子应该和文档具有相似度: +\[ + sel(s,d,S,t) = sigmoid (ncos^{+}(s,f(d),S)-t) + \] - 其中s是句子embedding,S代表句子集,t为阈值。 +sel代表select,即选择这个句子组成摘要的置信度,这个式子说明选出句子的embedding和文档embedding之间的相似度应该大于阈值t,且使用sigmoid做了软化,将{0,1}软化为[0,1] +- +之后进一步软化,作者并不根据分数选出句子组成文摘,而是根据分数直接近似文摘的embedding +\[ + app(d,S,t) = \sum _{s \in S} s * nb_w(s) * sel(s,d,S,t) + \] - 其中nb_w是number of words,即使用每个句子的字数和select +score对所有的句子embedding加权求和得到generated summary的embedding - +最后一步,和gold +summary比较embedding相似度计算损失,这里作者加入了一个正则项,希望提出来的摘要压缩比越高越好,这里我感觉是上一步一系列软化操作带来的补偿,因为没有选择句子,而是对所有句子加权,因此需要正则强迫模型放弃一些句子: +\[ + loss = \lambda * \frac{nb_w(gen_sum)}{nb_w(d)} + (1-\lambda) * +cos_{sim}(app(d,S,t),ref_{sum}) + \] - 这里有一个问题,gold summary的embedding是怎么得到的? - +另外为了保证能够对所有文档使用同一个阈值,作者还对cosine相似度计算的结果做了归一化 +- +从结果来看其实ROUGE还不如生成式的方法好,当然一方面原因是因为数据集本来就是生成式的,但是强在简单,快,而且用监督的方法做抽取式也不用考虑redundency的问题。

      +

      A +Robust Abstractive System for Cross-Lingual Summarization

        -
      • 最佳短论文,研究了一个非常有意思的方向:speaker -commitment,叫说话人承诺,或者叫事件事实。
      • -
      • 说话人承诺是指,通过说话人的描述,来判断某一事件是否发生,具体而言分三类:事实、非事实、不确定。模型需要从说话人的描述当中挖掘出事件的事实状态。传统的方法关注情态动词、动词短语,但作者引入了CommitmentBank数据集来测试各种已有模型,说明已有的数据集不能捕捉自然语言,尤其是口语当中的词法和句法多样性,且发现引入语言学知识的模型要优于LSTM,为深度学习树立了另一个有待攻克的目标。
      • -
      • 举个例子来形象说明一下说话人承诺问题,“我从没相信我会研究NLP”,“我不相信我可以研究NLP”,两句话都有“相信”作为动词,且都具有否定词“从没”、“不”,那么事件是“我研究NLP”,这个事件究竟有没有发生?显然前者倾向于事件已经发生,而后者倾向于事件还未发生。还有更复杂的情形,例如给定辩论双方的陈述,猜测双方讨论的某一事实是否发生。一般而言每一条样本还会有上下文,说话人承诺任务就是给定上下文、说话人表述和事件,判断事件是否是事实。
      • -
      • 作者在CommitmentBank数据集上测试了两个模型:基于规则的和基于神经网络的 +
      • 其实一句话就能概括这篇论文:做多语言生成式文摘,别人是先摘要再翻译,这篇文章是先翻译再生成摘要
      • +
      • 均是用已有框架实现
          -
        • 基于规则:Integrating Deep Linguistic Features in Factuality -Prediction over Unified Datasets。 -基于语言学的知识即人为给各种谓语词语/短语打上事实分数,找到谓语的隐藏签名,并根据句法树剖析来联系上形容词和情态动词,进行分数的增强或者反转,最后将各种人类知识库得分和句法结构作为特征输入SVM回归模型,计算出分数
        • -
        • 基于神经网络:Neural models of -factuality。使用多层双向LSTM和tree-LSTM对句子建模,然后过一个多层MLP计算出回归分数。作者测试了双向、树、集成三种模型。
        • +
        • 翻译:Marian: Fast Neural Machine Translation in C++
        • +
        • 摘要:pointer-generator
      • -
      • 文章的主要部分在结果分析,数据展示很丰富,但是作者也没有给出过多的原因分析,只是在陈述哪类事实、哪类状态、哪类语料、哪类情态下哪类模型表现更好。可能是我不做这方面工作,没有感受到从这些结论里能有哪些可以挖掘的研究点。最后得出总的结论,人类知识具有更强的泛化能力,深度模型需要整合人类知识,结论有点宽泛。
      • -
      • 这篇论文得了奖,表明学界还是希望NLP研究具有多样性,像这样具有挑战性的任务并不会有太多人做,但做好之后能给下游任务例如信息抽取、对话以极大的提升。
      • +
      • 作者其实有充足的监督数据,之前以为是多语言、小语料的摘要,或者是不借助于翻译的摘要,能够挖掘多语种共有的摘要特征
      • +
      • 但是这篇论文确实实现了robust:一般要做robust就是引入噪声,本文正好用了回译引入噪声:先把英语翻译成小语种,翻译回来,在这样的bad +english +document上训练生成式摘要模型,使得模型对噪声更加鲁棒,最后的结果也是提高了许多,并且对没有训练过的阿拉伯语也取得了较好的效果,说明不同的人翻译各有各的正确,而机器翻译的错误总是相似的。
      -

      A -Simple Theoretical Model of Importance for Summarization

      +

      Answering +while Summarizing: Multi-task Learning for Multi-hop QA with Evidence +Extraction

      +

      - +这篇论文来自号称全球最大电信公司NTT的智能实验室,提出了一个多任务模型:阅读理解+自动摘要 +- 论文做了很多实验和分析,并且详细分析了在何种情况下他们的module +works,对于摘要部分也利用了许多近年来提出的技巧,而不是简单的拼凑。 - +这篇论文同样也是在HotpotQA数据集上做,和CogQA那一篇一样,但那一篇用的是full +wiki setting,即没有gold evidence,而这篇需要gold +evidence因此用了HotpotQA 的distractor setting。 - +对于HotpotQA的distractor +setting,监督信号有两部分:answer和evidence,输入有两部分:query和context,其中evidence是context当中的句子。作者沿用了HotpotQA论文里的baseline:Simple +and effective multi-paragraph reading +comprehension,及上图中Query-Focused +Extractor以外的部分。基本思想就是将query和context结合,加上一堆FC,attention,BiRNN提取特征,最终在answer部分输出一个answer +type的分类和answer span的sequence +labelling,而在evidence部分直接接BiRNN输出的结果对每个句子做二分类。 +mtXczq.png +- 作者将evidence这边的监督任务细化为一个query +based的summarization,就在BiRNN后面加了一个模块,称之为Query-Focused +Extractor(QFE),相比原始的简单二分类,QFE强调了evidence应该是在query条件下从context中抽取出来的summary,因满足: +- summary内的句子之间应该不能冗余 - +summary内不同句子应该有着query上不同的注意力 - +针对第一点,作者在QFE内设计了一个RNN,使得在生成注意力乃至抽取摘要时都能注意到之前已经抽取出来的句子,其中RNN的时间步定义为每一次抽取一个句子,输入即某一时间步抽取出的句子的vector +- +针对第二点,作者在QFE内增加了一个针对query的注意力,加权之后的query向量称为glimpse,注意这里是QA +context对QA +query的注意力,attention里的key和value都是QA的query,而attention里的query不是直接拿整个QA +context,而是RNN的输出,即已经抽取出的句子集经过RNN编码的context,这样的设计也是符合直觉的。 +- +在RNN编码已抽取句子、注意力加权query形成glimpse向量之后,QFE拿到这两部分向量,结合每一个context未抽取句子的向量来输出每一个句子被抽取的概率,并选择最大概率的句子加入已抽取句子集合,然后接着循环计算RNN和glimpse。整个系统的依赖关系在上图中展示的很清晰。 +- 由于gold evidence的句子数目不固定,作者采用添加一个EOE的dummy +sentence的方法来动态抽取,当抽取到EOE时,模型就不再接着抽取句子。 - +在训练时,evidence这边的损失函数为: \[ + L_E = - \sum _{t=1}^{|E|} \log (max _{i \in E / E^{t-1}} +Pr(i;E^{t-1})) + \sum _i min(c_i^t, \alpha _i^t) + \] 这里\(E\)是gold +evidence的句子集合,\(E^t\)是QFE抽取出来的句子集合,\(\alpha +_i^t\)是t时间步query里第i个词的注意力,这里的时间步和前文一致,是抽句子的时间步。而\(c^t = \sum _{i=1}^{t-1} \alpha +^i\)是coverage向量。 损失的前半部分指的是gold +evidence的负对数似然损失,依次在抽取句子集合里找拥有最大QFE预测概率的gold +sentence,算损失,然后排除这个句子接着找下一个最大的,直到gold +sentence找完或者抽取句子集合里找不到gold +sentence,后半部分是coverage机制的一个正则化应用,保证挑出来计算损失的句子不会在query上拥有过于重复(集中)的注意力。 +- +作者在HotpotQA和文本蕴含数据集FEVER上做了结果,evidence部分的指标远好于baseline,而answer部分的指标也有较大提升,但不如evidence部分明显,且与BERT模型部分相比还差一点,在full +wiki setting的测试集上也被CogQA全面超过,这里作者说存在dataset +shift问题。但至少本文仅仅在baseline上添加了一个小模块,就获得了answer部分的8个点的提升,说明精心设计的summarization部分在多任务学习中确实帮助到了answer的选取。

      +

      BiSET: +Bi-directional Selective Encoding with Template for Abstractive +Summarization

        -
      • 杰出论文之一,单纯是因为我也做summarization才拎出来看。作者给出了一种简单的理论模型来定量分析文摘的重要性,在此之前重要性都没有直接的、显示的定义出来。作者将语义知识融入信息熵的概念,提出了语义单元,并泛化了之前summarization一直用的三大概念:冗余度、相关性和信息性(Redundancy, -Relevance and -Informativeness),将这三个概念统一于重要性之下,作者还指出重要性指标与人类直接高度吻合,而不像以前的自动衡量指标一样难以保证文摘质量,
      • -
      • 首先得说论文的相关工作做的很足,从上世纪50年代一直做到现在,串起了几条线,参考文献列表都值得一读。
      • -
      -

      定义

      +
    • 又是一篇将各个组件拼拼凑凑出来的一个模型,标题其实已经全写出来了:Bi-directional, +selective encoding, +template,共同组成了BiSET模块,另外两个前置过程:Retrieve和Fast +Rerank也是沿用Retrieve, Rerank and Rewrite: Soft Template Based Neural +Summarization这篇论文里的架构。应该大体是基于soft +template的summarization,加上了selective +encoding的机制,因此就把这两篇论文放在一起,讨论基于模板的生成式摘要及其改进。
    • +
    • 基于软模板的思想是,不要完全让模型来生成句子,而是人给出模板,模型只负责填词。然而完全人工设计模板那就退化到几十年前的方式了,作者的思路是,从已有的gold +summary中自动提取模板。
    • +
    • 大体分为三步:
        -
      • 语义单元:信息的原子单位,语义单元的集合记为\(\Omega\),一篇文档可以表述为在语义单元集合上的概率分布。语义单元适用于许多框架,例如frame,例如主题模型,例如深度学习常用的embedding。所有的语义单元形式都具有统一的一个特征:他们离散且独立,语言的意义基于这些语义单元产生。我们把文档和文摘标记为\(D\)\(S\),对应的在语义单元上的概率分布是\(P_D, P_S\)
      • -
      • 熵:有了概念分布就可以计算熵:\(H = - \sum -_{w} P(w) \log (P(w))\)
      • -
      • 冗余度(Redundancy):冗余度定义为最大熵与熵之差: \[ -Red(S) = H_{max} - H(S) -\] -最大熵在均匀分布取到。实际上就是将衡量不确定性的熵转成衡量确定性的冗余度。文摘应该具有低冗余度,即熵小,否则获取的信息在文档集中大量重复,并不能带来文摘熵的减少。由于对于给定语料,最大熵是固定的,因此可以简写为\(Red(S) = -H(S)\)
      • -
      • 相关性(Relevance):作者如此定义相关:当我们观察文摘来推断原文的信息时,与原文真实的信息之差(损失)应该最小。既然如此我们就用这个损失的相反数来定义相关性。损失的最简单定义就是文档和文摘的语义单元分布之间的交叉熵: -\[ -Rel(S,D) = - CrossEntrophy(S,D) \\ -= \sum _{w_i} P_S(w_i) \log (P_D(w_i)) \\ -\] 同时我们注意到: \[ -KL(S||D) = Red(S) - Rel(S,D) -\]
      • -
      • 低冗余,高相关的文摘,所带来的文摘与原文之间的KL散度最小。
      • -
      • 信息性(Informativeness):我们定义文摘的信息性为,能够改变人的常识或者知识。作者引入了背景知识\(K\)以及其概率分布\(P_K\),并定义信息性为 \[ -Inf(S,K) = CrossEntrophy(S,K) -\]
      • -
      • 即高信息性应该能够带来背景知识里没有的信息。接下来就是如何定义背景知识: -
          -
        • 背景知识应该分配已知的语义单元以高概率,代表这些语义单元在用户记忆中强度很高
        • -
        • 一般来讲背景知识可以设为无,即均匀分布,但是背景知识给了Summarization一种可控的选择,即用户可以给出查询表明他们感兴趣的语义单元,那么背景知识就应该给这些语义单元低概率。
        • -
        • 在多文档摘要中,背景知识可以简化为已经生成摘要的文档
        • +
        • Retrieve:从训练语料中检索出候选软模板
        • +
        • Rerank:让seq2seq模型学习到template saliency measurement
        • +
        • Rewrite:让seq2seq模型学习到final summary generation
      • -
      • 接下来就可以定义重要性来整合以上三种指标:重要性应该是衡量语义单元的重要性,我们想在文摘中只保留相对重要的语义单元,这意味着我们需要找一个概率分布统一文档和背景知识,编码需要保留在文摘中的语义单元的期望
      • +
      • 这种方法应该比较适用于长句压缩,或者说单句生成式摘要,这样待压缩的长句可以作为query进行retrieve
      -

      重要性

      -
        -
      • 摘要\(S\)应该能够从文档\(D\)的信息里提取出对拥有背景知识\(K\)的用户有用的部分,我们定义 -
          -
        • \(d_i = P_D(w_i)\):语义单元\(w_i\)在文档中的概率
        • -
        • \(k_i = P_K(w_i)\):语义单元\(w_i\)在背景知识中的概率
        • -
        • \(f(d_i,k_i)\):编码语义单元重要性的函数,这个函数应该满足: +

          Retrieve

            -
          • 信息性:\(\forall i \not= j \ \text{if} \ -d_i=d_j \ \text{and} \ k_i > k_j \ \text{then} \ f(d_i,k_i) < -f(d_j,k_j)\)
          • -
          • 相关性:\(\forall i \not= j \ \text{if} \ -d_i>d_j \ \text{and} \ k_i = k_j \ \text{then} \ f(d_i,k_i) > -f(d_j,k_j)\)
          • -
          • 可加性:\(I(f(d_i,k_i)) \equiv \alpha -I(d_i) + \beta I(k_i)\)
          • -
          • 归一性:\(\sum _i f(d_i,k_i) = -1\)
          • -
        • -
        • 四条性质的公式表述很简单易懂,其中\(I\)是自信息。前两条说明我们想要与文档相关的,且能带来新知识的语义单元。可加性保证了与自信息定义的一致性,归一性保证这个函数是一个概率分布
        • -
      • -
      • 满足以上性质的重要性编码函数为: \[ -P_{\frac DK}(w_i) = \frac 1C \frac {d_i^{\alpha}}{k_i^{\beta}} \\ -C = \sum _i \frac {d_i^{\alpha}}{k_i^{\beta}}, \alpha, \beta \in -\mathbb{R} ^{+} \\ -\]
      • -
      • 其中\(\alpha\)\(\beta\)代表了相关性和信息性的强度
      • -
      • 基于重要性的定义,我们可以找出最好的文摘应该满足: \[ -S^* = \text{argmax}_S \theta _I = \text{argmin} _S KL(S || P_{\frac DK}) -\]
      • -
      • 因此我们取\(\theta -_I\)作为衡量文摘质量的指标: \[ -\theta _I (S,D,K) = -KL(P_S||P_{\frac DK}) -\]
      • -
      • 重要性概率的熵可以衡量可能的好文摘候选数量
      • -
      • 衡量指标\(\theta -_I\)其实可以拆分为之前提到的三个指标: \[ -\theta _I (S,D,K) \equiv -Red(S) + \alpha Rel(S,D) + \beta Inf(S,K) -\]
      • +
      • 使用现成的Lucene搜索引擎,给定要压缩的一个长句作为query,从文档集中搜索出top +30篇文档的summary作为候选模板
      -

      结果

      +

      Rerank

        -
      • 作者用最简单的词作为语义单元,用词频归一化作为概率分布,两个超参数\(\alpha\)\(\beta\)均设置为1,对于增量摘要,背景知识是已经生成摘要的文档,对于普通摘要,背景知识设置为无,即均匀分布
      • -
      • 结果发现重要性衡量指标比传统指标更贴近人类的判断,且更具有区分性。
      • -
      • 本文作者提出的只是一个框架,背景知识、语义单元的定义可根据任务、模型灵活定义。文摘的评价问题一直缺乏好的指标,本文也算是啃了这个硬骨头,而且给出的方法简单有效。
      • +
      • 经过搜索搜出来的摘要(soft +template)是按照搜索相关度排序的,但我们需要的是按照摘要相似度排序,因此我们使用ROUGE值衡量soft +template和gold +summary之间的相似程度,这里的rerank并不是要真的排序出来,而是在生成摘要时综合考虑每个template的rank程度,之后在损失部分可以看出来。
      • +
      • 具体而言,先用一个BiLSTM编码器编码输入x和某一个候选模板r,这里是分别编码隐层状态,但是共用编码器,之后将两个隐层状态输入一个Bilinear网络预测出输入x对应的gold +summary y和r之间的ROUGE值,相当于这是一个给定x,给r做出saliency +prediction的网络: \[ +h_x = BiLSTM(x) \\ +h_r = BiLSTM(r) \\ +ROUGE(r,y) = sigmoid(h_r W_s h_x^T + b_s) \\ +\]
      • +
      • 这就完成了rerank的监督部分
      -

      Zero-Shot -Entity Linking by Reading Entity Descriptions

      -

      任务描述

      -
        -
      • 杰出论文,研究了实体链接的零次学习,提出了领域自适应预训练策略来解决链接新领域未知实体时存在的领域偏差问题。
      • -
      • 实体链接任务即给定一个query,其中包含待链接的实体,以及一系列候选实体描述,模型需要建立正确的实体链接,消除歧义。
      • -
      • 作者给出了个很有趣的例子,在上古卷轴游戏里,query的描述时The -Burden spell is the opposite of Feather , increasing a -character ' s -encumbrance.......显然这里的Burden描述的是法术的名字,待候选实体里有作为法术名字描述的Burden,也有作为法术效果描述的Burden,当然还有Burden在常规词典里的其他几种解释,模型需要将query里的Burden链接到作为法术名字描述的Burden上。对于这种具体名词任务还相对简单,困难的是将各种代词,例如“他”,“这个人”与具体的人物链接起来。实体链接任务与阅读理解任务紧密关联。
      • -
      • 零次学习即,训练集只在上古卷轴游戏的领域数据集上训练,但是要正确预测其他领域的测试集,例如乐高游戏数据集、冠冕街电视剧数据集。
      • -
      • 这就需要模型做到自然语言理解,而不是简单的领域内模式记忆。
      • -
      • 在零次学习实体链接任务中,没有别名表或者频率先验可以参考,模型需要阅读每一个候选实体的描述并建立与上下文的对应关系。
      • -
      • 一般的实体链接任务包含以下假设: -
          -
        • 单一实体集:训练和测试是在同一实体集合上做的
        • -
        • 别名表:对于每一个query实体,有一个候选实体表,或者叫query实体的别名表,不需要自己找
        • -
        • 频率统计信息:从大型标注语料中统计得到的信息,可以用来估计实体的popularity和一段文本链接到实体的概率,可以作为很重要的先验知识补充给模型
        • -
        • 结构化数据:一些系统提供了关系元组来帮助模型消歧
        • -
      • -
      • 然而零次学习抛弃了以上所有假设,只假定存在实体词典,即所有的实体好歹有一个对应的描述,将实体链接任务的人为假设降到最低,可以说是最难最极限的情况了。接下来任务显然就分成了两部分: +

        Rewrite

          -
        • 对于每个query实体,找出其候选链接实体集合
        • -
        • 将候选链接实体集合进行ranking
        • -
      • +
      • 这部分就是普通的seq2seq,依然是利用之前编码好的\(h_x, h_r\),将其拼接起来送入一个attentional +RNN decoder生成摘要,计算损失
      -

      两步走

      -
        -
      • 候选集生成采取了简单快速的方式:用信息检索的方式找出所有candidate。作者使用BM25来衡量query和document之间的相似度,找出来最相似的top-64篇文档作为候选集
      • -
      • 接下来的ranking任务类似于阅读理解或者自然语言推断,作者使用了transformer -based模型作为strong baseline。 +

        Jointly Learning

          -
        • 正式的定义应该叫Mention而不是query,即需要去找链接的实体存在的上下文,记为\(m\);而候选集实体的描述,记作\(e\)
        • -
        • \(m\)\(e\)作为句子对输入BERT模型,\(m\)还加上了额外的embedding以示区别于\(e\)
        • -
        • BERT得到句子对编码之后,将编码的向量与entity的词向量内积得到分数
        • -
        • 为了证明联合训练\(m\)\(e\)的自注意力的重要性,作者还控制变量做了两个对比的naive -bert模型,不过那就暂过不表了,毕竟self -attention很重要已经是通识了,不需要再强调了。
        • -
      • -
      • 以上的baseline其实很强大了,因为BERT经过预训练之后多少获得了领域迁移的能力,从结果也可以看出来,预训练和不预训练的BERT在平均准确度上差了3倍,而预训练的BERT无论使用src还是tgt还是都使用,差别都不大,不过都远远高于传统方法。
      • +
      • 模型的损失分为两部分,Rerank部分要保证编码出来的template和输入再经过bilinear之后能正确预测ROUGE值,Rewrite部分要保证生成正确的摘要,相当于在普通的seq2seq生成摘要之外,我还候选了一些其他的gold +summary作为输入,这个候选是通过retrieve的方式粗筛选的,具体使用时通过Rerank部分保证encode出来的部分是summary里的template成分,即可以拿出来和gold +summary比对的部分,从而辅助rewrite部分decoder的生成。
      -

      零次学习

      -
        -
      • 接下来就是作者提出的零次学习方法,主要还是利用预训练,传统的预训练迁移有两种: +

        result

          -
        • 任务自适应预训练:在src和tgt的无监督语料上预训练,在src的监督语料上微调
        • -
        • 开放语料预训练:就是BERT这一类的,不管src和tgt,自己先在超大规模无监督语料上预训练,再到src的监督语料上微调
        • -
      • -
      • 作者提出领域自适应:即在以上两种预训练之后插入一段仅仅在tgt语料上预训练的过程,理由是模型的表达容量有限,应该优先优化tgt领域的表示
      • +
      • 我们知道做summarization,decoder通过注意力其实是很依赖encoder的输入的,这里的encoder输入既包含template,又包含原始输入,作者给出了几个比较理想的例子,即输出的summary基本上按照template的格式,但是在关键实体部分从原始输入中提取实体填到template +summary当中。
      • +
      • 虽然如何提取soft template这方面使用了一个比较玄学的rerank +loss的方式,但是template的作用确实很明显,模型实际上是找到和gold +summary很接近的一个summary作为输入,在此基础上稍加更改(rewrite),效率远比端到端的seq2seq好,作者还尝试了去掉retrieve,直接从整个语料中找ROUGE最高的summary作为template,最后模型出来的结果高达50的ROUGE-1,48的ROUGE-L
      • +
      • 这种找输出作为输入的操作,其实是对decoder抽象能力不足的一种补偿,是对数据集观察得出的经验方法,能很实际的解决问题
      -

      结果

      +

      biset

        -
      • 结果当然是作者提出的领域自适应效果好一些,但其实差别不大,顶多1到2个点,而且提出的方法也不算新,仅仅改变语料多了一个预训练过程,整篇论文像是用BERT灌了一个新领域,和预训练模型训练指南一样。可能关键贡献也是提出了一个零次学习实体链接任务数据集吧。
      • +
      • 将rerank部分换成了CNN+GLU来编码文档和查询,编码后的向量计算sim +matrix,
      ]]> @@ -4170,219 +4364,152 @@ attention很重要已经是通识了,不需要再强调了。
    • deep learning + summarization natural language processing - machine learning - Summarization-Related Papers Reading (ACL/NAACL 2019) - /2019/08/15/acl2019-summarization/ - ACL/NAACL 2019 自动摘要相关论文选读 - DPPs 相似度度量改进 - -STRASS:抽取式摘要的反向传播 - 先翻译再生成摘要 - 阅读理解+自动摘要 - -BiSET:Retrieve + Fast Rerank + Selective Encoding + Template Based -

      -

      Improving -the Similarity Measure of Determinantal Point Processes for Extractive -Multi-Document Summarization

      + BERTology + /2020/03/02/bertology/ + 翻译A Primer in BERTology: What we know about how BERT +works一文,系统的介绍了近年来对于BERT可解释性以及扩展性方面的研究。 +原论文arxiv pdf

      + +

      BERT embeddings

        -
      • 这和我们组其他人做的很像,用DPPs处理抽取式文摘
      • -
      • 在上文的文摘指标论文中也提到了,搞文摘,尤其是抽取式文摘,就是三个词,qd,qd,还是qd! +
      • BERT作为一个NLU编码器,其生成的embedding是上下文相关的,关于embedding的研究有
          -
        • q:quality,哪个句子重要,需要被抽出来作为文摘。这一步是特征的构造
        • -
        • d:diversity,抽取出来的句子之间不能冗余,不能老抽一样的句子。重要的一样的句子多了,也就变得不重要了。这一步是抽样方法的构造
        • +
        • BERT embedding形成了明显的聚类,与word sense相关
        • +
        • 也有人发现,相同单词的embedding随着Position不同有差别,且该现象貌似与NSP任务有关
        • +
        • 有人研究了同一单词在不同层的representation,发现高层的表示更加与上下文相关,且越高层,embedding在高维空间中越密集(occupy +a narrow cone in the vector +space),在各向同性的情况下,两个随机单词之间的cosine距离比想象中的更为接近
      • -
      • DPPs(Determinantal Point -Processes)就是一种抽样方法,保证抽出来的句子重要(根据特征计算好的重要性数值),而且不重复。本文作者就是思路非常清晰:我要改进抽取式文摘中的DPPs,怎么改进?DPPs依赖句子之间的相似度来避免抽重复的句子,那我就改进不管DPPs怎么改,直接改相似度的计算,所以问题就换到了一个非常成熟的领域:语义相似度计算。
      • -
      • 接下来就随便套网络来做语义相似度计算就行了。作者比较新潮,用了胶囊网络,这个网络本来是提出用于解决计算机视觉中物体的位置相对变化问题的,作者认为可以将其泛化到提取底层语义特征的空间与方位信息,这里我对胶囊网络及其在NLP的应用不太了解,但是就作者给出的对比实验来说,改进其实也就1个点,而整个DPP相比之前最好系统(2009)也就好2个点,感觉还是有点刻意为之。
      • -
      • 另外作者给出的网络是真的复杂,不是原理复杂,而是用了很多组件,包括: +
      +

      Syntactic knowledge

        -
      • 三四五六七大小卷积核的CNN用于提取底层特征
      • -
      • 胶囊网络提取高层特征,用到了近年来的参数共享和路由等技巧
      • -
      • 还是用了one-hot向量,即一个词是否存在在某一个句子里
      • -
      • 各种特征的融合,包括内积,绝对差,再和所有独立的特征全部拼接到一起,预测两个句子的相似度
      • -
      • 而且相似度还只是一部分目标,另外作者还用了LSTM来重构两个句子,将重构损失加入最终的总损失 -
      • -
      -
    • 粗看图片绝对以为这是一篇CV的work
    • -
    • 作者好歹是把最近能用的技巧都用上了,做了一个集大成的网络,可能学术上看没那么简洁优美,但是就工业上来说很多这样的网络集成操作就是很work
    • -
    • 另外虽然是抽取式摘要,但作者的工作是完全监督,因此还需要构造数据集 +
    • BERT的表示是层次而非线性的,其捕捉到的更像是句法树的信息而不是词序信息。
    • +
    • BERT编码了pos,chunk等信息,但是并没有捕捉完整的句法信息(有些远距离的依赖被忽略)
    • +
    • 句法信息没有直接编码在self attention weight当中,而是需要转换
    • +
    • BERT在完形填空任务中考虑了主谓一致(subject-predicate +agreement)
    • +
    • BERT不能理解否定,对于malformed input不敏感
    • +
    • 其预测不会因为词序颠倒、句子切分、主谓语移除而改变
    • +
    • 即BERT编码了句法信息,但是没有利用上
    • +
    +

    Semantic knowledge

      -
    • 从生成式摘要数据集中构造有监督抽取式摘要数据集
    • -
    • 从生成式摘要数据集中构造有监督句子相似度计算据集
    • -
    • 这种构造也一定程度上限制了其泛化能力
    • -
  • -
  • 作者的出发点其实非常好:因为传统的相似度停留在词的粒度,没有深入到语义特征,因此构造网络提取特征的方向没错,只不过稍显复杂,而且由于仅仅改进了抽取式文摘中某一种抽样方法的相似度计算中的句子特征提取部分,对整体的影响并没有特别大,最后的结果虽然吊打了很多传统方法,但是相比传统最佳方法并没有提高多少,相比纯DPPs更是只有1个点左右的提高。
  • +
  • 通过在MLM任务中设置探针,一些研究表明BERT能编码一些语义角色信息
  • +
  • BERT编码了实体类型、关系、语义角色和proto-roles
  • +
  • 由于wordpiece的预处理,BERT在数字编码、推理上表现的并不好
  • -

    STRASS: -A Light and Effective Method for Extractive Summarization Based on -Sentence Embeddings

    -

    - -又是一篇用监督方法做抽取式文摘的,从标题就可以大致猜出来内容,基于embedding,还要light -and effective,那最简单的目标就是把摘要的embedding和gold -embedding保持一致。 - -困难的地方在于这是抽取式的,是离散的,因此需要一个流程把抽取、embedding、比较打分三个部分统一起来,软化使其可导,可以端到端训练,作者给出的是四个步骤: -- 将文档embedding映射到比较空间 - 抽句子组成摘要 - -去近似抽出的摘要的embedding - 和gold summary的embedding比较 - -首先给定一篇文档,直接用sent2vec获得doc -embedding和文档里每一句的sentence embedding - -之后只用一层全连接作为映射函数f(d),这里作者给出了第一个假设:抽取的摘要句子应该和文档具有相似度: -\[ - sel(s,d,S,t) = sigmoid (ncos^{+}(s,f(d),S)-t) - \] - 其中s是句子embedding,S代表句子集,t为阈值。 -sel代表select,即选择这个句子组成摘要的置信度,这个式子说明选出句子的embedding和文档embedding之间的相似度应该大于阈值t,且使用sigmoid做了软化,将{0,1}软化为[0,1] -- -之后进一步软化,作者并不根据分数选出句子组成文摘,而是根据分数直接近似文摘的embedding -\[ - app(d,S,t) = \sum _{s \in S} s * nb_w(s) * sel(s,d,S,t) - \] - 其中nb_w是number of words,即使用每个句子的字数和select -score对所有的句子embedding加权求和得到generated summary的embedding - -最后一步,和gold -summary比较embedding相似度计算损失,这里作者加入了一个正则项,希望提出来的摘要压缩比越高越好,这里我感觉是上一步一系列软化操作带来的补偿,因为没有选择句子,而是对所有句子加权,因此需要正则强迫模型放弃一些句子: -\[ - loss = \lambda * \frac{nb_w(gen_sum)}{nb_w(d)} + (1-\lambda) * -cos_{sim}(app(d,S,t),ref_{sum}) - \] - 这里有一个问题,gold summary的embedding是怎么得到的? - -另外为了保证能够对所有文档使用同一个阈值,作者还对cosine相似度计算的结果做了归一化 -- -从结果来看其实ROUGE还不如生成式的方法好,当然一方面原因是因为数据集本来就是生成式的,但是强在简单,快,而且用监督的方法做抽取式也不用考虑redundency的问题。

    -

    A -Robust Abstractive System for Cross-Lingual Summarization

    +

    World knowledge

      -
    • 其实一句话就能概括这篇论文:做多语言生成式文摘,别人是先摘要再翻译,这篇文章是先翻译再生成摘要
    • -
    • 均是用已有框架实现 +
    • 在某些关系中,BERT比基于知识库的方法更好,只要有好的模板句,BERT可以用于抽取知识
    • +
    • 但是BERT不能利用这些知识进行推理
    • +
    • 另外有研究发现BERT的知识是通过刻板的字符组合猜出来的,并不符合事实it +would predict that a person with an Italian-sounding name is Italian, +even when it is factually incorrect.
    • +
    +

    Self-attention heads

      -
    • 翻译:Marian: Fast Neural Machine Translation in C++
    • -
    • 摘要:pointer-generator
    • +
    • 研究发现attention heads可以分成几类 +
        +
      • attend to自己、前后单词、句子结尾
      • +
      • attend to前后单词、CLS、SEP,或者在整个序列上都有分布
      • +
      • 或者是以下5种
    • -
    • 作者其实有充足的监督数据,之前以为是多语言、小语料的摘要,或者是不借助于翻译的摘要,能够挖掘多语种共有的摘要特征
    • -
    • 但是这篇论文确实实现了robust:一般要做robust就是引入噪声,本文正好用了回译引入噪声:先把英语翻译成小语种,翻译回来,在这样的bad -english -document上训练生成式摘要模型,使得模型对噪声更加鲁棒,最后的结果也是提高了许多,并且对没有训练过的阿拉伯语也取得了较好的效果,说明不同的人翻译各有各的正确,而机器翻译的错误总是相似的。
    • +
    • attention +weight的含义:计算该词的下一层表示时,其他的单词如何加权
    • +
    • self +attention并没有直接编码语言学信息,因为大部分的head都是heterogeneous或者vertical的,与参数量过多有关
    • +
    • 少数的head编码了词的句法角色
    • +
    • 单一的head无法捕捉完整的句法树信息
    • +
    • 即便一些head能够捕捉语义关系,它们也不是带来相关任务上的提升的必须条件
    -

    Answering -while Summarizing: Multi-task Learning for Multi-hop QA with Evidence -Extraction

    -

    - -这篇论文来自号称全球最大电信公司NTT的智能实验室,提出了一个多任务模型:阅读理解+自动摘要 -- 论文做了很多实验和分析,并且详细分析了在何种情况下他们的module -works,对于摘要部分也利用了许多近年来提出的技巧,而不是简单的拼凑。 - -这篇论文同样也是在HotpotQA数据集上做,和CogQA那一篇一样,但那一篇用的是full -wiki setting,即没有gold evidence,而这篇需要gold -evidence因此用了HotpotQA 的distractor setting。 - -对于HotpotQA的distractor -setting,监督信号有两部分:answer和evidence,输入有两部分:query和context,其中evidence是context当中的句子。作者沿用了HotpotQA论文里的baseline:Simple -and effective multi-paragraph reading -comprehension,及上图中Query-Focused -Extractor以外的部分。基本思想就是将query和context结合,加上一堆FC,attention,BiRNN提取特征,最终在answer部分输出一个answer -type的分类和answer span的sequence -labelling,而在evidence部分直接接BiRNN输出的结果对每个句子做二分类。 -mtXczq.png -- 作者将evidence这边的监督任务细化为一个query -based的summarization,就在BiRNN后面加了一个模块,称之为Query-Focused -Extractor(QFE),相比原始的简单二分类,QFE强调了evidence应该是在query条件下从context中抽取出来的summary,因满足: -- summary内的句子之间应该不能冗余 - -summary内不同句子应该有着query上不同的注意力 - -针对第一点,作者在QFE内设计了一个RNN,使得在生成注意力乃至抽取摘要时都能注意到之前已经抽取出来的句子,其中RNN的时间步定义为每一次抽取一个句子,输入即某一时间步抽取出的句子的vector -- -针对第二点,作者在QFE内增加了一个针对query的注意力,加权之后的query向量称为glimpse,注意这里是QA -context对QA -query的注意力,attention里的key和value都是QA的query,而attention里的query不是直接拿整个QA -context,而是RNN的输出,即已经抽取出的句子集经过RNN编码的context,这样的设计也是符合直觉的。 -- -在RNN编码已抽取句子、注意力加权query形成glimpse向量之后,QFE拿到这两部分向量,结合每一个context未抽取句子的向量来输出每一个句子被抽取的概率,并选择最大概率的句子加入已抽取句子集合,然后接着循环计算RNN和glimpse。整个系统的依赖关系在上图中展示的很清晰。 -- 由于gold evidence的句子数目不固定,作者采用添加一个EOE的dummy -sentence的方法来动态抽取,当抽取到EOE时,模型就不再接着抽取句子。 - -在训练时,evidence这边的损失函数为: \[ - L_E = - \sum _{t=1}^{|E|} \log (max _{i \in E / E^{t-1}} -Pr(i;E^{t-1})) + \sum _i min(c_i^t, \alpha _i^t) - \] 这里\(E\)是gold -evidence的句子集合,\(E^t\)是QFE抽取出来的句子集合,\(\alpha -_i^t\)是t时间步query里第i个词的注意力,这里的时间步和前文一致,是抽句子的时间步。而\(c^t = \sum _{i=1}^{t-1} \alpha -^i\)是coverage向量。 损失的前半部分指的是gold -evidence的负对数似然损失,依次在抽取句子集合里找拥有最大QFE预测概率的gold -sentence,算损失,然后排除这个句子接着找下一个最大的,直到gold -sentence找完或者抽取句子集合里找不到gold -sentence,后半部分是coverage机制的一个正则化应用,保证挑出来计算损失的句子不会在query上拥有过于重复(集中)的注意力。 -- -作者在HotpotQA和文本蕴含数据集FEVER上做了结果,evidence部分的指标远好于baseline,而answer部分的指标也有较大提升,但不如evidence部分明显,且与BERT模型部分相比还差一点,在full -wiki setting的测试集上也被CogQA全面超过,这里作者说存在dataset -shift问题。但至少本文仅仅在baseline上添加了一个小模块,就获得了answer部分的8个点的提升,说明精心设计的summarization部分在多任务学习中确实帮助到了answer的选取。

    -

    BiSET: -Bi-directional Selective Encoding with Template for Abstractive -Summarization

    +

    layers

      -
    • 又是一篇将各个组件拼拼凑凑出来的一个模型,标题其实已经全写出来了:Bi-directional, -selective encoding, -template,共同组成了BiSET模块,另外两个前置过程:Retrieve和Fast -Rerank也是沿用Retrieve, Rerank and Rewrite: Soft Template Based Neural -Summarization这篇论文里的架构。应该大体是基于soft -template的summarization,加上了selective -encoding的机制,因此就把这两篇论文放在一起,讨论基于模板的生成式摘要及其改进。
    • -
    • 基于软模板的思想是,不要完全让模型来生成句子,而是人给出模板,模型只负责填词。然而完全人工设计模板那就退化到几十年前的方式了,作者的思路是,从已有的gold -summary中自动提取模板。
    • -
    • 大体分为三步: +
    • 底层包含了最多的线性词序关系,越高层,词序信息越弱,知识信息越强
    • +
    • BERT的中间层包含最强的句法信息,甚至可以设法还原句法树
    • +
    • BERT中间层的迁移表现和性能最好 3WJDg0.png
    • +
    • 但是该结论存在冲突,有些人发现底层做chunking更好,高层做parsing更好,有些人则发现中间层做tagging和chunking都是最好的
    • +
    • fine-tune时,底层不变对性能影响不大;最后一层在微调时变化最大
    • +
    • 语义信息在各个层中都存在
    • +
    +

    pre-training

      -
    • Retrieve:从训练语料中检索出候选软模板
    • -
    • Rerank:让seq2seq模型学习到template saliency measurement
    • -
    • Rewrite:让seq2seq模型学习到final summary generation
    • +
    • 原始的任务是MLM和NSP,有研究提出了更好的训练目标 +
        +
      • NSP移除影响不大,尤其在多语言版本中
      • +
      • NSP可以扩展为预测前后两句,也可以将前后翻转的句子作为negative +sample,而不是从其他的文档中随便找一句作为negative sample
      • +
      • dynamic mask可以改善性能
      • +
      • Beyond-sentence MLM,将句子替换为任意字符串
      • +
      • Permutation language +modeling,即XLNET当中的打乱单词顺序,再从左往右预测,结合了非回归和自回归的特点,既考虑了上下文,又不会有mask导致pre-training和fine-tune目标不一致
      • +
      • Span boundary objective,只用span边界的词来预测span
      • +
      • Phrase masking and named entity masking
      • +
      • Continual learning,持续学习
      • +
      • Conditional MLM,将segmentation embedding替换为label +embedding以适应序列标注任务
      • +
      • replacing the MASK token with [UNK] token
    • -
    • 这种方法应该比较适用于长句压缩,或者说单句生成式摘要,这样待压缩的长句可以作为query进行retrieve
    • +
    • 另外一条改进路线是数据集,有些研究试图将结构化数据融入BERT的pre-training,更为常见的融入常识信息的是加入entity +embedding或者semantic role information,例如E-BERT、ERNIE、SemBERT
    • +
    • 关于是否需要预训练,预训练使得模型更鲁棒,但是依然看任务,有些任务从头训练和预训练差别不大
    -

    Retrieve

    +

    Model architecture

      -
    • 使用现成的Lucene搜索引擎,给定要压缩的一个长句作为query,从文档集中搜索出top -30篇文档的summary作为候选模板
    • +
    • 层数比head数更重要
    • +
    • 大的batch能加速模型的收敛,with a batch size of 32k BERT’s training +time can be significantly reduced with no degradation in +performance
    • +
    • A robustly optimized BERT pretraining approach +公开了一些最优的参数设定
    • +
    • 因为高层的一些self attention +weight和底层很像,所以可以先训练浅层,在把浅层参数复制到深层,能带来25%的训练效率提升
    -

    Rerank

    +

    fine-tuning

      -
    • 经过搜索搜出来的摘要(soft -template)是按照搜索相关度排序的,但我们需要的是按照摘要相似度排序,因此我们使用ROUGE值衡量soft -template和gold -summary之间的相似程度,这里的rerank并不是要真的排序出来,而是在生成摘要时综合考虑每个template的rank程度,之后在损失部分可以看出来。
    • -
    • 具体而言,先用一个BiLSTM编码器编码输入x和某一个候选模板r,这里是分别编码隐层状态,但是共用编码器,之后将两个隐层状态输入一个Bilinear网络预测出输入x对应的gold -summary y和r之间的ROUGE值,相当于这是一个给定x,给r做出saliency -prediction的网络: \[ -h_x = BiLSTM(x) \\ -h_r = BiLSTM(r) \\ -ROUGE(r,y) = sigmoid(h_r W_s h_x^T + b_s) \\ -\]
    • -
    • 这就完成了rerank的监督部分
    • -
    -

    Rewrite

    +
  • 有人认为fine-tuning是告诉BERT该忽略哪些信息
  • +
  • 一些fine-tune的建议
      -
    • 这部分就是普通的seq2seq,依然是利用之前编码好的\(h_x, h_r\),将其拼接起来送入一个attentional -RNN decoder生成摘要,计算损失
    • +
    • 考虑多层的加权输出,而不仅仅使用最后一层去predict
    • +
    • Two-stage fine-tuning
    • +
    • Adversarial token perturbations
    • +
  • +
  • 可以插入adapter modules来加速fine-tune
  • +
  • 初始化很重要,但没有论文针对初始化系统的试验过
  • -

    Jointly Learning

    +

    Overparametrization

      -
    • 模型的损失分为两部分,Rerank部分要保证编码出来的template和输入再经过bilinear之后能正确预测ROUGE值,Rewrite部分要保证生成正确的摘要,相当于在普通的seq2seq生成摘要之外,我还候选了一些其他的gold -summary作为输入,这个候选是通过retrieve的方式粗筛选的,具体使用时通过Rerank部分保证encode出来的部分是summary里的template成分,即可以拿出来和gold -summary比对的部分,从而辅助rewrite部分decoder的生成。
    • +
    • BERT没有很好的利用其庞大的参数,大部分head可以被裁剪掉
    • +
    • 一层的head大部分相似,甚至可以将一层的head数裁剪为一个
    • +
    • 有些层和head会降低模型的性能
    • +
    • 在主谓一致、主语检测任务上,大的BERT模型表现反而不如小的
    • +
    • 同一层使用同一个MLP、attention +dropout可能导致了这样的head冗余现象
    -

    result

    +

    Compression

      -
    • 我们知道做summarization,decoder通过注意力其实是很依赖encoder的输入的,这里的encoder输入既包含template,又包含原始输入,作者给出了几个比较理想的例子,即输出的summary基本上按照template的格式,但是在关键实体部分从原始输入中提取实体填到template -summary当中。
    • -
    • 虽然如何提取soft template这方面使用了一个比较玄学的rerank -loss的方式,但是template的作用确实很明显,模型实际上是找到和gold -summary很接近的一个summary作为输入,在此基础上稍加更改(rewrite),效率远比端到端的seq2seq好,作者还尝试了去掉retrieve,直接从整个语料中找ROUGE最高的summary作为template,最后模型出来的结果高达50的ROUGE-1,48的ROUGE-L
    • -
    • 这种找输出作为输入的操作,其实是对decoder抽象能力不足的一种补偿,是对数据集观察得出的经验方法,能很实际的解决问题
    • +
    • 主要两种方式:量化与知识蒸馏
    • +
    • 还有一些方式例如progressive model +replacing、对embedding矩阵做分解、化多层为循环单层等等。
    -

    biset

    +

    Multilingual BERT

      -
    • 将rerank部分换成了CNN+GLU来编码文档和查询,编码后的向量计算sim -matrix,
    • +
    • 多语言版本的BERT在许多任务的零次学习迁移上表现非常好,但是在语言生成任务上表现不佳
    • +
    • 一些改进mBERT的手段 +
        +
      • fine-tune时固定低层
      • +
      • translation language modeling
      • +
      • improving word alignment in fine-tuning
      • +
      • combine 5 pre-training tasks (monolingual and cross-lingual MLM, +translation language modeling, cross-lingual word recovery and +paraphrase classification)
      • +
    ]]>
    @@ -4390,420 +4517,371 @@ matrix, deep learning - summarization natural language processing + bert
    - Paper Reading 1 - /2018/03/07/PaperReading/ - -
  • attention开山作(机器翻译)
  • -
  • Luong attention,全局与局部注意力、
  • -
  • attention开山作(自动文摘)
  • -
  • 生成式摘要技巧集合:LVT,开关网络,层次注意力
  • -
  • 对话系统,端到端的层次RNN
  • -
  • 微博摘要,补充micropoints
  • -
  • disan,有向的transformer,注意力掩码
  • -
  • 注意力抽取器
  • -
  • 基于强化学习的生成式摘要
  • -
  • w2v,负采样
  • - -
    -i0o00J.jpg - -
    + Outstanding Papers Reading (ACL 2019) + /2019/07/28/acl2019/ + ACL 2019获奖论文选读。 - 利用oracle来做句子级别的teacher forcing - +speaker commitment - 适用于摘要的一套评价指标框架,结合了多个指标 - +Zero-Shot Entity Linking

    +

    Neural -Machine Translation By Jointly Learning To Align And Translate

    +id="bridging-the-gap-between-training-and-inference-for-neural-machine-translation">Bridging +the Gap between Training and Inference for Neural Machine +Translation +

    Background

      -
    • 发布于2015.5(ICLR2015),作者Dzmitry Bahdanau。
    • -
    • 编码器解码器模型,翻译任务。
    • -
    • 其中双向GRU做编码器。编码隐藏层向量由双向连接而成。
    • -
    • 生成每一个单词时有不同的表示。
    • -
    • 权重由所有步编码隐藏层向量和前一步的解码隐藏层向量决定。
    • -
    • 对所有步编码隐藏层向量加权生成表示。 i0oB79.png
    • -
    -

    Effective -Approaches to Attention-based Neural Machine Translation

    +
  • 最佳长论文,这个方向就很吸引人,属于很常见,大家都知道但都选择无视,或者找不出优雅有效解法的问题。
  • +
  • 本文试图解决所有seq2seq都会遇到的问题,训练与推理的不一致,即exposure +bias。
  • +
  • exposure +bias是解码时产生的偏差。正常来讲,我们生成一句话,是从左往右逐字生成,怎么个逐字?模型生成一个字,然后这个字接着输入解码器解码出下一个字,也就是解码出每一个字时使用的上文是之前解码出的句子片段。但是这样训练收敛很慢,容易导致错误的累积。想想模型一开始本来就难以生成正确的字,现在还要基于这个错误的字生成接下来的字,那就是错上加错了。因此一般训练时,都需要使用teacher +forcing的方法:forcing模型在生成每一个字的时候,依靠的是训练数据中正确的上文,也就是不管已经生成的字,只管前提正确的情况下去生成正确的字。但是这种技巧只能用于训练,测试的时候没有ground +truth来teacher forcing。
  • +
  • 这个问题说大不大,说小不小,之前做summarization也会遇到这个问题,导致训练的反应很好,但是测试效果差,或者出现难以解释的偏差。如今的seq2seq在编码端已经取得了长足的进步,CNN和Transformer等特征抽取器已经摆脱了单向的抽取方式,但是无论什么模型,在解码端,都得老老实实从左往右生成,都避免不了exposure +bias。
  • +
  • 对于翻译,exposure +bias还和另一个问题打包影响了翻译的质量:逐字计算的交叉熵损失。模型需要学习到在正确的位置生成正确的词,这个双重正确的标准对于翻译来说太过苛刻,模型难以学到灵活的翻译关系,也就是over +correction.
  • +
  • 现有的解决exposure bias以及word-level CrossEntrophy +Loss的方法有哪些?
      -
    • 发布于2015.8,作者(Minh-Thang -Luong)使用RNN编码器解码器模型,翻译任务。
    • -
    • 其中解码时是将包含注意力的表示和目标单词对应的解码隐藏层向量连接再经激活函数生成注意力向量: -\[ -h_t = tanh(W_c[c_t;h_t]) -\] 之后注意力向量过softmax生成概率分布。
    • +
    • 在生成词的时候,有时用ground +truth,有时用自己的预测的输出,采样中庸一下,即scheduled sampling
    • +
    • 使用预训练模型,做Masked Seq2seq pretraining
    • +
    • 使用句子级别的损失函数,目标是整个句子的分数最高,而不是逐字贪心,这里包括了各种各样的优化指标以及强化学习的方法,例如mixed +incremental cross-entrophy reinforce
    • +
    • 其中预训练是比较新的方法,其余两类方法早在2015年就已经提出,作者也把自己的方法与他们的方法做了对比
    • +
  • -

    全局注意力

    +

    Methods

      -
    • 文章先介绍全局注意力模型,即对全部编码隐藏层信息进行注意力加权生成表示,这样会导致对齐向量长度不定(对齐向量对输入信息加权,长度和输入句子的单词数相同).上文中Dzmitry -Bahdanau提出的模型即全局注意力模型。本文中的全局注意力模型更为一般化:未使用双向RNN拼接输入向量而是普通的RNN;直接用当前步解码隐藏层向量计算权重,而不是前一步,避免了复杂计算。 -
    • -
    • 之后引入了两种Effective -Approaches,即局部注意力和input-feeding。
    • -
    -

    局部注意力

    +
  • 本文想要解决以上两个问题,粗看思路还是和以前一样:通过从ground truth +和 predicted +results中采样来中和偏差,以及使用句子级别的优化指标来放宽损失的约束。
  • +
  • 具体怎么采样?作者给出的方法如下图(这不就是scheduled +sampling的图吗。。。。): e26fV1.png
      -
    • 局部注意力:不使用全部输入信息,而是对每一个输出的单词先生成一个对齐位置,然后只对对齐位置附近窗内的输入信息注意力加权生成表示。文章给出了两种种生成对齐位置的方式:
    • -
    • 单调对齐:简单的将第i输出单词的对齐位置设为i,显然在文摘中这种方式不可取。
    • -
    • 预测对齐:训练对齐位置。 \[ -p_t = S \cdots sigmoid(v_p^T tanh(W_ph_t)) \\ -\] 其中\(h_t\)是第t个生成单词的隐藏层向量 \(W_p\)\(v_p\)都是需要训练的权重 -S是输入单词长度,与sigmoid相乘就得到输入句中任意位置
    • -
    • 另外为了使得对齐位置的权重最大,先以对齐位置为期望、半窗长为标准差生成高斯分布,再以此为基础生成权重。 -\[ -a_t(s) = align(h_t,h_s)exp(-\frac{(s-p_t)^2}{2\sigma ^2}) -\]
    • -
    -

    Input-feeding

    +
  • 先选出oracle +word,即模型预测的词:注意,这里用模型预测的词其实不太准确,因为模型预测的词是确定的,是decoder解码出词典概率分布取最大得到的(不考虑束搜索的话),然而这里的oracle应该表述为not +ground +truth,即非真实词。假如我们直接用预测的词,那就会错上加错;假如我们用ground +truth,那就会有exposure +bias。因此作者取了个折中,不同于之前概率上的折中(可能取预测词可能取ground +truth),还做了选词上的优化,不是简单的拿预测出的词作为oracle,具体而言:
      -
    • Input-feeding:生成对齐时还需要依赖过去的对齐,实际实现是将上一步的注意力向量作为下一步解码隐藏层的feed,好处在于模型可以完全了解之前的对齐决策,而且在水平层次和垂直层次上创造了一个非常深的网络。
    • -
    • 实验结果表明使用预测对齐的局部注意力模型表现最好。 i0oyfx.png
    • -
    -

    A -Neural Attention Model for Abstractive Sentence Summarization

    +
  • 假如直接取decoder预测概率最大的词作为Oracle,那就是普通的scheduled +sampling。
  • +
  • 然而作者使用Gumbel-Max正则化方法对预测概率分布调整,引入两个参数:一个由01均匀分布变量\(u\)计算得来的Gumbel noise \(\eta\);以及一个温度变量\(\gamma\)。假设原始概率分布为\(o\),则调整后的概率分布\(P\)\[ +\eta = - \log ( - \log u) \\ +\overline{o} _{j-1} = (o_{j-1} + \eta) / \gamma \\ +\overline{P} _{j-1} = softmax(\overline{o} _{j-1}) \\ +y_{j-1}^{\text {oracle +}}=y_{j-1}^{\mathrm{WO}}=\operatorname{argmax}\left(\tilde{P}_{j-1}\right) +\\ +\]
  • +
  • 这个加入噪音的过程只影响选择 oracle,而不影响模型的损失。增加Gumbel +noise的操作可以使得argmax操作等效于依据softmax的概率进行采样操作,使得softmax得到的概率分布有意义,而不是单纯取最大。这里只是用了Gumbel-Max(式子里那个softmax其实不需要)。Gumbel的另一个更为常见的应用是Gumbel-Softmax,用于在假设隐变量分布为category +distribution时实现重参数化(reparameterization),相比普通的softmax,Gumbel-Softmax的效果等价于用softmax计算出了一系列样本,这些样本是按照原始softmax概率依概率采样得到。
  • + +
  • 这是单词级别的oracle选择,还可以做句子级别的选择,具体做法是
      -
    • 发布于2015.9,作者Alexander M. -Rush,解码器编码器模型,文摘任务。
    • -
    • 提出了一种注意力编码器,使用普通的NNLM解码器。
    • -
    • 未使用RNN,直接用词向量。
    • -
    • 使用全部输入信息,局部输出信息(yc)构建注意力权重。
    • -
    • 直接对平滑化的输入句子的词向量矩阵加权而不是RNN隐藏层向量。
    • -
    • 模型如下图:
    • +
    • 先用单词级别的方法,加上beam search,选出几个候选句
    • +
    • 通过BLEU,ROUGE等指标选出最好的句子,将这个句子的每一个词作为oracle
    • +
    • 显然这里有一个问题,就是得保证beam search出的oracle句子和ground +truth的句子长度一致,作者引入了force +decoding,当解码出的句子还不够ground +truth长度时,假如解码出了EOS,就排除EOS,取剩下的概率最大前k个单词做beam +search;假如长度已经够了,但是还没解码出EOS,就强制设置为EOS并结束解码
    • +
  • +
  • 再计算概率,决定是用oracle还是ground truth:和scheduled +sampling一样,也是要设置动态采样概率,刚开始训练的时候多用ground +truth,然后慢慢提高oracle的比例,作者给出的概率设置为: \[ +p = \frac{\mu}{\mu + exp(e / \mu)} +\]
  • + +
  • 结果当然是比naive RNN and +Transformer要好,BLEU能有2个点的提升。作者也做了大量实验来测试超参数的影响。很简单很work,尤其是引入句子层级优化的方法简单明了,比一堆目标函数的改动要直观的多。
  • Abstractive -Text Summarization using Sequence-to-sequence RNNs and Beyond

    +id="do-you-know-that-florence-is-packed-with-visitors-evaluating-state-of-the-art-models-of-speaker-commitment">Do +you know that Florence is packed with visitors? Evaluating +state-of-the-art models of speaker commitment
      -
    • 发布于2016.8,作者Ramesh -Nallapati。编码器解码器模型,使用RNN,注意力,文摘任务。
    • -
    • 基于Dzmitry -Bahdanau的机器翻译模型(双向GRU编码,单向GRU解码)进行改进。
    • -
    • 改进包括LVT(large vocabulary trick)、Feature-rich -encoder、switching generator-pointer、分层注意力。
    • -
    -

    LVT

    +
  • 最佳短论文,研究了一个非常有意思的方向:speaker +commitment,叫说话人承诺,或者叫事件事实。
  • +
  • 说话人承诺是指,通过说话人的描述,来判断某一事件是否发生,具体而言分三类:事实、非事实、不确定。模型需要从说话人的描述当中挖掘出事件的事实状态。传统的方法关注情态动词、动词短语,但作者引入了CommitmentBank数据集来测试各种已有模型,说明已有的数据集不能捕捉自然语言,尤其是口语当中的词法和句法多样性,且发现引入语言学知识的模型要优于LSTM,为深度学习树立了另一个有待攻克的目标。
  • +
  • 举个例子来形象说明一下说话人承诺问题,“我从没相信我会研究NLP”,“我不相信我可以研究NLP”,两句话都有“相信”作为动词,且都具有否定词“从没”、“不”,那么事件是“我研究NLP”,这个事件究竟有没有发生?显然前者倾向于事件已经发生,而后者倾向于事件还未发生。还有更复杂的情形,例如给定辩论双方的陈述,猜测双方讨论的某一事实是否发生。一般而言每一条样本还会有上下文,说话人承诺任务就是给定上下文、说话人表述和事件,判断事件是否是事实。
  • +
  • 作者在CommitmentBank数据集上测试了两个模型:基于规则的和基于神经网络的
      -
    • 减少解码器的softmax层大小,加速计算,加速收敛。实际实现是在每一个mini-batch中解码器的词典只限于本batch内的输入文本,而且把之前batch内解码词典中最频繁的单词加入之后batch的解码词典(直至达到一个上限)。
    • +
    • 基于规则:Integrating Deep Linguistic Features in Factuality +Prediction over Unified Datasets。 +基于语言学的知识即人为给各种谓语词语/短语打上事实分数,找到谓语的隐藏签名,并根据句法树剖析来联系上形容词和情态动词,进行分数的增强或者反转,最后将各种人类知识库得分和句法结构作为特征输入SVM回归模型,计算出分数
    • +
    • 基于神经网络:Neural models of +factuality。使用多层双向LSTM和tree-LSTM对句子建模,然后过一个多层MLP计算出回归分数。作者测试了双向、树、集成三种模型。
    • +
  • +
  • 文章的主要部分在结果分析,数据展示很丰富,但是作者也没有给出过多的原因分析,只是在陈述哪类事实、哪类状态、哪类语料、哪类情态下哪类模型表现更好。可能是我不做这方面工作,没有感受到从这些结论里能有哪些可以挖掘的研究点。最后得出总的结论,人类知识具有更强的泛化能力,深度模型需要整合人类知识,结论有点宽泛。
  • +
  • 这篇论文得了奖,表明学界还是希望NLP研究具有多样性,像这样具有挑战性的任务并不会有太多人做,但做好之后能给下游任务例如信息抽取、对话以极大的提升。
  • -

    Feature-rich Encoder

    +

    A +Simple Theoretical Model of Importance for Summarization

      -
    • 不使用简单的只表示语义距离的词向量,而是构建包含了实体信息等多种语义特征,分别构成向量并拼接起来形成新的词向量 -
    • +
    • 杰出论文之一,单纯是因为我也做summarization才拎出来看。作者给出了一种简单的理论模型来定量分析文摘的重要性,在此之前重要性都没有直接的、显示的定义出来。作者将语义知识融入信息熵的概念,提出了语义单元,并泛化了之前summarization一直用的三大概念:冗余度、相关性和信息性(Redundancy, +Relevance and +Informativeness),将这三个概念统一于重要性之下,作者还指出重要性指标与人类直接高度吻合,而不像以前的自动衡量指标一样难以保证文摘质量,
    • +
    • 首先得说论文的相关工作做的很足,从上世纪50年代一直做到现在,串起了几条线,参考文献列表都值得一读。
    -

    Switching Generator-pointer

    +

    定义

      -
    • 解决罕见词,额外词问题。解码器的词典是固定的,如果测试文本中包含词典外的单词该如何解决。其提供的解决方案是给解码器加上一个开关,开关打开时就普通的使用自己词典生成,开关关上时,就产生一个指针指向输入文本中的一个单词,并将其复制入文摘。 -) Switching generator/pointer model -开关为G时就用传统方法生成文摘 开关为P时就从输入中拷贝单词到文摘中
    • -
    -

    分层注意力

    +
  • 语义单元:信息的原子单位,语义单元的集合记为\(\Omega\),一篇文档可以表述为在语义单元集合上的概率分布。语义单元适用于许多框架,例如frame,例如主题模型,例如深度学习常用的embedding。所有的语义单元形式都具有统一的一个特征:他们离散且独立,语言的意义基于这些语义单元产生。我们把文档和文摘标记为\(D\)\(S\),对应的在语义单元上的概率分布是\(P_D, P_S\)
  • +
  • 熵:有了概念分布就可以计算熵:\(H = - \sum +_{w} P(w) \log (P(w))\)
  • +
  • 冗余度(Redundancy):冗余度定义为最大熵与熵之差: \[ +Red(S) = H_{max} - H(S) +\] +最大熵在均匀分布取到。实际上就是将衡量不确定性的熵转成衡量确定性的冗余度。文摘应该具有低冗余度,即熵小,否则获取的信息在文档集中大量重复,并不能带来文摘熵的减少。由于对于给定语料,最大熵是固定的,因此可以简写为\(Red(S) = -H(S)\)
  • +
  • 相关性(Relevance):作者如此定义相关:当我们观察文摘来推断原文的信息时,与原文真实的信息之差(损失)应该最小。既然如此我们就用这个损失的相反数来定义相关性。损失的最简单定义就是文档和文摘的语义单元分布之间的交叉熵: +\[ +Rel(S,D) = - CrossEntrophy(S,D) \\ += \sum _{w_i} P_S(w_i) \log (P_D(w_i)) \\ +\] 同时我们注意到: \[ +KL(S||D) = Red(S) - Rel(S,D) +\]
  • +
  • 低冗余,高相关的文摘,所带来的文摘与原文之间的KL散度最小。
  • +
  • 信息性(Informativeness):我们定义文摘的信息性为,能够改变人的常识或者知识。作者引入了背景知识\(K\)以及其概率分布\(P_K\),并定义信息性为 \[ +Inf(S,K) = CrossEntrophy(S,K) +\]
  • +
  • 即高信息性应该能够带来背景知识里没有的信息。接下来就是如何定义背景知识:
      -
    • 传统的注意力是指关注句子中的关键词位置,分层还包括上一层,即文本中的关键句位置。使用两层双向RNN分别在词层次和句层次捕捉注意力。注意力机制同时运行在两个层次之上,词层次的注意力权重会被句层次的注意力权重重新加权调整。 -
    • +
    • 背景知识应该分配已知的语义单元以高概率,代表这些语义单元在用户记忆中强度很高
    • +
    • 一般来讲背景知识可以设为无,即均匀分布,但是背景知识给了Summarization一种可控的选择,即用户可以给出查询表明他们感兴趣的语义单元,那么背景知识就应该给这些语义单元低概率。
    • +
    • 在多文档摘要中,背景知识可以简化为已经生成摘要的文档
    • +
  • +
  • 接下来就可以定义重要性来整合以上三种指标:重要性应该是衡量语义单元的重要性,我们想在文摘中只保留相对重要的语义单元,这意味着我们需要找一个概率分布统一文档和背景知识,编码需要保留在文摘中的语义单元的期望
  • -

    Recurrent Neural -Network Regularization

    +

    重要性

      -
    • 本文介绍了如何在循环神经网络中使用dropout来防止过拟合
    • -
    • Dropout是指在深度神经网络当中,在每次训练时随机丢掉某些隐藏层的某些节点,测试时不丢弃节点但是将节点输出乘以丢弃概率。这种方法可以有效解决深度学习费时且容易过拟合的问题。
    • -
    • 对于dropout的理解有两种,1:它强迫一个神经单元,和随机挑选出来的其他神经单元共同工作,达到好的效果。消除减弱了神经元节点间的联合适应性,增强了泛化能力。2:它相当于创造了一些噪声数据,增加了训练数据的稀疏性,增加了特征的区分度。
    • -
    • 在RNN中不能直接按时间步丢弃隐藏层节点,因为这样会丢失RNN所需要的长期依赖信息,引入很大的噪声破坏了学习过程。
    • -
    • 作者提出的是按层丢弃节点,即使用多层RNN结构,即便丢失了一层中的某一时间步的节点,其他层的相同时间步的节点也能传递过来,不破坏序列的长期依赖信息
    • -
    • 效果如图:
    • -
    -

    Building -End-To-End Dialogue Systems Using Generative Hierarchical Neural Network -Models

    +
  • 摘要\(S\)应该能够从文档\(D\)的信息里提取出对拥有背景知识\(K\)的用户有用的部分,我们定义
      -
    • 本文介绍了使用完全数据驱动的分层RNN端到端模型来构建non-goal-driven的自然语言对话系统。
    • -
    • 训练数据是从电影字幕中提取的triples,即两个对话人按A-B-A的顺序完成三次表达。
    • -
    • 分层的结构不是简单的增加RNN隐藏层层数,而是分别在词水平和句水平构建两个RNN,如下图。 -i0TC90.png -三段式对话包含在两个词水平RNN端到端系统中 -中间生成的句表示又作为更高层次即句水平RNN的隐藏层向量
    • -
    • 文章中使用了bootstrapping的技巧,即用一些预先训练好的数据作为模型的初始值。例如用w2v在大语料库中训练好词嵌入矩阵的初始值。本文中甚至将整个模型都预训练好了,原理是使用QA系统的二段式对话大语料库预训练整个模型,第三段设为空。在实际训练中,先预训练词嵌入完成词嵌入的初始化,然后预训练整个模型4个epoch,最后固定词嵌入不变接着预训练整个模型到最佳值。
    • -
    • 系统是给定三段式对话中的前两段推测出第三段。Evaluation使用两种标准:word -perplexity衡量语法准确度,word classification error衡量语义准确度
    • -
    • 论文最后总结了一种不好的现象出现的原因。在最大后验概率输出时经常出现一些通常的回答,例如”i -don’t know”或者”i’m -sorry”。作者认为原因有三种:1:数据太少。因为对话系统是有内在歧义性和多模态性的,大规模数据才能训练出较好的结果。2:标点符号和代词在对话中占有很大比例,但是系统很难区分不同上下文环境中标点符号和代词的意义。3:对话一般很简短,因此infer时一个triple可以提供的信息太少。区分度不够。因此设计自然语言神经模型时应尽量区分语义和语法结构。作者还发现,如果不用最大后验概率而是随机输出时不会出现此问题,且infer出来的句子一般能保持话题,出现一个与话题相关的特殊词。
    • -
    -

    News Event -Summarization Complemented by Micropoints

    +
  • \(d_i = P_D(w_i)\):语义单元\(w_i\)在文档中的概率
  • +
  • \(k_i = P_K(w_i)\):语义单元\(w_i\)在背景知识中的概率
  • +
  • \(f(d_i,k_i)\):编码语义单元重要性的函数,这个函数应该满足:
      -
    • 这是来自北大的一篇论文,使用微博上的数据,其工作是给定从传统新闻中提取出的文摘,在相同主题的微博博文中构造出一些micropoints来补充文摘,实验证明这种补充的文摘能在ROUGE中取得更好分数。
    • -
    • 文章的阐述重点在于提取micropoints而不是如何将micropoints整合进原始文摘。
    • -
    • 这个团队之前提出了两种工具:用于提取新闻关键词的一种文本聚类模型CDW;用于将一段博文分割成各自拥有相对完整含义的片段(几句话)的Snippet -Growth Model。
    • -
    • Micropoints生成的主要步骤:筛选博文、将博文按主题分类、将博文分割成片段、从同一主题的博文片段中挑选一些组成micropoints、对micropoints进行筛选。
    • -
    • 筛选博文考虑两个指标:相关性和差异性,既要与原新闻文摘主题相关,又不能太重复而导致冗余。作者使用CDW提取原新闻多个角度的关键词,并将博文与这些关键词计算cos相似度,以筛选多个具有相关性的博文。另外作者利用Joint -Topic Modeling(Joint topic modeling for event summarization across news -and social media -streams)计算博文和文摘的差异性。将计算出的两个指标取调和平均作为总体筛选的指标。
    • -
    • 将博文按主题分类:受限使用LDA得到p(topic|tweet),再利用此条件概率为每一个博文构造向量v(t) -= (p(topic 1 |t), p(topic 2 |t), ..., p(topic n -|t)),最后使用DBSCAN完成主题聚类。
    • -
    • 使用团队之前提出的Snippet Growth -Model将博文分成片段,大致方法是先取一个句子,然后计算其他句子与这个句子之间的文本相似度、距离度量、影响度量来决定是否将其他句子加入这个句子所在的片段当中。
    • -
    • 现在已经得到了按主题分类的一堆片段,之后需要在一个主题的片段中挑一些最能代表本主题的片段出来。其方法是挑选到同主题其他片段平均距离最小的前几个片段。因为句子不太长,作者将一个片段用词袋表示,词袋中装了组成本片段中所有句子的所有词,用词向量表示。距离用KL散度衡量。如果新挑出来的片段与已挑片段距离太近则放弃,以保证挑选出来的片段依然具有差异性。
    • -
    • 得到这些片段将组成micropoints,但是在补充进文摘之前还要进行筛选。作者提出了三个指标:信息量,流行度,简洁性。信息量即补充进文摘之后文摘获得信息熵增益,信息量越大越好;流行度用原博文评论数来衡量,越流行的博文越不容易极端,用流行度来防止极端、三观不正的博文被补充进文摘。流行度越大越好;简洁性用补充的部分和原文摘的长度比来描述,越小表示补充的越简洁,不会喧宾夺主。此时问题就化成在给定简洁性要求下,每一个片段能带来信息量和流行度的收益,同时耗费一定的简洁性,选择片段使收益最大,即离散的有限制条件的最优化问题,可以抽象为0-1背包问题,用动态规划解决。作者还设置了阈值,使用分段函数:当流行度大于阈值时,信息增益对于收益的贡献会更大。这样设置是为了保证不会因为出现流行度和信息增益一方很大而另一方几乎没有的片段被加入文摘。
    • +
    • 信息性:\(\forall i \not= j \ \text{if} \ +d_i=d_j \ \text{and} \ k_i > k_j \ \text{then} \ f(d_i,k_i) < +f(d_j,k_j)\)
    • +
    • 相关性:\(\forall i \not= j \ \text{if} \ +d_i>d_j \ \text{and} \ k_i = k_j \ \text{then} \ f(d_i,k_i) > +f(d_j,k_j)\)
    • +
    • 可加性:\(I(f(d_i,k_i)) \equiv \alpha +I(d_i) + \beta I(k_i)\)
    • +
    • 归一性:\(\sum _i f(d_i,k_i) = +1\)
    • +
  • +
  • 四条性质的公式表述很简单易懂,其中\(I\)是自信息。前两条说明我们想要与文档相关的,且能带来新知识的语义单元。可加性保证了与自信息定义的一致性,归一性保证这个函数是一个概率分布
  • + +
  • 满足以上性质的重要性编码函数为: \[ +P_{\frac DK}(w_i) = \frac 1C \frac {d_i^{\alpha}}{k_i^{\beta}} \\ +C = \sum _i \frac {d_i^{\alpha}}{k_i^{\beta}}, \alpha, \beta \in +\mathbb{R} ^{+} \\ +\]
  • +
  • 其中\(\alpha\)\(\beta\)代表了相关性和信息性的强度
  • +
  • 基于重要性的定义,我们可以找出最好的文摘应该满足: \[ +S^* = \text{argmax}_S \theta _I = \text{argmin} _S KL(S || P_{\frac DK}) +\]
  • +
  • 因此我们取\(\theta +_I\)作为衡量文摘质量的指标: \[ +\theta _I (S,D,K) = -KL(P_S||P_{\frac DK}) +\]
  • +
  • 重要性概率的熵可以衡量可能的好文摘候选数量
  • +
  • 衡量指标\(\theta +_I\)其实可以拆分为之前提到的三个指标: \[ +\theta _I (S,D,K) \equiv -Red(S) + \alpha Rel(S,D) + \beta Inf(S,K) +\]
  • + +

    结果

    +
      +
    • 作者用最简单的词作为语义单元,用词频归一化作为概率分布,两个超参数\(\alpha\)\(\beta\)均设置为1,对于增量摘要,背景知识是已经生成摘要的文档,对于普通摘要,背景知识设置为无,即均匀分布
    • +
    • 结果发现重要性衡量指标比传统指标更贴近人类的判断,且更具有区分性。
    • +
    • 本文作者提出的只是一个框架,背景知识、语义单元的定义可根据任务、模型灵活定义。文摘的评价问题一直缺乏好的指标,本文也算是啃了这个硬骨头,而且给出的方法简单有效。

    DiSAN: -Directional Self-Attention Network for RNN/CNN-Free Language -Understanding

    +id="zero-shot-entity-linking-by-reading-entity-descriptions">Zero-Shot +Entity Linking by Reading Entity Descriptions +

    任务描述

      -
    • 更新,作者后来又推出了fast -disan,貌似是改了注意力的计算,细节待补充
    • -
    • 作者提出了一种有向自注意网络,不依赖RNN或者CNN结构也能很好的完成NLP问题中的编码任务。
    • -
    • 作者认为现有的编码器中,使用RNN能很好的捕捉序列的顺序信息但是慢;使用纯注意力机制(就如同A -Neural Attention Model for Abstractive Sentence -Summarization中不使用RNN而是直接对词向量序列进行注意力加权)虽然能利用现有的分布式或者并行式计算框架加速运算,却丢失了序列的顺序信息。因此作者提出了一种能捕捉序列顺序信息的纯注意力编码器结构,结合了两者的优点。
    • -
    • 作者首先提出了三种注意力概念:多维度注意力,自注意力,有向注意力。
    • -
    • 传统的注意力是对一个句子中各个单词加权,权值是标量。而多维度注意力中权值是向量,维度和词向量维度相同。使用多维度的理由在于这样是对每一个词的每一个特征进行注意力加权,词向量本身具有一词多义性,传统的对整个词向量进行加权的注意力机制对同一个词在不同上下文环境中的情况不能很好区分,多维度是对词向量的每一个分量加权,它可以给能表示当前上下文环境的特征更多的注意力权重。我的理解是对词向量的分量进行注意力加权,这样相当于同一个词在不同的上下文环境中有略微不同的表示,可以用来区分。下图是传统注意力与多维度注意力的区别。 -i0ojBQ.png -右边是多维度注意力 -可以看到注意力权重变成了向量,与输入词向量维度数相同
    • -
    • 一般的注意力权重是编码输入和一个解码输出作为参数生成,权重与当前输出有关。自注意力与解码端无关,要么用本句子中的每一个词替代解码输出,要么用整个输入句子替代解码输出。前者与多维度结合形成token2token注意力,后者与多维度结合形成source2token。
    • -
    • 有向注意力即在生成token2token注意力时根据需要添加一个掩码矩阵,矩阵元素为0或者负无穷。矩阵可以为上三角或者下三角,代表两个方向的掩码,例如从i到j是0,从j到i是负无穷,则在token2token中词之间的注意力就有了方向,不正确方向的注意力过softmax之后会降到0,而正确方向的注意力不受影响。掩码矩阵还有第三种,无对角线矩阵,即对角线上的值为负无穷,这样token2token中一个单词对自己不会产生注意力。有向注意力如下图: -
    • -
    • 最后有向自注意网络的构成利用了以上三种注意力,首先上下三角两种掩码搭配多维度token2token可以产生前向后向两个自注意力向量,类似blstm,然后将向量连接,过一个多维度source2token产生最终的编码输出。作者测试了这种编码能在自然语言推测和情感分析任务中达到最佳水平,也可以作为其他模型的一部分在其他任务中使用。
    • +
    • 杰出论文,研究了实体链接的零次学习,提出了领域自适应预训练策略来解决链接新领域未知实体时存在的领域偏差问题。
    • +
    • 实体链接任务即给定一个query,其中包含待链接的实体,以及一系列候选实体描述,模型需要建立正确的实体链接,消除歧义。
    • +
    • 作者给出了个很有趣的例子,在上古卷轴游戏里,query的描述时The +Burden spell is the opposite of Feather , increasing a +character ' s +encumbrance.......显然这里的Burden描述的是法术的名字,待候选实体里有作为法术名字描述的Burden,也有作为法术效果描述的Burden,当然还有Burden在常规词典里的其他几种解释,模型需要将query里的Burden链接到作为法术名字描述的Burden上。对于这种具体名词任务还相对简单,困难的是将各种代词,例如“他”,“这个人”与具体的人物链接起来。实体链接任务与阅读理解任务紧密关联。
    • +
    • 零次学习即,训练集只在上古卷轴游戏的领域数据集上训练,但是要正确预测其他领域的测试集,例如乐高游戏数据集、冠冕街电视剧数据集。
    • +
    • 这就需要模型做到自然语言理解,而不是简单的领域内模式记忆。
    • +
    • 在零次学习实体链接任务中,没有别名表或者频率先验可以参考,模型需要阅读每一个候选实体的描述并建立与上下文的对应关系。
    • +
    • 一般的实体链接任务包含以下假设: +
        +
      • 单一实体集:训练和测试是在同一实体集合上做的
      • +
      • 别名表:对于每一个query实体,有一个候选实体表,或者叫query实体的别名表,不需要自己找
      • +
      • 频率统计信息:从大型标注语料中统计得到的信息,可以用来估计实体的popularity和一段文本链接到实体的概率,可以作为很重要的先验知识补充给模型
      • +
      • 结构化数据:一些系统提供了关系元组来帮助模型消歧
      • +
    • +
    • 然而零次学习抛弃了以上所有假设,只假定存在实体词典,即所有的实体好歹有一个对应的描述,将实体链接任务的人为假设降到最低,可以说是最难最极限的情况了。接下来任务显然就分成了两部分: +
        +
      • 对于每个query实体,找出其候选链接实体集合
      • +
      • 将候选链接实体集合进行ranking
      • +
    -

    Neural -Summarization by Extracting Sentences and Words

    +

    两步走

      -
    • 本文是使用了完全数据驱动的模型来完成抽取式文摘。其模型结构由一个分层文本编码器和一个注意力机制抽取器构成。
    • -
    • 与生成式注意力机制文摘不同的地方在于:使用CNN而不是w2v构建词嵌入;注意力用来直接抽取词而不是加权生成中间表示。
    • -
    • 因为本文是用数据驱动的抽取式文摘,所以需要大量的抽取式文摘训练数据,这样的训练数据很少,作者提出了制造词水平和句水平的抽取式训练数据的方法:对于句抽取,作者的思路是将生成式文摘转换成抽取式文摘,首先获得生成式文摘,然后将原文中每一句与生成式文摘对比以决定是否应该抽取出来,对比的指标包括句子在文档中的位置,一元语法和二元语法重叠性,出现的命名实体数量等等;对于词抽取,同样也是对比生成式文摘和原文中词的词义重叠程度来决定该词是否应该抽取出来。对于那些生成式文摘中出现而原文中没有的词,作者的解决方案是用原文中词嵌入距离相近的词替代形成训练数据。
    • -
    • 编码时,用CNN形成词嵌入,将句子表示为词嵌入序列,再用RNN形成文档层次上的编码(一个句子为一个时间步输入)。
    • -
    • 句抽取时,与生成式不同,抽取的RNN输出依赖是上一个抽取生成的句子乘以一个置信系数,这个置信系数代表上一个句子有多大可能被抽取出来。
    • -
    • 与生成式一样,train和infer存在差异,前期抽取infer出现的问题会在后期越滚越大。为了解决这个问题,作者使用了一种“课程学习策略”:训练刚开始置信水平不能准确预测,就设为1,之后随着训练进行逐渐将置信水平恢复成训练出来的值。
    • -
    • 与句抽取相比,词抽取更加贴近生成式算法,可以看成是词典受限的词水平上的生成式文摘。
    • -
    • 抽取式文摘在处理稀疏词汇和命名实体上有优势,可以让模型检查这些词汇或实体的上下文、句中相对位置等来降低注意力权重,减少这类词影响。
    • -
    • 抽取式要解决的一个问题是决定抽取数量。作者取抽取置信水平最高的三句作为文摘。另一个问题是每一个batch的词典一般是不同的。作者采用了一种负采样的解决方案。
    • +
    • 候选集生成采取了简单快速的方式:用信息检索的方式找出所有candidate。作者使用BM25来衡量query和document之间的相似度,找出来最相似的top-64篇文档作为候选集
    • +
    • 接下来的ranking任务类似于阅读理解或者自然语言推断,作者使用了transformer +based模型作为strong baseline。 +
        +
      • 正式的定义应该叫Mention而不是query,即需要去找链接的实体存在的上下文,记为\(m\);而候选集实体的描述,记作\(e\)
      • +
      • \(m\)\(e\)作为句子对输入BERT模型,\(m\)还加上了额外的embedding以示区别于\(e\)
      • +
      • BERT得到句子对编码之后,将编码的向量与entity的词向量内积得到分数
      • +
      • 为了证明联合训练\(m\)\(e\)的自注意力的重要性,作者还控制变量做了两个对比的naive +bert模型,不过那就暂过不表了,毕竟self +attention很重要已经是通识了,不需要再强调了。
      • +
    • +
    • 以上的baseline其实很强大了,因为BERT经过预训练之后多少获得了领域迁移的能力,从结果也可以看出来,预训练和不预训练的BERT在平均准确度上差了3倍,而预训练的BERT无论使用src还是tgt还是都使用,差别都不大,不过都远远高于传统方法。
    -

    A DEEP -REINFORCED MODEL FOR ABSTRACTIVE SUMMARIZATION

    +

    零次学习

      -
    • 使用强化学习来优化当前的端到端生成式文摘模型 i0TicT.png
    • -
    • 解决长文摘生成和重复短语问题
    • -
    • 强化学习需要外界给予模型反馈,这里作者使用人工对生成的文摘进行评价并反馈给模型,使得模型可以生成可读性更好的文摘
    • -
    • 模型的改进主要在两点:在编码端和解码端分别加入了内注意力,其中编码端是之前提出过的,本文主要引入解码端的内注意力机制;提出了一种新的目标函数,结合了交叉熵损失和来自强化学习的奖励
    • -
    • 编码解码两端的内注意力是从两个方面解决重复短语问题,因为重复问题在长文本生成文摘中相比短文本更加严重。
    • -
    • 编码端加入内注意力是认为重复来自于在解码各个时间步对输入长文本的注意力分布不均匀,没用充分利用长文本,在解码各个时间步可能注意力的分布都相似,导致生成重复语段。因此作者在模型中对过去已经获得高注意力权重的输入位置给予惩罚,保证输入文本的各个部分充分利用。引入惩罚的方式是在新的某一解码时间步,某一编码输入位置的注意力权重是本次产生的注意力权重除以之前所有时间步注意力权重之和,这样如果过去的产生了大的注意力权重,则新产生的注意力权重会变小。
    • -
    • 解码端加入内注意力是认为重复还来源于解码端本身的隐藏状态重复。作者认为解码时依赖的解码端信息应该不止包含上一时间步的解码端隐藏层状态,而是过去所有时间步的隐藏层状态并给予注意力加权,因此在解码端引入了类似的内注意力机制和惩罚机制。
    • -
    • 在这个端到端模型中注意力并不是沟通编码端和解码端的方式,而是独立在两端,仅依赖于编码/解码端之前的状态和当前状态产生,因此是内注意力(自注意力)。
    • -
    • 在搭建端到端模型时作者还采用了一些其他前人提出过的技巧,例如使用复制指针和开关解决稀疏词问题,编码解码共享词嵌入矩阵,另外还特别提出了一个小技巧:基于观察,一般文摘中不会出现重复的三词短语,因此在解码端束搜索中若出现了重复的三词短语就剪枝。
    • -
    • 之后作者分析了静态的监督学习在文摘评价标准中常常取不到理想结果的两个原因:一是exposure -bias,即模型在训练时是接触到了正确的输出(ground -truth),但是在infer时是没有正确输出做矫正的,因此如果infer时错了一个词,之后错误会越积越大;二是文摘生成本身不是静态的,没有标准答案,而好的文摘有许多种可能(文摘评价标准中一般考虑了这些可能),但使用最大似然目标函数的静态的学习方法扼杀了这些可能。
    • -
    • 因此作者在监督学习之外为文摘任务引入了policy -learning,一种策略搜索强化学习方式。在强化学习中模型不是以生成与标签最相似的输出为目标,而是以最大化某一种指标为目标。在这里作者借鉴了图像标注任务中的一种强化学习算法:self-critical -policy gradient training algorithm: \[ -L_{rl} = (r(y)-r(y^s))\sum _{t=1}^n log p(y_t^s | y_1^s,...,y_{t-1}^s,x) -\] r是人工评价奖励函数 -两个r函数的参数:前者是最大化输出概率得到的基准句子,后者是根据每一步输出条件概率分布采样得到的句子 -目标是最小化这个L目标函数,假如采样的句子得到的人工奖励比基准句子多,则这个最小化目标函数等价于最大化采样句子的条件概率(前面的两个r函数计算之后为负号)
    • -
    • 之后作者将监督学习和强化学习的两种目标函数结合起来:
    • +
    • 接下来就是作者提出的零次学习方法,主要还是利用预训练,传统的预训练迁移有两种: +
        +
      • 任务自适应预训练:在src和tgt的无监督语料上预训练,在src的监督语料上微调
      • +
      • 开放语料预训练:就是BERT这一类的,不管src和tgt,自己先在超大规模无监督语料上预训练,再到src的监督语料上微调
      • +
    • +
    • 作者提出领域自适应:即在以上两种预训练之后插入一段仅仅在tgt语料上预训练的过程,理由是模型的表达容量有限,应该优先优化tgt领域的表示
    -

    Distributed -Representations of Words and Phrases and their Compositionality

    +

    结果

      -
    • 介绍了w2v的负采样版本。
    • -
    • 以短语为基本单位训练而不是单词,这样能够更好的表示一些idiomatic -phrase。
    • -
    • 用nce(噪声对比估计)替代分层softmax,nce近似最大化softmax的对数概率,在w2v中只关心学到好的表示,因此用简化版的nce,负采样,用下式替代输出的条件概率: -\[ -p(w_O | w_I) = \frac {exp(v_{w_O}^T v_{w_I})}{\sum _{w=1}^W -exp(v_{w_O}^T v_{w_I})} -\] 被替换成 $$ log (v_{w_O}^T v_{w_I}) + {i=1}^k E{w_i -P_n(w)} [log (v_{w_O}^T v_{w_I})]
    • -
    • 每次在softmax输出层只激活目标label和k个噪声label(即非目标label),即对每一个单词,有k+1个样本,1个正样本,k个采样得到的负样本,进行logistic回归分类,上式即logistics回归的似然函数,其中Pn是噪声的概率分布。
    • -
    • 对常见词进行降采样,因为常见词的向量表示容易稳定,再训练几百万次也不会发生大的改变,因此每一次对词的训练以一定概率跳过:
    • -
    • 这样训练出来的skip-gram模型具有很好的加法语义合成性(两个向量的逐分量相加),即俄国+河与伏尔加河相近,因为向量与输出层的概率对数相关,两个向量相加与两个上下文的乘积相关,这种乘积相当于逻辑与:高概率乘高概率为高概率,其余为低概率。因此具有这种简单的算术语义合成性。
    • +
    • 结果当然是作者提出的领域自适应效果好一些,但其实差别不大,顶多1到2个点,而且提出的方法也不算新,仅仅改变语料多了一个预训练过程,整篇论文像是用BERT灌了一个新领域,和预训练模型训练指南一样。可能关键贡献也是提出了一个零次学习实体链接任务数据集吧。
    ]]>
    - 机器学习 + 自然语言处理 + deep learning + natural language processing machine learning - math - abstractive summarization - theory - nlp
    - BERTology - /2020/03/02/bertology/ - 翻译A Primer in BERTology: What we know about how BERT -works一文,系统的介绍了近年来对于BERT可解释性以及扩展性方面的研究。 -原论文arxiv pdf

    + A summary of my Android apps:BuptRoom + /2017/01/16/buptroomreview/ + +

    简介

    +

    写了一个查询学校空闲教室的APP +拉取学校教务处网站的信息,分类显示,还加了一些杂七杂八的 +毕竟第一次写android,什么都想尝试一下 点这下载:BuptRoom repository地址:一个简单的北邮自习室查询系统 +完成第一个版本大概是3个周末 之后花了1个月陆陆续续更新了杂七杂八的 +很多东西写的不规范,也是临时查到了就用上 总结一下这次写App的经过:

    -

    BERT embeddings

    -
      -
    • BERT作为一个NLU编码器,其生成的embedding是上下文相关的,关于embedding的研究有 +
      +i0IHL4.png + +
      +

      学习的内容

        -
      • BERT embedding形成了明显的聚类,与word sense相关
      • -
      • 也有人发现,相同单词的embedding随着Position不同有差别,且该现象貌似与NSP任务有关
      • -
      • 有人研究了同一单词在不同层的representation,发现高层的表示更加与上下文相关,且越高层,embedding在高维空间中越密集(occupy -a narrow cone in the vector -space),在各向同性的情况下,两个随机单词之间的cosine距离比想象中的更为接近
      • -
    • +
    • Android基本架构,组件,生命周期
    • +
    • Fragment的使用
    • +
    • Java库与库之间的调用
    • +
    • Github的使用
    • +
    • 部署app
    • +
    • 图像处理的一些方法
    • +
    • 一个愚蠢的拉取网页内容的方式
    • +
    • GitHub第三方库的利用
    • +
    • 颜色方面的知识
    • +
    • Android Material Design
    • +
    • 简单的优化
    • +
    • 多线程与Handler
    -

    Syntactic knowledge

    +

    解决的问题

    +

    主要解决了这么几个问题

      -
    • BERT的表示是层次而非线性的,其捕捉到的更像是句法树的信息而不是词序信息。
    • -
    • BERT编码了pos,chunk等信息,但是并没有捕捉完整的句法信息(有些远距离的依赖被忽略)
    • -
    • 句法信息没有直接编码在self attention weight当中,而是需要转换
    • -
    • BERT在完形填空任务中考虑了主谓一致(subject-predicate -agreement)
    • -
    • BERT不能理解否定,对于malformed input不敏感
    • -
    • 其预测不会因为词序颠倒、句子切分、主谓语移除而改变
    • -
    • 即BERT编码了句法信息,但是没有利用上
    • +
    • Android6.0以上的版本貌似权限需要动态验证,现在写的只支持5.0及以下版本,用到的permisson:
    -

    Semantic knowledge

    +
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
      -
    • 通过在MLM任务中设置探针,一些研究表明BERT能编码一些语义角色信息
    • -
    • BERT编码了实体类型、关系、语义角色和proto-roles
    • -
    • 由于wordpiece的预处理,BERT在数字编码、推理上表现的并不好
    • +
    • 网页是jsp动态网页,不能简单地parse,最后采用在webview中loadurl,执行javascript命令,需下载jsoup-1.9.2.jar这个包添加到库文件中
    -

    World knowledge

    +
    final class MyWebViewClient extends WebViewClient {
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    view.loadUrl(url);
    return true;
    }
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
    Log.d("WebView","onPageStarted");
    super.onPageStarted(view, url, favicon);
    }
    public void onPageFinished(WebView view, String url) {
    Log.d("WebView","onPageFinished ");
    view.loadUrl("javascript:window.handler.getContent(document.body.innerHTML);");
    super.onPageFinished(view, url);
    }
    }
      -
    • 在某些关系中,BERT比基于知识库的方法更好,只要有好的模板句,BERT可以用于抽取知识
    • -
    • 但是BERT不能利用这些知识进行推理
    • -
    • 另外有研究发现BERT的知识是通过刻板的字符组合猜出来的,并不符合事实it -would predict that a person with an Italian-sounding name is Italian, -even when it is factually incorrect.
    • +
    • 写一个handler响应javascript命令,这样在content中就拿到String形式的html文件中body内容
    -

    Self-attention heads

    +
    final  class JavascriptHandler{
    @JavascriptInterface
    public void getContent(String htmlContent){
    Log.i(Tag,"html content: "+htmlContent);
    document= Jsoup.parse(htmlContent);
    htmlstring=htmlContent;
    content=document.getElementsByTag("body").text();
    Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
    }
    }
      -
    • 研究发现attention heads可以分成几类 +
    • 之后是字符串处理,根据教务处给的格式精简分类
    • +
    +
    去逗号
    String contenttemp=content;
    content="";
    String[] contentstemp=contenttemp.split(",");
    for (String temp:contentstemp){
    content=content+temp;
    }

    分组
    contents=content.split(" |:");
    String showcontent="";
    count=0;
    int tsgflag=0;
    int cishu=0;
    j12.clear();
    j34.clear();
    j56.clear();
    j78.clear();
    j9.clear();
    j1011.clear();
    if (keyword.contains("图书馆")) tsgflag=1;
    for (String temp:contents){
    if (temp.contains(keyword)){
    cishu++;
    SaveBuidlingInfo(count,cishu,tsgflag);
    }
    count++;
    }

    SaveBuildingInfo是按教学楼分类存取一天教室,其中再按时间段分类存到j12,j34.....
    while (1 == 1) {
    if (contents[k].contains("楼") || contents[k].contains("节") || contents[k].contains("图"))
    break;
    ;
    switch (c) {
    case 1:
    j12.add(contents[k]);
    break;
    case 2:
    j34.add(contents[k]);
    break;
    case 3:
    j56.add(contents[k]);
    break;
    case 4:
    j78.add(contents[k]);
    break;
    case 5:
    j9.add(contents[k]);
    break;
    case 6:
    j1011.add(contents[k]);
    break;
    default:
    break;
    }
    k++;
    }
      -
    • attend to自己、前后单词、句子结尾
    • -
    • attend to前后单词、CLS、SEP,或者在整个序列上都有分布
    • -
    • 或者是以下5种
    • -
    -
  • attention -weight的含义:计算该词的下一层表示时,其他的单词如何加权
  • -
  • self -attention并没有直接编码语言学信息,因为大部分的head都是heterogeneous或者vertical的,与参数量过多有关
  • -
  • 少数的head编码了词的句法角色
  • -
  • 单一的head无法捕捉完整的句法树信息
  • -
  • 即便一些head能够捕捉语义关系,它们也不是带来相关任务上的提升的必须条件
  • - -

    layers

    -
      -
    • 底层包含了最多的线性词序关系,越高层,词序信息越弱,知识信息越强
    • -
    • BERT的中间层包含最强的句法信息,甚至可以设法还原句法树
    • -
    • BERT中间层的迁移表现和性能最好 3WJDg0.png
    • -
    • 但是该结论存在冲突,有些人发现底层做chunking更好,高层做parsing更好,有些人则发现中间层做tagging和chunking都是最好的
    • -
    • fine-tune时,底层不变对性能影响不大;最后一层在微调时变化最大
    • -
    • 语义信息在各个层中都存在
    • -
    -

    pre-training

    -
      -
    • 原始的任务是MLM和NSP,有研究提出了更好的训练目标 -
        -
      • NSP移除影响不大,尤其在多语言版本中
      • -
      • NSP可以扩展为预测前后两句,也可以将前后翻转的句子作为negative -sample,而不是从其他的文档中随便找一句作为negative sample
      • -
      • dynamic mask可以改善性能
      • -
      • Beyond-sentence MLM,将句子替换为任意字符串
      • -
      • Permutation language -modeling,即XLNET当中的打乱单词顺序,再从左往右预测,结合了非回归和自回归的特点,既考虑了上下文,又不会有mask导致pre-training和fine-tune目标不一致
      • -
      • Span boundary objective,只用span边界的词来预测span
      • -
      • Phrase masking and named entity masking
      • -
      • Continual learning,持续学习
      • -
      • Conditional MLM,将segmentation embedding替换为label -embedding以适应序列标注任务
      • -
      • replacing the MASK token with [UNK] token
      • -
    • -
    • 另外一条改进路线是数据集,有些研究试图将结构化数据融入BERT的pre-training,更为常见的融入常识信息的是加入entity -embedding或者semantic role information,例如E-BERT、ERNIE、SemBERT
    • -
    • 关于是否需要预训练,预训练使得模型更鲁棒,但是依然看任务,有些任务从头训练和预训练差别不大
    • -
    -

    Model architecture

    -
      -
    • 层数比head数更重要
    • -
    • 大的batch能加速模型的收敛,with a batch size of 32k BERT’s training -time can be significantly reduced with no degradation in -performance
    • -
    • A robustly optimized BERT pretraining approach -公开了一些最优的参数设定
    • -
    • 因为高层的一些self attention -weight和底层很像,所以可以先训练浅层,在把浅层参数复制到深层,能带来25%的训练效率提升
    • -
    -

    fine-tuning

    -
      -
    • 有人认为fine-tuning是告诉BERT该忽略哪些信息
    • -
    • 一些fine-tune的建议 -
        -
      • 考虑多层的加权输出,而不仅仅使用最后一层去predict
      • -
      • Two-stage fine-tuning
      • -
      • Adversarial token perturbations
      • -
    • -
    • 可以插入adapter modules来加速fine-tune
    • -
    • 初始化很重要,但没有论文针对初始化系统的试验过
    • -
    -

    Overparametrization

    -
      -
    • BERT没有很好的利用其庞大的参数,大部分head可以被裁剪掉
    • -
    • 一层的head大部分相似,甚至可以将一层的head数裁剪为一个
    • -
    • 有些层和head会降低模型的性能
    • -
    • 在主谓一致、主语检测任务上,大的BERT模型表现反而不如小的
    • -
    • 同一层使用同一个MLP、attention -dropout可能导致了这样的head冗余现象
    • -
    -

    Compression

    -
      -
    • 主要两种方式:量化与知识蒸馏
    • -
    • 还有一些方式例如progressive model -replacing、对embedding矩阵做分解、化多层为循环单层等等。
    • +
    • 界面上套了一个NavigationView,没有什么特别设计的,因为没有设置多界面,就靠刷新TextView来伪装多个界面

    • +
    • 尝试了MaterialDesign组件,加入一点系统时间方面的东西

    -

    Multilingual BERT

    -
      -
    • 多语言版本的BERT在许多任务的零次学习迁移上表现非常好,但是在语言生成任务上表现不佳
    • -
    • 一些改进mBERT的手段 +
      final Calendar c = Calendar.getInstance();
      c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
      mYear = String.valueOf(c.get(Calendar.YEAR)); // 获取当前年份
      mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
      mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
      mWay = String.valueOf(c.get(Calendar.DAY_OF_WEEK));
      mHour= c.get(Calendar.HOUR_OF_DAY);
      mMinute= c.get(Calendar.MINUTE);

      if (mHour>=8&&mHour<10){
      nowtime="现在是一二节课";
      }else
      if (mHour>=10&&mHour<12){
      nowtime="现在是三四节课";
      }else
      if ((mHour==13&&mMinute>=30)||(mHour==14)||(mHour==15&&mMinute<30)){
      nowtime="现在是五六节课";
      }else
      if ((mHour==15&&mMinute>=30)||(mHour==16)||(mHour==17&&mMinute<30)){
      nowtime="现在是七八节课";
      }else
      if ((mHour==17&&mMinute>=30)||(mHour==18&&mMinute<30)){
      nowtime="现在是第九节课";
      }else
      if ((mHour==18&&mMinute>=30)||(mHour==19)||(mHour==20&&mMinute<30)){
      nowtime="现在是十、十一节课";
      }else
      nowtime="现在是休息时间";

      if("1".equals(mWay)){
      mWay ="天";
      daycount=6;
      }else if("2".equals(mWay)){
      mWay ="一";
      daycount=0;
      }else if("3".equals(mWay)){
      mWay ="二";
      daycount=1;
      }else if("4".equals(mWay)){
      mWay ="三";
      daycount=2;
      }else if("5".equals(mWay)){
      mWay ="四";
      daycount=3;
      }else if("6".equals(mWay)){
      mWay ="五";
      daycount=4;
      }else if("7".equals(mWay)){
      mWay ="六";
      daycount=5;
      }
      Timestring=mYear + "年" + mMonth + "月" + mDay+"日"+"星期"+mWay;

      FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
      fab.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      Snackbar.make(view, "今天是"+Timestring+"\n"+nowtime+" "+interesting[daycount], Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      }
      });
      +

      在GitHub上学到的

      +

      此外还尝试引用了其他的一些GitHub库,学习了许多,包括调色盘,摇一摇模块,fir更新模块,滑动卡片界面等等 +部分GitHub repository链接在这里 - 滑动卡片界面:Android-SwipeToDismiss +- fir更新模块:UpdateDemo

      +

      还有一些直接写在代码里了,忘记原地址了.... - 摇一摇的传感器调用 +

      public class ShakeService extends Service {
      public static final String TAG = "ShakeService";
      private SensorManager mSensorManager;
      public boolean flag=false;
      private ShakeBinder shakebinder= new ShakeBinder();
      private String htmlbody="";

      @Override
      public void onCreate() {
      // TODO Auto-generated method stub
      super.onCreate();
      mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
      Log.i(TAG,"Shake Service Create");
      }

      @Override
      public void onDestroy() {
      // TODO Auto-generated method stub
      flag=false;
      super.onDestroy();
      mSensorManager.unregisterListener(mShakeListener);
      }

      @Override
      public void onStart(Intent intent, int startId) {
      // TODO Auto-generated method stub
      super.onStart(intent, startId);
      Log.i(TAG,"Shake Service Start");
      }

      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
      // TODO Auto-generated method stub
      mSensorManager.registerListener(mShakeListener,
      mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
      //SensorManager.SENSOR_DELAY_GAME,
      50 * 1000); //batch every 50 milliseconds
      htmlbody=intent.getStringExtra("htmlbody");

      return super.onStartCommand(intent, flags, startId);
      }

      private final SensorEventListener mShakeListener = new SensorEventListener() {
      private static final float SENSITIVITY = 10;
      private static final int BUFFER = 5;
      private float[] gravity = new float[3];
      private float average = 0;
      private int fill = 0;

      @Override
      public void onAccuracyChanged(Sensor sensor, int acc) {
      }

      public void onSensorChanged(SensorEvent event) {
      final float alpha = 0.8F;

      for (int i = 0; i < 3; i++) {
      gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
      }

      float x = event.values[0] - gravity[0];
      float y = event.values[1] - gravity[1];
      float z = event.values[2] - gravity[2];

      if (fill <= BUFFER) {
      average += Math.abs(x) + Math.abs(y) + Math.abs(z);
      fill++;
      } else {
      Log.i(TAG, "average:"+average);
      Log.i(TAG, "average / BUFFER:"+(average / BUFFER));
      if (average / BUFFER >= SENSITIVITY) {
      handleShakeAction();//如果达到阈值则处理摇一摇响应
      }
      average = 0;
      fill = 0;
      }
      }
      };

      protected void handleShakeAction() {
      // TODO Auto-generated method stub
      flag=true;
      Toast.makeText(getApplicationContext(), "摇一摇成功", Toast.LENGTH_SHORT).show();
      Intent intent= new Intent();
      intent.putExtra("htmlbody",htmlbody);
      intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
      intent.setClassName(this,"thinkwee.buptroom.ShakeTestActivity");
      startActivity(intent);
      }

      @Override
      public IBinder onBind(Intent intent) {
      // TODO Auto-generated method stub
      return shakebinder;
      }
      class ShakeBinder extends Binder{

      }
      }

      +

      独立网络拉取,并使用多线程

        -
      • fine-tune时固定低层
      • -
      • translation language modeling
      • -
      • improving word alignment in fine-tuning
      • -
      • combine 5 pre-training tasks (monolingual and cross-lingual MLM, -translation language modeling, cross-lingual word recovery and -paraphrase classification)
      • -
    • +
    • 在之前的结构中网络拉取整合在欢迎界面的activity中,为了在主界面中添加刷新功能,随时调用网络拉取,我把网络拉取单独写成了一个类,需要的时候调用
    • +
    • 然而在欢迎界面中显示欢迎动画和网络拉取在两个独立的线程中(为了使得动画不卡顿),这样就出现了可能欢迎动画做完了进入主界面时网络拉取还没有完成,传不了拉取的内容到主界面,最后的解决方案是设置网络拉取2s超时,若没拉取到则传一个错误的参数到启动主界面的activity中,提示刷新 +
          webget = new Webget();
      webget.init(webView);
      HaveNetFlag = webget.WebInit();

      new Handler().postDelayed(new Runnable() {
      public void run() {
      //execute the task
      ImageView img = (ImageView) findViewById(R.id.welcomeimg);
      Animation animation = AnimationUtils.loadAnimation(WelcomeActivity.this, R.anim.enlarge);
      animation.setFillAfter(true);
      img.startAnimation(animation);
      }
      }, 50);

      new Handler().postDelayed(new Runnable() {
      public void run() {
      //execute the task
      WrongNet = webget.getWrongnet();
      HaveNetFlag = webget.getHaveNetFlag();
      htmlbody = webget.getHtmlbody();
      Log.i("welcome", "2HaveNetFlag: " + HaveNetFlag);
      Log.i("welcome", "2Wrongnet: " + WrongNet);
      Log.i("welcome", "2html: " + htmlbody);
      }
      }, 2000);

      new Handler().postDelayed(new Runnable() {

      @Override
      public void run() {
      Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);
      intent.putExtra("WrongNet", WrongNet);
      intent.putExtra("HtmlBody", htmlbody);
      startActivity(intent);
      WelcomeActivity.this.finish();

      }

      }, 2500);
      }
    ]]>
    - 自然语言处理 + Android - deep learning - natural language processing - bert + code + android
    @@ -4960,2287 +5038,1920 @@ class="math inline">\(L_{ij}\)是句子a的i号词和句子b的j号词的 - Future of Computing Salon - Reading Comprehension Session - /2018/10/13/compute-future/ - 去清华的FIT听了一次轻沙龙,介绍了关于机器阅读理解的一些进展,有趣的是上午九点演讲的博士还说有一个还没公开的工作:BERT,很牛逼,很有钱,八块p100训一年,结果十点半机器之心就发了报道,下午就知乎满天飞了,说NLP新的时代到来了...... -这个沙龙是一个系列,之后可能会有机器翻译、深度贝叶斯、迁移学习和知识图谱啥的,要是有时间的话再听再记录吧

    - -

    2018.10.13 机器阅读理解

    -
      -
    • 三场演讲,第一场是概述;第二场是当时在SQuAD2.0上拿到第一名的nlnet作者的presentation,国防科大和微软合作的成果;第三场是一位清华的博士,介绍了他关于开放领域问答中噪声过滤和信息集合的研究。
    • -
    -

    概述

    -
      -
    • 现在的阅读理解和人们所期望的人工智能阅读理解差了太多,研究者把阅读理解的过程分解成了任务,例如选词、选span、生成短文本。深度学习兴起之前都是一些手工设计特征,一些Pipiline的操作,使用深度学习之后就专注于输入到输出的端到端研究,绕过了很多阅读理解过程所需要的东西。
    • -
    • 以前的关于阅读理解的研究可以作为一个测试方法,检验模型对于词法、修辞、利用知识的能力。
    • -
    • 目前的大规模机器阅读理解数据集处于很低级的推断阶段,提到了一篇论文:Efficient -and Robust Question Answering from Minimal Context over -Documents。里面讲到如果用深度学习,只用你找出的span来训练,砍掉上下文,其实结果不会差很多,因此端到端的学习并没有“通读全文掌握大意”的过程,而是“你问什么我答什么,别问我为什么这么答,背的”。提到了东京大学一份工作,建立了对模型阅读理解能力的评价指标,30多项,包括消除歧义、指代消解等等,大而简单的数据集无法体现这些特征,而设计巧妙的数据集规模不够大。
    • -
    • 还提到了一篇关于衡量模型推断能力的论文,TOWARDS AI-COMPLETE QUESTION -ANSWERING:A SET OF PREREQUISITE TOY TASKS。
    • -
    • 工业上使用阅读理解所需要解决的问题:简化模型或者加速模型,介绍了诸如SKIM-RNN之类的技巧,虽然训练的时候会变复杂,但推断时能加速。论文:NEURAL -SPEED READING VIA SKIM-RNN
    • -
    • 现在NLP的迁移学习,预训练词嵌入或者预训练语言模型,用的最多最广泛的,比如Glove和Elmo,然后就提到了BERT,4亿参数,无监督,最重要的是其模型是双向设计,且充分训练了上层参数:BERT: -Pre-training of Deep Bidirectional Transformers for Language -Understanding.另外一种迁移学习是直接将某一任务中训练好的模块做其他任务,例如直接将seq2seq中训练好的encoder拿出来计算语义表示(深度学习本来就是表示学习),记得fast -Disan就直接一个函数返回句子的向量表示,也是类似的思想。
    • -
    • 最新的研究领域:open domain question-answering和learning to -ask。前者实际上是加了一个信息检索的过程,阅读理解所需要的相关语料是通过提问检索到的。后者是将回答任务反过来做提问,演讲者提到反向可以辅助阅读理解,且有一个工业上比较有用的设计:做检索时不用query和文档(或者文档关键词)相比较,而是和针对文档生成的提问相比较,相当于两个提问之间计算相似度。
    • -
    • 演讲者提到了他关于attention的一个观点:attention是从模型中筛选信息,不代表原模型没有表示出此信息的能力。
    • -
    • 介绍了当前比较流行的几个数据集,2015之前用MCTest、ProcessBank,15到17年之间用CNNDM、SQuAD、MS -MARCO,17年之后用TriviaQA、SQuAD2.0、CoQA、QuAC、HotpotQA。(然而文摘还在用CNNDM......)
    • -
    -

    NLNet

    + Notes for Computational Linguistics + /2018/11/16/coling/ + 计算语言学课程笔记 参考教材:Speech and Language Processing:An +Introduction to Natural Language Processing,Computational Linguistics, +and Speech Recognition 一些公式待修订

    +

    第二章:正则表达式与自动机

      -
    • 论文:Squad上可以看到,但是好像还没发?
    • -
    • NLNet的设计初衷是为了解决阅读理解问题中的鲁棒性和有效性,都是针对集成模型说的,所以NLNet是在集成模型的基础上加了一个蒸馏的过程,使用单模型提升效率,另外还有一个read -and -verify的过程来提升鲁棒性,所以在加入了对抗样本的SQuAD2.0数据集上表现优异,目前第一。在1.0上落后于四处碾压的BERT,但其实落后也不多。不过1.0版本中nlnet的ensemble版本要好于单模型版本,2.0中没有提交ensemble版本,就很迷......
    • -
    • 蒸馏的意思没太听明白,效果是12个模型压缩成一个模型,模型的结构完全相同,但是初始化不同。不是简单的选最优,单一的模型是训练出来的,论文里叫那12个模型为teacher,单一模型为student,student使用teacher训练的结果来指导训练。
    • -
    • 设计了一个read and -verify机制,在抽取出span回答问题之后还会根据该回答和问题计算一个置信度,置信度太低就认为是没有答案,也就是squad2.0里对抗样本的情况。感觉听下来就是有问题就加loss。
    • -
    • 听说一些选取特征的细节没有在论文中表出,而且最后用强化学习优化了一下模型?
    • +
    • 正则表达式:一种用于查找符合特定模式的子串或者用于以标准形式定义语言的工具,本章主要讨论其用于查找子串的功能。正则表达式用代数的形式来表示一些字符串集合。
    • +
    • 正则表达式接收一个模式,然后在整个语料中查找符合这个模式的子串,这个功能可以通过设计有限状态自动机实现。
    • +
    • 字符串看成符号的序列,所有的字符,数字,空格,制表符,标点和空格均看成符号。
    -

    Open Domain -QA噪声过滤和信息集合

    +

    基本正则表达式模式

      -
    • 论文(ACL 2018):Denoising Distantly Supervised Open-Domain -Question Answering
    • -
    • 这个噪声是指在检索文档的过程搜到了很多相关但提供的不是正确答案的文档,是对文档的过滤。这一步的过滤本来应该放在检索的过程里,但是作者最后也是用深度学习算概率加loss的方式解决了。
    • -
    • 去噪过程是一个document -selector,然后阅读理解是一个reader,作者认为对应于人做阅读理解的fast -skimming 和careful reading & summarizing。
    • -
    • 信息集合没太注意听,就是充分利用多篇文档的信息提取出答案
    • -
    -]]>
    - - 自然语言处理 - - - comprehension - NLI - -
    - - A summary of my Android apps:BuptRoom - /2017/01/16/buptroomreview/ - -

    简介

    -

    写了一个查询学校空闲教室的APP -拉取学校教务处网站的信息,分类显示,还加了一些杂七杂八的 -毕竟第一次写android,什么都想尝试一下 点这下载:BuptRoom repository地址:一个简单的北邮自习室查询系统 -完成第一个版本大概是3个周末 之后花了1个月陆陆续续更新了杂七杂八的 -很多东西写的不规范,也是临时查到了就用上 总结一下这次写App的经过:

    - -
    -i0IHL4.png - -
    -

    学习的内容

    +
  • 用双斜线表示正则表达式开始和结束(perl中的形式)
      -
    • Android基本架构,组件,生命周期
    • -
    • Fragment的使用
    • -
    • Java库与库之间的调用
    • -
    • Github的使用
    • -
    • 部署app
    • -
    • 图像处理的一些方法
    • -
    • 一个愚蠢的拉取网页内容的方式
    • -
    • GitHub第三方库的利用
    • -
    • 颜色方面的知识
    • -
    • Android Material Design
    • -
    • 简单的优化
    • -
    • 多线程与Handler
    • +
    • 查找子串,大小写敏感:/woodchuck/-> woodchuck
    • +
    • 用方括号代表取其中一个,或:/[Ww]oodchuck/->woodchuck or +Woodchuck
    • +
    • 方括号加减号,范围内取或:/[2-5]/->/[2345]
    • +
    • 插入符号放在左方括号后,代表模式中不出现后接的所有符号,取非: /^Ss/ +->既不是大写S也不是小写s
    • +
    • 问号代表之前的符号出现一个或不出现:/colou?r/->color or +colour
    • +
    • 星号代表之前的符号出现多个或不出现:/ba*/->b or ba or baa or +baaa......
    • +
    • 加号代表之前的符号出现至少一次:/ba+/->ba or baa or +baaa.......
    • +
    • 小数点代表通配符,与任何除了回车符之外的符号匹配:/beg.n/->begin +or begun or beg’n or .......
    • +
    • 锚符号,用来表示特定位置的子串,插入符号代表行首,美元符号代表行尾,,,perl将单词的定义为数字、下划线、字母的序列,不在其中的符号便可以作为单词的分界。
    • +
  • -

    解决的问题

    -

    主要解决了这么几个问题

    +

    析取、组合和优先

      -
    • Android6.0以上的版本貌似权限需要动态验证,现在写的只支持5.0及以下版本,用到的permisson:
    • +
    • 用竖线代表析取,字符串之间的或:/cat|dog/->cat or dog
    • +
    • 用圆括号代表部分析取(组合),圆括号内也可以用基本算符:/gupp(y|ies)/->guppy +or guppies
    • +
    • 优先级:圆括号>计数符>序列与锚>析取符
    -
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
    +

    高级算符

      -
    • 网页是jsp动态网页,不能简单地parse,最后采用在webview中loadurl,执行javascript命令,需下载jsoup-1.9.2.jar这个包添加到库文件中
    • +
    • 任何数字
    • +
    • :任何非数字字符
    • +
    • :任何字母、数字、空格
    • +
    • :与
    • +
    • :空白区域
    • +
    • :与
    • +
    • {n}:前面的模式出现n个
    • +
    • {n,m}:前面的模式出现n到m个
    • +
    • {n,}:前面的模式至少出现n个
    • +
    • :换行
    • +
    • 表格符
    -
    final class MyWebViewClient extends WebViewClient {
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    view.loadUrl(url);
    return true;
    }
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
    Log.d("WebView","onPageStarted");
    super.onPageStarted(view, url, favicon);
    }
    public void onPageFinished(WebView view, String url) {
    Log.d("WebView","onPageFinished ");
    view.loadUrl("javascript:window.handler.getContent(document.body.innerHTML);");
    super.onPageFinished(view, url);
    }
    }
    +

    替换、寄存器

      -
    • 写一个handler响应javascript命令,这样在content中就拿到String形式的html文件中body内容
    • +
    • 替换s/A/B/:A替换成B
    • +
    • s/(A)/<\1>/:用数字算符\1指代A,在A的两边加上尖括号
    • +
    • 在查找中也可以用数字算符,指代圆括号内内容,可以多个算符指代多个圆括号内内容
    • +
    • 这里数字算符起到了寄存器的作用
    -
    final  class JavascriptHandler{
    @JavascriptInterface
    public void getContent(String htmlContent){
    Log.i(Tag,"html content: "+htmlContent);
    document= Jsoup.parse(htmlContent);
    htmlstring=htmlContent;
    content=document.getElementsByTag("body").text();
    Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
    }
    }
    +

    有限状态自动机

      -
    • 之后是字符串处理,根据教务处给的格式精简分类
    • -
    -
    去逗号
    String contenttemp=content;
    content="";
    String[] contentstemp=contenttemp.split(",");
    for (String temp:contentstemp){
    content=content+temp;
    }

    分组
    contents=content.split(" |:");
    String showcontent="";
    count=0;
    int tsgflag=0;
    int cishu=0;
    j12.clear();
    j34.clear();
    j56.clear();
    j78.clear();
    j9.clear();
    j1011.clear();
    if (keyword.contains("图书馆")) tsgflag=1;
    for (String temp:contents){
    if (temp.contains(keyword)){
    cishu++;
    SaveBuidlingInfo(count,cishu,tsgflag);
    }
    count++;
    }

    SaveBuildingInfo是按教学楼分类存取一天教室,其中再按时间段分类存到j12,j34.....
    while (1 == 1) {
    if (contents[k].contains("楼") || contents[k].contains("节") || contents[k].contains("图"))
    break;
    ;
    switch (c) {
    case 1:
    j12.add(contents[k]);
    break;
    case 2:
    j34.add(contents[k]);
    break;
    case 3:
    j56.add(contents[k]);
    break;
    case 4:
    j78.add(contents[k]);
    break;
    case 5:
    j9.add(contents[k]);
    break;
    case 6:
    j1011.add(contents[k]);
    break;
    default:
    break;
    }
    k++;
    }
    +
  • 有限状态自动机和正则表达式彼此对称,正则表达式是刻画正则语言的一种方法。正则表达式、正则语法和自动状态机都是表达正则语言的形式。FSA用有向图表示,圆圈或点代表状态,箭头或者弧代表状态转移,用双圈表示最终状态,如下图表示识别/baa+!/的状态机图: +
  • +
  • 状态机从初始状态出发,依次读入符号,若满足条件,则进行状态转移,若读入的符号序列满足模式,则状态机可以到达最终状态;若符号序列不满足模式,或者自动机在某个非最终状态卡住,则称自动机拒绝了此次输入。
  • +
  • 另一种表示方式是状态转移表: FoVqNn.png
  • +
  • 一个有限自动机可以用5个参数定义:
      -
    • 界面上套了一个NavigationView,没有什么特别设计的,因为没有设置多界面,就靠刷新TextView来伪装多个界面

    • -
    • 尝试了MaterialDesign组件,加入一点系统时间方面的东西

    • +
    • \(Q\):状态{q_i}的有限集合
    • +
    • :有限的输入符号字母表
    • +
    • \(q_0\):初始状态
    • +
    • \(F\):终极状态集合
    • +
    • \(\delta +(q,i)\):状态之间的转移函数或者转移矩阵,是从\(Q × \Sigma\)\(2^Q\)的一个关系
    • +
  • +
  • 以上描述的自动机是确定性的,即DFSA,在已知的记录在状态转移表上的状态时,根据查表自动机总能知道如何进行状态转移。算法如下,给定输入和自动机模型,算法确定输入是否被状态机接受: +
  • +
  • 当出现了表中没有的状态时自动机就会出错,可以添加一个失败状态处理这些情况。
  • -
    final Calendar c = Calendar.getInstance();
    c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
    mYear = String.valueOf(c.get(Calendar.YEAR)); // 获取当前年份
    mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
    mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
    mWay = String.valueOf(c.get(Calendar.DAY_OF_WEEK));
    mHour= c.get(Calendar.HOUR_OF_DAY);
    mMinute= c.get(Calendar.MINUTE);

    if (mHour>=8&&mHour<10){
    nowtime="现在是一二节课";
    }else
    if (mHour>=10&&mHour<12){
    nowtime="现在是三四节课";
    }else
    if ((mHour==13&&mMinute>=30)||(mHour==14)||(mHour==15&&mMinute<30)){
    nowtime="现在是五六节课";
    }else
    if ((mHour==15&&mMinute>=30)||(mHour==16)||(mHour==17&&mMinute<30)){
    nowtime="现在是七八节课";
    }else
    if ((mHour==17&&mMinute>=30)||(mHour==18&&mMinute<30)){
    nowtime="现在是第九节课";
    }else
    if ((mHour==18&&mMinute>=30)||(mHour==19)||(mHour==20&&mMinute<30)){
    nowtime="现在是十、十一节课";
    }else
    nowtime="现在是休息时间";

    if("1".equals(mWay)){
    mWay ="天";
    daycount=6;
    }else if("2".equals(mWay)){
    mWay ="一";
    daycount=0;
    }else if("3".equals(mWay)){
    mWay ="二";
    daycount=1;
    }else if("4".equals(mWay)){
    mWay ="三";
    daycount=2;
    }else if("5".equals(mWay)){
    mWay ="四";
    daycount=3;
    }else if("6".equals(mWay)){
    mWay ="五";
    daycount=4;
    }else if("7".equals(mWay)){
    mWay ="六";
    daycount=5;
    }
    Timestring=mYear + "年" + mMonth + "月" + mDay+"日"+"星期"+mWay;

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    Snackbar.make(view, "今天是"+Timestring+"\n"+nowtime+" "+interesting[daycount], Snackbar.LENGTH_SHORT)
    .setAction("Action", null).show();
    }
    });
    -

    在GitHub上学到的

    -

    此外还尝试引用了其他的一些GitHub库,学习了许多,包括调色盘,摇一摇模块,fir更新模块,滑动卡片界面等等 -部分GitHub repository链接在这里 - 滑动卡片界面:Android-SwipeToDismiss -- fir更新模块:UpdateDemo

    -

    还有一些直接写在代码里了,忘记原地址了.... - 摇一摇的传感器调用 -

    public class ShakeService extends Service {
    public static final String TAG = "ShakeService";
    private SensorManager mSensorManager;
    public boolean flag=false;
    private ShakeBinder shakebinder= new ShakeBinder();
    private String htmlbody="";

    @Override
    public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    Log.i(TAG,"Shake Service Create");
    }

    @Override
    public void onDestroy() {
    // TODO Auto-generated method stub
    flag=false;
    super.onDestroy();
    mSensorManager.unregisterListener(mShakeListener);
    }

    @Override
    public void onStart(Intent intent, int startId) {
    // TODO Auto-generated method stub
    super.onStart(intent, startId);
    Log.i(TAG,"Shake Service Start");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    // TODO Auto-generated method stub
    mSensorManager.registerListener(mShakeListener,
    mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
    //SensorManager.SENSOR_DELAY_GAME,
    50 * 1000); //batch every 50 milliseconds
    htmlbody=intent.getStringExtra("htmlbody");

    return super.onStartCommand(intent, flags, startId);
    }

    private final SensorEventListener mShakeListener = new SensorEventListener() {
    private static final float SENSITIVITY = 10;
    private static final int BUFFER = 5;
    private float[] gravity = new float[3];
    private float average = 0;
    private int fill = 0;

    @Override
    public void onAccuracyChanged(Sensor sensor, int acc) {
    }

    public void onSensorChanged(SensorEvent event) {
    final float alpha = 0.8F;

    for (int i = 0; i < 3; i++) {
    gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
    }

    float x = event.values[0] - gravity[0];
    float y = event.values[1] - gravity[1];
    float z = event.values[2] - gravity[2];

    if (fill <= BUFFER) {
    average += Math.abs(x) + Math.abs(y) + Math.abs(z);
    fill++;
    } else {
    Log.i(TAG, "average:"+average);
    Log.i(TAG, "average / BUFFER:"+(average / BUFFER));
    if (average / BUFFER >= SENSITIVITY) {
    handleShakeAction();//如果达到阈值则处理摇一摇响应
    }
    average = 0;
    fill = 0;
    }
    }
    };

    protected void handleShakeAction() {
    // TODO Auto-generated method stub
    flag=true;
    Toast.makeText(getApplicationContext(), "摇一摇成功", Toast.LENGTH_SHORT).show();
    Intent intent= new Intent();
    intent.putExtra("htmlbody",htmlbody);
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(this,"thinkwee.buptroom.ShakeTestActivity");
    startActivity(intent);
    }

    @Override
    public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return shakebinder;
    }
    class ShakeBinder extends Binder{

    }
    }

    -

    独立网络拉取,并使用多线程

    +

    形式语言

      -
    • 在之前的结构中网络拉取整合在欢迎界面的activity中,为了在主界面中添加刷新功能,随时调用网络拉取,我把网络拉取单独写成了一个类,需要的时候调用
    • -
    • 然而在欢迎界面中显示欢迎动画和网络拉取在两个独立的线程中(为了使得动画不卡顿),这样就出现了可能欢迎动画做完了进入主界面时网络拉取还没有完成,传不了拉取的内容到主界面,最后的解决方案是设置网络拉取2s超时,若没拉取到则传一个错误的参数到启动主界面的activity中,提示刷新 -
          webget = new Webget();
      webget.init(webView);
      HaveNetFlag = webget.WebInit();

      new Handler().postDelayed(new Runnable() {
      public void run() {
      //execute the task
      ImageView img = (ImageView) findViewById(R.id.welcomeimg);
      Animation animation = AnimationUtils.loadAnimation(WelcomeActivity.this, R.anim.enlarge);
      animation.setFillAfter(true);
      img.startAnimation(animation);
      }
      }, 50);

      new Handler().postDelayed(new Runnable() {
      public void run() {
      //execute the task
      WrongNet = webget.getWrongnet();
      HaveNetFlag = webget.getHaveNetFlag();
      htmlbody = webget.getHtmlbody();
      Log.i("welcome", "2HaveNetFlag: " + HaveNetFlag);
      Log.i("welcome", "2Wrongnet: " + WrongNet);
      Log.i("welcome", "2html: " + htmlbody);
      }
      }, 2000);

      new Handler().postDelayed(new Runnable() {

      @Override
      public void run() {
      Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);
      intent.putExtra("WrongNet", WrongNet);
      intent.putExtra("HtmlBody", htmlbody);
      startActivity(intent);
      WelcomeActivity.this.finish();

      }

      }, 2500);
      }
    • +
    • 形式语言是一个模型,能且只能生成和识别一些满足形式语言定义的某一语言的符号串。形式语言是一种特殊的正则语言。通常使用形式语言来模拟自然语言的某些部分。以上例/baa+!/为例,设对应的自动机模型为m,输入符号表\(\Sigma = {a,b,!}\)\(L(m)\)代表由m刻画的形式语言,是一个无限集合\({baa!,baaa!,baaaa!,…}\)
    -]]>
    - - Android - - - code - android - -
    - - Study Notes for CS224w - /2020/03/30/cs224w/ - Jure Leskovec, Stanford CS224W: Machine Learning with -Graphs学习笔记,未完待续

    -

    网络、随机图的属性

    -
      -
    • degree distribution:P(k) +

      非确定有限自动机

        -
      • 即节点度的分布
      • -
    • -
    • path length:h +
    • 非确定的有限自动机NFSA,把之前的例子稍微改动,自返圈移动到状态2,就形成了NFSA,因为此时在状态2,输入a,有两种转移可选,自动机无法确定转移路径: +
    • +
    • 另一种NFSA的形式是引入\(\epsilon\)转移,即不需要输入符号也可以通过此\(\epsilon\)转移进行转移,如下图,在状态3时依然不确定如何进行转移: +
    • +
    • 在NFSA时,面临转移选择时自动机可能做出错误的选择,此时存在三种解决方法:
        -
      • path:即路径,可以与自己相交并通过同一条边多次
      • -
      • distance:两点之间最短路径
      • -
      • diameter:一个图的直径即该图上任意两点最短路径的最大值
      • -
      • average path length:distance之和除以节点对数量
      • +
      • 回退:标记此时状态,当确定发生错误选择之后,回退到此状态
      • +
      • 前瞻:在输入中向前看,帮助判定进行选择
      • +
      • 并行:并行的进行所有可能的转移
    • -
    • clustering coefficient:C +
    • 在自动机中,采用回退算法时需要标记的状态称为搜索状态,包括两部分:状态节点和输入位置。对于NFSA,其状态转移表也有相应改变,如图,添加了代表\(\epsilon\)转移的\(\epsilon\)列,且转移可以转移到多个状态: +
    • +
    • 采用回退策略的非确定自动机算法如下,是一种搜索算法: FoZSuF.png
    • +
    • 子函数GENERATE-NEW-STATES接受一个搜索状态,提取出状态节点和输入位置,查找这个状态节点上的所有状态转移可能,生成一个搜索状态列表作为返回值;
    • +
    • 子函数ACCEPT-STATE接受一个搜索状态,判断是否接受,接受时的搜索状态应该是最终状态和输入结束位置的二元组。
    • +
    • 算法使用进程表(agenda)记录所有的搜索状态,初始只包括初始的搜索状态,即自动机初始状态节点和输入起始。之后不断循环,从进程表中调出搜索状态,先调用ACCEPT-STATE判断是否搜索成功,之后再调用GENERATE-NEW-STATES生成新的搜索状态加入进程表。循环直到搜索成功或者进程表为空(所有可能转移均尝试且未成功)返回拒绝。
    • +
    • 可以注意到NFSA算法就是一种状态空间搜索,可以通过改变搜索状态的顺序提升搜索效率,例如用栈实现进程表,进行深度优先搜索DFS;或者使用队列实现进程表,进行宽度优先搜索BFS。
    • +
    • 对于任何NFSA,存在一个完全等价的DFSA。
    • +
    +

    正则语言和NFSA

      -
    • 衡量了节点的邻居的连接状况:邻居之间相连的边数除以节点的度: \[ -C_{i}=\frac{2 e_{i}}{k_{i}\left(k_{i}-1\right)} -\]
    • -
    -
  • connected components +
  • 定义字母表为所有输入符号集合;空符号串\(\epsilon\),空符号串不包含再字母表中;空集∅。在上的正则语言的类(或者正则集)可以形式的定义如下:
      -
    • largest component(giant -component)的size称为connectivity,即最大连通子图的节点数
    • +
    • ∅是正则语言
    • +
    • ∀a ∈ \(\sum\)\(\epsilon\),{a}是形式语言
    • +
    • 如果\(L_1\)\(L_2\)是正则语言,那么:
    • +
    • \(L_1\)\(L_2\)的拼接是正则语言
    • +
    • \(L_1\)\(L_2\)的合取、析取也是正则语言
    • +
    • \(L_1\)^*,即\(L_1\)的Kleene闭包也是正则语言
  • -
  • Random Graph Model +
  • 可见正则语言的三种基本算符:拼接、合取及析取、Kleene闭包。任何正则表达式可以写成只使用这三种基本算符的形式。
  • +
  • 正则语言对以下运算也封闭(\(L_1\)\(L_2\)均为正则语言):
      -
    • 将图看成随机过程生成的结果,两个参数,n,p,即总共n个节点,每条边独立同分布按概率p建立,显然这两个参数不足以唯一确定一个图,考虑这样一个图上的degree -distribution, path length以及clustering coefficient
    • -
    • P(k): \[ -P(k)=\left(\begin{array}{c} -n-1 \\ -k -\end{array}\right) p^{k}(1-p)^{n-1-k} -\]
    • -
    • h:Olog(n)
    • -
    • C: \[ -=\frac{p \cdot -k_{i}\left(k_{i}-1\right)}{k_{i}\left(k_{i}-1\right)}=p=\frac{\bar{k}}{n-1} -\approx \frac{\bar{k}}{n} -\]
    • -
    • connectivity:随着p的增大,图越来越可能出现连接子图,具体如下: GuQgQf.png
    • +
    • 交:\(L_1\)\(L_2\)的符号串集合的交构成的语言也是正则语言
    • +
    • 差:\(L_1\)\(L_2\)的符号串集合的差构成的语言也是正则语言
    • +
    • 补:不在\(L_1\)的符号串集合中的集合构成的语言也是正则语言
    • +
    • 逆:\(L_1\)所有符号串的逆构成的集合构成的语言也是正则语言
  • -
  • small world model +
  • 可以证明正则表达式和自动机等价,一个证明任何正则表达式可以建立对应的自动机的方法是,根据正则语言的定义,构造基础自动机代表\(\epsilon\)、∅以及\(\sum\)中的单个符号a,然后将三种基本算符表示为自动机上的操作,归纳性的,在基础自动机上应用这些操作,得到新的基础自动机,这样就可以构造满足任何正则表达式的自动机,如下图: +FoVxjU.png +基础自动机 拼接算符 FoZ9HJ.png +Kleene闭包算符 合取析取算符
  • + +

    第三章:形态学与有限状态转录机

      -
    • 在内聚程度很高的图上依然有很短的直径
    • -
    • 如何构造这样的图?首先以高内聚长直径的图作为起始图,在其中引入shortcut就可以了: -
    • -
    -
  • Kronecker graphs:递归的产生 large realistic graphs
  • +
  • 剖析:取一个输入并产生关于这个输入的各类结构
  • -

    图的特征:纹理、子图、小图

    +

    英语形态学概论

      -
    • 子图,以三个节点构成的子图为例: Gu8hj0.png
    • -
    • 这里假设所有的节点都是相同的,子图只关注节点和边构成的结构特征。假如用一个significance来衡量每个子图,那么就可以构建一个feature -vector。
    • -
    • 定义纹理:motifs,“recurring, significant patterns of -interconnections”,即图中出现很多次,具有显著程度(More frequent than -expected, i.e., in randomly generated networks)的Small induced -subgraph
    • -
    • 通过某一个motifs在真实图和随机图中的出现次数之比就可以定义这个motifs的significance: -\[ -Z_{i}=\left(N_{i}^{\mathrm{real}}-\bar{N}_{i}^{\mathrm{rand}}\right) / -\operatorname{std}\left(N_{i}^{\mathrm{rand}}\right) -\]
    • -
    • RECAP算法:找出一个图的motifs, +
    • 形态学研究词的构成,词可以进一步拆解为语素,语素可分为词干和词缀,词缀可分为前缀、中缀、后缀、位缀。
    • +
    • 屈折形态学:英语中,名词只包括两种屈折变化:一个词缀表示复数,一个词缀表示领属:
        -
      • 根据真实图,定义一个随机图,其拥有和真实图一样的节点数、边数和度分布
      • -
      • 找出每一个子图在真实图和其对应的随机图上的significance,那么significance大的subgraph就是motifs
      • +
      • 复数:-s,-es,不规则复数形式
      • +
      • 领属:-‘s,-s’
    • -
    • 小图(graphlet):节点特征向量,graphlet的定义:connected -non-isomorphic -subgraphs,在graphlet中,我们灌注node-level的特征,例如三个节点只有两种graphlet,即三角形或者一条直线连接三个点。在三角形中,每个节点是等价的(相对于graphlet中其他节点而言),而在一条直线中,两端的节点等价,中间的节点是另一类。graphlet非常稀疏,n=10的graphlet有11716571种,且不算其中不同类的节点。
    • -
    • 将度的概念泛化,Graphlet degree -vector(GDV)指一个节点接触到的graphlet,每一类占一个feature,值为接触到的这一类graphlet的数量: -
    • -
    • GDV衡量了节点的局部拓扑状态
    • -
    • 寻找graphlet/motifs:三类算法 +
    • 动词的屈折变化包括规则动词和非规则动词的变化:
        -
      • Exact subgraph enumeration (ESU) [Wernicke 2006]
      • -
      • Kavosh [Kashani et al. 2009]
      • -
      • Subgraph sampling [Kashtan et al. 2004]
      • +
      • 规则动词:主要动词和基础动词,-s,-ing,-ed,
      • +
      • 非规则动词
    • -
    • 图的同构:如何判断两个图是topologically equivalent的? +
    • 派生形态学:派生将词干和一个语法语素结合起来,形成新的单词
        -
      • 定义roles:节点在图中所起的功能,通过结构信息来衡量,比如可以认为星型子图的中心节点具有相似的功能,或者直接归为一类功能,因此role也可以定义为A -collection of nodes which have similar positions in a -network。其和communities的区别:同一类role之间并不需要结构上互相连接或者有一定程度上的间接交互,而是他们在邻域结构内处于相同的位置
      • -
      • 那么可以定义节点级别的structurally equivalent: Nodes are -structurally equivalent if they have the same relationships to all other -nodes
      • -
      • 如何发现role?ROIX算法 GuUd3Q.png
      • -
      • recursive feature extraction:构建一些base -feature,然后不断的aggregate不断的迭代,例如取mean,取sum,再通过相关性剪枝
      • -
      • role extraction,实际上是一个矩阵的分解,将role看成latent -topic?:RolX uses non negative matrix factorization for clustering, MDL -for model selection, and KL divergence to measure likelihood。
      • +
      • 名词化:-ation,-ee,-er,-ness
      • +
      • 派生出形容词:-al,-able,-less
    -

    图谱聚类

    +

    形态剖析

      -
    • 三步走 +
    • 例子:我们希望建立一个形态剖析器,输入单词,输出其词干和有关的形态特征,如下表,我们的目标是产生第二列和第四列: +
    • +
    • 我们至少需要:
        -
      • 预处理:得到一个能够包含整图信息的矩阵
      • -
      • 分解:做特征分解,将每个节点映射到低维嵌入
      • -
      • 分组:根据低维嵌入做聚类
      • +
      • 词表(lexicon):词干和词缀表及其基本信息
      • +
      • 形态顺序规则(morphotactics):什么样的语素跟在什么样的语素之后
      • +
      • 正词法规则(orthographic rule):语素结合时拼写规则的变化
    • -
    • 定义问题: graph -partition,即将图的节点分为几个互不相交的集合,一个好的划分应该保证集合内节点之间的连接尽量多,集合之间节点之间的连接尽量少。
    • -
    • 定义cut(A,B)为AB两个集合节点之间的连接权重之和,那么最小切就是使得cut(A,B)最小的AB划分
    • -
    • 如何再考虑上AB集合内部的连接,定义vol(A)为A内部节点的度加权之和,那么可以得到衡量partition的一个指标Conductance: -\[ -\phi(A, B)=\frac{\operatorname{cut}(A, B)}{\min (\operatorname{vol}(A), -\operatorname{vol}(B))} -\]
    • -
    • 找到一个好的partition是np-hard
    • -
    • 基于图谱的划分: +
    • 一般不直接构造词表,而是根据形态顺序规则,设计FSA对词干进行屈折变化生成词语。例如一个名词复数化的简单自动机如下图: +
    • +
    • 其中reg-noun代表规则名词,可以通过加s形成复数形式,并且忽略了非规则单数名词(irreg-sg-noun)和非规则复数名词(irreg-pl-noun)。另外一个模拟动词屈折变化的自动机如下图: +
    • +
    • 使用FSA解决形态识别问题(判断输入符号串是否合法)的一种方法是,将状态转移细分到字母层次,但是这样仍然会存在一些问题: +
    • +
    +

    有限状态转录机

      -
    • 我们定义A为无向图的邻接矩阵,x为节点相关的向量,那么Ax得到就是邻域求和的结果 -\[ -y_{i}=\sum_{j=1}^{n} A_{i j} x_{j}=\sum_{(i, j) \in E} x_{j} -\]
    • -
    • 我们定义"spectrum of -graph",即图谱为A的特征向量构成的矩阵,按特征值\(\lambda\)大小排序,\(Ax=\lambda x\)
    • -
    • 那么假设图是d-regular,即所有节点的度都是d,那么很容易得到\(\lambda = d, -x=(1,1,...,1)\)是该图的一组特征值/特征向量,且可以证明d是最大的特征值
    • -
    • 假如图是有两个连通分量,分别都是d-regular,那么对应的特征值依然是d,对应的特征向量有两个,分别是A分量里的节点置1,B置0以及vice -versa
    • -
    • 这样根据node eigen -vector的分量是1还是0就可以做一个划分,将节点分为两部分。显然两个d-regular的分量,用少数几条边连接起来,这应该是整图的一个好的划分。
    • -
    • 那么现在假设存在一个好的划分,整图是一个d-regular的图(这样两个分量就不是d-regular了,因为要考虑划分之间的连接所有节点的度才为d),分量之间有很少的连接。我们已知一个特征向量是全1的,且对应着最大的特征值d,那么直觉上第二大的特征值应该和d非常接近,因为我们知道断开的两个分量构成的图最大的特征值也为d,现在的图跟断开的图差别不是很大。而且由于特征向量之间相互正交而已知一个特征向量是全1,那么第二大的特征值对应的特征向量应该和为1,有正有负。类比于断开成两个分量的场景,我们也可以根据特征向量中分量的正负来划分节点。当然这都是直觉上的推测,下面引入Laplacian矩阵来详细说明。
    • -
    • 邻接矩阵的性质:n*n方阵,对称,n个实特征值,特征向量相互正交
    • -
    • 再定义度矩阵D,这是一个对角阵,第i个对角值存储第i个节点的度
    • -
    • 定义Laplacian矩阵,\(L=D-A\),显然\(\lambda = 0, -x=(1,1,...,1)\)是该图的一组特征值/特征向量。L矩阵的一些性质包括: +
    • 双层形态学:将一个词表示为词汇层和表层,词汇层表示该词语素之间的简单毗连(拼接,concatenation),表层表示单词实际最终的拼写,有限状态转录机是一种有限状态自动机,但其实现的是转录,实现词汇层和表层之间的对应,它有两个输入,产生和识别字符串对,每一个状态转移的弧上有两个标签,代表两个输入。 +
    • +
    • 从四个途径看待FST:
        -
      • 所有特征值非负
      • -
      • 半正定
      • -
      • 可以分解为\(N^TN\)
      • -
      • 实际上三个性质是等价的
      • -
    • -
    • 那么L矩阵的二次型的含义是什么? \[ -\begin{array}{l} -x^{T} L x=\sum_{i, j=1}^{n} L_{i j} x_{i} x_{j}=\sum_{i, -j=1}^{n}\left(D_{i j}-A_{i j}\right) x_{i} x_{j} \\ -=\sum_{i} D_{i i} x_{i}^{2}-\sum_{(i, j) \in E} 2 x_{i} x_{j} \\ -=\sum_{(i, j) \in E_{1}}\left(x_{i}^{2}+x_{j}^{2}-2 x_{i} -x_{j}\right)=\sum_{(i, j) \in E}\left(x_{i}-x_{j}\right)^{2} -\end{array} -\]
    • -
    • 可以证明,二次型等价于矩阵的特征值加权x在对应特征向量上的坐标的平方求和 -\[ -x = \sum _{i=1}^n \alpha _i w_i \\ -x^TMx = \sum _i \lambda _i \alpha _i^2 \\ -\]
    • -
    • 回到我们要找第二大的特征值,可以证明,对于对称阵: \[ -\lambda_{2}=\min _{x: x^{T} w_{1}=0} \frac{x^{T} M x}{x^{T} x} \\ -\left(\mathbf{w}_{1} \text { is eigenvector corresponding to } -\lambda_{1}\right) \\ -\]
    • -
    • 当这个对称阵是L矩阵时,有 \[ -\lambda _ 2 = min \frac{\sum _{i,j \in E}(x_i - x_j)^2}{\sum _i x_i^2} -\\ -\sum x_i = 0 \\ -\]
    • -
    • 根据Fiedler'73的寻找最佳划分的方法,令节点label为1,-1来表示划分,所有节点求和为0来强制两个划分的集合大小一致,其提出的最佳划分是 -\[ -\arg \min _{y \in\{-1,+1\}^{n}} f(y)=\sum_{(i, j) \in -E}\left(y_{i}-y_{j}\right)^{2} -\]
    • -
    • 可以发现将其label的限制从离散的1,-1放宽到实数值之后,等价于我们找L矩阵的第二大特征值和特征向量,第二特征值对应的特征向量分量的正负决定了划分情况(节点的分配情况)
    • +
    • 作为识别器:FST接受一对字符串,作为输入,如果这对字符串在语言的字符串对中则输出接受否则拒绝
    • +
    • 作为生成器:生成语言的字符串对
    • +
    • 作为翻译器:读入一个字符串,输出另一个
    • +
    • 作为关联器:计算两个集合之间的关系
    -
  • 回到spectral clustering +
  • 定义有限状态转录机:
      -
    • 预处理:构建L矩阵
    • -
    • 分解:对L矩阵做特征分解,得到每个节点在第二大特征值对应的特征向量上的分量
    • -
    • 分组:将节点按分量大小排序,找一个切分值,大于切分值的划为一组,小于切分值的划为一组。怎么找切分值?naive的方法就是设为0,expensive的方法就是都试一遍,取最好的
    • -
    • 通过可视化结果可以看到最优切分能够很好的对应聚类,而且多类也是一样,存在明显的分量差异: -
    • -
    • 聚多类的两种方式:迭代式的聚类,每次聚两类;聚k类,找k个特征向量,而不仅仅是第二大的,然后相当于每个节点有k维特征,用k-means做聚类
    • -
    • 怎么确定聚几类?聚成k类时,第k大特征值和第k-1大特征值之间的差应该最大
    • +
    • Q:状态{q_i}的有限集合
    • +
    • :有限的输入符号字母表
    • +
    • ∆:有限的输出符号字母表
    • +
    • \(q_0 \in Q\):初始状态
    • +
    • \(F⊆Q\):终极状态集合
    • +
    • \(\delta +(q,w)\):状态之间的转移函数或者转移矩阵,是从Q×到2^Q的一个关系,q是状态,w是字符串,返回新状态集合
    • +
    • \(\sigma +(q,w)\):输出函数,给定每一个状态和输入,返回可能输出字符串的集合,是从\(Q × \Sigma\)\(2^∆\)的一个关系
  • -
  • 基于motifs的spectral clustering +
  • 在FST中,字母表的元素不是单个符号,而是符号对,称为可行偶对。类比于FSA和正则语言,FST和正则关系同构,对于并运算封闭,一般对于差、补、交运算不封闭。
  • +
  • 此外,FST,
      -
    • 当我们把边的概念升级到motifs时,就可以得到以motifs为特征的谱聚类
    • -
    • 同样的,我们可以得到基于motifs的Conductance,直接找也依然是NP-hard
    • -
    • 事实上,给定图G和motifs -M,可以构建一个新图,在新图上做谱聚类即可
    • -
    • 定义新图为\(W\),则\(W_{ij}^M\) = # times edge (i,j) -participates in the motif M
    • +
    • 关于逆反(逆的逆)闭包,逆反用于方便的实现作为剖析器的FST到作为生成器的FST的转换
    • +
    • 关于组合(嵌套)闭包,用于将多个转录机用一个更复杂的转录机替换。
  • +
  • 转录机一般是非确定性的,如果用FSA的搜索算法会很慢,如果用非确定性到确定性的转换算法,则有些FST本身是不可以被转换为为确定的。
  • +
  • 顺序转录机是一种输入确定的转录机,每个状态转移在给定状态和输入之后是确定的,不像上图中的FST,状态0在输入b时有两种状态转移(转移到相同的状态,但是输出不同)。顺序转录机可以使用\(\epsilon\)符号,但是只能加在输出字符串上,不能加在输入字符串上,如下图: +
  • +
  • 顺序转录机输出不一定是序列的,即从同一状态发出的不同转移可能产生相同输出,因此顺序转录机的逆不一定是顺序转录机,所以在定义顺序转录机时需要定义方向,且转移函数和输出函数需要稍微修改,输出空间缩小为Q和∆。
  • +
  • 顺序转录机的一种泛化形式是并发转录机,其在最终状态额外输出一个字符串,拼接到已经输出的字符串之后。顺序和并发转录机的效率高,且有有效的算法对其进行确定化和最小化,因此很重要。P并发转录机在此基础上可以解决歧义问题。
  • -

    消息传递和节点分类

    +

    用有限状态转录机进行形态剖析

      -
    • 在直推式学习中,已知图上部分节点的label,如何根据图的结构和已知节点,推断出其他节点的label?这就是半监督节点分类
    • -
    • 三种技术: +
    • 将单词看成词汇层和表层之间的关系,如下图: FoZnDe.png
    • +
    • 在之前双层形态学的基础定义上,定义自己到自己的映射为基本对,用一个字母表示;用^代表语素边界;用#代表单词边界,在任务中提到需要输出+SG之类的语素特征,这些特征在另一个输出上没有对应的输出符号,因此映射到空字符串或边界符号。我们把输入输出对用冒号连接,也可以写在弧的上下。一个抽象的表示英语名词复数屈折变化的转录机如下图: +
    • +
    • 之后我们需要更新词表,使得非规则复数名词能够被剖析为正确的词干: +
    • +
    • 之后将抽象的转录机写成具体的,由字母组成转移弧的转录机,如下图,只展示了具体化部分非规则复数和单数名词之后的转录机: +
    • +
    +

    转录机和正词法规则

      -
    • Relational classification
    • -
    • Iterative classification
    • -
    • Belief propagation
    • -
    -
  • 关键在于利用网络(图)当中的关系(边),有三种重要的关系 +
  • 用拼写规则,也就是正词法规则来处理英语中经常在语素边界发生拼写错误的问题。
  • +
  • 以下是一些拼写规则实例:
      -
    • Homophily: the tendency of individuals to associate and bond with -similar others
    • -
    • Influence: social connections can influence the individual -characteristics of a person
    • -
    • Confounding
    • +
    • 辅音重叠:beg/beggin
    • +
    • E的删除:make/making
    • +
    • E的插入:watch/watches
    • +
    • Y的替换:try/tries
    • +
    • K的插入:panic/panicked
  • -
  • 最直观的想法,相邻的节点具有相似的label
  • -
  • collective -classification做出了马尔可夫假设,即节点的分类只受其一阶邻居影响 +
  • 为了实现拼写规则,我们在词汇层和表层之间加入中间层,以符合特定规则的语素毗连作为输入,以修改之后的正确的语素毗连作为输出,例如fox ++N +PL输入到中间层即第一次转录,得到fox ^ s +#,之后中间层到表层的第二次转录检测到特殊语素毗连:x^和s#,就在表层的x和s之间插入一个e,得到foxes。下面的转录机示意图展示了这个过程: +
  • +
  • 这个转录机只考虑x^和s#毗连需插入e这一正词法规则
  • +
  • 其他的词能正常通过
  • +
  • \(Q_0\)代表无关词通过,是接受状态
  • +
  • \(Q_1\)代表看见了zsx,作为中间状态保存,一直保存的是最后的与语素毗连的z,s,x,如果出现了其他字母则返回到q0,其本身也可以作为接受态
  • +
  • \(Q_2\)代表看见了与z,s,x毗连的语素,这之后有四种转移
      -
    • load classifier:不使用网络信息,先根据节点特征做出分类
    • -
    • relational -classifier:学习到一个分类器,输入邻接节点的label和特征,输出中心节点的label
    • -
    • collective -inference:不断的传播网络的相关性,对每个节点迭代的使用relational -classifier
    • +
    • 接了\(x\),\(z\),回到\(q_1\),也就是认为重新接到了可能和语素毗连的x,z
    • +
    • 接了\(s\),分为两种情况,一种是正常需要插入e,这时通过\(\epsilon\)转移到\(q_3\)再到\(q_4\);另一种是本来就需要插入\(e\),这就到达\(q_5\),之后视情况回退了\(q_1\)\(q_0\),或者\(s\)又毗连语素回到\(q_2\)。两种情况不确定,需要通过搜索解决
    • +
    • 接单词边界和其他符号,回到\(q_0\)
    • +
    • \(q_2\)本身也可以作为接受态
  • -
  • 精确的推断是np-hard的,这里介绍三种近似推断的方法: + +

    结合

      -
    • Relational classification:对邻域节点的label概率加权求和 \[ -P\left(Y_{i}=c\right)=\frac{1}{\sum_{(i, j) \in E} W(i, j)} \sum_{(i, j) -\in E} W(i, j) P\left(Y_{j}=c\right) -\] 缺点:不保证收敛,且没有用到节点特征
    • -
    • Iterative -classification:先对每个节点初始化一个特征向量,训练一个分类器(用有gold -label的节点训练),输入特征向量输出Label,这是一个Local -classifier,不考虑网络结构。等到每个节点都预测了label之后,根据网络结构进行消息传递,更新节点的特征向量,然后再用local -classifier预测label,如此迭代。一篇应用论文REV2: -Fraudulent User Prediction in Rating Platforms
    • -
    • Belief propagation:基于动态规划的方法,"Belief Propagation is a -dynamic programming approach to answering conditional probability -queries in a graphical model" +
    • 现在可以通过三层结构,结合产生语素和进行正词法规则矫正的转录机。从词汇层到中间层用一个转录机产生语素,从中间层到表层可并行使用多个转录机进行正词法规则的矫正。
    • +
    • 两类转录机叠加时可以改写成一类转录机,这时需要对两类状态机状态集合计算笛卡尔积,对新集合内每一个元素建立状态。
    • +
    • 这种三层结构是可逆的,但是进行剖析时(从表层到词汇层)会出现歧义问题,即一个单词可能剖析出多种语素结合,这时单纯依靠转录机无法消歧,需要借助上下文。
    • +
    +

    其他应用(简单介绍)

      -
    • 定义label的矩阵\(\psi\),其定义了邻域节点label为i时,中心节点的label为j的概率\(\psi _{ij}\)
    • -
    • 给定每个节点的初始概率(先验)\(\phi\)
    • -
    • \(m_{i \rightarrow -j}\left(Y_{j}\right)\)代表i到j的belief,即邻居i对于节点j的label为\(Y_j\)的估计
    • -
    • 则有: GKoNtK.png -即每次我们根据先验、label的转移概率、上一轮邻域节点的信念更新这一轮的信念;收敛之后根据先验和最终的邻域信念就可以推断中心节点的label
    • -
    • 参考论文:Netprobe: A Fast and Scalable System for Fraud Detection -in Online Auction Networks Pandit et al., World Wide Web conference -2007
    • -
  • - +
  • 不需要词表的FST,PORTER词干处理器:将层叠式重写规则用FST实现,提取出单词的词干。
  • +
  • 分词和分句:一个简单的英文分词可以基于正则表达式实现,一个简单的中文分词可以通过maxmatch(一种基于最大长度匹配的贪婪搜索算法)实现。
  • +
  • 拼写检查与矫正:使用了投影操作的FST可以完成非词错误的检测,然后基于最小编辑距离(使用动态规划算法实现)可以矫正。正常词错误检测和矫正需借助N元语法模型。
  • -

    图表示学习

    +

    人如何进行形态处理

      -
    • 希望用无监督的方法学习到任务无关的节点通用特征
    • -
    • 和word -embedding一样,一个目标是,网络中相邻的节点,在embedding当中应该相似,因此框架是 +
    • 研究表明,人的心理词表存储了一部分形态机构,其他的结构不组合在心理词表中,而需要分别提取并组合。研究说明了两个问题:
        -
      • 定义一个编码器,将节点编码成embedding
      • -
      • 定义一个节点相似度函数
      • -
      • 优化编码器参数,使得\(similarity(u,v) -\approx z_v^Tz_u\)
      • +
      • 形态尤其是屈折变化之类的能产性形态在人的心理词表中起作用,且人的语音词表和正词法词表可能具有相同结构。
      • +
      • 例如形态这种语言处理的很多性质,可以应用于语言的理解和生成。
    • -
    • 最简单的方法:编码器只是一个embedding look -up,每个节点预先分配一个embedding -vector,例如DeepWalk,node2vec,TransE
    • -
    • 因此主要区别在于如何定义similarity
    • -
    • DeepWalk: +
    +

    第四章:N元语法

      -
    • 每次随机游走采样出固定长序列,希望游走出发点和序列中的点比较相似,因此这里similarity定义为随机游走序列中的共现
    • -
    • 优化目标是softmax之后的log-likelihood,和word -embedding一样,这里需要对所有节点计算来配分母,计算量太大,解决方案也是与word2vec类似,采用negative -sampling,只采样部分负样本,用Noise Contrastive -Estimation的目标函数来近似softmax之后的结果 GMWPvn.png
    • -
    • 假如我们对所有节点无差别的sample出一个定长的随机游走序列,那就是DeepWalk模型
    • -
    -
  • node2vec +
  • 语言模型是关于单词序列的统计模型,N元语法模型是其中的一种,它根据之前N-1个单词推测第N个单词,且这样的条件概率可以组成整个单词序列(句子)的联合概率。
  • + +

    在语料库中统计单词

      -
    • 同样是基于随机游走,node2vec在游走策略上做出了改进
    • -
    • 游走时不仅做dfs,还做bfs:前者获取Global macroscopic -view;后者获取Local microscopic view
    • -
    • node2vec在两者之间做了插值,定义参数q为Moving outwards (DFS) vs. -inwards (BFS)的比例,同时还定义了返回参数p,即返回到初始点
    • -
    • 具体的游走策略如下: GMfTOI.png
    • -
    -
  • TransE -
      -
    • 在知识图谱中,三元组(subject,predicate,object)表示了图中两个节点以及相连的边,都有feature -vector
    • -
    • TransE的目标是学习到所有实体节点和关系边的embedding,该算法将边解释为一种翻译,即predicate将subject翻译为Object
    • -
    • 数学表示就是简单的\(u_{subject} + -v_{predicate} = u_{object}\)
    • -
    • 训练采用了对比学习,采样负样本,用margin loss 区别:word type或者叫 vocabulary size +V,代表语料中不同单词的个数,而tokens,不去重,代表语料的大小。有研究认为词典大小不低于tokens数目的平方根。 +非平滑N元语法模型
    • +
    • 任务:根据以前的单词推断下一个单词的概率:\(P(w|h)\),以及计算整个句子的概率\(P(W)\)
    • +
    • 最朴素的做法是用古典概型,统计所有历史h和当前词w组成的片段在整个语料中出现的次数,并除以历史h片段在整个语料中出现的次数。句子的概率也用相似的方法产生。缺点:依赖大语料,且语言本身多变,这样的计算限制过于严格。
    • +
    • 接下来引入N元语法模型,首先通过概率的链式法则,可以得到条件概率\(P(w|h)\)和整个句子的联合概率\(P(W)\)之间的关系: \[ -\begin{aligned} -&\sum \quad \nabla\left[\gamma+d(\boldsymbol{h}+\ell, -\boldsymbol{t})-d\left(\boldsymbol{h}^{\prime}+\ell, -\boldsymbol{t}^{\prime}\right)\right]_{+}\\ -&\left((h, \ell, t),\left(h^{\prime}, \ell, t^{\prime}\right)\right) -\in T_{\text {batch}} \quad -\end{aligned} +P(w_1^n) = P(w_1)P(w_2|w_1)P(w_3|w_1^2)...P(w_n|w_1^{n-1}) \\ += \prod _{k=1}^n P(w_k|w_1^{k-1}) \\ \]
    • -
  • -
  • 如何embedding整张图? +
  • N元语法模型放松了条件概率的限制,做出一个马尔可夫假设:每个单词的概率只和它之前N-1个单词相关,例如二元语法模型,只和前一个单词相关,用这个条件概率去近似\(P(w|h)\): \[ +P(w_n|w_1^{n-1}) \approx P(w_n|w_{n-1}) \\ +\]
  • +
  • N元语法模型里的条件概率用最大似然估计来估算,统计语料中各种N元语法的个数,并归一化,其中可以简化的一点是:以二元语法为例,所有给定单词开头的二元语法总数必定等于该单词一元语法的计数: +\[ +P(w_n|w_{n-1}) = \frac {C(w_{n-1}w_n)}{C(w_{n-1})} \\ +\]
  • +
  • 使用N元语法之后,句子概率的链式分解变得容易计算,我们可以通过计算各种句子的概率来判断句子是否包含错字,或者计算某些句子在给定上下文中出现的可能,因为N元语法能捕捉一些语言学上的特征,或者一些用语习惯。在语料充足的时候,我们可以使用三元语法模型获得更好的效果。
  • + +

    训练集和测试集

      -
    • 最简单的方法:学到节点的embedding,然后所有节点做平均或者求和
    • -
    • 或者引入一个虚节点,其和所有节点相连接,然后跑node-level -embedding的方法,得到这个虚节点的embedding作为图的embedding,这种方法还可以得到子图的embedding
    • -
    • Anonymous Walk -Embedding:我们将节点匿名,用其在随机游走学列中第一次出现的index来代表,那么长度为3的游走序列就有111,112,121,122,123五种可能。那么就可以: +
    • N元语法模型对训练集非常敏感。N元语法的N越大,依赖的上下文信息越多,利用N元语法模型生成的句子就越流畅,但这些未必“过于流畅”,其原因在于N元语法概率矩阵非常大且非常稀疏,在N较大例如四元语法中,一旦生成了第一个单词,之后可供的选择非常少,接着生成第二个单词之后选择更少了,往往只有一个选择,这样生成的就和原文中某一个四元语法一模一样。过于依赖训练集会使得模型的泛化能力变差。因此我们选择的训练集和测试集应来自同一细分领域。
    • +
    • 有时候测试集中会出现训练集词典里没有的词,即出现未登录词(Out Of +Vocabulty,OOV)。在开放词典系统中,我们先固定词典大小,并将所有未登录词用特殊符号代替,然后才进行训练。
    • +
    +

    评价N元语法模型:困惑度

      -
    • 统计图中长度为l的所有序列,将图表示为匿名序列的特征向量,分量的值是该序列在图中出现的次数
    • -
    • 对每张图采样m个匿名序列,再统计特征向量
    • -
    • 学习到每个匿名序列的embedding,进而得到图的embedding。类似于语言模型,已知前n个匿名序列,预测第n+1个匿名序列,建立模型来学习参数
    • -
    +
  • 模型的评价分两种:外在评价和内在评价。外在评价是一种端到端的评价,看看某一模块的改进是否改进了整个模型的效果。内在评价的目的是快速衡量模块的潜在改进效果。内在评价的潜在改进效果不一定会使得端到端的外在评价提高,但是一般两者都存在某种正相关关系。
  • +
  • 困惑度(Perplexsity,PP)是一种关于概率模型的内在评价方法。语言模型的在测试集上的困惑度是语言模型给测试集分配的概率的函数。以二元语法为例,测试集上的困惑度为: +\[ +PP(W) = \sqrt[n]{\prod _{i=1}^N \frac {1}{P(w_i|w_{i-1})}} \\ +\]
  • +
  • 概率越高,困惑度越低。困惑度的两种解释: +
      +
    • 加权的平均分支因子:分支因子是指可能接在任何上文之后的单词的数目。显然,如果我们的模型啥也没学习到,那么测试集任何单词可以接在任何上文之后,分支因子很高,困惑度很高;相反,如果我们的模型学习到了具体的规则,那么单词被限制接在一些指定上文之后,困惑度变低。困惑度使用了概率加权分支因子,分支因子的大小在模型学习前后不变,”morning”仍然可以接到任何上文之后,但是它接到”good”之后的概率变大了,因此是加权的分支因子。
    • +
    • 熵:对于语言序列,我们定义一个序列的熵为: \[H(w_1,w_2,…,w_n )=-\sum _{W_1^n \in L} p(W_1^n) +\log +⁡p(W_1^n)\]也就是这个序列中所有前缀子序列的熵之和,其均值是序列的熵率。计算整个语言的熵,假设语言是一个产生单词序列的随机过程,单词序列无限长,则其熵率是:\[H(L)=\lim _{n \rightarrow \infty}⁡ \frac 1n +H(w_1,w_2,…,w_n) =\lim _{n \rightarrow \infty} -⁡\frac 1n \sum _{W \in L} +p(W_1^n) \log +⁡p(W_1^n)\]根据Shannon-McMillan-Breiman理论,在n趋于无穷的情况下,如果语言既是平稳又是正则的,上面这些子串的和的熵,可以用最大串代替每一个子串得到,这里的代替是指log后面求的是最大串的概率,log之前的概率依然是各个子串的概率?假如是这样的话提出最大串的概率对数,对所有子串概率求和得到:\[H(L)=\lim _{n \rightarrow \infty} -⁡ \frac 1n \log +⁡p(w_1,w_2,…,w_n)\]交叉熵可以衡量我们的模型生成的概率分布到指定概率分布之间的距离,我们希望模型生成概率分布尽可能近似真实分布,即交叉熵小。具体衡量时是对相同的语言序列,计算训练得到的模型m和理想模型p在生成这个序列上的概率的交叉熵:\[H(p,m) = \lim _{n \rightarrow \infty}⁡ - \frac 1n +\sum _{W \in L} p(W_1^n) \log⁡ +m(W_1^n)\]但是我们不知道理想的分布p,这时根据之前的Shannon-McMillan-Breiman定理,得到了只包含一个概率分布的序列交叉熵(?):\[H(p,m)=\lim _{n \rightarrow \infty}⁡ - \frac 1n +\log⁡ +m(W_1^n)\]在测试数据上我们没有无限长的序列,就用有限长的序列的交叉熵近似这个无限长序列的交叉熵。困惑度则是这个(近似的?只包含一个概率分布的?)交叉熵取指数运算: +\[ +Perplexity(W) = 2^{H(W)} \\ += P(w_1 w_2 ... w_N)^{\frac {-1}{N}} \\ += \sqrt[n]{\frac {1}{P(w_1 w_2 ... w_N)}} \\ += \sqrt[n]{\prod _{i=1}^N \frac {1}{P(w_i | w_1 ... w_{i-1})}} \\ +\]
  • -

    图神经网络

    +

    平滑

      -
    • 基于随机游走的方法其实是在similarity这部分做文章,在encoder这一块依然采用最简单的embedding -lookup
    • -
    • 图神经网络就为encoder引入了deep neural network
    • -
    • GCN +
    • 因为N元语法模型依赖语料,一般而言对于N越高的N元语法,语料提供的数据越稀疏。这种情况下N元语法对于那些计数很小的语法估计很差,且如果测试集中某一句包含了训练集中没有出现的N元语法时,我们无法使用困惑度进行评价。因此我们使用平滑作为一种改进方法,使得N元语法的最大似然估计能够适应这些存在0概率的情况。
    • +
    • 接下来介绍了两种平滑:
        -
      • idea:邻接关系定义了计算图,GCN利用图的结构来传播信息,更新节点的embedding
      • -
      • 通过aggregate邻域节点来生成node -embedding,aggregate的过程使用神经网络,每一个节点基于其邻接状态定义了一个计算图
      • -
      • 最简单的aggregate:收集邻域节点的embedding,做平均,然后当前节点embedding和邻域平均embedding做拼接输入一个神经网络,获得当前节点下一层的embedding: -
      • -
      • 这样就完成了encoder的定义,可以直接进行supervised -learning,也可以接上random walks里的各种无监督目标函数来训练node -embedding
      • -
      • 由于aggregate的参数在所有节点上共享,因此对于图上其他未知的节点也可以使用同一套encoder,新的一张图也可以。
      • +
      • 拉普拉斯平滑(加1平滑)
      • +
      • Good-Turing 打折法
    • -
    • GraphSage +
    +

    拉普拉斯平滑

      -
    • 在aggregate的形式上做了进一步扩展
    • -
    • 除了mean,其实任意的将多个embedding映射到一个embedding的函数都可以用来做聚合,例如pool,例如LSTM,
    • +
    • 加1平滑就是在计算概率归一化之前,给每个计数加1,对应的,归一化时分母整体加了一个词典大小: +\[ +P_{Laplace}(w_i) = \frac {c_i + 1}{N+V} \\ +\]
    • +
    • 为了表现平滑的作用,引入调整计数\(c^{*}\),将平滑后的概率写成和平滑之前一样的形式: +\[ +P_{Laplace} (w_i) = \frac {(C_i^{*})}{N} \\ +C_i^{*} = \frac {(C_i+1)N}{(N+V)} \\ +\]
    • +
    • 一种看待平滑的角度是:对每个非0计数打折,分一些概率给0计数,定义相对打折\(d_c\)(定义在非0计数上), \[ +d_c = \frac {c^{*}} {c} +\]
    • +
    • \(d_c\)代表了打折前后单词计数的变化。平滑之后,对于非0计数,当\(C_i < \frac +NV\)时,计数增加;否则计数减少。计数越大,打折越多,增加越少(减少越多)。当0计数很多时,N/V较小,这时大部分非0计数都会减少,且减少较多。
    • +
    • 而0计数则没有收到打折的影响。因此在一轮不同程度的增长之后,再归一化的结果就是非0计数分享了一些概率给0计数。写成调整计数的形式,就是非0计数减少数值,0计数变化(一般是减少)数值(但不是减少的完全等于增加的)。 +书中给出了一个例子,下图是一部分语料的二元语法平滑之后的计数,蓝色代表平滑加1之后的0计数: +FoZNDg.png +如果把表写成调整计数的形式: FoZtKS.png
    • +
    • 可以看到,本来的0计数(蓝色)从0变大,而其他的计数减少,例如< i +want>,从827减少到527,从608减少到238。
    • +
    • 当0计数很多时,非0计数减少的数值很多,可以使用一个小于1的小数\(\delta\)代替1,即加\(\delta\)平滑。通常这个\(\delta\)是动态变化的。
    • +
    +

    GT打折法

    +
      +
    • 类似于Good-Turing打折法, Witten-Bell打折法, Kneyser-Ney +平滑一类的方法,它们的基本动机是用只出现一次的事物的计数来估计从未出现的事物的计数。只出现一次的语法称为单件(singleton)或者罕见语(hapax +legomena)。Good-Turing打折法用单件的频率来估计0计数二元语法。
    • +
    • 定义N_c为出现c次的N元语法的总个数(不是总个数乘以c),并称之为频度c的频度。对N_c中的c的最大似然估计是c。这样相当于将N元语法按其出现次数分成了多个桶,GT打折法用c+1号桶里语法概率的最大似然估计来重新估计c号桶内语法的概率。因此GT估计之后最大似然估计得到的c被替换成: +\[ +c^{*}=(c+1) \frac {N_{c+1}}{N_c} +\]
    • +
    • 之后计算某N元语法的概率: +
        +
      • 从未出现:\(P_{GT}^{*}=\frac{N_1}{N}\)。其中N是所有N元语法数\((\sum _i N_i * +i)\)。这里假设了我们已知\(N_0\),则此式表示某一具体未知计数N元语法概率时还应除以\(N_0\)
      • +
      • 已出现(已知计数):\(P_{GT}^{*} = +\frac{c^{*}}{N}\)
    • -
    • Kipf GCN +
    • 这样计算,\(N_1\)的一些概率转移到了\(N_0\)上。GT打折法假设所有的N元语法概率分布满足二项式分布,且假设我们已知\(N_0\),以二元语法为例: \[ +N_0 = V^2 - \sum _{i>0} N_i \\ +\]
    • +
    • 其他注意事项:
        -
      • 将每一层的aggregate&update操作写成矩阵形式,就可以利用高效的稀疏矩阵操作来提速 -
      • -
      • 其中的A都加了自环,邻域中包含了自己,而不是邻域与自己拼接,这里稍有不同。Kipf的形式其实是加权求和时权重做了对称归一化,考虑了邻域节点的度,而不仅仅考虑自身的度。
      • +
      • 有些\(N_c\)为0,这时我们无法用这些\(N_c\)来计算平滑后的c。这种情况下我们直接放弃平滑,令\(c^{*} = +c\),再根据正常的数据计算出一个对数线性映射,\(log⁡(N_c) = a + b +\log(c)\),代入放弃平滑的c并用其倒推计算计数为0的\(N_c\),使得这些\(N_c\)有值,不会影响更高阶的c的计算。
      • +
      • 只对较小c的\(N_c\)进行平滑,较大c的\(N_c\)认为足够可靠,设定一个阈值k,对\(c < k\)\(N_c\)计算: \[ +c^{*} = \frac {(c+1) \frac {N_c+1}{N_c} - c \frac {(k+1) N_{k+1} }{N_1} +} {1- \frac {(k+1)N_{k+1}} {N_1}} \\ +\]
      • +
      • 计算较小的c如c=1时,也看成c=0的情况进行平滑
    • -
    • GAT +
    • 一个例子:
    • +
    +

    插值与回退

      -
    • 可以看到GCN和GraphSage在聚合邻域节点时,不同邻居节点的权重都是一样的,那么自然可以使用注意力机制,根据邻域节点和自身的embedding计算出注意力作为权重再聚合。
    • -
    • 参考transformer,使用multi-head attention
    • +
    • 上述的平滑只考虑了如何转移概率到计数为0的语法上去,对于条件概率\(p(w|h)\),我们也可以采用类似的思想,假如不存在某个三元语法帮助计算\(p(w_n |w_{n-1} +w_{n-2})\),则可以用阶数较低的语法\(p(w_n |w_{n-1})\)帮助计算,有两种方案: +
        +
      • 回退:用低阶数语法的替代0计数的高阶语法
      • +
      • 插值:用低阶数语法的加权估计高阶语法
    • -
    • GNN的训练技巧 +
    • 在Katz回退中,我们使用GT打折作为方法的一部分:GT打折告诉我们有多少概率可以从已知语法中分出来,Katz回退告诉我们如何将这些分出来的概率分配给未知语法。在之前的GT打折法中,我们将分出的概率均匀分给每一个未知语法,而Katz回退则依靠低阶语法的信息来分配: +
    • +
    • 其中\(P^{*}\)是打折之后得到的概率;,保证分出去的概率等于未知语法分配得到的概率。
    • +
    • 插值则是用低阶语法概率加权求和得到未知高阶语法概率: FoZUbQ.png
    • +
    • 加权的系数还可以通过上下文动态计算。具体系数的计算有两种方法:
        -
      • 预处理很重要,Use renormalization tricks、 Variance-scaled -initialization、 Network data whitening
      • -
      • adam优化,relu激活
      • -
      • output layer不需要激活
      • -
      • 每一层记得加bias
      • +
      • 尝试各种系数,用在验证集上表现最好的系数组合
      • +
      • 将系数看成是概率生成模型的隐变量,使用EM算法进行推断
    -]]>
    - - 机器学习 - - - gnn - math - graph - -
    - - Notes for the server of Melodia - /2017/05/26/dachuangserver/ - +

    实际问题:工具和数据格式

      -
    • 大创项目的服务器端,大创以及客户端介绍见Melodia客户端
    • -
    • 我们大创项目的服务器承担的功能比较少,只与android设备收发文件,用Python写了一个简单的服务器端
    • +
    • 在语言模型计算中,一般将概率取对数进行计算,原因有二:防止数值下溢;取对数能将累乘运算变成累加,加速计算。
    • +
    • 回退N元语法模型一般采用ARPA格式。ARPA格式文件由一些头部信息和各类N元语法的列表组成,列表中包含了该类N元语法下所有语法,概率,和回退的归一化系数。只有能够称为高阶语法前缀的低阶语法才能在回退中被利用,并拥有归一化系数。
    • +
    • 两种计算N元语法模型的工具包:SRILM toolkit 和Cambridge-CMU +toolkit
    - -

    功能

    +

    语言建模中的高级问题

    +

    高级平滑方法:Kneser-Ney平滑

      -
    • 从android客户端接收的数据都是json格式,base64编解码。以我们自定义的特殊字符串结尾,服务器在建立与一个终端的连接后开一个处理的线程
    • -
    • 客户端完成一次wav到midi转换需要两次通信,第一次json中request值为1,data中是wav文件,服务器负责生成md5编码的时间戳,并用时间戳命名一个wav文件存下,再调用我们的核心程序将wav转换,生成md5.mid和md5.png,即乐曲和曲谱,并回传给客户端md5值。第二次客户端发来的json中request值为2,data值为md5,服务器根据md5索引生成的midi文件回传给客户端
    • -
    -

    代码

    -
    # -*- coding:utf-8 -*- 
    # ! usr/bin/python

    from socket import *
    import time
    import threading
    import os
    import md5
    import warnings

    Host = ''
    Port = 2017
    Addr = (Host, Port)
    midi_dict = {}

    warnings.filterwarnings("ignore")


    def md5_encode(src):
    m1 = md5.new()
    m1.update(src)
    return m1.hexdigest()


    def tcplink(sock, addr):
    sessnum = 0
    music_data = ''
    while True:
    data = sock.recv(1480)
    if data[-9:]=='endbidou1':
    print 'wav recv finished'
    music_data+=data
    music_data=music_data[:-9]
    midi_data = eval(music_data)
    sessnum = midi_data['request']
    if midi_data['request'] == 1:
    flag_md5 = md5_encode(str(time.time()))
    print 'md5: ', flag_md5
    wav_name = flag_md5 + '.wav'
    with open(wav_name, 'w+') as f:
    f.write(midi_data['data'].decode('base64'))
    f.close()
    n = midi_data['config']['n'];
    m = midi_data['config']['m'];
    w = midi_data['config']['w'];
    midi_name = flag_md5 + '.mid'
    with open(midi_name, 'w') as f:
    f.close()
    shellmid = '../mldm/hum2midi.py -n '+str(n)+' -m '+str(m)+' -w '+str(w)+' -o ' + midi_name + ' ' + wav_name
    print "running wav2midi shell"
    retmid = os.system(shellmid)
    retmid >= 8
    if retmid == 0:
    print 'generate midi successful'
    shellpng = 'mono ../mlds/sheet '+midi_name+' '+flag_md5
    retpng = os.system(shellpng)
    if retpng == 0:
    sock.send(flag_md5.encode())
    print 'generate png successful'
    midi_dict[flag_md5] = midi_name
    break
    else:
    print 'generate png error'
    break
    else:
    print 'generate midi error'
    break
    elif midi_data['request'] == 2:
    flag = midi_data['data']
    if flag in midi_dict.keys():
    fo = open(flag+'.mid', 'rb')
    while True:
    filedata = fo.read(1024)
    if not filedata:
    break
    sock.send(filedata)
    print 'midi file sent'
    fo.close()
    break
    else:
    print 'can not find midi'
    break
    else:
    print 'json error'
    else:
    music_data += data
    sock.close()
    print 'session '+str(sessnum)+' for '+str(addr)+' finished'

    tcpSerSock = socket(AF_INET, SOCK_STREAM)
    tcpSerSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    tcpSerSock.bind(Addr)
    tcpSerSock.listen(5)

    while True:
    tcpCliSock, tcpCliAddr = tcpSerSock.accept()
    print 'add ', tcpCliAddr
    t = threading.Thread(target=tcplink, args=(tcpCliSock, tcpCliAddr))
    t.start()
    tcpSerSock.close()
    -]]>
    - - Python - - - code - server - linux - -
    - - DeepBayes 2018 - /2018/09/22/deepbayes2018/ - Deep-Bayes 2018 Summer Camp的习题 填不动了,就到这吧

    -

    Deep|Bayes summer school. Practical session on EM -algorithm

    +
  • 注意到在GT打折法当中,打折之后估计的c值比最大似然估计得到的c值近似多出一个定值d。绝对打折法便考虑了这一点,在每个计数中减去这个d: +
  • +
  • Kneser-Ney平滑吸收了这种观点,并且还考虑了连续性:在不同上文中出现的单词更有可能出现在新的上文之后,在回退时,我们应该优先考虑这种在多种上文环境里出现的词,而不是那些出现次数很多,但仅仅在特定上文中出现的词。 +
  • +
  • 在Kneser-Ney中,插值法能够比回退法取得更加好的效果: FoZ05n.png
  • + +

    基于分类的N元语法

      -
    • 第一题就是应用EM算法还原图像,人像和背景叠加在一起,灰度值的概率分布形式已知,设计人像在背景中的位置为隐变量,进行EM迭代推断。
    • -
    • 具体说明在官网和下面的notebook注释中有,实际上公式已经给出,想要完成作业就是把公式打上去,可以自己推一下公式。
    • +
    • 这种方法是为了解决训练数据的稀疏性。例如IBM聚类,每个单词只能属于一类,以二元语法为例,某个二元语法的条件概率的计算变为给定上文所在类,某个单词的条件概率,还可以进一步链式分解为两个类的条件概率乘以某个单词在给定其类条件下的条件概率: +\[ +p(w_i│w_{i-1} ) \approx p(w_i│c_{i-1} ) = p(c_i |c_{i-1}) \cdot p(w_i +|c_i) +\]
    -

    One of the school organisers decided to prank us and hid all games -for our Thursday Game Night somewhere.

    -

    Let's find the prankster!

    -

    When you recognize him or -her, send: * name * reconstructed photo * this notebook with your -code (doesn't matter how awful it is :)

    -

    privately to Nadia Chirkova at Facebook -or to info@deepbayes.ru. The first three participants will receive a -present. Do not make spoilers to other participants!

    -

    Please, note that you have only one attempt to send -a message!

    -
    import numpy as np
    from matplotlib import pyplot as plt
    %matplotlib inline
    -
    DATA_FILE = "data_em"
    w = 73 # face_width
    -

    Data

    -

    We are given a set of \(K\) images -with shape \(H \times W\).

    -

    It is represented by a numpy-array with shape \(H \times W \times K\):

    -
    X = np.load(DATA_FILE)
    -
    X.shape # H, W, K
    -
    (100, 200, 1000)
    -

    Example of noisy image:

    -
    plt.imshow(X[:, :, 0], cmap="Greys_r")
    plt.axis("off")
    print(X[1,:,0])
    -
    [255. 255.  41. 255.   0.  51. 255.  15. 255.  59.   0.   0.   0. 255.
    -   0. 255. 255.   0. 175.  74. 184.   0.   0. 150. 255. 255.   0.   0.
    - 148.   0. 255. 181. 255. 255. 255.   0. 255. 255.  30.   0.   0. 255.
    -   0. 255. 255. 206. 234. 255.   0. 255. 255. 255.   0. 255.   0. 255.
    -   0. 255. 255. 175.  30. 255.   0.   0. 255.   0. 255.  48.   0.   0.
    -   0. 232. 162. 255.  26.   0.   0. 255.   0. 255. 173. 255. 255.   0.
    -   0. 255. 255. 119.   0.   0.   0.   0.   0.   0. 255. 255. 255. 255.
    -   0.   0. 248.   5. 149. 255.   0. 255. 255. 255.   0. 108.   0.   0.
    - 255.   0. 255. 255. 255.   0.   0. 193.  79.   0. 255.   0.   0.   0.
    - 233. 255.   0.  65. 255. 255. 255.   0. 255.   0.   0.   0. 255.  58.
    - 226. 255.   0. 242. 255. 255.   0. 255.   4. 255. 255.  97. 255.   0.
    -   0. 255.   0. 255.   0.   0.   0. 255.   0.  43. 219.   0. 255. 255.
    - 255. 166. 255.   0. 255.  42. 255.  44. 255. 255. 255. 255. 255. 255.
    - 255. 255.  28.   0.  52. 255.  81. 104. 255. 255.  48. 255. 255. 255.
    - 102.  25.  30.  73.]
    -
    -i0Ihiq.png - -
    -

    Goal and plan

    -

    Our goal is to find face \(F\) -(\(H \times w\)).

    -

    Also, we will find: * \(B\): -background (\(H \times W\)) * \(s\): noise standard deviation (float) * -\(a\): discrete prior over face -positions (\(W-w+1\)) * \(q(d)\): discrete posterior over face -positions for each image ((\(W-w+1\)) x -\(K\))

    -

    Implementation plan: 1. calculating \(log\, -p(X \mid d,\,F,\,B,\,s)\) 1. calculating objective 1. E-step: -finding \(q(d)\) 1. M-step: estimating -\(F,\, B, \,s, \,a\) 1. composing -EM-algorithm from E- and M-step

    -

    Implementation

    -
    ### Variables to test implementation
    tH, tW, tw, tK = 2, 3, 1, 2
    tX = np.arange(tH*tW*tK).reshape(tH, tW, tK)
    tF = np.arange(tH*tw).reshape(tH, tw)
    tB = np.arange(tH*tW).reshape(tH, tW)
    ts = 0.1
    ta = np.arange(1, (tW-tw+1)+1)
    ta = ta / ta.sum()
    tq = np.arange(1, (tW-tw+1)*tK+1).reshape(tW-tw+1, tK)
    tq = tq / tq.sum(axis=0)[np.newaxis, :]
    -

    1. Implement -calculate_log_probability

    -

    For \(k\)-th image \(X_k\) and some face position \(d_k\): \[p(X_k \mid d_k,\,F,\,B,\,s) = \prod_{ij} - \begin{cases} - \mathcal{N}(X_k[i,j]\mid F[i,\,j-d_k],\,s^2), - & \text{if}\, (i,j)\in faceArea(d_k)\\ - \mathcal{N}(X_k[i,j]\mid B[i,j],\,s^2), & \text{else} - \end{cases}\]

    -

    Important notes: * Do not forget about logarithm! * This -implementation should use no more than 1 cycle!

    -
    def calculate_log_probability(X, F, B, s):
    """
    Calculates log p(X_k|d_k, F, B, s) for all images X_k in X and
    all possible face position d_k.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.

    Returns
    -------
    ll : array, shape(W-w+1, K)
    ll[dw, k] - log-likelihood of observing image X_k given
    that the prankster's face F is located at position dw
    """
    # your code here
    H = X.shape[0]
    W = X.shape[1]
    K = X.shape[2]
    w = F.shape[1]
    ll = np.zeros((W-w+1,K))
    for k in range(K):
    X_minus_B = X[:,:,k]-B[:,:]
    XB = np.multiply(X_minus_B,X_minus_B)
    for dk in range(W-w+1):
    F_temp = np.zeros((H,W))
    F_temp[:,dk:dk+w] = F
    X_minus_F = X[:,:,k] - F_temp[:,:]
    XF = np.multiply(X_minus_F,X_minus_F)
    XB_mask = np.ones((H,W))
    XB_mask[:,dk:dk+w] = 0
    XF_mask = 1-XB_mask
    XB_temp = np.multiply(XB,XB_mask)
    XF_temp = np.multiply(XF,XF_mask)
    Sum = (np.sum(XB_temp+XF_temp))*(-1/(2*s**2))-H*W*np.log(np.sqrt(2*np.pi)*s)
    ll[dk][k]=Sum
    return ll
    -
    # run this cell to test your implementation
    expected = np.array([[-3541.69812064, -5541.69812064],
    [-4541.69812064, -6741.69812064],
    [-6141.69812064, -8541.69812064]])
    actual = calculate_log_probability(tX, tF, tB, ts)
    assert np.allclose(actual, expected)
    print("OK")
    -
    OK
    -

    2. Implement -calculate_lower_bound

    -

    \[\mathcal{L}(q, \,F, \,B,\, s,\, a) = -\sum_k \biggl (\mathbb{E} _ {q( d_k)}\bigl ( \log p( X_{k} \mid -{d}_{k} , \,F,\,B,\,s) + - \log p( d_k \mid a)\bigr) - \mathbb{E} _ {q( d_k)} \log q( -d_k)\biggr) \]

    -

    Important notes: * Use already implemented calculate_log_probability! -* Note that distributions \(q( d_k)\) -and \(p( d_k \mid a)\) are discrete. -For example, \(P(d_k=i \mid a) = -a[i]\). * This implementation should not use cycles!

    -
    def calculate_lower_bound(X, F, B, s, a, q):
    """
    Calculates the lower bound L(q, F, B, s, a) for
    the marginal log likelihood.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1)
    Estimate of prior on position of face in any image.
    q : array
    q[dw, k] - estimate of posterior
    of position dw
    of prankster's face given image Xk

    Returns
    -------
    L : float
    The lower bound L(q, F, B, s, a)
    for the marginal log likelihood.
    """
    # your code here
    K = X.shape[2]
    ll = calculate_log_probability(X,F,B,s)
    ll_expectation = np.multiply(ll,q)
    q_expectation = np.multiply(np.log(q),q)
    dk_expection = 0
    for k in range(K):
    dk_expection += np.multiply(np.log(a),q[:,k])
    L = np.sum(ll_expectation)-np.sum(q_expectation)+np.sum(dk_expection)

    return L
    -
    # run this cell to test your implementation
    expected = -12761.1875
    actual = calculate_lower_bound(tX, tF, tB, ts, ta, tq)
    assert np.allclose(actual, expected)
    print("OK")
    -
    OK
    -

    3. Implement E-step

    -

    \[q(d_k) = p(d_k \mid X_k, \,F, \,B, -\,s,\, a) = -\frac {p( X_{k} \mid {d}_{k} , \,F,\,B,\,s)\, p(d_k \mid a)} -{\sum_{d'_k} p( X_{k} \mid d'_k , \,F,\,B,\,s) \,p(d'_k -\mid a)}\]

    -

    Important notes: * Use already implemented calculate_log_probability! -* For computational stability, perform all computations with logarithmic -values and apply exp only before return. Also, we recommend using this -trick: \[\beta_i = \log{p_i(\dots)} -\quad\rightarrow \quad - \frac{e^{\beta_i}}{\sum_k e^{\beta_k}} = - \frac{e^{(\beta_i - \max_j \beta_j)}}{\sum_k e^{(\beta_k- \max_j -\beta_j)}}\] * This implementation should not use cycles!

    -
    def run_e_step(X, F, B, s, a):
    """
    Given the current esitmate of the parameters, for each image Xk
    esitmates the probability p(d_k|X_k, F, B, s, a).

    Parameters
    ----------
    X : array, shape(H, W, K)
    K images of size H x W.
    F : array_like, shape(H, w)
    Estimate of prankster's face.
    B : array shape(H, W)
    Estimate of background.
    s : float
    Eestimate of standard deviation of Gaussian noise.
    a : array, shape(W-w+1)
    Estimate of prior on face position in any image.

    Returns
    -------
    q : array
    shape (W-w+1, K)
    q[dw, k] - estimate of posterior of position dw
    of prankster's face given image Xk
    """
    # your code here
    ll = calculate_log_probability(X,F,B,s)
    K = X.shape[2]
    for k in range(K):
    max_ll = ll[:,k].max()
    ll[:,k] -= max_ll
    ll[:,k] = np.exp(ll[:,k])*a
    denominator = np.sum(ll[:,k])
    ll[:,k] /= denominator
    q = ll
    return q
    -
    # run this cell to test your implementation
    expected = np.array([[ 1., 1.],
    [ 0., 0.],
    [ 0., 0.]])
    actual = run_e_step(tX, tF, tB, ts, ta)
    assert np.allclose(actual, expected)
    print("OK")
    -
    OK
    -

    4. Implement M-step

    -

    \[a[j] = \frac{\sum_k q( d_k = j -)}{\sum_{j'} \sum_{k'} q( d_{k'} = j')}\] \[F[i, m] = \frac 1 K \sum_k \sum_{d_k} q(d_k)\, -X^k[i,\, m+d_k]\] \[B[i, j] = \frac -{\sum_k \sum_{ d_k:\, (i, \,j) \,\not\in faceArea(d_k)} q(d_k)\, X^k[i, -j]} - {\sum_k \sum_{d_k: \,(i, \,j)\, \not\in faceArea(d_k)} -q(d_k)}\] \[s^2 = \frac 1 -{HWK} \sum_k \sum_{d_k} q(d_k) - \sum_{i,\, j} (X^k[i, \,j] - Model^{d_k}[i, \,j])^2\]

    -

    where \(Model^{d_k}[i, j]\) is an -image composed from background and face located at \(d_k\).

    -

    Important notes: * Update parameters in the following order: \(a\), \(F\), \(B\), \(s\). * When the parameter is updated, its -new value is used to update other parameters. * This -implementation should use no more than 3 cycles and no embedded -cycles!

    -
    def run_m_step(X, q, w):
    """
    Estimates F, B, s, a given esitmate of posteriors defined by q.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    q :
    q[dw, k] - estimate of posterior of position dw
    of prankster's face given image Xk
    w : int
    Face mask width.

    Returns
    -------
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1)
    Estimate of prior on position of face in any image.
    """
    # your code here
    K = X.shape[2]
    W = X.shape[1]
    H = X.shape[0]

    a = np.sum(q,axis=1) / np.sum(q)

    F = np.zeros((H,w))
    for k in range(K):
    for dk in range(W-w+1):
    F+=q[dk][k]*X[:,dk:dk+w,k]
    F = F / K


    B = np.zeros((H,W))
    denominator = np.zeros((H,W))
    for k in range(K):
    for dk in range(W-w+1):
    mask = np.ones((H,W))
    mask[:,dk:dk+w] = 0
    B += np.multiply(q[dk][k]*X[:,:,k],mask)
    denominator += q[dk][k]*mask
    denominator = 1/denominator
    B = B * denominator

    s = 0
    for k in range(K):
    for dk in range(W-w+1):
    F_B = np.zeros((H,W))
    F_B[:,dk:dk+w]=F
    mask = np.ones((H,W))
    mask[:,dk:dk+w] = 0
    Model = F_B + np.multiply(B,mask)
    temp = X[:,:,k]-Model[:,:]
    temp = np.multiply(temp,temp)
    temp = np.sum(temp)
    temp *= q[dk][k]
    s += temp
    s = np.sqrt(s /(H*W*K))

    return F,B,s,a


    -
    # run this cell to test your implementation
    expected = [np.array([[ 3.27777778],
    [ 9.27777778]]),
    np.array([[ 0.48387097, 2.5 , 4.52941176],
    [ 6.48387097, 8.5 , 10.52941176]]),
    0.94868,
    np.array([ 0.13888889, 0.33333333, 0.52777778])]
    actual = run_m_step(tX, tq, tw)
    for a, e in zip(actual, expected):
    assert np.allclose(a, e)
    print("OK")
    -
    OK
    -

    5. Implement EM_algorithm

    -

    Initialize parameters, if they are not passed, and then repeat E- and -M-steps till convergence.

    -

    Please note that \(\mathcal{L}(q, \,F, \,B, -\,s, \,a)\) must increase after each iteration.

    -
    def run_EM(X, w, F=None, B=None, s=None, a=None, tolerance=0.001,
    max_iter=50):
    """
    Runs EM loop until the likelihood of observing X given current
    estimate of parameters is idempotent as defined by a fixed
    tolerance.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    w : int
    Face mask width.
    F : array, shape (H, w), optional
    Initial estimate of prankster's face.
    B : array, shape (H, W), optional
    Initial estimate of background.
    s : float, optional
    Initial estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1), optional
    Initial estimate of prior on position of face in any image.
    tolerance : float, optional
    Parameter for stopping criterion.
    max_iter : int, optional
    Maximum number of iterations.

    Returns
    -------
    F, B, s, a : trained parameters.
    LL : array, shape(number_of_iters + 2,)
    L(q, F, B, s, a) at initial guess,
    after each EM iteration and after
    final estimate of posteriors;
    number_of_iters is actual number of iterations that was done.
    """
    H, W, N = X.shape
    if F is None:
    F = np.random.randint(0, 255, (H, w))
    if B is None:
    B = np.random.randint(0, 255, (H, W))
    if a is None:
    a = np.ones(W - w + 1)
    a /= np.sum(a)
    if s is None:
    s = np.random.rand()*pow(64,2)
    # your code here
    LL = [-100000]
    for i in range(max_iter):
    q = run_e_step(X,F,B,s,a)
    F,B,s,a = run_m_step(X,q,w)
    LL.append(calculate_lower_bound(X,F,B,s,a,q))
    if LL[-1]-LL[-2] < tolerance :
    break
    LL = np.array(LL)
    return F,B,s,a,LL


    -
    # run this cell to test your implementation
    res = run_EM(tX, tw, max_iter=10)
    LL = res[-1]
    assert np.alltrue(LL[1:] - LL[:-1] > 0)
    print("OK")
    -
    OK
    -

    Who is the prankster?

    -

    To speed up the computation, we will perform 5 iterations over small -subset of images and then gradually increase the subset.

    -

    If everything is implemented correctly, you will recognize the -prankster (remember he is the one from DeepBayes team).

    -

    Run EM-algorithm:

    -
    def show(F, i=1, n=1):
    """
    shows face F at subplot i out of n
    """
    plt.subplot(1, n, i)
    plt.imshow(F, cmap="Greys_r")
    plt.axis("off")
    -
    F, B, s, a = [None] * 4
    LL = []
    lens = [50, 100, 300, 500, 1000]
    iters = [5, 1, 1, 1, 1]
    plt.figure(figsize=(20, 5))
    for i, (l, it) in enumerate(zip(lens, iters)):
    F, B, s, a, _ = run_EM(X[:, :, :l], w, F, B, s, a, max_iter=it)
    show(F, i+1, 5)
    -
    -i0omSf.png - -
    -

    And this is the background:

    -
    show(B)
    -
    -i0I4J0.png - -
    -

    Optional part: hard-EM

    -

    If you have some time left, you can implement simplified version of -EM-algorithm called hard-EM. In hard-EM, instead of finding posterior -distribution \(p(d_k|X_k, F, B, s, A)\) -at E-step, we just remember its argmax \(\tilde d_k\) for each image \(k\). Thus, the distribution q is replaced -with a singular distribution: \[q(d_k) = -\begin{cases} 1, \, if d_k = \tilde d_k \\ 0, \, -otherwise\end{cases}\] This modification simplifies formulas for -\(\mathcal{L}\) and M-step and speeds -their computation up. However, the convergence of hard-EM is usually -slow.

    -

    If you implement hard-EM, add binary flag hard_EM to the parameters -of the following functions: * calculate_lower_bound * run_e_step * -run_m_step * run_EM

    -

    After implementation, compare overall computation time for EM and -hard-EM till recognizable F.

    -]]>
    - - 数学 - - - machine learning - math - bayes - -
    - - Notes for Computational Linguistics - /2018/11/16/coling/ - 计算语言学课程笔记 参考教材:Speech and Language Processing:An -Introduction to Natural Language Processing,Computational Linguistics, -and Speech Recognition 一些公式待修订

    -

    第二章:正则表达式与自动机

    +

    语言模型适应和网络应用

      -
    • 正则表达式:一种用于查找符合特定模式的子串或者用于以标准形式定义语言的工具,本章主要讨论其用于查找子串的功能。正则表达式用代数的形式来表示一些字符串集合。
    • -
    • 正则表达式接收一个模式,然后在整个语料中查找符合这个模式的子串,这个功能可以通过设计有限状态自动机实现。
    • -
    • 字符串看成符号的序列,所有的字符,数字,空格,制表符,标点和空格均看成符号。
    • +
    • 适应是指在大型宽泛的语料库上训练语言模型,并在小的细分领域的语言模型上进一步改进。网络是大型语料库的一个重要来源。在实际应用时我们不可能搜索每一个语法并统计搜索得到所有页面上的所有语法,我们用搜索得到的页面数来近似计数。
    -

    基本正则表达式模式

    +

    利用更长距离的上文信息

      -
    • 用双斜线表示正则表达式开始和结束(perl中的形式) +
    • 通常我们使用二元和三元语法模型,但是更大的N能够带来更好的效果。为了捕捉更长距离的上文信息,有以下几种方法:
        -
      • 查找子串,大小写敏感:/woodchuck/-> woodchuck
      • -
      • 用方括号代表取其中一个,或:/[Ww]oodchuck/->woodchuck or -Woodchuck
      • -
      • 方括号加减号,范围内取或:/[2-5]/->/[2345]
      • -
      • 插入符号放在左方括号后,代表模式中不出现后接的所有符号,取非: /^Ss/ -->既不是大写S也不是小写s
      • -
      • 问号代表之前的符号出现一个或不出现:/colou?r/->color or -colour
      • -
      • 星号代表之前的符号出现多个或不出现:/ba*/->b or ba or baa or -baaa......
      • -
      • 加号代表之前的符号出现至少一次:/ba+/->ba or baa or -baaa.......
      • -
      • 小数点代表通配符,与任何除了回车符之外的符号匹配:/beg.n/->begin -or begun or beg’n or .......
      • -
      • 锚符号,用来表示特定位置的子串,插入符号代表行首,美元符号代表行尾,,,perl将单词的定义为数字、下划线、字母的序列,不在其中的符号便可以作为单词的分界。
      • +
      • 基于缓存机制的N元语法模型
      • +
      • 基于主题建模的N元语法模型,对不同主题建模语言模型,再加权求和
      • +
      • 不一定使用相邻的上文信息,例如skip +N-grams或者不一定使用定长的上文信息,例如变长N-grams
    -

    析取、组合和优先

    +

    第十六章:语言的复杂性

    +

    Chomsky层级

      -
    • 用竖线代表析取,字符串之间的或:/cat|dog/->cat or dog
    • -
    • 用圆括号代表部分析取(组合),圆括号内也可以用基本算符:/gupp(y|ies)/->guppy -or guppies
    • -
    • 优先级:圆括号>计数符>序列与锚>析取符
    • +
    • Chomsky层级反映了不同形式化方法描述的语法之间的蕴含关系,较强生成能力或者说更复杂的语法在层级的外层。从外到内,加在可重写语法规则上的约束增加,语言的生成能力逐渐降低。 +
    • +
    • 五种语法对应的规则和应用实例: Foepxf.png +
        +
      • 0型语法:规则上只有一个限制,即规则左侧不能为空字符串。0型语法刻画了递归可枚举语言
      • +
      • 上下文相关语法:可以把上下文,
      • +
      • 温和的上下文相关语法
      • +
      • 上下文无关语法:可以把任何单独的非终极符号重写为由终极符号和非终极符号构成的字符串,也可以重写为空字符串
      • +
      • 正则语法:可以是右线性也可以是左线性,以右线性为例,非终极符号可以重写为左边加了若干终极符号的另一个非终极符号,右线性不断地在字符串左侧生成终极符号。
      • +
    -

    高级算符

    +

    自然语言是否正则

      -
    • 任何数字
    • -
    • :任何非数字字符
    • -
    • :任何字母、数字、空格
    • -
    • :与
    • -
    • :空白区域
    • -
    • :与
    • -
    • {n}:前面的模式出现n个
    • -
    • {n,m}:前面的模式出现n到m个
    • -
    • {n,}:前面的模式至少出现n个
    • -
    • :换行
    • -
    • 表格符
    • +
    • 判断语言是否正则能够让我们了解应该用哪一层次的语法来描述一门语言,且这个问题能够帮助我们了解自然语言的不同方面的某些形式特性。
    • +
    • 抽吸引理:用来证明一门语言不是正则语言。 +
        +
      • 如果一门语言可以被有限状态自动机来描述,则与自动机对应有一个记忆约束量。这个约束量对于不同的符号串不会增长的很大,因为其状态数目是固定的,更长的符号串应该是通过状态之间转移产生而不是增加状态数目。因此这个记忆量不一定和输入的长度成比例。
      • +
      • 如果一个正则语言能够描述任意长的符号序列,比自动机的状态数目还多,则该语言的自动机中必然存在回路。 +
      • +
    • +
    • 如图所示自动机,可以表述xyz,xyyz,xyyyz.....,当然也可以将中间无限长的y序列“抽吸掉”,表述xz。抽吸引理表述如下:
    • +
    • 设L是一个有限的正则语言,那么必然存在符号串x,y,z,使得对于任意n≥0,y≠\(\epsilon\),且xy^n z∈L
    • +
    • 即假如一门语言是正则语言,则存在某一个符号串y,可以被适当的“抽吸”。这个定理是一门语言是正则语言的必要非充分条件。
    • +
    • 有学者证明英语不是一门正则语言: +
        +
      • 具有镜像性质的句子通过抽吸原理可以证明不是正则语言,而英语中一个特殊的子集合和这种镜像性质的句子是同态的。
      • +
      • 另一种证明基于某些带有中心-嵌套结构的句子。这种句子可以由英语和某一类简单的正则表达式相交得到,通过抽吸原理可以得到这种句子不是正则语言。英语和正则语言的交不是正则语言,则英语不是正则语言。
      • +
    -

    替换、寄存器

    +

    自然语言是否上下文无关

      -
    • 替换s/A/B/:A替换成B
    • -
    • s/(A)/<\1>/:用数字算符\1指代A,在A的两边加上尖括号
    • -
    • 在查找中也可以用数字算符,指代圆括号内内容,可以多个算符指代多个圆括号内内容
    • -
    • 这里数字算符起到了寄存器的作用
    • +
    • 既然自然语言不是正则语言,我们接着考虑更宽松的限定,自然语言是否是上下文无关的?
    • +
    • 不是......
    -

    有限状态自动机

    +

    计算复杂性和人的语言处理

      -
    • 有限状态自动机和正则表达式彼此对称,正则表达式是刻画正则语言的一种方法。正则表达式、正则语法和自动状态机都是表达正则语言的形式。FSA用有向图表示,圆圈或点代表状态,箭头或者弧代表状态转移,用双圈表示最终状态,如下图表示识别/baa+!/的状态机图: -
    • -
    • 状态机从初始状态出发,依次读入符号,若满足条件,则进行状态转移,若读入的符号序列满足模式,则状态机可以到达最终状态;若符号序列不满足模式,或者自动机在某个非最终状态卡住,则称自动机拒绝了此次输入。
    • -
    • 另一种表示方式是状态转移表: FoVqNn.png
    • -
    • 一个有限自动机可以用5个参数定义: +
    • 人对中心嵌套句子处理很困难,因为人们剖析时利用的栈记忆有限,且栈中不同层次记忆容易混淆。
    • +
    +

    第五章:词类标注

      -
    • \(Q\):状态{q_i}的有限集合
    • -
    • :有限的输入符号字母表
    • -
    • \(q_0\):初始状态
    • -
    • \(F\):终极状态集合
    • -
    • \(\delta -(q,i)\):状态之间的转移函数或者转移矩阵,是从\(Q × \Sigma\)\(2^Q\)的一个关系
    • +
    • 各种表述:POS(Part Of Speech)、word classes(词类)、morphological +classes(形态类)、lexical tags(词汇标记)。
    • +
    • POS的意义在于: +
        +
      • 能够提供关于单词及其上下文的大量信息。
      • +
      • 同一单词在不同词类下发音不同,因此POS还能为语音处理提供信息。
      • +
      • 进行词干分割(stemming),辅助信息检索
      • +
    • +
    • 本章介绍三种词类标注算法: +
        +
      • 基于规则的算法
      • +
      • 基于概率的算法,隐马尔科夫模型
      • +
      • 基于变换的算法
    • -
    • 以上描述的自动机是确定性的,即DFSA,在已知的记录在状态转移表上的状态时,根据查表自动机总能知道如何进行状态转移。算法如下,给定输入和自动机模型,算法确定输入是否被状态机接受: -
    • -
    • 当出现了表中没有的状态时自动机就会出错,可以添加一个失败状态处理这些情况。
    -

    形式语言

    +

    一般词类

      -
    • 形式语言是一个模型,能且只能生成和识别一些满足形式语言定义的某一语言的符号串。形式语言是一种特殊的正则语言。通常使用形式语言来模拟自然语言的某些部分。以上例/baa+!/为例,设对应的自动机模型为m,输入符号表\(\Sigma = {a,b,!}\)\(L(m)\)代表由m刻画的形式语言,是一个无限集合\({baa!,baaa!,baaaa!,…}\)
    • +
    • POS分为封闭集和开放集,封闭集集合相对稳定,例如介词,开放集的词语则不断动态扩充,例如名词和动词。特定某个说话人或者某个语料的开放集可能不同,但是所有说一种语言以及各种大规模语料库可能共享相同的封闭集。封闭集的单词称为虚词(功能词,function +word),这些词是语法词,一般很短,出现频次很高。
    • +
    • 四大开放类:名词、动词、形容词、副词。
    • +
    • 名词是从功能上定义的而不是从语义上定义的,因此名词一般表示人、地点、事物,但既不充分也不必要。定义名词: +
        +
      • 与限定词同时出现
      • +
      • 可以受主有代词修饰
      • +
      • 大多数可以以复数形式出现(即可数名词),物质名词不可数。单数可数名词出现时不能没有冠词
      • +
    • +
    • 动词,表示行为和过程的词,包括第三人称单数、非第三人称单数、进行时、过去分词几种形态
    • +
    • 形容词,描述性质和质量
    • +
    • 副词,用于修饰,副词可以修饰动词、动词短语、其它副词。
    • +
    • 英语中的一些封闭类: +
        +
      • 介词 prepositions:出现在名词短语之前,表示关系
      • +
      • 限定词 determiners 冠词 articles:与有定性(definiteness)相关
      • +
      • 代词 pronouns:简短的援引某些名词短语、实体、或事件的一种形式
      • +
      • 连接词 conjunctions:用于连接和补足(complementation)
      • +
      • 助动词 auxiliary +verbs:标志主要动词的某些语义特征,包括:时态、完成体、极性对立、情态
      • +
      • 小品词 particles:与动词结合形成短语动词
      • +
      • 数词 numerals
      • +
    -

    非确定有限自动机

    +

    词类标注

      -
    • 非确定的有限自动机NFSA,把之前的例子稍微改动,自返圈移动到状态2,就形成了NFSA,因为此时在状态2,输入a,有两种转移可选,自动机无法确定转移路径: -
    • -
    • 另一种NFSA的形式是引入\(\epsilon\)转移,即不需要输入符号也可以通过此\(\epsilon\)转移进行转移,如下图,在状态3时依然不确定如何进行转移: -
    • -
    • 在NFSA时,面临转移选择时自动机可能做出错误的选择,此时存在三种解决方法: +
    • 标注算法的输入是单词的符号串和标记集,输出要让每一个单词标注上一个单独且最佳的标记。如果每个单词只对应一种词性,那么根据已有的标记集,词类标注就是一个简单的查表打标的过程,但是很多词存在多种词性,例如book既可以是名词也可以是动词,因此要进行消歧,词类标注是歧义消解的一个重要方面。
    • +
    +

    基于规则的词类标注

      -
    • 回退:标记此时状态,当确定发生错误选择之后,回退到此状态
    • -
    • 前瞻:在输入中向前看,帮助判定进行选择
    • -
    • 并行:并行的进行所有可能的转移
    • +
    • 介绍了ENGTWOL系统,根据双层形态学构建,对于每一个词的每一种词类分别立条,计算时不计屈折形式和派生形式.
    • +
    • 标注算法的第一阶段是将单词通过双层转录机,得到该单词的所有可能词类
    • +
    • 之后通过施加约束规则排除不正确的词类。这些规则通过上下文的类型来决定排除哪些词类。
    • +
    +

    基于隐马尔科夫模型的词类标注

    +
      +
    • 使用隐马尔科夫模型做词类标注是一类贝叶斯推断,这种方法将词类标注看成是序列分类任务。观察量为一个词序列(比如句子),任务是给这个序列分配一个标注序列。
    • +
    • 给定一个句子,贝叶斯推断想要在所有标注序列可能中选择最好的一个序列,即 +\[ +{t_1^n} _{best} = {argmax} _{t_1^n} P(t_1^n |w_1^n) +\]
    • +
    • 使用贝叶斯法则将其转化为: \[ +{t_1^n} _{best}={argmax} +_{t_1^n} \frac{P(w_1^n│t_1^n)P(t_1^n)}{P(w_1^n)} = {argmax} _{t_1^n} +P(w_1^n│t_1^n)P(t_1^n) +\]
    • +
    • 隐马尔科夫模型在此基础上做了两点假设 +
        +
      • 一个词出现的概率只与该词的词类标注有关,与上下文其他词和其他标注无关,从而将序列的联合概率拆解为元素概率之积,即:P(w_1n│t_1n) +_{i=1}^n P(w_i |t_i)
      • +
      • 一个标注出现的概率只与前一个标注相关,类似于二元语法的假设:P(t_1^n +) {i=1}^n P(t_i |t{i-1})
    • -
    • 在自动机中,采用回退算法时需要标记的状态称为搜索状态,包括两部分:状态节点和输入位置。对于NFSA,其状态转移表也有相应改变,如图,添加了代表\(\epsilon\)转移的\(\epsilon\)列,且转移可以转移到多个状态: -
    • -
    • 采用回退策略的非确定自动机算法如下,是一种搜索算法: FoZSuF.png
    • -
    • 子函数GENERATE-NEW-STATES接受一个搜索状态,提取出状态节点和输入位置,查找这个状态节点上的所有状态转移可能,生成一个搜索状态列表作为返回值;
    • -
    • 子函数ACCEPT-STATE接受一个搜索状态,判断是否接受,接受时的搜索状态应该是最终状态和输入结束位置的二元组。
    • -
    • 算法使用进程表(agenda)记录所有的搜索状态,初始只包括初始的搜索状态,即自动机初始状态节点和输入起始。之后不断循环,从进程表中调出搜索状态,先调用ACCEPT-STATE判断是否搜索成功,之后再调用GENERATE-NEW-STATES生成新的搜索状态加入进程表。循环直到搜索成功或者进程表为空(所有可能转移均尝试且未成功)返回拒绝。
    • -
    • 可以注意到NFSA算法就是一种状态空间搜索,可以通过改变搜索状态的顺序提升搜索效率,例如用栈实现进程表,进行深度优先搜索DFS;或者使用队列实现进程表,进行宽度优先搜索BFS。
    • -
    • 对于任何NFSA,存在一个完全等价的DFSA。
    • +
    • 在两种假设下简化后的最好标注序列表达式为: \[ +{t_1^n}_{best} = {argmax} _{t_1^n} P(t_1^n│w_1^n) \approx {argmax} +_{t_1^n} \prod _{i=1}^n P(w_i│t_i) P(t_i |t_{i-1}) +\]
    • +
    • 上面这个概率表达式实际上将HMM模型的联合概率拆成了各个部分转移概率的乘积,具体而言分为标签转移概率(隐变量之间转移)和词似然(隐变量转移到可观察变量)。通过最大似然估计,我们可以通过古典概型的方法从已标注的语料中计算出这两类概率: +\[ +P(t_i│t _{i-1} ) = (C(t _{i-1},t_i))/C(t _{i-1} ) \\ +P(w_i│t_i ) = \frac{C(t_i,w_i)}{C(t_i)} \\ +\]
    • +
    • 一个例子:HMM模型如何正确的将下句中的race识别为动词而不是名词:
    • +
    • Secretariat is expected to race tomorrow.
    • +
    • 画出上句中race被识别为动词和名词两种情况下的HMM模型,可以看到两个模型对比只有三个转移概率不同,用加粗线标出: +
    • +
    • HMM词类标注器消歧的方式是全局的而不是局部的。我们在语料中统计得到这三种转移概率,再累乘,结果是(a)的概率是(b)概率的843倍。显然race应该被标注为动词。
    -

    正则语言和NFSA

    -
      -
    • 定义字母表为所有输入符号集合;空符号串\(\epsilon\),空符号串不包含再字母表中;空集∅。在上的正则语言的类(或者正则集)可以形式的定义如下: +

      形式化隐马尔科夫模型标注器

        -
      • ∅是正则语言
      • -
      • ∀a ∈ \(\sum\)\(\epsilon\),{a}是形式语言
      • -
      • 如果\(L_1\)\(L_2\)是正则语言,那么:
      • -
      • \(L_1\)\(L_2\)的拼接是正则语言
      • -
      • \(L_1\)\(L_2\)的合取、析取也是正则语言
      • -
      • \(L_1\)^*,即\(L_1\)的Kleene闭包也是正则语言
      • -
    • -
    • 可见正则语言的三种基本算符:拼接、合取及析取、Kleene闭包。任何正则表达式可以写成只使用这三种基本算符的形式。
    • -
    • 正则语言对以下运算也封闭(\(L_1\)\(L_2\)均为正则语言): +
    • HMM模型是有限自动机的扩展,具体而言是一种加权有限自动机,马尔可夫链的扩展,这种模型允许我们考虑观察量和隐变量,考虑包含隐变量的概率模型。HMM包含以下组件:
        -
      • 交:\(L_1\)\(L_2\)的符号串集合的交构成的语言也是正则语言
      • -
      • 差:\(L_1\)\(L_2\)的符号串集合的差构成的语言也是正则语言
      • -
      • 补:不在\(L_1\)的符号串集合中的集合构成的语言也是正则语言
      • -
      • 逆:\(L_1\)所有符号串的逆构成的集合构成的语言也是正则语言
      • +
      • Q:大小为N的状态集
      • +
      • A:大小为N*N的转移概率矩阵
      • +
      • O:大小为T的观察事件集
      • +
      • B:观察似然序列,又叫发射概率,\(b_i +(o_t)\)描述了从状态i里生成观察o_t的概率
      • +
      • \(q_0,q_F\):特殊的起始状态和最终状态,没有相连接的观察量
    • -
    • 可以证明正则表达式和自动机等价,一个证明任何正则表达式可以建立对应的自动机的方法是,根据正则语言的定义,构造基础自动机代表\(\epsilon\)、∅以及\(\sum\)中的单个符号a,然后将三种基本算符表示为自动机上的操作,归纳性的,在基础自动机上应用这些操作,得到新的基础自动机,这样就可以构造满足任何正则表达式的自动机,如下图: -FoVxjU.png -基础自动机 拼接算符 FoZ9HJ.png -Kleene闭包算符 合取析取算符
    • +
    • A中的概率和B中的概率对应着之前式子中每一个累乘项里的先验\(P(w_i│t_i )\)和似然\(P(t_i |t _{i-1})\)概率: \[ +{t_1^n}_{best}={argmax} _{t_1^n} P(t_1^n│w_1^n ) \approx {argmax} +_{t_1^n} \prod _{i=1}^n P(w_i│t_i)P(t_i |t _{i-1}) +\]
    -

    第三章:形态学与有限状态转录机

    +

    HMM标注的维特比算法

      -
    • 剖析:取一个输入并产生关于这个输入的各类结构
    • +
    • 在HMM模型中,已知转移概率和观察序列,求隐变量的任务叫做解码。解码的一种算法即维特比算法,实质上是一种动态规划算法,与之前求最小编辑距离的算法类似。
    • +
    • 首先我们从语料中计算得到A和B两个矩阵,即模型的转移概率已知,对于给定的观察序列,按照以下步骤执行维特比算法: +
    • +
    • 算法维护一个\((N+2)*T\)的概率矩阵viterbi,加了2代表初始状态和结束状态,viterbi[s,t]代表了在第t步状态为s时的最佳路径概率,而backpointer[s,t]对应着保存了该最佳路径的上一步是什么状态,用于回溯输出整个最佳路径。
    • +
    • 关键的转移在于\(viterbi[s,t] \leftarrow +max _{s^{*}=1}^N⁡ viterbi[s^{*},t-1] * a_{s^{*},s} * b_s +(o_t)\)即当前时间步最佳路径是由上一时间步各个状态的最佳路径转移过来的,选择上一步最佳路径概率与转移概率乘积最大的路径作为当前时间步的最佳路径。从动态规划的角度而言,即长度为t的最佳路径,必定是从长度为t-1的最佳路径里选择一条转移得到,否则肯定可以从另一条概率更大的路径转移获得更优解。这样就限制了最佳路径的生成可能,减少了计算量。
    -

    英语形态学概论

    +

    将HMM算法扩展到三元语法

      -
    • 形态学研究词的构成,词可以进一步拆解为语素,语素可分为词干和词缀,词缀可分为前缀、中缀、后缀、位缀。
    • -
    • 屈折形态学:英语中,名词只包括两种屈折变化:一个词缀表示复数,一个词缀表示领属: +
    • 现代的HMM标注器一般在标注转移概率上考虑更长的上文历史: \[ +P(t_1^n ) \approx \prod_{i=1}^n P(t_i |t _{i-1},t_{i-2}) +\]
    • +
    • 这样的话需要在序列开头和结尾做一些边界处理。使用三元语法的一个问题是数据稀疏:例如我们从没有在训练集中见过标注序列PRP +VB TO,则我们无法计算P(TO|PRP,VB)。一种解决办法是线性插值: \[ +P(t_i│t _{i-1} t _{i-2} ) = \lambda _1 P ̂(t_i│t _{i-1} t _{i-2} +)+\lambda _2 P ̂(t_i│t _{i-1} )+\lambda _3 P ̂(t_i) +\]
    • +
    • 使用删除插值的办法确定系数\(\lambda\)FoZr80.png
    • +
    +

    基于变换的标注

      -
    • 复数:-s,-es,不规则复数形式
    • -
    • 领属:-‘s,-s’
    • -
    -
  • 动词的屈折变化包括规则动词和非规则动词的变化: +
  • 基于变换的方法结合了基于规则和基于概率方法的优点。基于变换的方法依然需要规则,但是从数据中总结出规则,是一种监督学习方法,称为基于变换的学习(Transformation +Based +Learning,TBL)。在TBL算法中,语料库首先用比较宽的规则来标注,然后再选择稍微特殊的规则来修改,接着再使用更窄的规则来修改数量更少的标记。
  • + +

    如何应用TBL规则

      -
    • 规则动词:主要动词和基础动词,-s,-ing,-ed,
    • -
    • 非规则动词
    • -
    -
  • 派生形态学:派生将词干和一个语法语素结合起来,形成新的单词 +
  • 首先应用最宽泛的规则,就是根据概率给每个词标注,选择概率最大的词类作为标注。之后应用变换规则,即如果满足某一条件,就将之前标注的某一词类变换(纠正)为正确的词类,之后不断应用更严格的变换,在上一次变换的基础上进行小部分的修改。
  • +
  • 如何学习到TBL规则
      -
    • 名词化:-ation,-ee,-er,-ness
    • -
    • 派生出形容词:-al,-able,-less
    • +
    • 首先给每个词打上最可能的标签
    • +
    • 检查每一个可能的变换,选择效果提升最多的变换,此处需要直到每一个词正确的标签来衡量变换带来的提升效果,因此是监督学习。
    • +
    • 根据这个被选择的变换给数据重新打标,重复步骤2,直到收敛(提升效果小于某一阈值)
  • +
  • 以上过程输出的结果是一有序变换序列,用来组成一个标注过程,在新语料上应用。虽然可以穷举所有的规则,但是那样复杂度太高,因此我们需要限制变换集合的大小。解决方案是设计一个小的模板集合(抽象变换),每一个允许的变换都是其中一个模板的实例化。
  • -

    形态剖析

    +

    评价和错误分析

      -
    • 例子:我们希望建立一个形态剖析器,输入单词,输出其词干和有关的形态特征,如下表,我们的目标是产生第二列和第四列: -
    • -
    • 我们至少需要: +
    • 一般分为训练集、验证集、测试集,在训练集内做十折交叉验证。
    • +
    • 与人类标注的黄金标准比较计算准确率作为衡量指标。
    • +
    • 一般用人类表现作为ceiling,用一元语法最大概率标注的结果作为baseline。
    • +
    • 通过含混矩阵或者列联表来进行错误分析。在N分类任务中,一个N*N的含混矩阵的第i行第j列元素指示第i类被错分为第j类的次数在总分错次数中的占比。一些常见的容易分错的词性包括:
        -
      • 词表(lexicon):词干和词缀表及其基本信息
      • -
      • 形态顺序规则(morphotactics):什么样的语素跟在什么样的语素之后
      • -
      • 正词法规则(orthographic rule):语素结合时拼写规则的变化
      • +
      • 单数名词、专有名词、形容词
      • +
      • 副词、小品词、介词
      • +
      • 动词过去式、动词过去分词、形容词
    • -
    • 一般不直接构造词表,而是根据形态顺序规则,设计FSA对词干进行屈折变化生成词语。例如一个名词复数化的简单自动机如下图: -
    • -
    • 其中reg-noun代表规则名词,可以通过加s形成复数形式,并且忽略了非规则单数名词(irreg-sg-noun)和非规则复数名词(irreg-pl-noun)。另外一个模拟动词屈折变化的自动机如下图: -
    • -
    • 使用FSA解决形态识别问题(判断输入符号串是否合法)的一种方法是,将状态转移细分到字母层次,但是这样仍然会存在一些问题: -
    -

    有限状态转录机

    +

    词性标注中的一些其他问题

      -
    • 双层形态学:将一个词表示为词汇层和表层,词汇层表示该词语素之间的简单毗连(拼接,concatenation),表层表示单词实际最终的拼写,有限状态转录机是一种有限状态自动机,但其实现的是转录,实现词汇层和表层之间的对应,它有两个输入,产生和识别字符串对,每一个状态转移的弧上有两个标签,代表两个输入。 -
    • -
    • 从四个途径看待FST: +
    • 标注不确定性:一个词在多个词性之间存在歧义,很难区分。这种情况下有些标注器允许一个词被打上多个词性标注。在训练和测试的时候,有三种方式解决这种多标注词:
        -
      • 作为识别器:FST接受一对字符串,作为输入,如果这对字符串在语言的字符串对中则输出接受否则拒绝
      • -
      • 作为生成器:生成语言的字符串对
      • -
      • 作为翻译器:读入一个字符串,输出另一个
      • -
      • 作为关联器:计算两个集合之间的关系
      • +
      • 通过某种方式从这些候选标注中选择一个标注
      • +
      • 训练时指定一个词性,测试时只要打上了候选词性中任意一个就认为标注正确
      • +
      • 将整个不确定的词性集看成一个新的复杂词性
    • -
    • 定义有限状态转录机: +
    • 多部分词:在标注之前需要先分词,一些多部分词是否应该被分为一部分,例如New +York City应该分成三部分还是一个整体,也是各个标注系统需要考虑的。
    • +
    • 未知词:不在词典中的词称为未知词。对于未知词,训练集无法给出它的似然P(w_i +|t_i),可以通过以下几种方式解决:
        -
      • Q:状态{q_i}的有限集合
      • -
      • :有限的输入符号字母表
      • -
      • ∆:有限的输出符号字母表
      • -
      • \(q_0 \in Q\):初始状态
      • -
      • \(F⊆Q\):终极状态集合
      • -
      • \(\delta -(q,w)\):状态之间的转移函数或者转移矩阵,是从Q×到2^Q的一个关系,q是状态,w是字符串,返回新状态集合
      • -
      • \(\sigma -(q,w)\):输出函数,给定每一个状态和输入,返回可能输出字符串的集合,是从\(Q × \Sigma\)\(2^∆\)的一个关系
      • +
      • 只依赖上下文的POS信息预测
      • +
      • 用只出现一次的词来估计未知词的分布,类似于Good Turing打折法
      • +
      • 使用未知词的单词拼写信息,正词法信息。例如连字符、ed结尾、首字母大写等特征。之后在训练集中计算每个特征的似然,并假设特征之间独立,然后累乘特征似然作为未知词的似然:\(P(w_i│t_i )=p(unknown word│t_i ) * p(capital│t_i ) +* p(endings/hyph|t_i)\)
      • +
      • 使用最大熵马尔可夫模型
      • +
      • 使用对数线性模型
    • -
    • 在FST中,字母表的元素不是单个符号,而是符号对,称为可行偶对。类比于FSA和正则语言,FST和正则关系同构,对于并运算封闭,一般对于差、补、交运算不封闭。
    • -
    • 此外,FST, +
    +

    噪声信道模型

      -
    • 关于逆反(逆的逆)闭包,逆反用于方便的实现作为剖析器的FST到作为生成器的FST的转换
    • -
    • 关于组合(嵌套)闭包,用于将多个转录机用一个更复杂的转录机替换。
    • -
    -
  • 转录机一般是非确定性的,如果用FSA的搜索算法会很慢,如果用非确定性到确定性的转换算法,则有些FST本身是不可以被转换为为确定的。
  • -
  • 顺序转录机是一种输入确定的转录机,每个状态转移在给定状态和输入之后是确定的,不像上图中的FST,状态0在输入b时有两种状态转移(转移到相同的状态,但是输出不同)。顺序转录机可以使用\(\epsilon\)符号,但是只能加在输出字符串上,不能加在输入字符串上,如下图: -
  • -
  • 顺序转录机输出不一定是序列的,即从同一状态发出的不同转移可能产生相同输出,因此顺序转录机的逆不一定是顺序转录机,所以在定义顺序转录机时需要定义方向,且转移函数和输出函数需要稍微修改,输出空间缩小为Q和∆。
  • -
  • 顺序转录机的一种泛化形式是并发转录机,其在最终状态额外输出一个字符串,拼接到已经输出的字符串之后。顺序和并发转录机的效率高,且有有效的算法对其进行确定化和最小化,因此很重要。P并发转录机在此基础上可以解决歧义问题。
  • +
  • 贝叶斯推断用于标注可以认为是一种噪声信道模型的应用,本节介绍如何用噪声信道模型来完成拼写纠正任务。 +之前对于非单词错误,通过词典查找可以检测到错误,并根据最小编辑距离纠正错误,但这种方法对于真实单词错误无能为力。噪声信道模型可以纠正这两种类型的拼写错误。
  • +
  • 噪声信道模型的动机在于将错误拼写的单词看成是一个正确拼写的单词经过一个噪声信道时受到干扰扭曲得到。我们尝试所有可能的正确的词,将其输入信道,最后得到的干扰之后的词与错误拼写的词比较,最相似的例子对应的输入词就认为是正确的词。这类噪声信道模型,比如之前的HMM标注模型,是贝叶斯推断的一种特例。我们看到一个观察两(错误拼写词)并希望找到生成这个观察量的隐变量(正确拼写词),也就是找最大后验。
  • +
  • 将噪声信道模型应用于拼写纠正:首先假设各种拼写错误类型,错拼一个、错拼两个、漏拼一个等,然后产生所有可能的纠正,除去词典中不存在的,最后分别计算后验概率,选择后验概率最大的作为纠正。其中需要根据局部上下文特征来计算似然。
  • +
  • 另一种纠正算法是通过迭代来改进的方法:先假设拼写纠正的含混矩阵是均匀分布的,之后根据含混矩阵运行纠正算法,根据纠正之后的数据集更新含混矩阵,反复迭代。这种迭代的算法是一种EM算法。
  • -

    用有限状态转录机进行形态剖析

    +

    根据上下文进行拼写纠正

      -
    • 将单词看成词汇层和表层之间的关系,如下图: FoZnDe.png
    • -
    • 在之前双层形态学的基础定义上,定义自己到自己的映射为基本对,用一个字母表示;用^代表语素边界;用#代表单词边界,在任务中提到需要输出+SG之类的语素特征,这些特征在另一个输出上没有对应的输出符号,因此映射到空字符串或边界符号。我们把输入输出对用冒号连接,也可以写在弧的上下。一个抽象的表示英语名词复数屈折变化的转录机如下图: -
    • -
    • 之后我们需要更新词表,使得非规则复数名词能够被剖析为正确的词干: -
    • -
    • 之后将抽象的转录机写成具体的,由字母组成转移弧的转录机,如下图,只展示了具体化部分非规则复数和单数名词之后的转录机: -
    • +
    • 即真实单词拼写错误的纠正。为了解决这类任务需要对噪声信道模型进行扩展:在产生候选纠正词时,需要包括该单词本身以及同音异形词。之后根据整个句子的最大似然来选择正确的纠正词。
    -

    转录机和正词法规则

    +

    第六章:隐马尔科夫模型和最大熵模型

      -
    • 用拼写规则,也就是正词法规则来处理英语中经常在语素边界发生拼写错误的问题。
    • -
    • 以下是一些拼写规则实例: +
    • 隐马尔科夫模型用来解决序列标注(序列分类问题)。
    • +
    • 最大熵方法是一种分类思想,在满足给定条件下分类应满足限制最小(熵最大),满足奥卡姆剃刀原理。
    • +
    • 最大熵马尔可夫模型是最大熵方法在序列标注任务上的扩展。
    • +
    +

    马尔可夫链

      -
    • 辅音重叠:beg/beggin
    • -
    • E的删除:make/making
    • -
    • E的插入:watch/watches
    • -
    • Y的替换:try/tries
    • -
    • K的插入:panic/panicked
    • +
    • 加权有限自动状态机是对有限自动状态机的扩展,每条转移路径上加上了概率作为权重,说明从这条路径转移的可能性。马尔可夫链是加权有限状态自动机的一种特殊情况,其输入序列唯一确定了自动机会经过的状态序列。马尔可夫链只能对确定性序列分配概率。
    • +
    • 我们将马尔可夫链看作一种概率图模型,一个马尔可夫链由下面的成分确定: +\[ +Q=q_1 q_2…q_N \\ +A=a_{01} a_{02} … a_{n1} … a_{nn} \\ +q_0,q_F \\ +\]
    • +
    • 分别是 +
        +
      • 状态集合
      • +
      • 转移概率矩阵,其中a_ij代表了从状态i转移到状态j的概率\(P(q_j |q_i)\)
      • +
      • 特殊的开始状态和结束状态
    • -
    • 为了实现拼写规则,我们在词汇层和表层之间加入中间层,以符合特定规则的语素毗连作为输入,以修改之后的正确的语素毗连作为输出,例如fox -+N +PL输入到中间层即第一次转录,得到fox ^ s -#,之后中间层到表层的第二次转录检测到特殊语素毗连:x^和s#,就在表层的x和s之间插入一个e,得到foxes。下面的转录机示意图展示了这个过程: -
    • -
    • 这个转录机只考虑x^和s#毗连需插入e这一正词法规则
    • -
    • 其他的词能正常通过
    • -
    • \(Q_0\)代表无关词通过,是接受状态
    • -
    • \(Q_1\)代表看见了zsx,作为中间状态保存,一直保存的是最后的与语素毗连的z,s,x,如果出现了其他字母则返回到q0,其本身也可以作为接受态
    • -
    • \(Q_2\)代表看见了与z,s,x毗连的语素,这之后有四种转移 +
    • 概率图表示将状态看成图中的点,将转移看成边。
    • +
    • 一阶马尔可夫对转移做了很强的假设:某一状态的概率只与前一状态相关: +\[ +P(q_i│q_1…q _{i-1} )=P(q_i |q _{i-1}) +\]
    • +
    • 马尔可夫链的另一种表示不需要开始和结束状态: \[ +\pi = \pi _1,\pi _2 , … , \pi _N \\ +QA={q_x,q_y…} \\ +\]
    • +
    • 分别是:
        -
      • 接了\(x\),\(z\),回到\(q_1\),也就是认为重新接到了可能和语素毗连的x,z
      • -
      • 接了\(s\),分为两种情况,一种是正常需要插入e,这时通过\(\epsilon\)转移到\(q_3\)再到\(q_4\);另一种是本来就需要插入\(e\),这就到达\(q_5\),之后视情况回退了\(q_1\)\(q_0\),或者\(s\)又毗连语素回到\(q_2\)。两种情况不确定,需要通过搜索解决
      • -
      • 接单词边界和其他符号,回到\(q_0\)
      • -
      • \(q_2\)本身也可以作为接受态
      • +
      • 状态的初始概率分布,马尔可夫链以概率\(\pi +_i\)从状态i开始
      • +
      • 集合QA是Q的子集,代表合法的接受状态
    • +
    • 因此状态1作为初始状态的概率既可以写成\(a_{01}\)也可以写成\(\pi _1\)
    -

    结合

    +

    隐马尔科夫模型

      -
    • 现在可以通过三层结构,结合产生语素和进行正词法规则矫正的转录机。从词汇层到中间层用一个转录机产生语素,从中间层到表层可并行使用多个转录机进行正词法规则的矫正。
    • -
    • 两类转录机叠加时可以改写成一类转录机,这时需要对两类状态机状态集合计算笛卡尔积,对新集合内每一个元素建立状态。
    • -
    • 这种三层结构是可逆的,但是进行剖析时(从表层到词汇层)会出现歧义问题,即一个单词可能剖析出多种语素结合,这时单纯依靠转录机无法消歧,需要借助上下文。
    • -
    -

    其他应用(简单介绍)

    +
  • 当马尔可夫链已知时,我们可以用其计算一个观测序列出现的概率。但是观测序列可能依赖于一些不可观测的隐变量,我们可能感兴趣的是推断出这些隐变量。隐马尔科夫模型允许我们同时考虑观测变量和隐变量。
  • +
  • 如之前一样定义隐马尔科夫模型:
      -
    • 不需要词表的FST,PORTER词干处理器:将层叠式重写规则用FST实现,提取出单词的词干。
    • -
    • 分词和分句:一个简单的英文分词可以基于正则表达式实现,一个简单的中文分词可以通过maxmatch(一种基于最大长度匹配的贪婪搜索算法)实现。
    • -
    • 拼写检查与矫正:使用了投影操作的FST可以完成非词错误的检测,然后基于最小编辑距离(使用动态规划算法实现)可以矫正。正常词错误检测和矫正需借助N元语法模型。
    • +
    • Q:大小为N的状态集
    • +
    • A:大小为N*N的转移概率矩阵
    • +
    • O:大小为T的观察事件集
    • +
    • B:观察似然序列,又叫发射概率,\(b_i +(o_t)\)描述了从状态i里生成观察\(o_t\)的概率
    • +
    • \(q_0,q_F\):特殊的起始状态和最终状态,没有相连接的观察量
    • +
  • +
  • 同样的,隐马尔科夫也可以用另一种不依赖初始和结束状态的方式表示。隐马尔科夫模型也做了两个假设,分别是隐状态之间转移和隐状态到观察量转移的一阶马尔可夫性。
  • +
  • 对于隐马尔科夫模型需要解决三类问题: +
      +
    • 似然计算:已知参数和观测序列,求似然\(P(O|\lambda)\)
    • +
    • 解码:已知参数和观测序列,求隐状态序列
    • +
    • 学习:已知观测序列和隐状态集合,求解模型参数
    • +
  • -

    人如何进行形态处理

    +

    计算似然:前向算法

      -
    • 研究表明,人的心理词表存储了一部分形态机构,其他的结构不组合在心理词表中,而需要分别提取并组合。研究说明了两个问题: +
    • 对于马尔可夫链,其没有隐状态到观测量的转移概率矩阵,可以看成观察量与隐状态相同。在隐马尔科夫模型中不能直接计算似然,我们需要直到隐状态序列。
    • +
    • 先假设隐状态序列已知,则似然计算为: \[ +P(O│Q) = \prod _{i=1}^T P(o_i |q_i) +\]
    • +
    • 根据隐状态转移的一阶马尔可夫性,可以求得隐状态的先验,乘以似然得到观测序列和隐状态序列的联合概率: +\[ +P(O,Q)=P(O│Q) * P(Q) = \prod _{i=1}^n P(o_i│q_i ) \prod _{i=1}^n P(q_i +|q _{i-1}) +\]
    • +
    • 对于联合概率积分掉隐状态序列,就可以得到观测概率的似然: \[ +P(O) = \sum _Q P(O,Q) = \sum _Q P(O|Q)P(Q) +\]
    • +
    • 这样计算相当于考虑了所有的隐状态可能,并对每一种可能从隐状态序列开始到结束计算一次似然,实际上可以保留每次计算的中间状态来减少重复计算,也就是动态规划。在前向计算HMM观测似然使用的动态规划算法称为前向算法:
        -
      • 形态尤其是屈折变化之类的能产性形态在人的心理词表中起作用,且人的语音词表和正词法词表可能具有相同结构。
      • -
      • 例如形态这种语言处理的很多性质,可以应用于语言的理解和生成。
      • +
      • \(\alpha _t +(j)\)代表在得到前t个观测量之后当前时刻隐变量处于状态j的概率,: +\[ +\alpha _t (j) = P(o_1,o_2…o_t,q_t=j|\lambda) +\]
      • +
      • 这个概率值可以根据前一时间步的,避免了每次从头开始计算: \[ +\alpha _t (j) = \sum _{i=1}^N \alpha _{t-1} (i) a_{ij} b_j (o_t) +\]
      • +
      • 初始化\(\alpha _1 (j)\)\[ +\alpha _1 (j)=a_{0s} b_s (o_1) +\]
      • +
      • 终止状态: \[ +P(O│\lambda) = \alpha _T (q_F) = \sum _{i=1}^N \alpha _T (i) \alpha +_{iF} +\]
    -

    第四章:N元语法

    +

    解码:维特比算法

      -
    • 语言模型是关于单词序列的统计模型,N元语法模型是其中的一种,它根据之前N-1个单词推测第N个单词,且这样的条件概率可以组成整个单词序列(句子)的联合概率。
    • -
    -

    在语料库中统计单词

    +
  • 解码任务是根据观测序列和参数推断出最有可能隐状态序列。最朴素的做法:对于每种可能的隐状态序列,计算观测序列的似然,取似然最大时对应的隐状态序列。但是这样做就如同朴素的计算似然方法一样,时间复杂度过高,同样的,我们使用动态规划来缩小求解的规模。在解码时使用了一种维特比算法。
      -
    • 区别:word type或者叫 vocabulary size -V,代表语料中不同单词的个数,而tokens,不去重,代表语料的大小。有研究认为词典大小不低于tokens数目的平方根。 -非平滑N元语法模型
    • -
    • 任务:根据以前的单词推断下一个单词的概率:\(P(w|h)\),以及计算整个句子的概率\(P(W)\)
    • -
    • 最朴素的做法是用古典概型,统计所有历史h和当前词w组成的片段在整个语料中出现的次数,并除以历史h片段在整个语料中出现的次数。句子的概率也用相似的方法产生。缺点:依赖大语料,且语言本身多变,这样的计算限制过于严格。
    • -
    • 接下来引入N元语法模型,首先通过概率的链式法则,可以得到条件概率\(P(w|h)\)和整个句子的联合概率\(P(W)\)之间的关系: \[ -P(w_1^n) = P(w_1)P(w_2|w_1)P(w_3|w_1^2)...P(w_n|w_1^{n-1}) \\ -= \prod _{k=1}^n P(w_k|w_1^{k-1}) \\ +
    • \(v_t +(j)\)代表已知前t个观测量(1t)和已知前t个隐状态(0t-1)的条件下,当前时刻隐状态为j的概率: +\[ +v_t (j)=max _{q_0,q_1,…,q_{t-1}} P(q_0,q_1…q_{t-1},o_1,o_2 … +o_t,q_t=j|\lambda) \]
    • -
    • N元语法模型放松了条件概率的限制,做出一个马尔可夫假设:每个单词的概率只和它之前N-1个单词相关,例如二元语法模型,只和前一个单词相关,用这个条件概率去近似\(P(w|h)\): \[ -P(w_n|w_1^{n-1}) \approx P(w_n|w_{n-1}) \\ +
    • 其中我们已知了前t个时间步最大可能的隐状态序列,这些状态序列也是通过动态规划得到的: +\[ +v_t (j)=max _{i=1}^N⁡ v_{t-1} (i) a_{ij} b_j (o_t) \]
    • -
    • N元语法模型里的条件概率用最大似然估计来估算,统计语料中各种N元语法的个数,并归一化,其中可以简化的一点是:以二元语法为例,所有给定单词开头的二元语法总数必定等于该单词一元语法的计数: +
    • 为了得到最佳的隐状态序列,还需要记录每一步的最佳选择,方便回溯得到路径: \[ -P(w_n|w_{n-1}) = \frac {C(w_{n-1}w_n)}{C(w_{n-1})} \\ +{bt}_t (j) = argmax _{i=1}^N v_{t-1} (i) a_{ij} b_j (o_t) \]
    • -
    • 使用N元语法之后,句子概率的链式分解变得容易计算,我们可以通过计算各种句子的概率来判断句子是否包含错字,或者计算某些句子在给定上下文中出现的可能,因为N元语法能捕捉一些语言学上的特征,或者一些用语习惯。在语料充足的时候,我们可以使用三元语法模型获得更好的效果。
    • +
    • 初始化: \[ +v_1 (j) = a_{0j} b_j (o_1) \ \ 1 \leq j \leq N \\ +{bt}_1 (j) = 0 \\ +\]
    • +
    • 终止,分别得到最佳隐状态序列(回溯开始值)及其似然值: \[ +P * = v_t (q_F ) = max_{i=1}^N⁡ v_T (i) * a_{i,F} \\ +q_{T*} = {bt}_T (q_F ) = argmax _{i=1}^N v_T (i) * a_{i,F} \\ +\]
    • +
  • +
  • 维特比算法减小时间复杂度的原因在于其并没有计算所有的隐状态路径,而是利用了每一时间步的最佳路径只能从上一时间步的最佳路径中延伸而来这一条件,减少了路径候选,避免了许多不必要的路径计算。并且每一步利用上一步的结果也是用了动态规划的思想减少了计算量。
  • -

    训练集和测试集

    +

    训练隐马尔科夫模型:前向后向算法

      -
    • N元语法模型对训练集非常敏感。N元语法的N越大,依赖的上下文信息越多,利用N元语法模型生成的句子就越流畅,但这些未必“过于流畅”,其原因在于N元语法概率矩阵非常大且非常稀疏,在N较大例如四元语法中,一旦生成了第一个单词,之后可供的选择非常少,接着生成第二个单词之后选择更少了,往往只有一个选择,这样生成的就和原文中某一个四元语法一模一样。过于依赖训练集会使得模型的泛化能力变差。因此我们选择的训练集和测试集应来自同一细分领域。
    • -
    • 有时候测试集中会出现训练集词典里没有的词,即出现未登录词(Out Of -Vocabulty,OOV)。在开放词典系统中,我们先固定词典大小,并将所有未登录词用特殊符号代替,然后才进行训练。
    • -
    -

    评价N元语法模型:困惑度

    +
  • 学习问题是指已知观测序列和隐状态集合,求解模型参数。
  • +
  • 前向后向算法,又称Baum-Welch算法,是EM算法的一种特例,用来求解包含隐变量的概率生成模型的参数。该算法通过迭代的方式反复更新转移概率和生成概率,直到收敛。BW算法通过设计计数值之比作为隐变量,将转移概率矩阵和生成概率矩阵一起迭代更新。
  • +
  • 先考虑马尔科夫链的学习问题。马尔科夫链可以看作是退化的隐马尔科夫模型,即每个隐变量只生成和自己一样的观测量,生成其他观测量的概率为0。因此只需学习转移概率。
  • +
  • 对于马尔可夫链,可以通过古典概型统计出转移概率: \[ +a_{ij} = \frac {Count(i \rightarrow j)} {\sum _{q \in Q} Count(i +\rightarrow q)} +\]
  • +
  • 我们可以这样直接计算概率是因为在马尔可夫链中我们知道当前所处的状态。对于隐马尔科夫模型我们无法这样直接计算是因为对于给定输入,隐状态序列无法确定。Badum-Welch算法使用了两种简洁的直觉来解决这一问题:
      -
    • 模型的评价分两种:外在评价和内在评价。外在评价是一种端到端的评价,看看某一模块的改进是否改进了整个模型的效果。内在评价的目的是快速衡量模块的潜在改进效果。内在评价的潜在改进效果不一定会使得端到端的外在评价提高,但是一般两者都存在某种正相关关系。
    • -
    • 困惑度(Perplexsity,PP)是一种关于概率模型的内在评价方法。语言模型的在测试集上的困惑度是语言模型给测试集分配的概率的函数。以二元语法为例,测试集上的困惑度为: +
    • 迭代估计,先假设一种转移概率和生成概率,再根据假设的概率推出更好的概率
    • +
    • 计算某一观测量的前向概率,并将这个概率分摊到不同的路径上,通过这种方式估计概率
    • +
  • +
  • 首先类似于前向概率,我们定义后向概率: +
      +
    • \(\beta _t +(i)\)代表在得到后t个观测量之后当前时刻隐变量处于状态i的概率,\(\lambda\)为模型参数: \[ +\beta _t (i) = P(o_{t+1},o_{t+2}…o_T,q_t=i|\lambda) +\]
    • +
    • 类似于后向概率的归纳计算: \[ +\beta_t (i) = \sum _{j=1}^N a_{ij} b_j (o_{t+1} ) \beta _{t+1} (j), \ +\ 1≤i≤N,1≤t<T +\]
    • +
    • 初始化\(\alpha _1 (j)\)\[ +\beta _T (i)=\alpha _(i,F) +\]
    • +
    • 终止状态: \[ +P(O│\lambda)=\alpha _t (q_F )=\beta_1 (0)= \sum _{i=1}^N a_{0j} b_j +(o_1) \beta _1 (j) +\]
    • +
  • +
  • 类似的,我们希望马尔可夫链中的古典概率能帮助我们估计转移概率: \[ +a_{ij}^{*} = +\frac{从状态i转移到状态j的计数值期望}{从状态i转移出去的计数值期望} +\]
  • +
  • 如何估计计数值:我们将整个序列的转移路径计数值转化为时间步之间转移路径计数值之和,时间步之间某一条转移路径的概率为: \[ -PP(W) = \sqrt[n]{\prod _{i=1}^N \frac {1}{P(w_i|w_{i-1})}} \\ +P(q_t=i,q_{t+1}=j) \]
  • -
  • 概率越高,困惑度越低。困惑度的两种解释: +
  • 首先考虑所有的观测序列和这一转移路径的联合概率(省略了以参数\(\lambda\)为条件): \[ +P(q_t=i,q_{t+1}=j,O) +\]
  • +
  • 观察下面的概率图: FoZWVJ.png
  • +
  • 可以看到这一联合概率包含了三个部分:
      -
    • 加权的平均分支因子:分支因子是指可能接在任何上文之后的单词的数目。显然,如果我们的模型啥也没学习到,那么测试集任何单词可以接在任何上文之后,分支因子很高,困惑度很高;相反,如果我们的模型学习到了具体的规则,那么单词被限制接在一些指定上文之后,困惑度变低。困惑度使用了概率加权分支因子,分支因子的大小在模型学习前后不变,”morning”仍然可以接到任何上文之后,但是它接到”good”之后的概率变大了,因此是加权的分支因子。
    • -
    • 熵:对于语言序列,我们定义一个序列的熵为: \[H(w_1,w_2,…,w_n )=-\sum _{W_1^n \in L} p(W_1^n) -\log -⁡p(W_1^n)\]也就是这个序列中所有前缀子序列的熵之和,其均值是序列的熵率。计算整个语言的熵,假设语言是一个产生单词序列的随机过程,单词序列无限长,则其熵率是:\[H(L)=\lim _{n \rightarrow \infty}⁡ \frac 1n -H(w_1,w_2,…,w_n) =\lim _{n \rightarrow \infty} -⁡\frac 1n \sum _{W \in L} -p(W_1^n) \log -⁡p(W_1^n)\]根据Shannon-McMillan-Breiman理论,在n趋于无穷的情况下,如果语言既是平稳又是正则的,上面这些子串的和的熵,可以用最大串代替每一个子串得到,这里的代替是指log后面求的是最大串的概率,log之前的概率依然是各个子串的概率?假如是这样的话提出最大串的概率对数,对所有子串概率求和得到:\[H(L)=\lim _{n \rightarrow \infty} -⁡ \frac 1n \log -⁡p(w_1,w_2,…,w_n)\]交叉熵可以衡量我们的模型生成的概率分布到指定概率分布之间的距离,我们希望模型生成概率分布尽可能近似真实分布,即交叉熵小。具体衡量时是对相同的语言序列,计算训练得到的模型m和理想模型p在生成这个序列上的概率的交叉熵:\[H(p,m) = \lim _{n \rightarrow \infty}⁡ - \frac 1n -\sum _{W \in L} p(W_1^n) \log⁡ -m(W_1^n)\]但是我们不知道理想的分布p,这时根据之前的Shannon-McMillan-Breiman定理,得到了只包含一个概率分布的序列交叉熵(?):\[H(p,m)=\lim _{n \rightarrow \infty}⁡ - \frac 1n -\log⁡ -m(W_1^n)\]在测试数据上我们没有无限长的序列,就用有限长的序列的交叉熵近似这个无限长序列的交叉熵。困惑度则是这个(近似的?只包含一个概率分布的?)交叉熵取指数运算: +
    • T时刻隐状态为i的前向概率
    • +
    • T+1时刻隐状态为j的后向概率
    • +
    • T时刻与T+1时刻的状态转移概率以及生成对应观测量的生成概率
    • +
  • +
  • 所以有: \[ +P(q_t=i,q_{t+1}=j,O)=\alpha _t (i) a_{ij} b_j (o_{t+1} ) \beta _{t+1} +(j) +\]
  • +
  • 为了从联合分布中得到已知观测序列求转移路径的联合概率,需要计算观测序列的概率,可以通过前向概率或者后向概率求得: +\[ +P(O)=\alpha _t (N)=\beta _T (1) = \sum _{j=1}^N \alpha _t (j) \beta_t +(j) +\]
  • +
  • 最终得到 \[ +ξ_t (i,j)=P(q_t=i,q_{t+1}=j│O) = \frac {(\alpha _t (i) a_{ij} b_j +(o_{t+1} ) \beta_{t+1} (j))}{(\alpha _t (N))} +\]
  • +
  • 最后,对所有时间步求和就可以得到从状态i转移到状态j的期望计数值,从而进一步得到转移概率的估计: +\[ +a_{ij}^{*} = \frac {\sum _{t=1}^{T-1} ξ_t (i,j)}{\sum _{t=1}^{T-1} \sum +_{j=1}^{N-1} ξ_t (i,j)} +\]
  • +
  • 同样的,我们还希望得到生成概率的估计: \[ +b_{j}^{*} (v_k) = \frac {在状态j观测到符号v_k +的计数值期望}{状态j观测到所有符号的计数值期望} +\]
  • +
  • 类似的,通过先计算联合分布再计算条件分布的方式得到在t时刻处于隐状态j的概率: +\[ +γ_t (j)=P(q_t=j│O) = \frac {P(q_t=j,O)}{P(O)} +\]
  • +
  • 联合概率包含两个部分,即t时刻处于状态j的前向概率和后向概率,所以有: +\[ +γ_t (j) = \frac {\alpha _t (j) \beta_t (j)}{\alpha _t (N)} +\]
  • +
  • 类似的,对所有时间步累加,进而得到生成概率的估计: \[ +b_{j}^{*} (v_k) = \frac{\sum _{t=1 s.t. O_t=v_k}^T γ_t (j) }{\sum +_{t=1}^T γ_t (j) } +\]
  • +
  • 这两个式子是在已知前向概率和后向概率\((\alpha,\beta)\)的情况下,计算出中间变量(隐变量)(ξ,γ),引入隐变量的动机是将a、b估计值的期望计数值之比转化为概率之比,且这两个隐变量可以用a,b表示。再由隐变量计算出转移概率和生成概率,因此形成了一个迭代的循环,可以用EM算法求解: \[ -Perplexity(W) = 2^{H(W)} \\ -= P(w_1 w_2 ... w_N)^{\frac {-1}{N}} \\ -= \sqrt[n]{\frac {1}{P(w_1 w_2 ... w_N)}} \\ -= \sqrt[n]{\prod _{i=1}^N \frac {1}{P(w_i | w_1 ... w_{i-1})}} \\ +a,b→\alpha,\beta→ξ,γ→a,b \]
  • - +
  • E-step: \[ +γ_t (j) = (\alpha _t (j) \beta_t (j))/(\alpha _t (N)) ξ_t (i,j) \\ += (\alpha _t (i) a_{ij} b_j (o_{t+1} ) \beta_{t+1} (j))/(\alpha _t (N)) +\\ +\]
  • +
  • M-step(最大化的目标是什么): \[ +a _{ij} = (\sum _{t=1}^{T-1} ξ_t (i,j) )/(\sum _{t=1}^{T-1} \sum +_{j=1}^{N-1} ξ_t (i,j) ) \\ +b ̂_j(v_k) = (\sum _{t=1 s.t. O_t=v_k}^T γ_t (j) )/(\sum +_{t=1}^T γ_t (j) ) \\ +\]
  • +
  • 迭代时需重新计算: \[ +\alpha _t (j) = \sum _{i=1}^N \alpha_{t-1} (i) a_ij b_j (o_t) \\ +\beta_t (i) = \sum _{j=1}^N a_ij b_j (o_{t+1} ) \beta_{t+1} (j) \\ +\]
  • +
  • 迭代的初始状态对于EM算法来说很重要,经常是通过引入一些外部信息来设计一个好的初始状态。
  • -

    平滑

    -
      -
    • 因为N元语法模型依赖语料,一般而言对于N越高的N元语法,语料提供的数据越稀疏。这种情况下N元语法对于那些计数很小的语法估计很差,且如果测试集中某一句包含了训练集中没有出现的N元语法时,我们无法使用困惑度进行评价。因此我们使用平滑作为一种改进方法,使得N元语法的最大似然估计能够适应这些存在0概率的情况。
    • -
    • 接下来介绍了两种平滑: +

      最大熵模型:背景

        -
      • 拉普拉斯平滑(加1平滑)
      • -
      • Good-Turing 打折法
      • -
    • +
    • 最大熵模型另一种广为人知的形式是多项Logistic回归(Softmax?)。
    • +
    • 最大熵模型解决分类问题,最大熵模型作为一种概率分类器,能够根据样本的特征求出样本属于每一个类别的概率,进而进行分类。
    • +
    • 最大熵模型属于指数家族(对数线性)分类器,通过将特征线性组合,取指数得到分类概率: +\[ +p(c│x)=\frac 1Z exp⁡(\sum _i weight_i feature_i) +\]
    • +
    • Z是一个归一化系数,使得生成的概率之和为1。
    -

    拉普拉斯平滑

    +

    最大熵建模

      -
    • 加1平滑就是在计算概率归一化之前,给每个计数加1,对应的,归一化时分母整体加了一个词典大小: -\[ -P_{Laplace}(w_i) = \frac {c_i + 1}{N+V} \\ +
    • 将二分类Logistic回归推广到多分类问题就得到: \[ +P(c│x) = \frac {exp⁡(\sum _(i=0)^N w_ci f_i) } {\sum _{c^{*} in +C} exp⁡(\sum _{i=0}^N w_{c^{*} i} f_i) } \]
    • -
    • 为了表现平滑的作用,引入调整计数\(c^{*}\),将平滑后的概率写成和平滑之前一样的形式: +
    • 语音和语言处理中的特征通常是二值的(是否有该特征),因此使用指示函数表示特征 \[ -P_{Laplace} (w_i) = \frac {(C_i^{*})}{N} \\ -C_i^{*} = \frac {(C_i+1)N}{(N+V)} \\ +P(c│x) = \frac {exp⁡(\sum _{i=0}^N w_{c_i} f_i (c,x)) }{\sum _{c^{*} +\in C} exp⁡(\sum _{i=0}^N w_{c^{*} i} f_i (c^{*},x)) } \]
    • -
    • 一种看待平滑的角度是:对每个非0计数打折,分一些概率给0计数,定义相对打折\(d_c\)(定义在非0计数上), 注意到在该模型中每一个类都有其独立的线性权重w_c。相比于硬分布,最大熵模型能够给出分到每一类的概率,因此可以求出每一时刻的分类概率进而求出整体分类概率,得到全局最优分类结果。注意到不同于支持向量机等模型,最大熵模型无法利用特征之间的组合,必须手动构造组合作为新的特征。
    • +
    • 一般使用加了正则化的最大似然作为优化的目标函数: \[ -d_c = \frac {c^{*}} {c} +w ̂={argmax} _w \sum _i \log P(y^{(i)}│x^{(i) } ) - \alpha \sum +_{j=1}^N w_j^2 \]
    • -
    • \(d_c\)代表了打折前后单词计数的变化。平滑之后,对于非0计数,当\(C_i < \frac -NV\)时,计数增加;否则计数减少。计数越大,打折越多,增加越少(减少越多)。当0计数很多时,N/V较小,这时大部分非0计数都会减少,且减少较多。
    • -
    • 而0计数则没有收到打折的影响。因此在一轮不同程度的增长之后,再归一化的结果就是非0计数分享了一些概率给0计数。写成调整计数的形式,就是非0计数减少数值,0计数变化(一般是减少)数值(但不是减少的完全等于增加的)。 -书中给出了一个例子,下图是一部分语料的二元语法平滑之后的计数,蓝色代表平滑加1之后的0计数: -FoZNDg.png -如果把表写成调整计数的形式: FoZtKS.png
    • -
    • 可以看到,本来的0计数(蓝色)从0变大,而其他的计数减少,例如< i -want>,从827减少到527,从608减少到238。
    • -
    • 当0计数很多时,非0计数减少的数值很多,可以使用一个小于1的小数\(\delta\)代替1,即加\(\delta\)平滑。通常这个\(\delta\)是动态变化的。
    • -
    -

    GT打折法

    -
      -
    • 类似于Good-Turing打折法, Witten-Bell打折法, Kneyser-Ney -平滑一类的方法,它们的基本动机是用只出现一次的事物的计数来估计从未出现的事物的计数。只出现一次的语法称为单件(singleton)或者罕见语(hapax -legomena)。Good-Turing打折法用单件的频率来估计0计数二元语法。
    • -
    • 定义N_c为出现c次的N元语法的总个数(不是总个数乘以c),并称之为频度c的频度。对N_c中的c的最大似然估计是c。这样相当于将N元语法按其出现次数分成了多个桶,GT打折法用c+1号桶里语法概率的最大似然估计来重新估计c号桶内语法的概率。因此GT估计之后最大似然估计得到的c被替换成: +
    • 这种正则化相当于给权重的概率分布加了一个零均值高斯先验,权重越偏离均值,即权重越大,其概率越低。
    • +
    • 为什么多分类Logistic回归是最大熵模型:最大熵模型保证在满足给定约束下,无约束的部分分类应该是等概率分配,例如在两个约束下: \[ -c^{*}=(c+1) \frac {N_{c+1}}{N_c} +P(NN)+P(JJ)+P(NNS)+P(VB)=1 \\ +P(t_i=NN or t_i=NNS)=8/10 \\ \]
    • -
    • 之后计算某N元语法的概率: -
        -
      • 从未出现:\(P_{GT}^{*}=\frac{N_1}{N}\)。其中N是所有N元语法数\((\sum _i N_i * -i)\)。这里假设了我们已知\(N_0\),则此式表示某一具体未知计数N元语法概率时还应除以\(N_0\)
      • -
      • 已出现(已知计数):\(P_{GT}^{*} = -\frac{c^{*}}{N}\)
      • -
    • -
    • 这样计算,\(N_1\)的一些概率转移到了\(N_0\)上。GT打折法假设所有的N元语法概率分布满足二项式分布,且假设我们已知\(N_0\),以二元语法为例: 则满足这两个约束,最大熵模型分配的概率结果为: \[ -N_0 = V^2 - \sum _{i>0} N_i \\ -\]
    • -
    • 其他注意事项: -
        -
      • 有些\(N_c\)为0,这时我们无法用这些\(N_c\)来计算平滑后的c。这种情况下我们直接放弃平滑,令\(c^{*} = -c\),再根据正常的数据计算出一个对数线性映射,\(log⁡(N_c) = a + b -\log(c)\),代入放弃平滑的c并用其倒推计算计数为0的\(N_c\),使得这些\(N_c\)有值,不会影响更高阶的c的计算。
      • -
      • 只对较小c的\(N_c\)进行平滑,较大c的\(N_c\)认为足够可靠,设定一个阈值k,对\(c < k\)\(N_c\)计算: \[ -c^{*} = \frac {(c+1) \frac {N_c+1}{N_c} - c \frac {(k+1) N_{k+1} }{N_1} -} {1- \frac {(k+1)N_{k+1}} {N_1}} \\ +p(NN)=4/10 \\ +p(JJ)=1/10 \\ +p(NNS)=4/10 \\ +p(VB)=1/10 \\ \]
      • -
      • 计算较小的c如c=1时,也看成c=0的情况进行平滑
      • -
    • -
    • 一个例子:
    • -
    -

    插值与回退

    -
      -
    • 上述的平滑只考虑了如何转移概率到计数为0的语法上去,对于条件概率\(p(w|h)\),我们也可以采用类似的思想,假如不存在某个三元语法帮助计算\(p(w_n |w_{n-1} -w_{n-2})\),则可以用阶数较低的语法\(p(w_n |w_{n-1})\)帮助计算,有两种方案: -
        -
      • 回退:用低阶数语法的替代0计数的高阶语法
      • -
      • 插值:用低阶数语法的加权估计高阶语法
      • -
    • -
    • 在Katz回退中,我们使用GT打折作为方法的一部分:GT打折告诉我们有多少概率可以从已知语法中分出来,Katz回退告诉我们如何将这些分出来的概率分配给未知语法。在之前的GT打折法中,我们将分出的概率均匀分给每一个未知语法,而Katz回退则依靠低阶语法的信息来分配: -
    • -
    • 其中\(P^{*}\)是打折之后得到的概率;,保证分出去的概率等于未知语法分配得到的概率。
    • -
    • 插值则是用低阶语法概率加权求和得到未知高阶语法概率: FoZUbQ.png
    • -
    • 加权的系数还可以通过上下文动态计算。具体系数的计算有两种方法: -
        -
      • 尝试各种系数,用在验证集上表现最好的系数组合
      • -
      • 将系数看成是概率生成模型的隐变量,使用EM算法进行推断
      • -
    • -
    -

    实际问题:工具和数据格式

    -
      -
    • 在语言模型计算中,一般将概率取对数进行计算,原因有二:防止数值下溢;取对数能将累乘运算变成累加,加速计算。
    • -
    • 回退N元语法模型一般采用ARPA格式。ARPA格式文件由一些头部信息和各类N元语法的列表组成,列表中包含了该类N元语法下所有语法,概率,和回退的归一化系数。只有能够称为高阶语法前缀的低阶语法才能在回退中被利用,并拥有归一化系数。
    • -
    • 两种计算N元语法模型的工具包:SRILM toolkit 和Cambridge-CMU -toolkit
    • -
    -

    语言建模中的高级问题

    -

    高级平滑方法:Kneser-Ney平滑

    -
      -
    • 注意到在GT打折法当中,打折之后估计的c值比最大似然估计得到的c值近似多出一个定值d。绝对打折法便考虑了这一点,在每个计数中减去这个d: -
    • -
    • Kneser-Ney平滑吸收了这种观点,并且还考虑了连续性:在不同上文中出现的单词更有可能出现在新的上文之后,在回退时,我们应该优先考虑这种在多种上文环境里出现的词,而不是那些出现次数很多,但仅仅在特定上文中出现的词。 -
    • -
    • 在Kneser-Ney中,插值法能够比回退法取得更加好的效果: FoZ05n.png
    • +
    • 在The equivalence of logistic regression and maximum entropy +models一文中证明了在广义线性回归模型的平衡条件约束下,满足最大熵分布的非线性激活函数就是sigmoid,即logistic回归。
    -

    基于分类的N元语法

    +

    最大熵马尔可夫模型

      -
    • 这种方法是为了解决训练数据的稀疏性。例如IBM聚类,每个单词只能属于一类,以二元语法为例,某个二元语法的条件概率的计算变为给定上文所在类,某个单词的条件概率,还可以进一步链式分解为两个类的条件概率乘以某个单词在给定其类条件下的条件概率: +
    • 最大熵模型只能对单一观测量分类,使用最大熵马尔可夫模型可以将其扩展到序列分类问题上。
    • +
    • 最大熵马尔可夫比隐马尔科夫模型好在哪儿?隐马尔科夫模型对于每个观测量的分类依赖于转移概率和生成概率,假如我们想要在标注过程中引入外部知识,则需要将外部知识编码进这两类概率中,不方便。最大熵马尔可夫模型能够更简单的引入外部知识。
    • +
    • 在隐马尔科夫模型中我们优化似然,并且乘以先验来估计后验: \[ +T ̂= {argmax}_T ∏_i P(word_i│tag_i ) ∏_i P(tag_i│tag _{i-1} ) +\]
    • +
    • 在最大熵隐马尔科夫模型中,我们直接计算后验。因为我们直接训练模型来分类,即最大熵马尔可夫模型是一类判别模型,而不是生成模型: \[ -p(w_i│w_{i-1} ) \approx p(w_i│c_{i-1} ) = p(c_i |c_{i-1}) \cdot p(w_i -|c_i) +T ̂= {argmax}_T ∏_i P(tag_i |word_i,tag _{i-1}) +\]
    • +
    • 因此在最大熵隐马尔科夫模型中没有分别对似然和先验建模,而是通过一个单一的概率模型来估计后验。两者的区别如下图所示: +
    • +
    • 另外最大熵马尔可夫模型可以依赖的特征更多,依赖方式更灵活,如下图: +
    • +
    • 用公式表示这一差别: \[ +HMM:P(Q│O)=∏_{i=1}^n P(o_i |q_i)×∏_{i=1}^n P(q_i |q _{i-1}) \\ +MEMM:P(Q│O)=∏_{i=1}^n P(q_i |q _{i-1},o_i) \\ +\]
    • +
    • 当估计单一转移概率(从状态q^{*}转移到状态q,产生观测量o)时,我们使用以下的最大熵模型: +\[ +P(q│q^{*},o)=\frac{1}{Z(o,q^{*})} exp⁡(\sum _i w_i f_i (o,q)) \]
    -

    语言模型适应和网络应用

    -
      -
    • 适应是指在大型宽泛的语料库上训练语言模型,并在小的细分领域的语言模型上进一步改进。网络是大型语料库的一个重要来源。在实际应用时我们不可能搜索每一个语法并统计搜索得到所有页面上的所有语法,我们用搜索得到的页面数来近似计数。
    • -
    -

    利用更长距离的上文信息

    -
      -
    • 通常我们使用二元和三元语法模型,但是更大的N能够带来更好的效果。为了捕捉更长距离的上文信息,有以下几种方法: -
        -
      • 基于缓存机制的N元语法模型
      • -
      • 基于主题建模的N元语法模型,对不同主题建模语言模型,再加权求和
      • -
      • 不一定使用相邻的上文信息,例如skip -N-grams或者不一定使用定长的上文信息,例如变长N-grams
      • -
    • -
    -

    第十六章:语言的复杂性

    -

    Chomsky层级

    -
      -
    • Chomsky层级反映了不同形式化方法描述的语法之间的蕴含关系,较强生成能力或者说更复杂的语法在层级的外层。从外到内,加在可重写语法规则上的约束增加,语言的生成能力逐渐降低。 -
    • -
    • 五种语法对应的规则和应用实例: Foepxf.png -
        -
      • 0型语法:规则上只有一个限制,即规则左侧不能为空字符串。0型语法刻画了递归可枚举语言
      • -
      • 上下文相关语法:可以把上下文,
      • -
      • 温和的上下文相关语法
      • -
      • 上下文无关语法:可以把任何单独的非终极符号重写为由终极符号和非终极符号构成的字符串,也可以重写为空字符串
      • -
      • 正则语法:可以是右线性也可以是左线性,以右线性为例,非终极符号可以重写为左边加了若干终极符号的另一个非终极符号,右线性不断地在字符串左侧生成终极符号。
      • -
    • -
    -

    自然语言是否正则

    -
      -
    • 判断语言是否正则能够让我们了解应该用哪一层次的语法来描述一门语言,且这个问题能够帮助我们了解自然语言的不同方面的某些形式特性。
    • -
    • 抽吸引理:用来证明一门语言不是正则语言。 -
        -
      • 如果一门语言可以被有限状态自动机来描述,则与自动机对应有一个记忆约束量。这个约束量对于不同的符号串不会增长的很大,因为其状态数目是固定的,更长的符号串应该是通过状态之间转移产生而不是增加状态数目。因此这个记忆量不一定和输入的长度成比例。
      • -
      • 如果一个正则语言能够描述任意长的符号序列,比自动机的状态数目还多,则该语言的自动机中必然存在回路。 -
      • -
    • -
    • 如图所示自动机,可以表述xyz,xyyz,xyyyz.....,当然也可以将中间无限长的y序列“抽吸掉”,表述xz。抽吸引理表述如下:
    • -
    • 设L是一个有限的正则语言,那么必然存在符号串x,y,z,使得对于任意n≥0,y≠\(\epsilon\),且xy^n z∈L
    • -
    • 即假如一门语言是正则语言,则存在某一个符号串y,可以被适当的“抽吸”。这个定理是一门语言是正则语言的必要非充分条件。
    • -
    • 有学者证明英语不是一门正则语言: +

      最大熵马尔可夫模型的解码(推断)

        -
      • 具有镜像性质的句子通过抽吸原理可以证明不是正则语言,而英语中一个特殊的子集合和这种镜像性质的句子是同态的。
      • -
      • 另一种证明基于某些带有中心-嵌套结构的句子。这种句子可以由英语和某一类简单的正则表达式相交得到,通过抽吸原理可以得到这种句子不是正则语言。英语和正则语言的交不是正则语言,则英语不是正则语言。
      • -
    • +
    • MEMM同样使用维特比算法进行解码
    • +
    • 使用维特比算法解码的通用框架是: \[ +v_t (j)=max_{i=1}^N⁡ v_{t-1} (i)P(s_j│s_i )P(o_t |s_j) +\]
    • +
    • 在HMM模型中这一框架具体化为: \[ +v_t (j)=max_{i=1}^N⁡ v_{t-1} (i) a_ij b_j (o_t) +\]
    • +
    • 在MEMM中直接将似然和先验替换为后验: \[ +v_t (j)=max_{i=1}^N⁡ v_{t-1} (j)P(s_j |s_i,o_t) +\]
    -

    自然语言是否上下文无关

    +

    最大熵马尔可夫模型的训练

      -
    • 既然自然语言不是正则语言,我们接着考虑更宽松的限定,自然语言是否是上下文无关的?
    • -
    • 不是......
    • +
    • MEMM作为最大熵模型的推广,训练过程使用和最大熵模型一样的监督算法。如果训练数据的标签序列存在缺失,也可以通过EM算法进行半监督学习。
    -

    计算复杂性和人的语言处理

    +

    第十二章:英语的形式语法

    +

    组成性

      -
    • 人对中心嵌套句子处理很困难,因为人们剖析时利用的栈记忆有限,且栈中不同层次记忆容易混淆。
    • +
    • 英语中的单词是如何组成一个词组的呢?
    • +
    • 换句话说,我们如何判断一些单词组合成了一个部分?一种可能是这种组合都能在相似的句法环境中出现,例如名词词组都能在一个动词之前出现。另一种可能依据来自于前置和后置结构,例如前置短语on +September +seventeenth可以放在句子的前面,中间或者后面,但是组合成这个短语的各个部分不能拆出来放在句子的不同位置,因此我们判断on +September seventeenth这三个词组成了一个短语。
    -

    第五章:词类标注

    +

    上下文无关法则

      -
    • 各种表述:POS(Part Of Speech)、word classes(词类)、morphological -classes(形态类)、lexical tags(词汇标记)。
    • -
    • POS的意义在于: +
    • 上下文无关语法,简称CFG,又称为短语结构语法,其形式化方法等价于Backus-Naur范式。一个上下文无关语法包含两个部分:规则或者产生式,词表。
    • +
    • 例如,用上下文无关语法描述名词词组,一种描述方式是名词词组可以由一个专有名词构成,也可以由一个限定词加一个名词性成分构成,而名词性成分可以是一个或多个名词,此CFG的规则为:
        -
      • 能够提供关于单词及其上下文的大量信息。
      • -
      • 同一单词在不同词类下发音不同,因此POS还能为语音处理提供信息。
      • -
      • 进行词干分割(stemming),辅助信息检索
      • +
      • NP→Det Nominal
      • +
      • NP→ProperNoun
      • +
      • Nominal→Noun|Noun Nominal
    • -
    • 本章介绍三种词类标注算法: +
    • CFG可以层级嵌套,因此上面的规则可以与下面表示词汇事实的规则(词表)结合起来:
        -
      • 基于规则的算法
      • -
      • 基于概率的算法,隐马尔科夫模型
      • -
      • 基于变换的算法
      • +
      • Det→a
      • +
      • Det→the
      • +
      • Noun→flight
    • -
    -

    一般词类

    +
  • 符号分为两类:
      -
    • POS分为封闭集和开放集,封闭集集合相对稳定,例如介词,开放集的词语则不断动态扩充,例如名词和动词。特定某个说话人或者某个语料的开放集可能不同,但是所有说一种语言以及各种大规模语料库可能共享相同的封闭集。封闭集的单词称为虚词(功能词,function -word),这些词是语法词,一般很短,出现频次很高。
    • -
    • 四大开放类:名词、动词、形容词、副词。
    • -
    • 名词是从功能上定义的而不是从语义上定义的,因此名词一般表示人、地点、事物,但既不充分也不必要。定义名词: +
    • 终极符号:与现实中单词对应的符号,词表是引入终极符号的规则的集合
    • +
    • 非终极符号:表示终极符号的聚类或者概括性符号
    • +
  • +
  • 在每个规则里箭头右边包含一个或多个终极符号和非终极符号,箭头左边为一个非终极符号,与每个单词相关联的是其词类范畴(词类)。
  • +
  • CFG既可以看成是生成句子的一种机制,也可以看成是给一个句子分配结构的机制。
  • +
  • 以之前提到的CFG为例,对一个符号串NP,可以逐步生成: \[ +NP→Det Nominal→Det Noun→a flight +\]
  • +
  • 称 a flight是NP的一个推导,一般用一个剖析树表示一种推导: FoZ5P1.png +一个CFG定义了一个形式语言,形式语言是符号串的集合,如果有一个语法推导出的句子处于由该语法定义的形式语言中,这个句子就是合语法的。使用形式语言来模拟自然语言的语法成为生成式语法。
  • +
  • 上下文无关语法的正式定义:
      -
    • 与限定词同时出现
    • -
    • 可以受主有代词修饰
    • -
    • 大多数可以以复数形式出现(即可数名词),物质名词不可数。单数可数名词出现时不能没有冠词
    • +
    • N:非终止符号(或者变量)的集合
    • +
    • Sigma:终止符号的集合,与N不相交
    • +
    • R:规则或者产生式的集合
    • +
    • S:指定的开始符号
  • -
  • 动词,表示行为和过程的词,包括第三人称单数、非第三人称单数、进行时、过去分词几种形态
  • -
  • 形容词,描述性质和质量
  • -
  • 副词,用于修饰,副词可以修饰动词、动词短语、其它副词。
  • -
  • 英语中的一些封闭类: +
  • 一些约定定义:
      -
    • 介词 prepositions:出现在名词短语之前,表示关系
    • -
    • 限定词 determiners 冠词 articles:与有定性(definiteness)相关
    • -
    • 代词 pronouns:简短的援引某些名词短语、实体、或事件的一种形式
    • -
    • 连接词 conjunctions:用于连接和补足(complementation)
    • -
    • 助动词 auxiliary -verbs:标志主要动词的某些语义特征,包括:时态、完成体、极性对立、情态
    • -
    • 小品词 particles:与动词结合形成短语动词
    • -
    • 数词 numerals
    • +
    • 大写字母:代表非终止符号
    • +
    • S:开始符号
    • +
    • 小写希腊字母:从非终止符号和终止符号的并集中抽取出来的符号串
    • +
    • 小写罗马字母:终止符号串
  • +
  • 直接导出的定义: 公式待补充
  • +
  • 导出是直接导出的泛化。之后我们可以正式定义由语法G生成的语言L是一个由终止符号组成的字符串集合,这些终止符号可以从指定的开始符号S通过语法G导出: +公式待补充
  • +
  • 将一个单词序列映射到其对应的剖析树成为句法剖析。
  • -

    词类标注

    +

    英语的一些语法规则

      -
    • 标注算法的输入是单词的符号串和标记集,输出要让每一个单词标注上一个单独且最佳的标记。如果每个单词只对应一种词性,那么根据已有的标记集,词类标注就是一个简单的查表打标的过程,但是很多词存在多种词性,例如book既可以是名词也可以是动词,因此要进行消歧,词类标注是歧义消解的一个重要方面。
    • -
    -

    基于规则的词类标注

    +
  • 英语中最常用最重要的四种句子结构:
      -
    • 介绍了ENGTWOL系统,根据双层形态学构建,对于每一个词的每一种词类分别立条,计算时不计屈折形式和派生形式.
    • -
    • 标注算法的第一阶段是将单词通过双层转录机,得到该单词的所有可能词类
    • -
    • 之后通过施加约束规则排除不正确的词类。这些规则通过上下文的类型来决定排除哪些词类。
    • +
    • 陈述式结构:主语名词短语加一个动词短语
    • +
    • 命令式结构:通常以一个动词短语开头,并且没有主语
    • +
    • Yes-no疑问式结构:通常用于提问,并且以一个助动词开头,后面紧跟一个主语NP,再跟一个VP
    • +
    • Wh疑问式结构:包含一个wh短语成分
    • +
  • +
  • 在之前的描述中开始符号用于单独生成整个句子,但是S也可以出现在语法生成规则的右边,嵌入到更大的句子当中。这样的S称为从句,拥有完整的语义。拥有完整的语义是指这个S在整体句子的语法剖析树当中,其子树当中的主要动词拥有所需的所有论元。
  • -

    基于隐马尔科夫模型的词类标注

    +

    名词短语

      -
    • 使用隐马尔科夫模型做词类标注是一类贝叶斯推断,这种方法将词类标注看成是序列分类任务。观察量为一个词序列(比如句子),任务是给这个序列分配一个标注序列。
    • -
    • 给定一个句子,贝叶斯推断想要在所有标注序列可能中选择最好的一个序列,即 -\[ -{t_1^n} _{best} = {argmax} _{t_1^n} P(t_1^n |w_1^n) -\]
    • -
    • 使用贝叶斯法则将其转化为: \[ -{t_1^n} _{best}={argmax} -_{t_1^n} \frac{P(w_1^n│t_1^n)P(t_1^n)}{P(w_1^n)} = {argmax} _{t_1^n} -P(w_1^n│t_1^n)P(t_1^n) -\]
    • -
    • 隐马尔科夫模型在此基础上做了两点假设 +
    • 限定词Det:名词短语可以以一些简单的词法限定词开始,例如a,the,this,those,any,some等等,限定词的位置也可以被更复杂的表示替代,例如所有格。这样的表示是可以递归定义的,例如所有格加名词短语可以构成更大的名词短语的限定词。在复数名词、物质名词之前不需要加限定词。
    • +
    • 名词性词Nominal:包含一些名词前或者名词后修饰语
    • +
    • 名词之前,限定词之后:一些特殊的词类可以出现在名词之前限定词之后,包括基数词Card、序数词Ord、数量修饰语Quant。
    • +
    • 形容词短语AP:形容词短语之前可以出现副词
    • +
    • 可以讲名词短语的前修饰语规则化如下(括号内代表可选):
    • +
    • NP->(Det)(Card)(Ord)(Quant)(AP)Nominal
    • +
    • 后修饰语主要包含三种:
        -
      • 一个词出现的概率只与该词的词类标注有关,与上下文其他词和其他标注无关,从而将序列的联合概率拆解为元素概率之积,即:P(w_1n│t_1n) -_{i=1}^n P(w_i |t_i)
      • -
      • 一个标注出现的概率只与前一个标注相关,类似于二元语法的假设:P(t_1^n -) {i=1}^n P(t_i |t{i-1})
      • +
      • 介词短语PP:Nominal->Nominal PP(PP)(PP)
      • +
      • 非限定从句:动名词后修饰语GerundVP,GerundVP->GerundV NP | GerundV +PP | GerundV | GerundV NP PP
      • +
      • 关系从句:以关系代词开头的从句 Nominal ->Nominal +RelCaluse;RelCaluse -> (who|that) VP
    • -
    • 在两种假设下简化后的最好标注序列表达式为: \[ -{t_1^n}_{best} = {argmax} _{t_1^n} P(t_1^n│w_1^n) \approx {argmax} -_{t_1^n} \prod _{i=1}^n P(w_i│t_i) P(t_i |t_{i-1}) -\]
    • -
    • 上面这个概率表达式实际上将HMM模型的联合概率拆成了各个部分转移概率的乘积,具体而言分为标签转移概率(隐变量之间转移)和词似然(隐变量转移到可观察变量)。通过最大似然估计,我们可以通过古典概型的方法从已标注的语料中计算出这两类概率: +
    +

    一致关系

    +
      +
    • 每当动词有一个名词作为它的主语时,就会发生一致关系的现象,凡是主语和他的动词不一致的句子都是不合语法的句子,例如第三人称单数动词没有加-s。可以使用多个规则的集合来扩充原有的语法,使得语法可以处理一致关系。例如yes-no疑问句的规则是 \[ -P(t_i│t _{i-1} ) = (C(t _{i-1},t_i))/C(t _{i-1} ) \\ -P(w_i│t_i ) = \frac{C(t_i,w_i)}{C(t_i)} \\ +S \rightarrow Aux \ NP \ VP \]
    • -
    • 一个例子:HMM模型如何正确的将下句中的race识别为动词而不是名词:
    • -
    • Secretariat is expected to race tomorrow.
    • -
    • 画出上句中race被识别为动词和名词两种情况下的HMM模型,可以看到两个模型对比只有三个转移概率不同,用加粗线标出: -
    • -
    • HMM词类标注器消歧的方式是全局的而不是局部的。我们在语料中统计得到这三种转移概率,再累乘,结果是(a)的概率是(b)概率的843倍。显然race应该被标注为动词。
    • +
    • 可以用如下形式的两个规则来替代: \[ +S \rightarrow 3sgAux \ 3sgNP \ VP \\ +S \rightarrow Non3sgAux \ Non3sgNP \ VP \\ +\]
    • +
    • 再分别指定第三人称单数和非第三人称单数的助动词形态。这样的方法会导致语法规模增加。
    -

    形式化隐马尔科夫模型标注器

    -
      -
    • HMM模型是有限自动机的扩展,具体而言是一种加权有限自动机,马尔可夫链的扩展,这种模型允许我们考虑观察量和隐变量,考虑包含隐变量的概率模型。HMM包含以下组件: +

      动词短语和次范畴化

        -
      • Q:大小为N的状态集
      • -
      • A:大小为N*N的转移概率矩阵
      • -
      • O:大小为T的观察事件集
      • -
      • B:观察似然序列,又叫发射概率,\(b_i -(o_t)\)描述了从状态i里生成观察o_t的概率
      • -
      • \(q_0,q_F\):特殊的起始状态和最终状态,没有相连接的观察量
      • -
    • -
    • A中的概率和B中的概率对应着之前式子中每一个累乘项里的先验\(P(w_i│t_i )\)和似然\(P(t_i |t _{i-1})\)概率: \[ -{t_1^n}_{best}={argmax} _{t_1^n} P(t_1^n│w_1^n ) \approx {argmax} -_{t_1^n} \prod _{i=1}^n P(w_i│t_i)P(t_i |t _{i-1}) -\]
    • +
    • 动词短语包括动词和其他一些成分的组合,包括NP和PP以及两者的组合。整个的嵌入句子也可以跟随在动词之后,成为句子补语。
    • +
    • 动词短语的另一个潜在成分是另一个动词短语。
    • +
    • 动词后面也可以跟随一个小品词,小品词类似于借此,但与动词组合在一起是构成一个短语动词,与动词不可分割。
    • +
    • 次范畴化即再分类。传统语法把动词次范畴化为及物动词和不及物动词,而现代语法已经把动词区分为100个次范畴。讨论动词和可能的成分之间的关系是将动词看成一个谓词,而成分想象成这个谓词的论元(argument)。
    • +
    • 对于动词和它的补语之间的关系,我们可以用上下文无关语法表示一致关系特征,且需要区分动词的各个次类。
    -

    HMM标注的维特比算法

    +

    助动词

      -
    • 在HMM模型中,已知转移概率和观察序列,求隐变量的任务叫做解码。解码的一种算法即维特比算法,实质上是一种动态规划算法,与之前求最小编辑距离的算法类似。
    • -
    • 首先我们从语料中计算得到A和B两个矩阵,即模型的转移概率已知,对于给定的观察序列,按照以下步骤执行维特比算法: -
    • -
    • 算法维护一个\((N+2)*T\)的概率矩阵viterbi,加了2代表初始状态和结束状态,viterbi[s,t]代表了在第t步状态为s时的最佳路径概率,而backpointer[s,t]对应着保存了该最佳路径的上一步是什么状态,用于回溯输出整个最佳路径。
    • -
    • 关键的转移在于\(viterbi[s,t] \leftarrow -max _{s^{*}=1}^N⁡ viterbi[s^{*},t-1] * a_{s^{*},s} * b_s -(o_t)\)即当前时间步最佳路径是由上一时间步各个状态的最佳路径转移过来的,选择上一步最佳路径概率与转移概率乘积最大的路径作为当前时间步的最佳路径。从动态规划的角度而言,即长度为t的最佳路径,必定是从长度为t-1的最佳路径里选择一条转移得到,否则肯定可以从另一条概率更大的路径转移获得更优解。这样就限制了最佳路径的生成可能,减少了计算量。
    • +
    • 助动词是动词的一个次类,具有特殊的句法约束。助动词包括情态动词、完成时助动词、进行时助动词、被动式助动词。每一个助动词都给他后面的动词形式一个约束,且需要按照一定的顺序进行结合。
    • +
    • 四种助动词给VP次范畴化时,VP的中心动词分别是光杆动词、过去分词形式、现在分词形式、过去分词形式。
    • +
    • 一个句子可以用多个助动词,但是要按照情态助动词、完成时助动词、进行式助动词、被动式助动词的顺序。
    -

    将HMM算法扩展到三元语法

    +

    树图资料库

      -
    • 现代的HMM标注器一般在标注转移概率上考虑更长的上文历史: \[ -P(t_1^n ) \approx \prod_{i=1}^n P(t_i |t _{i-1},t_{i-2}) -\]
    • -
    • 这样的话需要在序列开头和结尾做一些边界处理。使用三元语法的一个问题是数据稀疏:例如我们从没有在训练集中见过标注序列PRP -VB TO,则我们无法计算P(TO|PRP,VB)。一种解决办法是线性插值: \[ -P(t_i│t _{i-1} t _{i-2} ) = \lambda _1 P ̂(t_i│t _{i-1} t _{i-2} -)+\lambda _2 P ̂(t_i│t _{i-1} )+\lambda _3 P ̂(t_i) +
    • 上下文无关语法可以将一个句子剖析成一个句法剖析树,如果一个语料中所有句子都以句法剖析树的形式表示,这样的句法标注了的语料就称为树图资料库(treebank)。
    • +
    • 树图资料库中的句子隐含的组成了一种语言的语法,我们可以对于每一棵句法剖析树提取其中的CFG规则。从宾州树库中提取出来的CFG规则非常扁平化,使得规则数量很多且规则很长。
    • +
    • 在树库中搜索需要一种特殊的表达式,能够表示关于节点和连接的约束,用来搜索特定的模式。例如tgrep或者TGrep2。
    • +
    • 在tgrep、TGrep2中的一个模式由一个关于节点的描述组成,一个节点描述可以用来返回一个以此节点为根的子树。
    • +
    • 可以使用双斜线对某一类模式命名: \[ +/NNS?/ NN|NNS \]
    • -
    • 使用删除插值的办法确定系数\(\lambda\)FoZr80.png
    • +
    • Tgrep/Tgrep2模式的好处在于能够描述连接的信息。小于号代表直接支配,远小于符号代表支配,小数点代表线性次序。这种对于连接的描述反应在剖析树中的关系如下: +
    -

    基于变换的标注

    +

    中心词和中心词查找

      -
    • 基于变换的方法结合了基于规则和基于概率方法的优点。基于变换的方法依然需要规则,但是从数据中总结出规则,是一种监督学习方法,称为基于变换的学习(Transformation -Based -Learning,TBL)。在TBL算法中,语料库首先用比较宽的规则来标注,然后再选择稍微特殊的规则来修改,接着再使用更窄的规则来修改数量更少的标记。
    • +
    • 句法成分能够与一个词法中心词相关联。在一个简单的词法中心词模型中,每一个上下文无关规则与一个中心词相关联,中心词传递给剖析树,因此剖析树中每一个非终止符号都被一个单一单词所标注,这个单一单词就是这个非终止符号的中心词。一个例子如下: +
    • +
    • 为了生成这样一棵树,每一个CFG规则都必须扩充来识别一个右手方向的组成成分来作为中心词子女节点。一个节点的中心词词被设置为其子女中心词的中心词。
    • +
    • 另一种方式是通过一个计算系统来完成中心词查找。在这种方式下是依据树的上下文来寻找指定的句子,从而动态的识别中心词。一旦一个句子被解析出来,树将会被遍历一遍并使用合适的中心词来装饰每一个节点。
    -

    如何应用TBL规则

    -
      -
    • 首先应用最宽泛的规则,就是根据概率给每个词标注,选择概率最大的词类作为标注。之后应用变换规则,即如果满足某一条件,就将之前标注的某一词类变换(纠正)为正确的词类,之后不断应用更严格的变换,在上一次变换的基础上进行小部分的修改。
    • -
    • 如何学习到TBL规则 +

      语法等价与范式

        -
      • 首先给每个词打上最可能的标签
      • -
      • 检查每一个可能的变换,选择效果提升最多的变换,此处需要直到每一个词正确的标签来衡量变换带来的提升效果,因此是监督学习。
      • -
      • 根据这个被选择的变换给数据重新打标,重复步骤2,直到收敛(提升效果小于某一阈值)
      • -
    • -
    • 以上过程输出的结果是一有序变换序列,用来组成一个标注过程,在新语料上应用。虽然可以穷举所有的规则,但是那样复杂度太高,因此我们需要限制变换集合的大小。解决方案是设计一个小的模板集合(抽象变换),每一个允许的变换都是其中一个模板的实例化。
    • +
    • 语法等价包括两种:强等价,即两个语法生成相同的符号串集合,且他们对于每个句子都指派同样的短语结构;弱等价,即两个语法生成相同的符号串集合,但是不给每个句子指派相同的短语结构。
    • +
    • 语法都使用一个范式,在范式中每个产生式都使用一个特定的形式。例如一个上下文五官与法是sigma自由的,并且如果他们的每个产生式的形式为A->BC或者是A->a,就说明这个上下文无关语法是符合Chomsky范式的,简称CNF。凡是Chomsky范式的语法都具有二叉树形式。任何上下文无关语法都可以转变成一个弱等价的Chomsky范式语法。
    • +
    • 使用二叉树形式的剖析树能够产生更小的语法。形如A->A +B的规则称为Chomsky并连。
    -

    评价和错误分析

    +

    有限状态语法和上下文无关语法

      -
    • 一般分为训练集、验证集、测试集,在训练集内做十折交叉验证。
    • -
    • 与人类标注的黄金标准比较计算准确率作为衡量指标。
    • -
    • 一般用人类表现作为ceiling,用一元语法最大概率标注的结果作为baseline。
    • -
    • 通过含混矩阵或者列联表来进行错误分析。在N分类任务中,一个N*N的含混矩阵的第i行第j列元素指示第i类被错分为第j类的次数在总分错次数中的占比。一些常见的容易分错的词性包括: +
    • 复杂的语法模型必须表示组成性,因而不适合用有限状态模型来描述语法。
    • +
    • 当一个非终止符号的展开式中也包含了这个非终止符号时,就会产生语法的递归问题。
    • +
    • 例如,使用正则表达式来描述以Nominal为中心的名词短语: +(Det)(Card)(Ord)(Quant)(AP)Nominal(PP)*
    • +
    • 为了完成这个正则表达式,只需要按顺序展开PP,展开结果为(P +NP)*,这样就出现了地柜问题,因为此时出现了NP,在NP的正则表达式中出现了NP。
    • +
    • 一个上下文无关语法能够被有限自动机生成,当且仅当存在一个生成语言L的没有任何中心自嵌入递归的上下文无关语法。
    • +
    +

    依存语法

      -
    • 单数名词、专有名词、形容词
    • -
    • 副词、小品词、介词
    • -
    • 动词过去式、动词过去分词、形容词
    • -
    +
  • 依存语法与上下文无关语法相对,其句法结构完全由词、词与词之间的语义或句法关系描述。一个例子如下: +
  • +
  • 其中没有非终止符号或者短语节点,树中的连接只将两个词语相连。连接即依存关系,代表着语法功能或者一般的语义联系,例如句法主语、直接对象、间接宾语、时间状语等等。
  • +
  • 依存语法具有很强的预测剖析能力,且在处理具有相对自由词序的语言时表现更好。
  • -

    词性标注中的一些其他问题

    +

    第十三章:基于上下文无关语法的剖析

    +

    剖析即搜索

      -
    • 标注不确定性:一个词在多个词性之间存在歧义,很难区分。这种情况下有些标注器允许一个词被打上多个词性标注。在训练和测试的时候,有三种方式解决这种多标注词: +
    • 在句法剖析中,剖析可以看成对一个句子搜索一切可能的剖析树空间并发现正确的剖析树。
    • +
    • 对于某一个句子(输入符号串),剖析搜索的目标是发现以初始符号S为根并且恰好覆盖整个输入符号串的一切剖析树。搜索算法的约束来自两方面:
        -
      • 通过某种方式从这些候选标注中选择一个标注
      • -
      • 训练时指定一个词性,测试时只要打上了候选词性中任意一个就认为标注正确
      • -
      • 将整个不确定的词性集看成一个新的复杂词性
      • +
      • 来自数据的约束,即输入句子本身,搜索出来的剖析树的叶子应该是原句的所有单词。
      • +
      • 来自语法的约束,搜索出来的剖析树应该有一个根,即初始符号S
    • -
    • 多部分词:在标注之前需要先分词,一些多部分词是否应该被分为一部分,例如New -York City应该分成三部分还是一个整体,也是各个标注系统需要考虑的。
    • -
    • 未知词:不在词典中的词称为未知词。对于未知词,训练集无法给出它的似然P(w_i -|t_i),可以通过以下几种方式解决: +
    • 根据这两种约束,产生了两种搜索策略:自顶向下,目标制导的搜索;自下而上,数据制导的搜索。
    • +
    • 对于自顶向下的搜索,从根开始,我们通过生成式不断生成下一层的所有可能子节点,搜索每一层的每一种可能,如下图(对于句子book +that flight):
    • +
    • 对于自底向上的搜索,剖析从输入的单词开始,每次都使用语法中的规则,试图从底部的单词向上构造剖析树,如果剖析树成功的构造了以初始符号S为根的树,而且这个树覆盖了整个输入,那么就剖析成功。首先通过词表将每个单词连接到对应的词类,如果一个单词有不止一个词类,就需要考虑所有可能。与自顶向下相反,每次进入下一层时,自底向上需要考虑被剖析的成分是否与某个规则的右手边相匹配,而自顶向下是与左手边相匹配。中途如果无法匹配到规则则将这个树枝从搜索空间中删除,如下图所示: +
    • +
    • 两者对比:
        -
      • 只依赖上下文的POS信息预测
      • -
      • 用只出现一次的词来估计未知词的分布,类似于Good Turing打折法
      • -
      • 使用未知词的单词拼写信息,正词法信息。例如连字符、ed结尾、首字母大写等特征。之后在训练集中计算每个特征的似然,并假设特征之间独立,然后累乘特征似然作为未知词的似然:\(P(w_i│t_i )=p(unknown word│t_i ) * p(capital│t_i ) -* p(endings/hyph|t_i)\)
      • -
      • 使用最大熵马尔可夫模型
      • -
      • 使用对数线性模型
      • +
      • 自顶向下是从S开始搜索的,因此不会搜索那些在以S为根的树中找不到位置的子树,而自底向上会产生许多不可能的搜索树
      • +
      • 相对应的,自顶向下把搜索浪费在了不可能产生输入单词序列的树上
      • +
      • 综上,我们需要将自顶向下和自底向上相结合
    -

    噪声信道模型

    +

    歧义

      -
    • 贝叶斯推断用于标注可以认为是一种噪声信道模型的应用,本节介绍如何用噪声信道模型来完成拼写纠正任务。 -之前对于非单词错误,通过词典查找可以检测到错误,并根据最小编辑距离纠正错误,但这种方法对于真实单词错误无能为力。噪声信道模型可以纠正这两种类型的拼写错误。
    • -
    • 噪声信道模型的动机在于将错误拼写的单词看成是一个正确拼写的单词经过一个噪声信道时受到干扰扭曲得到。我们尝试所有可能的正确的词,将其输入信道,最后得到的干扰之后的词与错误拼写的词比较,最相似的例子对应的输入词就认为是正确的词。这类噪声信道模型,比如之前的HMM标注模型,是贝叶斯推断的一种特例。我们看到一个观察两(错误拼写词)并希望找到生成这个观察量的隐变量(正确拼写词),也就是找最大后验。
    • -
    • 将噪声信道模型应用于拼写纠正:首先假设各种拼写错误类型,错拼一个、错拼两个、漏拼一个等,然后产生所有可能的纠正,除去词典中不存在的,最后分别计算后验概率,选择后验概率最大的作为纠正。其中需要根据局部上下文特征来计算似然。
    • -
    • 另一种纠正算法是通过迭代来改进的方法:先假设拼写纠正的含混矩阵是均匀分布的,之后根据含混矩阵运行纠正算法,根据纠正之后的数据集更新含混矩阵,反复迭代。这种迭代的算法是一种EM算法。
    • -
    -

    根据上下文进行拼写纠正

    +
  • 在句法剖析中需要解决的一个问题是结构歧义,即语法会给一个句子多种剖析结果可能。
  • +
  • 最常见的两种歧义:附着歧义和并列连接歧义。
  • +
  • 如果一个特定的成分可以附着在剖析树的一个以上的位置,句子就会出现附着歧义。例如We +saw the Eiffel Tower flying to Paris一句中,flying to Paris可以修饰Eiffel +Tower也可以修饰We。
  • +
  • 在并列连接歧义中,存在着不同的短语,这些短语之间用and这样的连接词相连。例如old +men and +women可以是老年男性和老年女性,或者老年男性和普通女性,即old是否同时分配到men和women上。
  • +
  • 以上两种歧义还能相互组合嵌套形成更复杂的歧义。假如我们不消歧,仅仅返回所有的可能,留给用户或者人工判断,则随着剖析句子结构变复杂或者剖析规则的增加,得到的可能是成指数级增长的,具体而言,这种剖析句子可能的增长数和算术表达式插入括号问题相同,以Catalan数按指数增长: +\[ +C(n)=\frac{1}{1+n} C_{2n}^n +\]
  • +
  • 摆脱这种指数爆炸的方法有两个:
      -
    • 即真实单词拼写错误的纠正。为了解决这类任务需要对噪声信道模型进行扩展:在产生候选纠正词时,需要包括该单词本身以及同音异形词。之后根据整个句子的最大似然来选择正确的纠正词。
    • +
    • 动态规划,研究搜索空间的规律性,使得常见的部分只推导一次,减少与歧义相关的开销
    • +
    • 使用试探性的方法来改善剖析器的搜索策略
    • +
  • +
  • 使用例如深度优先搜索或者宽度优先搜索之类的有计划与回溯的搜索算法是在复杂搜索空间中搜索常用的算法,然而在复杂语法空间中无处不在的歧义使得这一类搜索算法效率低下,因为有许多重复的搜索过程。
  • -

    第六章:隐马尔科夫模型和最大熵模型

    +

    动态规划剖析方法

      -
    • 隐马尔科夫模型用来解决序列标注(序列分类问题)。
    • -
    • 最大熵方法是一种分类思想,在满足给定条件下分类应满足限制最小(熵最大),满足奥卡姆剃刀原理。
    • -
    • 最大熵马尔可夫模型是最大熵方法在序列标注任务上的扩展。
    • +
    • 在动态规划中,我们维护一个表,系统的将对于子问题的解填入表中,利用已经存储的子问题的解解决更大的子问题,而不用重复从头开始计算。
    • +
    • 在剖析中,这样的表用来存储输入中各个部分的子树,当子树被发现时就存入表中,以便以后调用,就这样解决了重复剖析的问题(只需查找子树而不需要重新剖析)和歧义问题(剖析表隐含的存储着所有可能的剖析结果)。
    • +
    • 主要的三种动态规划剖析方法有三种,CKY算法、Earley算法和表剖析算法。
    -

    马尔可夫链

    +

    CKY剖析

      -
    • 加权有限自动状态机是对有限自动状态机的扩展,每条转移路径上加上了概率作为权重,说明从这条路径转移的可能性。马尔可夫链是加权有限状态自动机的一种特殊情况,其输入序列唯一确定了自动机会经过的状态序列。马尔可夫链只能对确定性序列分配概率。
    • -
    • 我们将马尔可夫链看作一种概率图模型,一个马尔可夫链由下面的成分确定: -\[ -Q=q_1 q_2…q_N \\ -A=a_{01} a_{02} … a_{n1} … a_{nn} \\ -q_0,q_F \\ -\]
    • -
    • 分别是 +
    • CKY剖析要求语法必须满足Chomsky范式,即生成式右边要么时两个非终止符号要么是一个终止符号。如果不是Chomsky范式,则需要把一个一般的CFG转换成CNF:
        -
      • 状态集合
      • -
      • 转移概率矩阵,其中a_ij代表了从状态i转移到状态j的概率\(P(q_j |q_i)\)
      • -
      • 特殊的开始状态和结束状态
      • +
      • 右边有终止符号也有非终止符号:给右边的终止符号单独建一个非终止符号,例如:INF-VP +→ to VP,改成INF-VP → TO VP和TO → to
      • +
      • 右边只有一个非终止符号:这种非终止符号称为单元产物,它们最终会生成非单元产物,用最终生成的非单元产物规则来替换掉单元产物
      • +
      • 右边不止2个符号:引入新的非终止符号将规则分解
      • +
      • 词法规则保持不变,但是在转换的过程中可能会生成新的词法规则
    • -
    • 概率图表示将状态看成图中的点,将转移看成边。
    • -
    • 一阶马尔可夫对转移做了很强的假设:某一状态的概率只与前一状态相关: -\[ -P(q_i│q_1…q _{i-1} )=P(q_i |q _{i-1}) -\]
    • -
    • 马尔可夫链的另一种表示不需要开始和结束状态: \[ -\pi = \pi _1,\pi _2 , … , \pi _N \\ -QA={q_x,q_y…} \\ -\]
    • -
    • 分别是: +
    • 当所有的规则都转换成CNF之后,表中的非终止符号在剖析中有两个子节点,且表中每一个入口代表了输入中的某个区间,对于某个入口例如[0,3],其可以被拆分成两部分,假如一部分为[0,2],则另一部分为[2,3],前者在[0,3]的左边,后者在[0,3]的正下方,如下图: +
    • +
    • 接下来就是如何填表,我们通过自底向上的方法来剖析,对于每个入口[i,j],包含了输入中i到j这一区间部分的表格单元都会对这个入口值做出贡献,即入口[i,j]左边的单元和下边的单元。下表中的CKY伪算法图描述了这一过程: +
    • +
    • 外层循环从左往右循环列,内层循环从下往上循环行,而最里面的循环式遍历串[i,j]的所有可能二分子串,表中存的是可以代表[i,j]区间符号串的非终止符号集合,因为是集合,所以不会出现重复的非终止符号。
    • +
    • 现在我们完成了识别任务,接下来是剖析。剖析即在[0,N]入口,对应整个句子,找到一个非终止符号作为起始符号S。首先我们要对算法做两点更改:
        -
      • 状态的初始概率分布,马尔可夫链以概率\(\pi -_i\)从状态i开始
      • -
      • 集合QA是Q的子集,代表合法的接受状态
      • +
      • 存入表中的不仅仅是非终止符号,还有其对应的指针,指向生成这个非终止符号的表入口
      • +
      • 允许一个入口中存在同一个非终止符号的不同版本
    • -
    • 因此状态1作为初始状态的概率既可以写成\(a_{01}\)也可以写成\(\pi _1\)
    • +
    • 做了这些改动之后,这张表就包含了一个给定输入的所有可能剖析信息。我们可以选择[0,N]入口中任意一个非终止符号作为起始符号S,然后根据指针迭代提取出剖析信息。
    • +
    • 当然,返回所有的可能剖析会遇到指数爆炸的问题,因此我们在完整的表上应用维特比算法,计算概率最大的剖析并返回这个剖析结果。
    -

    隐马尔科夫模型

    +

    Early算法

      -
    • 当马尔可夫链已知时,我们可以用其计算一个观测序列出现的概率。但是观测序列可能依赖于一些不可观测的隐变量,我们可能感兴趣的是推断出这些隐变量。隐马尔科夫模型允许我们同时考虑观测变量和隐变量。
    • -
    • 如之前一样定义隐马尔科夫模型: +
    • 相比CKY自底向上的剖析,Early算法采用了自顶向下的剖析,而且只用了一维的表保存状态,每个状态包含三类信息:
        -
      • Q:大小为N的状态集
      • -
      • A:大小为N*N的转移概率矩阵
      • -
      • O:大小为T的观察事件集
      • -
      • B:观察似然序列,又叫发射概率,\(b_i -(o_t)\)描述了从状态i里生成观察\(o_t\)的概率
      • -
      • \(q_0,q_F\):特殊的起始状态和最终状态,没有相连接的观察量
      • +
      • 对应某一单一语法规则的子树
      • +
      • 子树的完成状态
      • +
      • 子树对应于输入中的位置
    • -
    • 同样的,隐马尔科夫也可以用另一种不依赖初始和结束状态的方式表示。隐马尔科夫模型也做了两个假设,分别是隐状态之间转移和隐状态到观察量转移的一阶马尔可夫性。
    • -
    • 对于隐马尔科夫模型需要解决三类问题: +
    • 算法流程图如下: FoZHKO.png
    • +
    • 算法对于状态的操作有三种:
        -
      • 似然计算:已知参数和观测序列,求似然\(P(O|\lambda)\)
      • -
      • 解码:已知参数和观测序列,求隐状态序列
      • -
      • 学习:已知观测序列和隐状态集合,求解模型参数
      • +
      • 预测:造出一个新的状态来表示在剖析过程中生成的自顶向下的预测。当待剖析的状态为非终极符号但又不是词类范畴时,对于这个非终极符号的不同展开,预测操作都造出一个新的状态。
      • +
      • 扫描:当待剖析的状态是词类范畴时,就检查输入符号串,并把对应于所预测的词类范畴的状态加入线图中。
      • +
      • 完成:当右边所有状态剖析完成时,完成操作查找输入中在这个位置的语法范畴,发现并推进前面造出的所有状态。
    -

    计算似然:前向算法

    +

    表剖析

      -
    • 对于马尔可夫链,其没有隐状态到观测量的转移概率矩阵,可以看成观察量与隐状态相同。在隐马尔科夫模型中不能直接计算似然,我们需要直到隐状态序列。
    • -
    • 先假设隐状态序列已知,则似然计算为: \[ -P(O│Q) = \prod _{i=1}^T P(o_i |q_i) -\]
    • -
    • 根据隐状态转移的一阶马尔可夫性,可以求得隐状态的先验,乘以似然得到观测序列和隐状态序列的联合概率: -\[ -P(O,Q)=P(O│Q) * P(Q) = \prod _{i=1}^n P(o_i│q_i ) \prod _{i=1}^n P(q_i -|q _{i-1}) -\]
    • -
    • 对于联合概率积分掉隐状态序列,就可以得到观测概率的似然: \[ -P(O) = \sum _Q P(O,Q) = \sum _Q P(O|Q)P(Q) -\]
    • -
    • 这样计算相当于考虑了所有的隐状态可能,并对每一种可能从隐状态序列开始到结束计算一次似然,实际上可以保留每次计算的中间状态来减少重复计算,也就是动态规划。在前向计算HMM观测似然使用的动态规划算法称为前向算法: +
    • 表剖析允许动态的决定表格处理的顺序,算法动态的依照计划依次删除图中的一条边,而计划中的元素排序是由规则决定的。 +
    • +
    +

    部分剖析

      -
    • \(\alpha _t -(j)\)代表在得到前t个观测量之后当前时刻隐变量处于状态j的概率,: -\[ -\alpha _t (j) = P(o_1,o_2…o_t,q_t=j|\lambda) -\]
    • -
    • 这个概率值可以根据前一时间步的,避免了每次从头开始计算: \[ -\alpha _t (j) = \sum _{i=1}^N \alpha _{t-1} (i) a_{ij} b_j (o_t) -\]
    • -
    • 初始化\(\alpha _1 (j)\)\[ -\alpha _1 (j)=a_{0s} b_s (o_1) -\]
    • -
    • 终止状态: \[ -P(O│\lambda) = \alpha _T (q_F) = \sum _{i=1}^N \alpha _T (i) \alpha -_{iF} -\]
    • -
    +
  • 有时我们只需要输入句子的部分剖析信息
  • +
  • 可以用有限状态自动机级联的方式完成部分剖析,这样会产生比之前提到的方法更加“平”的剖析树。
  • +
  • 另一种有效的部分剖析的方法是分块。使用最广泛覆盖的语法给句子做词类标注,将其分为有主要词类标注信息且不没有递归结构的子块,子块之间不重叠,就是分块。
  • +
  • 我们用中括号将每一个分块框起来,有可能一些词并没有被框住,属于分块之外。
  • +
  • 分块中最重要的是基本分块中不能递归包含相同类型的成分。
  • -

    解码:维特比算法

    +

    基于规则的有限状态分块

      -
    • 解码任务是根据观测序列和参数推断出最有可能隐状态序列。最朴素的做法:对于每种可能的隐状态序列,计算观测序列的似然,取似然最大时对应的隐状态序列。但是这样做就如同朴素的计算似然方法一样,时间复杂度过高,同样的,我们使用动态规划来缩小求解的规模。在解码时使用了一种维特比算法。 +
    • 利用有限状态方式分块,需要为了特定目的手动构造规则,之后从左到右,找到最长匹配分块,并接着依次分块下去。这是一个贪心的分块过程,不保证全局最优解。
    • +
    • 这些分块规则的主要限制是不能包含递归。
    • +
    • 使用有限状态分块的优点在于可以利用之前转录机的输出作为输入来组成级联,在部分剖析中,这种方法能够有效近似真正的上下文无关剖析器。
    • +
    +

    基于机器学习的分块

      -
    • \(v_t -(j)\)代表已知前t个观测量(1t)和已知前t个隐状态(0t-1)的条件下,当前时刻隐状态为j的概率: -\[ -v_t (j)=max _{q_0,q_1,…,q_{t-1}} P(q_0,q_1…q_{t-1},o_1,o_2 … -o_t,q_t=j|\lambda) -\]
    • -
    • 其中我们已知了前t个时间步最大可能的隐状态序列,这些状态序列也是通过动态规划得到的: -\[ -v_t (j)=max _{i=1}^N⁡ v_{t-1} (i) a_{ij} b_j (o_t) -\]
    • -
    • 为了得到最佳的隐状态序列,还需要记录每一步的最佳选择,方便回溯得到路径: -\[ -{bt}_t (j) = argmax _{i=1}^N v_{t-1} (i) a_{ij} b_j (o_t) -\]
    • -
    • 初始化: \[ -v_1 (j) = a_{0j} b_j (o_1) \ \ 1 \leq j \leq N \\ -{bt}_1 (j) = 0 \\ -\]
    • -
    • 终止,分别得到最佳隐状态序列(回溯开始值)及其似然值: \[ -P * = v_t (q_F ) = max_{i=1}^N⁡ v_T (i) * a_{i,F} \\ -q_{T*} = {bt}_T (q_F ) = argmax _{i=1}^N v_T (i) * a_{i,F} \\ -\]
    • +
    • 分块可以看成序列分类任务,每个位置分类为1(分块)或者0(不分块)。用于训练序列分类器的机器学习方法都能应用于分块中。
    • +
    • 一种卓有成效的方法是将分块看成类似于词类标注的序列标注任务,用一个小的标注符号集同时编码分块信息和每一个块的标注信息,这种方式称为IOB标注,用B表示分块开始,I表示块内,O表示块外。其中B和I接了后缀,代表该块的句法信息。
    • +
    • 机器学习需要训练数据,而分块的已标数据很难获得,一种方法是使用已有的树图资料库,例如宾州树库。
    • +
    +

    评价分块系统

    +
      +
    • 准确率:模型给出的正确分块数/模型给出的总分块数
    • +
    • 召回率:模型给出的正确分块数/文本中总的正确分块数
    • +
    • F1值:准确率和召回率的调和平均
    • +
    +

    第十四章:统计剖析

    +

    概率上下文无关语法

    +
      +
    • 概率上下文无关语法PCFG是上下文无关语法的一种简单扩展,又称随机上下文无关语法。PCFG在定义上做出了一点改变: +
        +
      • N:非终止符号集合
      • +
      • Σ:终止符号集合
      • +
      • R:规则集合,与上下文无关语法相同,只不过多了一个概率p,代表某一项规则执行的条件概率\(P(\beta|A)\)
      • +
      • S:一个指定的开始符号
    • -
    • 维特比算法减小时间复杂度的原因在于其并没有计算所有的隐状态路径,而是利用了每一时间步的最佳路径只能从上一时间步的最佳路径中延伸而来这一条件,减少了路径候选,避免了许多不必要的路径计算。并且每一步利用上一步的结果也是用了动态规划的思想减少了计算量。
    • +
    • 当某个语言中所有句子的概率和为1时,我们称这个PCFG时一致的。一些递归规则可能导致PCFG不一致。
    -

    训练隐马尔科夫模型:前向后向算法

    +

    用于消歧的PCFG

      -
    • 学习问题是指已知观测序列和隐状态集合,求解模型参数。
    • -
    • 前向后向算法,又称Baum-Welch算法,是EM算法的一种特例,用来求解包含隐变量的概率生成模型的参数。该算法通过迭代的方式反复更新转移概率和生成概率,直到收敛。BW算法通过设计计数值之比作为隐变量,将转移概率矩阵和生成概率矩阵一起迭代更新。
    • -
    • 先考虑马尔科夫链的学习问题。马尔科夫链可以看作是退化的隐马尔科夫模型,即每个隐变量只生成和自己一样的观测量,生成其他观测量的概率为0。因此只需学习转移概率。
    • -
    • 对于马尔可夫链,可以通过古典概型统计出转移概率: \[ -a_{ij} = \frac {Count(i \rightarrow j)} {\sum _{q \in Q} Count(i -\rightarrow q)} -\]
    • -
    • 我们可以这样直接计算概率是因为在马尔可夫链中我们知道当前所处的状态。对于隐马尔科夫模型我们无法这样直接计算是因为对于给定输入,隐状态序列无法确定。Badum-Welch算法使用了两种简洁的直觉来解决这一问题: +
    • 对于一个给定句子,其某一特定剖析的概率是所有规则概率的乘积,这个乘积既是一个剖析的概率,也是剖析和句子的联合概率。这样,对于出现剖析歧义的句子,其不同剖析的概率不同,通过选择概率大的剖析可以消歧。
    • +
    +

    用于语言建模的PCFG

      -
    • 迭代估计,先假设一种转移概率和生成概率,再根据假设的概率推出更好的概率
    • -
    • 计算某一观测量的前向概率,并将这个概率分摊到不同的路径上,通过这种方式估计概率
    • -
    -
  • 首先类似于前向概率,我们定义后向概率: +
  • PCFG为一个句子分配了一个概率(即剖析的概率),因此可以用于语言建模。相比n元语法模型,PCFG在计算生成每一个词的条件概率时考虑了整个句子,效果更好。对于含歧义的句子,其概率是所有可能剖析的概率之和。
  • + +

    PCFG的概率CKY剖析

      -
    • \(\beta _t -(i)\)代表在得到后t个观测量之后当前时刻隐变量处于状态i的概率,\(\lambda\)为模型参数: \[ -\beta _t (i) = P(o_{t+1},o_{t+2}…o_T,q_t=i|\lambda) -\]
    • -
    • 类似于后向概率的归纳计算: \[ -\beta_t (i) = \sum _{j=1}^N a_{ij} b_j (o_{t+1} ) \beta _{t+1} (j), \ -\ 1≤i≤N,1≤t<T -\]
    • -
    • 初始化\(\alpha _1 (j)\)\[ -\beta _T (i)=\alpha _(i,F) -\]
    • -
    • 终止状态: \[ -P(O│\lambda)=\alpha _t (q_F )=\beta_1 (0)= \sum _{i=1}^N a_{0j} b_j -(o_1) \beta _1 (j) -\]
    • -
    -
  • 类似的,我们希望马尔可夫链中的古典概率能帮助我们估计转移概率: \[ -a_{ij}^{*} = -\frac{从状态i转移到状态j的计数值期望}{从状态i转移出去的计数值期望} -\]
  • -
  • 如何估计计数值:我们将整个序列的转移路径计数值转化为时间步之间转移路径计数值之和,时间步之间某一条转移路径的概率为: -\[ -P(q_t=i,q_{t+1}=j) -\]
  • -
  • 首先考虑所有的观测序列和这一转移路径的联合概率(省略了以参数\(\lambda\)为条件): \[ -P(q_t=i,q_{t+1}=j,O) -\]
  • -
  • 观察下面的概率图: FoZWVJ.png
  • -
  • 可以看到这一联合概率包含了三个部分: +
  • PCFG的概率剖析问题:为一个句子产生概率最大的剖析
  • +
  • 概率CKY算法扩展了CKY算法,CKY剖析树中的每一个部分被编码进一个\((n+1)*(n+1)\)的矩阵(只用上三角部分),矩阵中每一个元素包含一个非终止符号集合上的概率分布,可以看成每一个元素也是V维,因此整个存储空间为\((n+1)*(n+1)*V\),其中[i,j,A]代表非终止符号A可以用来表示句子的i位置到j位置这一段的概率。
  • +
  • 算法伪代码:
  • +
  • 可以看到也是用k对某一区间[i,j]做分割遍历,取最大的概率组合作为该区间的概率,并向右扩展区间进行动态规划。
  • + +

    学习到PCFG的规则概率

      -
    • T时刻隐状态为i的前向概率
    • -
    • T+1时刻隐状态为j的后向概率
    • -
    • T时刻与T+1时刻的状态转移概率以及生成对应观测量的生成概率
    • -
    -
  • 所以有: \[ -P(q_t=i,q_{t+1}=j,O)=\alpha _t (i) a_{ij} b_j (o_{t+1} ) \beta _{t+1} -(j) -\]
  • -
  • 为了从联合分布中得到已知观测序列求转移路径的联合概率,需要计算观测序列的概率,可以通过前向概率或者后向概率求得: -\[ -P(O)=\alpha _t (N)=\beta _T (1) = \sum _{j=1}^N \alpha _t (j) \beta_t -(j) -\]
  • -
  • 最终得到 \[ -ξ_t (i,j)=P(q_t=i,q_{t+1}=j│O) = \frac {(\alpha _t (i) a_{ij} b_j -(o_{t+1} ) \beta_{t+1} (j))}{(\alpha _t (N))} -\]
  • -
  • 最后,对所有时间步求和就可以得到从状态i转移到状态j的期望计数值,从而进一步得到转移概率的估计: -\[ -a_{ij}^{*} = \frac {\sum _{t=1}^{T-1} ξ_t (i,j)}{\sum _{t=1}^{T-1} \sum -_{j=1}^{N-1} ξ_t (i,j)} -\]
  • -
  • 同样的,我们还希望得到生成概率的估计: \[ -b_{j}^{*} (v_k) = \frac {在状态j观测到符号v_k -的计数值期望}{状态j观测到所有符号的计数值期望} -\]
  • -
  • 类似的,通过先计算联合分布再计算条件分布的方式得到在t时刻处于隐状态j的概率: -\[ -γ_t (j)=P(q_t=j│O) = \frac {P(q_t=j,O)}{P(O)} -\]
  • -
  • 联合概率包含两个部分,即t时刻处于状态j的前向概率和后向概率,所以有: -\[ -γ_t (j) = \frac {\alpha _t (j) \beta_t (j)}{\alpha _t (N)} -\]
  • -
  • 类似的,对所有时间步累加,进而得到生成概率的估计: \[ -b_{j}^{*} (v_k) = \frac{\sum _{t=1 s.t. O_t=v_k}^T γ_t (j) }{\sum -_{t=1}^T γ_t (j) } -\]
  • -
  • 这两个式子是在已知前向概率和后向概率\((\alpha,\beta)\)的情况下,计算出中间变量(隐变量)(ξ,γ),引入隐变量的动机是将a、b估计值的期望计数值之比转化为概率之比,且这两个隐变量可以用a,b表示。再由隐变量计算出转移概率和生成概率,因此形成了一个迭代的循环,可以用EM算法求解: +
  • 上面的伪算法图用到了每一个规则的概率。如何获取这个概率?两种方法,第一种朴素的方法是在一个已知的树库数据集上用古典概型统计出概率: \[ -a,b→\alpha,\beta→ξ,γ→a,b -\]
  • -
  • E-step: \[ -γ_t (j) = (\alpha _t (j) \beta_t (j))/(\alpha _t (N)) ξ_t (i,j) \\ -= (\alpha _t (i) a_{ij} b_j (o_{t+1} ) \beta_{t+1} (j))/(\alpha _t (N)) -\\ -\]
  • -
  • M-step(最大化的目标是什么): \[ -a _{ij} = (\sum _{t=1}^{T-1} ξ_t (i,j) )/(\sum _{t=1}^{T-1} \sum -_{j=1}^{N-1} ξ_t (i,j) ) \\ -b ̂_j(v_k) = (\sum _{t=1 s.t. O_t=v_k}^T γ_t (j) )/(\sum -_{t=1}^T γ_t (j) ) \\ -\]
  • -
  • 迭代时需重新计算: \[ -\alpha _t (j) = \sum _{i=1}^N \alpha_{t-1} (i) a_ij b_j (o_t) \\ -\beta_t (i) = \sum _{j=1}^N a_ij b_j (o_{t+1} ) \beta_{t+1} (j) \\ +P(\alpha \rightarrow \beta | \alpha) = \frac{Count(\alpha \rightarrow +\beta)}{\sum _{\gamma} Count(\alpha \rightarrow \gamma)} \]
  • -
  • 迭代的初始状态对于EM算法来说很重要,经常是通过引入一些外部信息来设计一个好的初始状态。
  • +
  • 假如我们没有树库,则可以用非概率剖析算法来剖析一个数据集,再统计出概率。但是非概率剖析算法在剖析歧义句子时,需要对每一种可能剖析计算概率,但是计算概率需要概率剖析算法,这样就陷入了鸡生蛋蛋生鸡的死循环。一种解决方案是先用等概率的剖析算法,剖析句子,得出每一种剖析得概率,然后用概率加权统计量,然后重新估计剖析规则的概率,继续剖析,反复迭代直到收敛。这种算法称为inside-outside算法,是前向后向算法的扩展,同样也是EM算法的一种特例。
  • -

    最大熵模型:背景

    +

    PCFG的问题

      -
    • 最大熵模型另一种广为人知的形式是多项Logistic回归(Softmax?)。
    • -
    • 最大熵模型解决分类问题,最大熵模型作为一种概率分类器,能够根据样本的特征求出样本属于每一个类别的概率,进而进行分类。
    • -
    • 最大熵模型属于指数家族(对数线性)分类器,通过将特征线性组合,取指数得到分类概率: -\[ -p(c│x)=\frac 1Z exp⁡(\sum _i weight_i feature_i) -\]
    • -
    • Z是一个归一化系数,使得生成的概率之和为1。
    • +
    • 独立性假设导致不能很好的建模剖析树的结构性依存:每个PCFG规则被假定为与其他规则独立,例如,统计结果表明代词比名词更有可能称为主语,因此当NP被展开时,如果NP是主语,则展开为代词的可能性较高——这里需要考虑NP在句子种的位置,然而这种概率依存关系是PCFG所不允许的,
    • +
    • 缺乏对特定单词的敏感,导致次范畴化歧义、介词附着、联合结构歧义的问题:例如在介词附着问题中,某一个介词短语into +Afghanistan附着于哪一个部分,在PCFG中计算时被抽象化为介词短语应该附着一个哪一个部分,而抽象化的概率来自于对语料的统计,这种统计不会考虑特定的单词。又例如联合结构歧义,假如一个句子的两种可能剖析树使用了相同的规则,而规则在树中的位置不同,则PCFG对两种剖析计算出相同的概率:因为PCFG假定规则之间是独立的,联合概率是各个概率的乘积。
    -

    最大熵建模

    +

    通过拆分和合并非终止符号来改进PCFG

      -
    • 将二分类Logistic回归推广到多分类问题就得到: \[ -P(c│x) = \frac {exp⁡(\sum _(i=0)^N w_ci f_i) } {\sum _{c^{*} in -C} exp⁡(\sum _{i=0}^N w_{c^{*} i} f_i) } -\]
    • -
    • 语音和语言处理中的特征通常是二值的(是否有该特征),因此使用指示函数表示特征 -\[ -P(c│x) = \frac {exp⁡(\sum _{i=0}^N w_{c_i} f_i (c,x)) }{\sum _{c^{*} -\in C} exp⁡(\sum _{i=0}^N w_{c^{*} i} f_i (c^{*},x)) } -\]
    • -
    • 注意到在该模型中每一个类都有其独立的线性权重w_c。相比于硬分布,最大熵模型能够给出分到每一类的概率,因此可以求出每一时刻的分类概率进而求出整体分类概率,得到全局最优分类结果。注意到不同于支持向量机等模型,最大熵模型无法利用特征之间的组合,必须手动构造组合作为新的特征。
    • -
    • 一般使用加了正则化的最大似然作为优化的目标函数: \[ -w ̂={argmax} _w \sum _i \log P(y^{(i)}│x^{(i) } ) - \alpha \sum -_{j=1}^N w_j^2 -\]
    • -
    • 这种正则化相当于给权重的概率分布加了一个零均值高斯先验,权重越偏离均值,即权重越大,其概率越低。
    • -
    • 为什么多分类Logistic回归是最大熵模型:最大熵模型保证在满足给定约束下,无约束的部分分类应该是等概率分配,例如在两个约束下: -\[ -P(NN)+P(JJ)+P(NNS)+P(VB)=1 \\ -P(t_i=NN or t_i=NNS)=8/10 \\ -\]
    • -
    • 则满足这两个约束,最大熵模型分配的概率结果为: \[ -p(NN)=4/10 \\ -p(JJ)=1/10 \\ -p(NNS)=4/10 \\ -p(VB)=1/10 \\ -\]
    • -
    • 在The equivalence of logistic regression and maximum entropy -models一文中证明了在广义线性回归模型的平衡条件约束下,满足最大熵分布的非线性激活函数就是sigmoid,即logistic回归。
    • +
    • 先解决结构性依存的问题。之前提到了我们希望NP作为主语和宾语时有不同概率的规则,一种想法就是将NP拆分成主语NP和宾语NP。实现这种拆分的方法是父节点标注,及每个节点标注了其父节点,对于主语NP其父节点是S,对于宾语NP,其父节点是VP,因此不同的NP就得到了区分。除此之外,还可以通过词性拆分的方式增强剖析树。
    • +
    • 拆分会导致规则增多,用来训练每一条规则的数据变少,引起过拟合。因此要通过一个手写规则或者自动算法来根据每个训练集合并一些拆分。
    -

    最大熵马尔可夫模型

    +

    概率词汇化的CFG

      -
    • 最大熵模型只能对单一观测量分类,使用最大熵马尔可夫模型可以将其扩展到序列分类问题上。
    • -
    • 最大熵马尔可夫比隐马尔科夫模型好在哪儿?隐马尔科夫模型对于每个观测量的分类依赖于转移概率和生成概率,假如我们想要在标注过程中引入外部知识,则需要将外部知识编码进这两类概率中,不方便。最大熵马尔可夫模型能够更简单的引入外部知识。
    • -
    • 在隐马尔科夫模型中我们优化似然,并且乘以先验来估计后验: \[ -T ̂= {argmax}_T ∏_i P(word_i│tag_i ) ∏_i P(tag_i│tag _{i-1} ) -\]
    • -
    • 在最大熵隐马尔科夫模型中,我们直接计算后验。因为我们直接训练模型来分类,即最大熵马尔可夫模型是一类判别模型,而不是生成模型: -\[ -T ̂= {argmax}_T ∏_i P(tag_i |word_i,tag _{i-1}) -\]
    • -
    • 因此在最大熵隐马尔科夫模型中没有分别对似然和先验建模,而是通过一个单一的概率模型来估计后验。两者的区别如下图所示: -
    • -
    • 另外最大熵马尔可夫模型可以依赖的特征更多,依赖方式更灵活,如下图: -
    • -
    • 用公式表示这一差别: \[ -HMM:P(Q│O)=∏_{i=1}^n P(o_i |q_i)×∏_{i=1}^n P(q_i |q _{i-1}) \\ -MEMM:P(Q│O)=∏_{i=1}^n P(q_i |q _{i-1},o_i) \\ -\]
    • -
    • 当估计单一转移概率(从状态q^{*}转移到状态q,产生观测量o)时,我们使用以下的最大熵模型: -\[ -P(q│q^{*},o)=\frac{1}{Z(o,q^{*})} exp⁡(\sum _i w_i f_i (o,q)) +
    • 概率CKY剖析更改了语法规则,而概率词汇化模型更改了概率模型本身。对于每一条规则,不仅要产生成分的规则变化,还要在每个成分上标注其中心词和词性,如下图: +
    • +
    • 为了产生这样的剖析树,每一条PCFG规则右侧需要选择一个成分作为中心词子节点,用子节点的中心词和词性作为该节点的中心词和词性。 +其中,规则被分成了两类,内部规则和词法规则,后者是确定的,前者是需要我们估计的: +
    • +
    • 我们可以用类似父节点标注的思想来拆分规则,拆分后每一部分都对应一种可能的中心词选择。假如我们将概率词汇话的CFG看成一个大的有很多规则CFG,则可以用之前的古典概型来估计概率。但是这样的效果不会很好,因为这样的规则划分太细了,没有足够的数据来估计概率。因此我们需要做出一些独立性假设,将概率分解为更小的概率乘积,这些更小的概率能容易从语料中估计出来。
    • +
    • 不同的统计剖析器区别在于做出怎样的独立性假设。
    • +
    • Collins剖析如下图所示: FoZzGt.png
    • +
    • 其概率拆解为: \[ +P(VP(dumped,VBD)→VBD(dumped,VBD)NP(sacks,NNS)PP(into,P))= \\ +P_H (VBD│VP,dumped)* \\ +P_L (STOP│VP,VBD,dumped)* \\ +P_R (NP(sacks,NNS)│VP,VBD,dumped)* \\ +P_R (PP(into,P)│VP,VBD,dumped)* \\ +P_R (STOP|VP,VBD,dumped) \\ \]
    • +
    • 给出生成式左边之后,首先生成规则的中心词,之后一个一个从里到外生成中心词的依赖。先从中心词左侧一直生成直到遇到STOP符号,之后生成右边。如上式做出概率拆分之后,每一个概率都很容易从较小的数据量中统计出来。完整的Collins剖析器更为复杂,还考虑了词的距离关系、平滑技术、未知词等等。
    -

    最大熵马尔可夫模型的解码(推断)

    +

    评价剖析器

      -
    • MEMM同样使用维特比算法进行解码
    • -
    • 使用维特比算法解码的通用框架是: \[ -v_t (j)=max_{i=1}^N⁡ v_{t-1} (i)P(s_j│s_i )P(o_t |s_j) -\]
    • -
    • 在HMM模型中这一框架具体化为: \[ -v_t (j)=max_{i=1}^N⁡ v_{t-1} (i) a_ij b_j (o_t) -\]
    • -
    • 在MEMM中直接将似然和先验替换为后验: \[ -v_t (j)=max_{i=1}^N⁡ v_{t-1} (j)P(s_j |s_i,o_t) -\]
    • +
    • 剖析器评价的标准方法叫做PARSEVAL测度,对于每一个句子s: +
        +
      • 标记召回率=(Count(s的候选剖析中正确成分数))/(Count(s的树库中正确成分数))
      • +
      • 标记准确率=(Count(s的候选剖析中正确成分数))/(Count(s的候选剖析中全部成分数))
      • +
    -

    最大熵马尔可夫模型的训练

    +

    判别式重排序

      -
    • MEMM作为最大熵模型的推广,训练过程使用和最大熵模型一样的监督算法。如果训练数据的标签序列存在缺失,也可以通过EM算法进行半监督学习。
    • +
    • PCFG剖析和Collins词法剖析都属于生成式剖析器。生成式模型的缺点在于很难引入任意信息,即很难加入对某一个PCFG规则局部不相关的特征。例如剖析树倾向于右生成这一特征就不方便加入生成式模型当中。
    • +
    • 对于句法剖析,有两类判别式模型,基于动态规划的和基于判别式重排序的。
    • +
    • 判别式重排包含两个阶段,第一个阶段我们用一般的统计剖析器产生前N个最可能的剖析及其对应的概率序列。第二个阶段我们引入一个分类器,将一系列句子以及每个句子的前N个剖析-概率对作为输入,抽取一些特征的大集合并针对每一个句子选择最好的剖析。特征包括:剖析概率、剖析树中的CFG规则、平行并列结构的数量、每个成分的大小、树右生成的程度、相邻非终止符号的二元语法、树的不同部分出现的次数等等。
    -

    第十二章:英语的形式语法

    -

    组成性

    +

    基于剖析的语言建模

      -
    • 英语中的单词是如何组成一个词组的呢?
    • -
    • 换句话说,我们如何判断一些单词组合成了一个部分?一种可能是这种组合都能在相似的句法环境中出现,例如名词词组都能在一个动词之前出现。另一种可能依据来自于前置和后置结构,例如前置短语on -September -seventeenth可以放在句子的前面,中间或者后面,但是组合成这个短语的各个部分不能拆出来放在句子的不同位置,因此我们判断on -September seventeenth这三个词组成了一个短语。
    • +
    • 使用统计剖析器来进行语言建模的最简单方式就是利用之前提到的二阶段算法。第一阶段我们运行一个普通的语音识别解码器或者机器翻译解码器(基于普通的N元语法),产生N个最好的候选;第二阶段,我们运行统计剖析器并为每一个候选句分配一个概率,选择概率最佳的。
    -

    上下文无关法则

    +

    人类剖析

      -
    • 上下文无关语法,简称CFG,又称为短语结构语法,其形式化方法等价于Backus-Naur范式。一个上下文无关语法包含两个部分:规则或者产生式,词表。
    • -
    • 例如,用上下文无关语法描述名词词组,一种描述方式是名词词组可以由一个专有名词构成,也可以由一个限定词加一个名词性成分构成,而名词性成分可以是一个或多个名词,此CFG的规则为: +
    • 人类在识别句子时也用到了类似的概率剖析思想,两个例子:
        -
      • NP→Det Nominal
      • -
      • NP→ProperNoun
      • -
      • Nominal→Noun|Noun Nominal
      • +
      • 对于出现频率高的二元语法,人们阅读这个二元语法所花的时间就更少
      • +
      • 一些实验表明人类在消歧时倾向于选择统计概率大的剖析
    • -
    • CFG可以层级嵌套,因此上面的规则可以与下面表示词汇事实的规则(词表)结合起来: +
    +]]>
    + + 机器学习 + + + math + machine learning + theory + nlp + +
    + + Study Notes for CS224w + /2020/03/30/cs224w/ + Jure Leskovec, Stanford CS224W: Machine Learning with +Graphs学习笔记,未完待续

    +

    网络、随机图的属性

      -
    • Det→a
    • -
    • Det→the
    • -
    • Noun→flight
    • +
    • degree distribution:P(k) +
        +
      • 即节点度的分布
    • -
    • 符号分为两类: +
    • path length:h
        -
      • 终极符号:与现实中单词对应的符号,词表是引入终极符号的规则的集合
      • -
      • 非终极符号:表示终极符号的聚类或者概括性符号
      • +
      • path:即路径,可以与自己相交并通过同一条边多次
      • +
      • distance:两点之间最短路径
      • +
      • diameter:一个图的直径即该图上任意两点最短路径的最大值
      • +
      • average path length:distance之和除以节点对数量
    • -
    • 在每个规则里箭头右边包含一个或多个终极符号和非终极符号,箭头左边为一个非终极符号,与每个单词相关联的是其词类范畴(词类)。
    • -
    • CFG既可以看成是生成句子的一种机制,也可以看成是给一个句子分配结构的机制。
    • -
    • 以之前提到的CFG为例,对一个符号串NP,可以逐步生成: clustering coefficient:C +
        +
      • 衡量了节点的邻居的连接状况:邻居之间相连的边数除以节点的度: \[ -NP→Det Nominal→Det Noun→a flight +C_{i}=\frac{2 e_{i}}{k_{i}\left(k_{i}-1\right)} \]
      • -
      • 称 a flight是NP的一个推导,一般用一个剖析树表示一种推导: FoZ5P1.png -一个CFG定义了一个形式语言,形式语言是符号串的集合,如果有一个语法推导出的句子处于由该语法定义的形式语言中,这个句子就是合语法的。使用形式语言来模拟自然语言的语法成为生成式语法。
      • -
      • 上下文无关语法的正式定义: -
          -
        • N:非终止符号(或者变量)的集合
        • -
        • Sigma:终止符号的集合,与N不相交
        • -
        • R:规则或者产生式的集合
        • -
        • S:指定的开始符号
      • -
      • 一些约定定义: +
      • connected components
          -
        • 大写字母:代表非终止符号
        • -
        • S:开始符号
        • -
        • 小写希腊字母:从非终止符号和终止符号的并集中抽取出来的符号串
        • -
        • 小写罗马字母:终止符号串
        • +
        • largest component(giant +component)的size称为connectivity,即最大连通子图的节点数
      • -
      • 直接导出的定义: 公式待补充
      • -
      • 导出是直接导出的泛化。之后我们可以正式定义由语法G生成的语言L是一个由终止符号组成的字符串集合,这些终止符号可以从指定的开始符号S通过语法G导出: -公式待补充
      • -
      • 将一个单词序列映射到其对应的剖析树成为句法剖析。
      • -
      -

      英语的一些语法规则

      -
        -
      • 英语中最常用最重要的四种句子结构: +
      • Random Graph Model
          -
        • 陈述式结构:主语名词短语加一个动词短语
        • -
        • 命令式结构:通常以一个动词短语开头,并且没有主语
        • -
        • Yes-no疑问式结构:通常用于提问,并且以一个助动词开头,后面紧跟一个主语NP,再跟一个VP
        • -
        • Wh疑问式结构:包含一个wh短语成分
        • +
        • 将图看成随机过程生成的结果,两个参数,n,p,即总共n个节点,每条边独立同分布按概率p建立,显然这两个参数不足以唯一确定一个图,考虑这样一个图上的degree +distribution, path length以及clustering coefficient
        • +
        • P(k): \[ +P(k)=\left(\begin{array}{c} +n-1 \\ +k +\end{array}\right) p^{k}(1-p)^{n-1-k} +\]
        • +
        • h:Olog(n)
        • +
        • C: \[ +=\frac{p \cdot +k_{i}\left(k_{i}-1\right)}{k_{i}\left(k_{i}-1\right)}=p=\frac{\bar{k}}{n-1} +\approx \frac{\bar{k}}{n} +\]
        • +
        • connectivity:随着p的增大,图越来越可能出现连接子图,具体如下: GuQgQf.png
      • -
      • 在之前的描述中开始符号用于单独生成整个句子,但是S也可以出现在语法生成规则的右边,嵌入到更大的句子当中。这样的S称为从句,拥有完整的语义。拥有完整的语义是指这个S在整体句子的语法剖析树当中,其子树当中的主要动词拥有所需的所有论元。
      • -
      -

      名词短语

      -
        -
      • 限定词Det:名词短语可以以一些简单的词法限定词开始,例如a,the,this,those,any,some等等,限定词的位置也可以被更复杂的表示替代,例如所有格。这样的表示是可以递归定义的,例如所有格加名词短语可以构成更大的名词短语的限定词。在复数名词、物质名词之前不需要加限定词。
      • -
      • 名词性词Nominal:包含一些名词前或者名词后修饰语
      • -
      • 名词之前,限定词之后:一些特殊的词类可以出现在名词之前限定词之后,包括基数词Card、序数词Ord、数量修饰语Quant。
      • -
      • 形容词短语AP:形容词短语之前可以出现副词
      • -
      • 可以讲名词短语的前修饰语规则化如下(括号内代表可选):
      • -
      • NP->(Det)(Card)(Ord)(Quant)(AP)Nominal
      • -
      • 后修饰语主要包含三种: +
      • small world model
          -
        • 介词短语PP:Nominal->Nominal PP(PP)(PP)
        • -
        • 非限定从句:动名词后修饰语GerundVP,GerundVP->GerundV NP | GerundV -PP | GerundV | GerundV NP PP
        • -
        • 关系从句:以关系代词开头的从句 Nominal ->Nominal -RelCaluse;RelCaluse -> (who|that) VP
        • +
        • 在内聚程度很高的图上依然有很短的直径
        • +
        • 如何构造这样的图?首先以高内聚长直径的图作为起始图,在其中引入shortcut就可以了: +
      • +
      • Kronecker graphs:递归的产生 large realistic graphs
      -

      一致关系

      +

      图的特征:纹理、子图、小图

        -
      • 每当动词有一个名词作为它的主语时,就会发生一致关系的现象,凡是主语和他的动词不一致的句子都是不合语法的句子,例如第三人称单数动词没有加-s。可以使用多个规则的集合来扩充原有的语法,使得语法可以处理一致关系。例如yes-no疑问句的规则是 +
      • 子图,以三个节点构成的子图为例: Gu8hj0.png
      • +
      • 这里假设所有的节点都是相同的,子图只关注节点和边构成的结构特征。假如用一个significance来衡量每个子图,那么就可以构建一个feature +vector。
      • +
      • 定义纹理:motifs,“recurring, significant patterns of +interconnections”,即图中出现很多次,具有显著程度(More frequent than +expected, i.e., in randomly generated networks)的Small induced +subgraph
      • +
      • 通过某一个motifs在真实图和随机图中的出现次数之比就可以定义这个motifs的significance: \[ -S \rightarrow Aux \ NP \ VP -\]
      • -
      • 可以用如下形式的两个规则来替代: \[ -S \rightarrow 3sgAux \ 3sgNP \ VP \\ -S \rightarrow Non3sgAux \ Non3sgNP \ VP \\ -\]
      • -
      • 再分别指定第三人称单数和非第三人称单数的助动词形态。这样的方法会导致语法规模增加。
      • -
      -

      动词短语和次范畴化

      -
        -
      • 动词短语包括动词和其他一些成分的组合,包括NP和PP以及两者的组合。整个的嵌入句子也可以跟随在动词之后,成为句子补语。
      • -
      • 动词短语的另一个潜在成分是另一个动词短语。
      • -
      • 动词后面也可以跟随一个小品词,小品词类似于借此,但与动词组合在一起是构成一个短语动词,与动词不可分割。
      • -
      • 次范畴化即再分类。传统语法把动词次范畴化为及物动词和不及物动词,而现代语法已经把动词区分为100个次范畴。讨论动词和可能的成分之间的关系是将动词看成一个谓词,而成分想象成这个谓词的论元(argument)。
      • -
      • 对于动词和它的补语之间的关系,我们可以用上下文无关语法表示一致关系特征,且需要区分动词的各个次类。
      • -
      -

      助动词

      -
        -
      • 助动词是动词的一个次类,具有特殊的句法约束。助动词包括情态动词、完成时助动词、进行时助动词、被动式助动词。每一个助动词都给他后面的动词形式一个约束,且需要按照一定的顺序进行结合。
      • -
      • 四种助动词给VP次范畴化时,VP的中心动词分别是光杆动词、过去分词形式、现在分词形式、过去分词形式。
      • -
      • 一个句子可以用多个助动词,但是要按照情态助动词、完成时助动词、进行式助动词、被动式助动词的顺序。
      • -
      -

      树图资料库

      -
        -
      • 上下文无关语法可以将一个句子剖析成一个句法剖析树,如果一个语料中所有句子都以句法剖析树的形式表示,这样的句法标注了的语料就称为树图资料库(treebank)。
      • -
      • 树图资料库中的句子隐含的组成了一种语言的语法,我们可以对于每一棵句法剖析树提取其中的CFG规则。从宾州树库中提取出来的CFG规则非常扁平化,使得规则数量很多且规则很长。
      • -
      • 在树库中搜索需要一种特殊的表达式,能够表示关于节点和连接的约束,用来搜索特定的模式。例如tgrep或者TGrep2。
      • -
      • 在tgrep、TGrep2中的一个模式由一个关于节点的描述组成,一个节点描述可以用来返回一个以此节点为根的子树。
      • -
      • 可以使用双斜线对某一类模式命名: \[ -/NNS?/ NN|NNS +Z_{i}=\left(N_{i}^{\mathrm{real}}-\bar{N}_{i}^{\mathrm{rand}}\right) / +\operatorname{std}\left(N_{i}^{\mathrm{rand}}\right) \]
      • -
      • Tgrep/Tgrep2模式的好处在于能够描述连接的信息。小于号代表直接支配,远小于符号代表支配,小数点代表线性次序。这种对于连接的描述反应在剖析树中的关系如下: -
      • -
      -

      中心词和中心词查找

      -
        -
      • 句法成分能够与一个词法中心词相关联。在一个简单的词法中心词模型中,每一个上下文无关规则与一个中心词相关联,中心词传递给剖析树,因此剖析树中每一个非终止符号都被一个单一单词所标注,这个单一单词就是这个非终止符号的中心词。一个例子如下: -
      • -
      • 为了生成这样一棵树,每一个CFG规则都必须扩充来识别一个右手方向的组成成分来作为中心词子女节点。一个节点的中心词词被设置为其子女中心词的中心词。
      • -
      • 另一种方式是通过一个计算系统来完成中心词查找。在这种方式下是依据树的上下文来寻找指定的句子,从而动态的识别中心词。一旦一个句子被解析出来,树将会被遍历一遍并使用合适的中心词来装饰每一个节点。
      • -
      -

      语法等价与范式

      +
    • RECAP算法:找出一个图的motifs,
        -
      • 语法等价包括两种:强等价,即两个语法生成相同的符号串集合,且他们对于每个句子都指派同样的短语结构;弱等价,即两个语法生成相同的符号串集合,但是不给每个句子指派相同的短语结构。
      • -
      • 语法都使用一个范式,在范式中每个产生式都使用一个特定的形式。例如一个上下文五官与法是sigma自由的,并且如果他们的每个产生式的形式为A->BC或者是A->a,就说明这个上下文无关语法是符合Chomsky范式的,简称CNF。凡是Chomsky范式的语法都具有二叉树形式。任何上下文无关语法都可以转变成一个弱等价的Chomsky范式语法。
      • -
      • 使用二叉树形式的剖析树能够产生更小的语法。形如A->A -B的规则称为Chomsky并连。
      • -
      -

      有限状态语法和上下文无关语法

      +
    • 根据真实图,定义一个随机图,其拥有和真实图一样的节点数、边数和度分布
    • +
    • 找出每一个子图在真实图和其对应的随机图上的significance,那么significance大的subgraph就是motifs
    • +
    +
  • 小图(graphlet):节点特征向量,graphlet的定义:connected +non-isomorphic +subgraphs,在graphlet中,我们灌注node-level的特征,例如三个节点只有两种graphlet,即三角形或者一条直线连接三个点。在三角形中,每个节点是等价的(相对于graphlet中其他节点而言),而在一条直线中,两端的节点等价,中间的节点是另一类。graphlet非常稀疏,n=10的graphlet有11716571种,且不算其中不同类的节点。
  • +
  • 将度的概念泛化,Graphlet degree +vector(GDV)指一个节点接触到的graphlet,每一类占一个feature,值为接触到的这一类graphlet的数量: +
  • +
  • GDV衡量了节点的局部拓扑状态
  • +
  • 寻找graphlet/motifs:三类算法
      -
    • 复杂的语法模型必须表示组成性,因而不适合用有限状态模型来描述语法。
    • -
    • 当一个非终止符号的展开式中也包含了这个非终止符号时,就会产生语法的递归问题。
    • -
    • 例如,使用正则表达式来描述以Nominal为中心的名词短语: -(Det)(Card)(Ord)(Quant)(AP)Nominal(PP)*
    • -
    • 为了完成这个正则表达式,只需要按顺序展开PP,展开结果为(P -NP)*,这样就出现了地柜问题,因为此时出现了NP,在NP的正则表达式中出现了NP。
    • -
    • 一个上下文无关语法能够被有限自动机生成,当且仅当存在一个生成语言L的没有任何中心自嵌入递归的上下文无关语法。
    • -
    -

    依存语法

    +
  • Exact subgraph enumeration (ESU) [Wernicke 2006]
  • +
  • Kavosh [Kashani et al. 2009]
  • +
  • Subgraph sampling [Kashtan et al. 2004]
  • + +
  • 图的同构:如何判断两个图是topologically equivalent的?
      -
    • 依存语法与上下文无关语法相对,其句法结构完全由词、词与词之间的语义或句法关系描述。一个例子如下: -
    • -
    • 其中没有非终止符号或者短语节点,树中的连接只将两个词语相连。连接即依存关系,代表着语法功能或者一般的语义联系,例如句法主语、直接对象、间接宾语、时间状语等等。
    • -
    • 依存语法具有很强的预测剖析能力,且在处理具有相对自由词序的语言时表现更好。
    • +
    • 定义roles:节点在图中所起的功能,通过结构信息来衡量,比如可以认为星型子图的中心节点具有相似的功能,或者直接归为一类功能,因此role也可以定义为A +collection of nodes which have similar positions in a +network。其和communities的区别:同一类role之间并不需要结构上互相连接或者有一定程度上的间接交互,而是他们在邻域结构内处于相同的位置
    • +
    • 那么可以定义节点级别的structurally equivalent: Nodes are +structurally equivalent if they have the same relationships to all other +nodes
    • +
    • 如何发现role?ROIX算法 GuUd3Q.png
    • +
    • recursive feature extraction:构建一些base +feature,然后不断的aggregate不断的迭代,例如取mean,取sum,再通过相关性剪枝
    • +
    • role extraction,实际上是一个矩阵的分解,将role看成latent +topic?:RolX uses non negative matrix factorization for clustering, MDL +for model selection, and KL divergence to measure likelihood。
    • +
  • -

    第十三章:基于上下文无关语法的剖析

    -

    剖析即搜索

    -
      -
    • 在句法剖析中,剖析可以看成对一个句子搜索一切可能的剖析树空间并发现正确的剖析树。
    • -
    • 对于某一个句子(输入符号串),剖析搜索的目标是发现以初始符号S为根并且恰好覆盖整个输入符号串的一切剖析树。搜索算法的约束来自两方面: +

      图谱聚类

        -
      • 来自数据的约束,即输入句子本身,搜索出来的剖析树的叶子应该是原句的所有单词。
      • -
      • 来自语法的约束,搜索出来的剖析树应该有一个根,即初始符号S
      • -
    • -
    • 根据这两种约束,产生了两种搜索策略:自顶向下,目标制导的搜索;自下而上,数据制导的搜索。
    • -
    • 对于自顶向下的搜索,从根开始,我们通过生成式不断生成下一层的所有可能子节点,搜索每一层的每一种可能,如下图(对于句子book -that flight):
    • -
    • 对于自底向上的搜索,剖析从输入的单词开始,每次都使用语法中的规则,试图从底部的单词向上构造剖析树,如果剖析树成功的构造了以初始符号S为根的树,而且这个树覆盖了整个输入,那么就剖析成功。首先通过词表将每个单词连接到对应的词类,如果一个单词有不止一个词类,就需要考虑所有可能。与自顶向下相反,每次进入下一层时,自底向上需要考虑被剖析的成分是否与某个规则的右手边相匹配,而自顶向下是与左手边相匹配。中途如果无法匹配到规则则将这个树枝从搜索空间中删除,如下图所示: -
    • -
    • 两者对比: +
    • 三步走
        -
      • 自顶向下是从S开始搜索的,因此不会搜索那些在以S为根的树中找不到位置的子树,而自底向上会产生许多不可能的搜索树
      • -
      • 相对应的,自顶向下把搜索浪费在了不可能产生输入单词序列的树上
      • -
      • 综上,我们需要将自顶向下和自底向上相结合
      • +
      • 预处理:得到一个能够包含整图信息的矩阵
      • +
      • 分解:做特征分解,将每个节点映射到低维嵌入
      • +
      • 分组:根据低维嵌入做聚类
    • -
    -

    歧义

    +
  • 定义问题: graph +partition,即将图的节点分为几个互不相交的集合,一个好的划分应该保证集合内节点之间的连接尽量多,集合之间节点之间的连接尽量少。
  • +
  • 定义cut(A,B)为AB两个集合节点之间的连接权重之和,那么最小切就是使得cut(A,B)最小的AB划分
  • +
  • 如何再考虑上AB集合内部的连接,定义vol(A)为A内部节点的度加权之和,那么可以得到衡量partition的一个指标Conductance: +\[ +\phi(A, B)=\frac{\operatorname{cut}(A, B)}{\min (\operatorname{vol}(A), +\operatorname{vol}(B))} +\]
  • +
  • 找到一个好的partition是np-hard
  • +
  • 基于图谱的划分:
      -
    • 在句法剖析中需要解决的一个问题是结构歧义,即语法会给一个句子多种剖析结果可能。
    • -
    • 最常见的两种歧义:附着歧义和并列连接歧义。
    • -
    • 如果一个特定的成分可以附着在剖析树的一个以上的位置,句子就会出现附着歧义。例如We -saw the Eiffel Tower flying to Paris一句中,flying to Paris可以修饰Eiffel -Tower也可以修饰We。
    • -
    • 在并列连接歧义中,存在着不同的短语,这些短语之间用and这样的连接词相连。例如old -men and -women可以是老年男性和老年女性,或者老年男性和普通女性,即old是否同时分配到men和women上。
    • -
    • 以上两种歧义还能相互组合嵌套形成更复杂的歧义。假如我们不消歧,仅仅返回所有的可能,留给用户或者人工判断,则随着剖析句子结构变复杂或者剖析规则的增加,得到的可能是成指数级增长的,具体而言,这种剖析句子可能的增长数和算术表达式插入括号问题相同,以Catalan数按指数增长: +
    • 我们定义A为无向图的邻接矩阵,x为节点相关的向量,那么Ax得到就是邻域求和的结果 \[ -C(n)=\frac{1}{1+n} C_{2n}^n +y_{i}=\sum_{j=1}^{n} A_{i j} x_{j}=\sum_{(i, j) \in E} x_{j} \]
    • -
    • 摆脱这种指数爆炸的方法有两个: +
    • 我们定义"spectrum of +graph",即图谱为A的特征向量构成的矩阵,按特征值\(\lambda\)大小排序,\(Ax=\lambda x\)
    • +
    • 那么假设图是d-regular,即所有节点的度都是d,那么很容易得到\(\lambda = d, +x=(1,1,...,1)\)是该图的一组特征值/特征向量,且可以证明d是最大的特征值
    • +
    • 假如图是有两个连通分量,分别都是d-regular,那么对应的特征值依然是d,对应的特征向量有两个,分别是A分量里的节点置1,B置0以及vice +versa
    • +
    • 这样根据node eigen +vector的分量是1还是0就可以做一个划分,将节点分为两部分。显然两个d-regular的分量,用少数几条边连接起来,这应该是整图的一个好的划分。
    • +
    • 那么现在假设存在一个好的划分,整图是一个d-regular的图(这样两个分量就不是d-regular了,因为要考虑划分之间的连接所有节点的度才为d),分量之间有很少的连接。我们已知一个特征向量是全1的,且对应着最大的特征值d,那么直觉上第二大的特征值应该和d非常接近,因为我们知道断开的两个分量构成的图最大的特征值也为d,现在的图跟断开的图差别不是很大。而且由于特征向量之间相互正交而已知一个特征向量是全1,那么第二大的特征值对应的特征向量应该和为1,有正有负。类比于断开成两个分量的场景,我们也可以根据特征向量中分量的正负来划分节点。当然这都是直觉上的推测,下面引入Laplacian矩阵来详细说明。
    • +
    • 邻接矩阵的性质:n*n方阵,对称,n个实特征值,特征向量相互正交
    • +
    • 再定义度矩阵D,这是一个对角阵,第i个对角值存储第i个节点的度
    • +
    • 定义Laplacian矩阵,\(L=D-A\),显然\(\lambda = 0, +x=(1,1,...,1)\)是该图的一组特征值/特征向量。L矩阵的一些性质包括:
        -
      • 动态规划,研究搜索空间的规律性,使得常见的部分只推导一次,减少与歧义相关的开销
      • -
      • 使用试探性的方法来改善剖析器的搜索策略
      • +
      • 所有特征值非负
      • +
      • 半正定
      • +
      • 可以分解为\(N^TN\)
      • +
      • 实际上三个性质是等价的
    • -
    • 使用例如深度优先搜索或者宽度优先搜索之类的有计划与回溯的搜索算法是在复杂搜索空间中搜索常用的算法,然而在复杂语法空间中无处不在的歧义使得这一类搜索算法效率低下,因为有许多重复的搜索过程。
    • -
    -

    动态规划剖析方法

    -
      -
    • 在动态规划中,我们维护一个表,系统的将对于子问题的解填入表中,利用已经存储的子问题的解解决更大的子问题,而不用重复从头开始计算。
    • -
    • 在剖析中,这样的表用来存储输入中各个部分的子树,当子树被发现时就存入表中,以便以后调用,就这样解决了重复剖析的问题(只需查找子树而不需要重新剖析)和歧义问题(剖析表隐含的存储着所有可能的剖析结果)。
    • -
    • 主要的三种动态规划剖析方法有三种,CKY算法、Earley算法和表剖析算法。
    • -
    -

    CKY剖析

    -
      -
    • CKY剖析要求语法必须满足Chomsky范式,即生成式右边要么时两个非终止符号要么是一个终止符号。如果不是Chomsky范式,则需要把一个一般的CFG转换成CNF: +
    • 那么L矩阵的二次型的含义是什么? \[ +\begin{array}{l} +x^{T} L x=\sum_{i, j=1}^{n} L_{i j} x_{i} x_{j}=\sum_{i, +j=1}^{n}\left(D_{i j}-A_{i j}\right) x_{i} x_{j} \\ +=\sum_{i} D_{i i} x_{i}^{2}-\sum_{(i, j) \in E} 2 x_{i} x_{j} \\ +=\sum_{(i, j) \in E_{1}}\left(x_{i}^{2}+x_{j}^{2}-2 x_{i} +x_{j}\right)=\sum_{(i, j) \in E}\left(x_{i}-x_{j}\right)^{2} +\end{array} +\]
    • +
    • 可以证明,二次型等价于矩阵的特征值加权x在对应特征向量上的坐标的平方求和 +\[ +x = \sum _{i=1}^n \alpha _i w_i \\ +x^TMx = \sum _i \lambda _i \alpha _i^2 \\ +\]
    • +
    • 回到我们要找第二大的特征值,可以证明,对于对称阵: \[ +\lambda_{2}=\min _{x: x^{T} w_{1}=0} \frac{x^{T} M x}{x^{T} x} \\ +\left(\mathbf{w}_{1} \text { is eigenvector corresponding to } +\lambda_{1}\right) \\ +\]
    • +
    • 当这个对称阵是L矩阵时,有 \[ +\lambda _ 2 = min \frac{\sum _{i,j \in E}(x_i - x_j)^2}{\sum _i x_i^2} +\\ +\sum x_i = 0 \\ +\]
    • +
    • 根据Fiedler'73的寻找最佳划分的方法,令节点label为1,-1来表示划分,所有节点求和为0来强制两个划分的集合大小一致,其提出的最佳划分是 +\[ +\arg \min _{y \in\{-1,+1\}^{n}} f(y)=\sum_{(i, j) \in +E}\left(y_{i}-y_{j}\right)^{2} +\]
    • +
    • 可以发现将其label的限制从离散的1,-1放宽到实数值之后,等价于我们找L矩阵的第二大特征值和特征向量,第二特征值对应的特征向量分量的正负决定了划分情况(节点的分配情况)
    • +
  • +
  • 回到spectral clustering
      -
    • 右边有终止符号也有非终止符号:给右边的终止符号单独建一个非终止符号,例如:INF-VP -→ to VP,改成INF-VP → TO VP和TO → to
    • -
    • 右边只有一个非终止符号:这种非终止符号称为单元产物,它们最终会生成非单元产物,用最终生成的非单元产物规则来替换掉单元产物
    • -
    • 右边不止2个符号:引入新的非终止符号将规则分解
    • -
    • 词法规则保持不变,但是在转换的过程中可能会生成新的词法规则
    • +
    • 预处理:构建L矩阵
    • +
    • 分解:对L矩阵做特征分解,得到每个节点在第二大特征值对应的特征向量上的分量
    • +
    • 分组:将节点按分量大小排序,找一个切分值,大于切分值的划为一组,小于切分值的划为一组。怎么找切分值?naive的方法就是设为0,expensive的方法就是都试一遍,取最好的
    • +
    • 通过可视化结果可以看到最优切分能够很好的对应聚类,而且多类也是一样,存在明显的分量差异: +
    • +
    • 聚多类的两种方式:迭代式的聚类,每次聚两类;聚k类,找k个特征向量,而不仅仅是第二大的,然后相当于每个节点有k维特征,用k-means做聚类
    • +
    • 怎么确定聚几类?聚成k类时,第k大特征值和第k-1大特征值之间的差应该最大
  • -
  • 当所有的规则都转换成CNF之后,表中的非终止符号在剖析中有两个子节点,且表中每一个入口代表了输入中的某个区间,对于某个入口例如[0,3],其可以被拆分成两部分,假如一部分为[0,2],则另一部分为[2,3],前者在[0,3]的左边,后者在[0,3]的正下方,如下图: -
  • -
  • 接下来就是如何填表,我们通过自底向上的方法来剖析,对于每个入口[i,j],包含了输入中i到j这一区间部分的表格单元都会对这个入口值做出贡献,即入口[i,j]左边的单元和下边的单元。下表中的CKY伪算法图描述了这一过程: -
  • -
  • 外层循环从左往右循环列,内层循环从下往上循环行,而最里面的循环式遍历串[i,j]的所有可能二分子串,表中存的是可以代表[i,j]区间符号串的非终止符号集合,因为是集合,所以不会出现重复的非终止符号。
  • -
  • 现在我们完成了识别任务,接下来是剖析。剖析即在[0,N]入口,对应整个句子,找到一个非终止符号作为起始符号S。首先我们要对算法做两点更改: +
  • 基于motifs的spectral clustering
      -
    • 存入表中的不仅仅是非终止符号,还有其对应的指针,指向生成这个非终止符号的表入口
    • -
    • 允许一个入口中存在同一个非终止符号的不同版本
    • +
    • 当我们把边的概念升级到motifs时,就可以得到以motifs为特征的谱聚类
    • +
    • 同样的,我们可以得到基于motifs的Conductance,直接找也依然是NP-hard
    • +
    • 事实上,给定图G和motifs +M,可以构建一个新图,在新图上做谱聚类即可
    • +
    • 定义新图为\(W\),则\(W_{ij}^M\) = # times edge (i,j) +participates in the motif M
  • -
  • 做了这些改动之后,这张表就包含了一个给定输入的所有可能剖析信息。我们可以选择[0,N]入口中任意一个非终止符号作为起始符号S,然后根据指针迭代提取出剖析信息。
  • -
  • 当然,返回所有的可能剖析会遇到指数爆炸的问题,因此我们在完整的表上应用维特比算法,计算概率最大的剖析并返回这个剖析结果。
  • -

    Early算法

    +

    消息传递和节点分类

      -
    • 相比CKY自底向上的剖析,Early算法采用了自顶向下的剖析,而且只用了一维的表保存状态,每个状态包含三类信息: +
    • 在直推式学习中,已知图上部分节点的label,如何根据图的结构和已知节点,推断出其他节点的label?这就是半监督节点分类
    • +
    • 三种技术:
        -
      • 对应某一单一语法规则的子树
      • -
      • 子树的完成状态
      • -
      • 子树对应于输入中的位置
      • +
      • Relational classification
      • +
      • Iterative classification
      • +
      • Belief propagation
    • -
    • 算法流程图如下: FoZHKO.png
    • -
    • 算法对于状态的操作有三种: +
    • 关键在于利用网络(图)当中的关系(边),有三种重要的关系
        -
      • 预测:造出一个新的状态来表示在剖析过程中生成的自顶向下的预测。当待剖析的状态为非终极符号但又不是词类范畴时,对于这个非终极符号的不同展开,预测操作都造出一个新的状态。
      • -
      • 扫描:当待剖析的状态是词类范畴时,就检查输入符号串,并把对应于所预测的词类范畴的状态加入线图中。
      • -
      • 完成:当右边所有状态剖析完成时,完成操作查找输入中在这个位置的语法范畴,发现并推进前面造出的所有状态。
      • +
      • Homophily: the tendency of individuals to associate and bond with +similar others
      • +
      • Influence: social connections can influence the individual +characteristics of a person
      • +
      • Confounding
    • -
    -

    表剖析

    -
      -
    • 表剖析允许动态的决定表格处理的顺序,算法动态的依照计划依次删除图中的一条边,而计划中的元素排序是由规则决定的。 -
    • -
    -

    部分剖析

    -
      -
    • 有时我们只需要输入句子的部分剖析信息
    • -
    • 可以用有限状态自动机级联的方式完成部分剖析,这样会产生比之前提到的方法更加“平”的剖析树。
    • -
    • 另一种有效的部分剖析的方法是分块。使用最广泛覆盖的语法给句子做词类标注,将其分为有主要词类标注信息且不没有递归结构的子块,子块之间不重叠,就是分块。
    • -
    • 我们用中括号将每一个分块框起来,有可能一些词并没有被框住,属于分块之外。
    • -
    • 分块中最重要的是基本分块中不能递归包含相同类型的成分。
    • -
    -

    基于规则的有限状态分块

    +
  • 最直观的想法,相邻的节点具有相似的label
  • +
  • collective +classification做出了马尔可夫假设,即节点的分类只受其一阶邻居影响
      -
    • 利用有限状态方式分块,需要为了特定目的手动构造规则,之后从左到右,找到最长匹配分块,并接着依次分块下去。这是一个贪心的分块过程,不保证全局最优解。
    • -
    • 这些分块规则的主要限制是不能包含递归。
    • -
    • 使用有限状态分块的优点在于可以利用之前转录机的输出作为输入来组成级联,在部分剖析中,这种方法能够有效近似真正的上下文无关剖析器。
    • -
    -

    基于机器学习的分块

    +
  • load classifier:不使用网络信息,先根据节点特征做出分类
  • +
  • relational +classifier:学习到一个分类器,输入邻接节点的label和特征,输出中心节点的label
  • +
  • collective +inference:不断的传播网络的相关性,对每个节点迭代的使用relational +classifier
  • + +
  • 精确的推断是np-hard的,这里介绍三种近似推断的方法:
      -
    • 分块可以看成序列分类任务,每个位置分类为1(分块)或者0(不分块)。用于训练序列分类器的机器学习方法都能应用于分块中。
    • -
    • 一种卓有成效的方法是将分块看成类似于词类标注的序列标注任务,用一个小的标注符号集同时编码分块信息和每一个块的标注信息,这种方式称为IOB标注,用B表示分块开始,I表示块内,O表示块外。其中B和I接了后缀,代表该块的句法信息。
    • -
    • 机器学习需要训练数据,而分块的已标数据很难获得,一种方法是使用已有的树图资料库,例如宾州树库。
    • -
    -

    评价分块系统

    +
  • Relational classification:对邻域节点的label概率加权求和 \[ +P\left(Y_{i}=c\right)=\frac{1}{\sum_{(i, j) \in E} W(i, j)} \sum_{(i, j) +\in E} W(i, j) P\left(Y_{j}=c\right) +\] 缺点:不保证收敛,且没有用到节点特征
  • +
  • Iterative +classification:先对每个节点初始化一个特征向量,训练一个分类器(用有gold +label的节点训练),输入特征向量输出Label,这是一个Local +classifier,不考虑网络结构。等到每个节点都预测了label之后,根据网络结构进行消息传递,更新节点的特征向量,然后再用local +classifier预测label,如此迭代。一篇应用论文REV2: +Fraudulent User Prediction in Rating Platforms
  • +
  • Belief propagation:基于动态规划的方法,"Belief Propagation is a +dynamic programming approach to answering conditional probability +queries in a graphical model"
      -
    • 准确率:模型给出的正确分块数/模型给出的总分块数
    • -
    • 召回率:模型给出的正确分块数/文本中总的正确分块数
    • -
    • F1值:准确率和召回率的调和平均
    • +
    • 定义label的矩阵\(\psi\),其定义了邻域节点label为i时,中心节点的label为j的概率\(\psi _{ij}\)
    • +
    • 给定每个节点的初始概率(先验)\(\phi\)
    • +
    • \(m_{i \rightarrow +j}\left(Y_{j}\right)\)代表i到j的belief,即邻居i对于节点j的label为\(Y_j\)的估计
    • +
    • 则有: GKoNtK.png +即每次我们根据先验、label的转移概率、上一轮邻域节点的信念更新这一轮的信念;收敛之后根据先验和最终的邻域信念就可以推断中心节点的label
    • +
    • 参考论文:Netprobe: A Fast and Scalable System for Fraud Detection +in Online Auction Networks Pandit et al., World Wide Web conference +2007
    • +
  • + -

    第十四章:统计剖析

    -

    概率上下文无关语法

    +

    图表示学习

      -
    • 概率上下文无关语法PCFG是上下文无关语法的一种简单扩展,又称随机上下文无关语法。PCFG在定义上做出了一点改变: +
    • 希望用无监督的方法学习到任务无关的节点通用特征
    • +
    • 和word +embedding一样,一个目标是,网络中相邻的节点,在embedding当中应该相似,因此框架是
        -
      • N:非终止符号集合
      • -
      • Σ:终止符号集合
      • -
      • R:规则集合,与上下文无关语法相同,只不过多了一个概率p,代表某一项规则执行的条件概率\(P(\beta|A)\)
      • -
      • S:一个指定的开始符号
      • +
      • 定义一个编码器,将节点编码成embedding
      • +
      • 定义一个节点相似度函数
      • +
      • 优化编码器参数,使得\(similarity(u,v) +\approx z_v^Tz_u\)
    • -
    • 当某个语言中所有句子的概率和为1时,我们称这个PCFG时一致的。一些递归规则可能导致PCFG不一致。
    • -
    -

    用于消歧的PCFG

    -
      -
    • 对于一个给定句子,其某一特定剖析的概率是所有规则概率的乘积,这个乘积既是一个剖析的概率,也是剖析和句子的联合概率。这样,对于出现剖析歧义的句子,其不同剖析的概率不同,通过选择概率大的剖析可以消歧。
    • -
    -

    用于语言建模的PCFG

    +
  • 最简单的方法:编码器只是一个embedding look +up,每个节点预先分配一个embedding +vector,例如DeepWalk,node2vec,TransE
  • +
  • 因此主要区别在于如何定义similarity
  • +
  • DeepWalk:
      -
    • PCFG为一个句子分配了一个概率(即剖析的概率),因此可以用于语言建模。相比n元语法模型,PCFG在计算生成每一个词的条件概率时考虑了整个句子,效果更好。对于含歧义的句子,其概率是所有可能剖析的概率之和。
    • -
    -

    PCFG的概率CKY剖析

    +
  • 每次随机游走采样出固定长序列,希望游走出发点和序列中的点比较相似,因此这里similarity定义为随机游走序列中的共现
  • +
  • 优化目标是softmax之后的log-likelihood,和word +embedding一样,这里需要对所有节点计算来配分母,计算量太大,解决方案也是与word2vec类似,采用negative +sampling,只采样部分负样本,用Noise Contrastive +Estimation的目标函数来近似softmax之后的结果 GMWPvn.png
  • +
  • 假如我们对所有节点无差别的sample出一个定长的随机游走序列,那就是DeepWalk模型
  • + +
  • node2vec
      -
    • PCFG的概率剖析问题:为一个句子产生概率最大的剖析
    • -
    • 概率CKY算法扩展了CKY算法,CKY剖析树中的每一个部分被编码进一个\((n+1)*(n+1)\)的矩阵(只用上三角部分),矩阵中每一个元素包含一个非终止符号集合上的概率分布,可以看成每一个元素也是V维,因此整个存储空间为\((n+1)*(n+1)*V\),其中[i,j,A]代表非终止符号A可以用来表示句子的i位置到j位置这一段的概率。
    • -
    • 算法伪代码:
    • -
    • 可以看到也是用k对某一区间[i,j]做分割遍历,取最大的概率组合作为该区间的概率,并向右扩展区间进行动态规划。
    • -
    -

    学习到PCFG的规则概率

    +
  • 同样是基于随机游走,node2vec在游走策略上做出了改进
  • +
  • 游走时不仅做dfs,还做bfs:前者获取Global macroscopic +view;后者获取Local microscopic view
  • +
  • node2vec在两者之间做了插值,定义参数q为Moving outwards (DFS) vs. +inwards (BFS)的比例,同时还定义了返回参数p,即返回到初始点
  • +
  • 具体的游走策略如下: GMfTOI.png
  • + +
  • TransE
      -
    • 上面的伪算法图用到了每一个规则的概率。如何获取这个概率?两种方法,第一种朴素的方法是在一个已知的树库数据集上用古典概型统计出概率: -\[ -P(\alpha \rightarrow \beta | \alpha) = \frac{Count(\alpha \rightarrow -\beta)}{\sum _{\gamma} Count(\alpha \rightarrow \gamma)} +
    • 在知识图谱中,三元组(subject,predicate,object)表示了图中两个节点以及相连的边,都有feature +vector
    • +
    • TransE的目标是学习到所有实体节点和关系边的embedding,该算法将边解释为一种翻译,即predicate将subject翻译为Object
    • +
    • 数学表示就是简单的\(u_{subject} + +v_{predicate} = u_{object}\)
    • +
    • 训练采用了对比学习,采样负样本,用margin loss \[ +\begin{aligned} +&\sum \quad \nabla\left[\gamma+d(\boldsymbol{h}+\ell, +\boldsymbol{t})-d\left(\boldsymbol{h}^{\prime}+\ell, +\boldsymbol{t}^{\prime}\right)\right]_{+}\\ +&\left((h, \ell, t),\left(h^{\prime}, \ell, t^{\prime}\right)\right) +\in T_{\text {batch}} \quad +\end{aligned} \]
    • -
    • 假如我们没有树库,则可以用非概率剖析算法来剖析一个数据集,再统计出概率。但是非概率剖析算法在剖析歧义句子时,需要对每一种可能剖析计算概率,但是计算概率需要概率剖析算法,这样就陷入了鸡生蛋蛋生鸡的死循环。一种解决方案是先用等概率的剖析算法,剖析句子,得出每一种剖析得概率,然后用概率加权统计量,然后重新估计剖析规则的概率,继续剖析,反复迭代直到收敛。这种算法称为inside-outside算法,是前向后向算法的扩展,同样也是EM算法的一种特例。
    • -
    -

    PCFG的问题

    -
      -
    • 独立性假设导致不能很好的建模剖析树的结构性依存:每个PCFG规则被假定为与其他规则独立,例如,统计结果表明代词比名词更有可能称为主语,因此当NP被展开时,如果NP是主语,则展开为代词的可能性较高——这里需要考虑NP在句子种的位置,然而这种概率依存关系是PCFG所不允许的,
    • -
    • 缺乏对特定单词的敏感,导致次范畴化歧义、介词附着、联合结构歧义的问题:例如在介词附着问题中,某一个介词短语into -Afghanistan附着于哪一个部分,在PCFG中计算时被抽象化为介词短语应该附着一个哪一个部分,而抽象化的概率来自于对语料的统计,这种统计不会考虑特定的单词。又例如联合结构歧义,假如一个句子的两种可能剖析树使用了相同的规则,而规则在树中的位置不同,则PCFG对两种剖析计算出相同的概率:因为PCFG假定规则之间是独立的,联合概率是各个概率的乘积。
    • -
    -

    通过拆分和合并非终止符号来改进PCFG

    +
  • +
  • 如何embedding整张图?
      -
    • 先解决结构性依存的问题。之前提到了我们希望NP作为主语和宾语时有不同概率的规则,一种想法就是将NP拆分成主语NP和宾语NP。实现这种拆分的方法是父节点标注,及每个节点标注了其父节点,对于主语NP其父节点是S,对于宾语NP,其父节点是VP,因此不同的NP就得到了区分。除此之外,还可以通过词性拆分的方式增强剖析树。
    • -
    • 拆分会导致规则增多,用来训练每一条规则的数据变少,引起过拟合。因此要通过一个手写规则或者自动算法来根据每个训练集合并一些拆分。
    • -
    -

    概率词汇化的CFG

    +
  • 最简单的方法:学到节点的embedding,然后所有节点做平均或者求和
  • +
  • 或者引入一个虚节点,其和所有节点相连接,然后跑node-level +embedding的方法,得到这个虚节点的embedding作为图的embedding,这种方法还可以得到子图的embedding
  • +
  • Anonymous Walk +Embedding:我们将节点匿名,用其在随机游走学列中第一次出现的index来代表,那么长度为3的游走序列就有111,112,121,122,123五种可能。那么就可以:
      -
    • 概率CKY剖析更改了语法规则,而概率词汇化模型更改了概率模型本身。对于每一条规则,不仅要产生成分的规则变化,还要在每个成分上标注其中心词和词性,如下图: -
    • -
    • 为了产生这样的剖析树,每一条PCFG规则右侧需要选择一个成分作为中心词子节点,用子节点的中心词和词性作为该节点的中心词和词性。 -其中,规则被分成了两类,内部规则和词法规则,后者是确定的,前者是需要我们估计的: -
    • -
    • 我们可以用类似父节点标注的思想来拆分规则,拆分后每一部分都对应一种可能的中心词选择。假如我们将概率词汇话的CFG看成一个大的有很多规则CFG,则可以用之前的古典概型来估计概率。但是这样的效果不会很好,因为这样的规则划分太细了,没有足够的数据来估计概率。因此我们需要做出一些独立性假设,将概率分解为更小的概率乘积,这些更小的概率能容易从语料中估计出来。
    • -
    • 不同的统计剖析器区别在于做出怎样的独立性假设。
    • -
    • Collins剖析如下图所示: FoZzGt.png
    • -
    • 其概率拆解为: \[ -P(VP(dumped,VBD)→VBD(dumped,VBD)NP(sacks,NNS)PP(into,P))= \\ -P_H (VBD│VP,dumped)* \\ -P_L (STOP│VP,VBD,dumped)* \\ -P_R (NP(sacks,NNS)│VP,VBD,dumped)* \\ -P_R (PP(into,P)│VP,VBD,dumped)* \\ -P_R (STOP|VP,VBD,dumped) \\ -\]
    • -
    • 给出生成式左边之后,首先生成规则的中心词,之后一个一个从里到外生成中心词的依赖。先从中心词左侧一直生成直到遇到STOP符号,之后生成右边。如上式做出概率拆分之后,每一个概率都很容易从较小的数据量中统计出来。完整的Collins剖析器更为复杂,还考虑了词的距离关系、平滑技术、未知词等等。
    • +
    • 统计图中长度为l的所有序列,将图表示为匿名序列的特征向量,分量的值是该序列在图中出现的次数
    • +
    • 对每张图采样m个匿名序列,再统计特征向量
    • +
    • 学习到每个匿名序列的embedding,进而得到图的embedding。类似于语言模型,已知前n个匿名序列,预测第n+1个匿名序列,建立模型来学习参数
    • +
  • + -

    评价剖析器

    +

    图神经网络

      -
    • 剖析器评价的标准方法叫做PARSEVAL测度,对于每一个句子s: +
    • 基于随机游走的方法其实是在similarity这部分做文章,在encoder这一块依然采用最简单的embedding +lookup
    • +
    • 图神经网络就为encoder引入了deep neural network
    • +
    • GCN
        -
      • 标记召回率=(Count(s的候选剖析中正确成分数))/(Count(s的树库中正确成分数))
      • -
      • 标记准确率=(Count(s的候选剖析中正确成分数))/(Count(s的候选剖析中全部成分数))
      • +
      • idea:邻接关系定义了计算图,GCN利用图的结构来传播信息,更新节点的embedding
      • +
      • 通过aggregate邻域节点来生成node +embedding,aggregate的过程使用神经网络,每一个节点基于其邻接状态定义了一个计算图
      • +
      • 最简单的aggregate:收集邻域节点的embedding,做平均,然后当前节点embedding和邻域平均embedding做拼接输入一个神经网络,获得当前节点下一层的embedding: +
      • +
      • 这样就完成了encoder的定义,可以直接进行supervised +learning,也可以接上random walks里的各种无监督目标函数来训练node +embedding
      • +
      • 由于aggregate的参数在所有节点上共享,因此对于图上其他未知的节点也可以使用同一套encoder,新的一张图也可以。
    • -
    -

    判别式重排序

    +
  • GraphSage
      -
    • PCFG剖析和Collins词法剖析都属于生成式剖析器。生成式模型的缺点在于很难引入任意信息,即很难加入对某一个PCFG规则局部不相关的特征。例如剖析树倾向于右生成这一特征就不方便加入生成式模型当中。
    • -
    • 对于句法剖析,有两类判别式模型,基于动态规划的和基于判别式重排序的。
    • -
    • 判别式重排包含两个阶段,第一个阶段我们用一般的统计剖析器产生前N个最可能的剖析及其对应的概率序列。第二个阶段我们引入一个分类器,将一系列句子以及每个句子的前N个剖析-概率对作为输入,抽取一些特征的大集合并针对每一个句子选择最好的剖析。特征包括:剖析概率、剖析树中的CFG规则、平行并列结构的数量、每个成分的大小、树右生成的程度、相邻非终止符号的二元语法、树的不同部分出现的次数等等。
    • -
    -

    基于剖析的语言建模

    +
  • 在aggregate的形式上做了进一步扩展
  • +
  • 除了mean,其实任意的将多个embedding映射到一个embedding的函数都可以用来做聚合,例如pool,例如LSTM,
  • + +
  • Kipf GCN
      -
    • 使用统计剖析器来进行语言建模的最简单方式就是利用之前提到的二阶段算法。第一阶段我们运行一个普通的语音识别解码器或者机器翻译解码器(基于普通的N元语法),产生N个最好的候选;第二阶段,我们运行统计剖析器并为每一个候选句分配一个概率,选择概率最佳的。
    • -
    -

    人类剖析

    +
  • 将每一层的aggregate&update操作写成矩阵形式,就可以利用高效的稀疏矩阵操作来提速 +
  • +
  • 其中的A都加了自环,邻域中包含了自己,而不是邻域与自己拼接,这里稍有不同。Kipf的形式其实是加权求和时权重做了对称归一化,考虑了邻域节点的度,而不仅仅考虑自身的度。
  • + +
  • GAT
      -
    • 人类在识别句子时也用到了类似的概率剖析思想,两个例子: +
    • 可以看到GCN和GraphSage在聚合邻域节点时,不同邻居节点的权重都是一样的,那么自然可以使用注意力机制,根据邻域节点和自身的embedding计算出注意力作为权重再聚合。
    • +
    • 参考transformer,使用multi-head attention
    • +
  • +
  • GNN的训练技巧
      -
    • 对于出现频率高的二元语法,人们阅读这个二元语法所花的时间就更少
    • -
    • 一些实验表明人类在消歧时倾向于选择统计概率大的剖析
    • +
    • 预处理很重要,Use renormalization tricks、 Variance-scaled +initialization、 Network data whitening
    • +
    • adam优化,relu激活
    • +
    • output layer不需要激活
    • +
    • 每一层记得加bias
  • ]]>
    @@ -7248,174 +6959,71 @@ P_R (STOP|VP,VBD,dumped) \\ 机器学习 - machine learning math - theory - nlp + gnn + graph
    - Easy Reinforcement Learning Notes - /2019/09/23/easyrl/ - 极简风格 - Q-learning - Sarsa - Sarsa(\(\lambda\)) - DQN - Double DQN - DQN with -Prioritized Experience replay - Dueling DQN - Policy Gradient

    - -

    定义

    -
      -
    • agent:智能体,智能体处在某一状态下,依据某种策略(policy),采取一个动作,到达下一个状态
    • -
    • s:status,状态
    • -
    • a:action,动作
    • -
    • r:reward,奖励
    • -
    • s,a:可以称之为一步。智能体的行为可以描述为一系列步。强化学习里agent的行为可以用DP(决策过程)表示,s是DP里的节点状态,a是状态之间的转移路径
    • -
    • Q:Q表,Q(s,a)即状态s下执行动作a的价值(infer时的可能性),用奖励期望来估计
    • -
    -

    Q-learning

    -
      -
    • 随机Q表,初始化状态,开始迭代,\(\epsilon\)贪心
    • -
    • 在状态s采取动作a,观察到奖励r和状态\(s -\prime\)
    • -
    • 关键迭代公式: \[ -Q(s,a) = Q(s,a) + \alpha [r + \gamma max_{a \prime}Q(s \prime,a \prime) -- Q(s,a)] \\ -\]
    • -
    • Q的更新包括两部分,一部分自然是奖励(假如这一步得到奖励的话),另一部分是时间差值,即TD-error,是现实和估计之间的差值。这里的现实是在新状态采取了最好动作后得到的奖励,这里的估计是指我们所有的奖励,除了最终步得到的真实奖励,其余中间步都是用Q表值来估计现实奖励,因此Q表的更新应该是加上(现实-估计),即让Q表更加贴近现实。
    • -
    • 值得注意的是,只有最后一步得到奖励时(假如我们只有终点一个奖励),现实才真的是现实的奖励,否则还是用Q表估计的。
    • -
    • 这里Q表的更新只与未来的状态和动作有关,在最开始,应该除了真正有奖励的最后一步,其余步骤的更新都是不确定的(因为现实也是用Q表估计的,只有最后一步现实才是现实),但第一次迭代之后最后一步的价值更新是确定的(在宝藏边上还是知道怎么走向宝藏),且与LSTM那种时间序列不同,它不是从最后一个时间步往前BPTT,而是更新了一个状态的转移价值(取哪个动作好),这个状态可能出现在每一次迭代的多个时间步上(或者说和时间步无关),接下来与该状态相邻的状态更新时,用Q表估计的现实就会准确一些,慢慢的整个算法达到收敛。
    • -
    -

    Sarsa

    -
      -
    • Q-learning是off-policy的,因为存在着现实和估计的差距,我们朝着现实优化,而实际采取的是根据Q表估计的现实,即异步的(off)。
    • -
    • Sarsa是on-policy的,与Q-learning在算法上的区别: -
        -
      • Q-learning:根据Q表选动作-执行动作观察到奖励和新状态-更新Q表-更新状态
      • -
      • Sarsa:执行动作观察到奖励和新状态-更新状态-根据Q表在新状态上选动作,在迭代之前先来一次根据Q表选动作
      • -
    • -
    • 可以看到Sarsa更改了学习算法的步骤顺序,这种更改带来了什么效果?效果就是将新状态和新动作的选取提前到Q表更新之前,这样Q表更新时,差距里现实的部分不用\(max_{a \prime}Q(s \prime,a -\prime)\)来估计,而直接用新状态和新动作: \[ -Q(s,a) = Q(s,a) + \alpha [r + \gamma Q(s \prime,a \prime) - Q(s,a)] \\ -\]
    • -
    • 也就是说现实和估计采用的是同一策略(确定的动作,而不是给定状态选最大价值),然后依然使用这个差距来更新。
    • -
    • 在更新的过程中,sarsa说到做到(因为现实采用的就是新状态和新动作,agent一定会按照这样更新),而Q-learning则比较乐观(因为现实采用的是新状态下的最大价值,但实际走不一定会采取最大价值的行动,有\(\epsilon\)的扰动)。Sarsa更为保守(每一步都想走好),而Q-learning更为激进(先rush到再说)。
    • -
    -

    Sarsa(\(\lambda\))

    -
      -
    • naive版本的Sarsa可以看成是Sarsa(0),因为每走一步就更新了Q表,即\(Q(s \prime,a \prime)\)只会带来上一步\(Q(s,a)\)的价值更新。假如我们考虑对所有步的更新,且离最终奖励近的步权重大,离最终奖励远的步权重小,那么调整这个权重的超参就是\(\lambda\),权重为0就是不考虑之前的步数,即naive -Sarsa。
    • -
    • 具体实现是添加一个trace矩阵E(矩阵中每一个元素对应一步(s,a))保存所有步在该次路径中的权重,离最终奖励越近,权重越大,因此每走一步,执行的那一步元素对应矩阵值加1,然后用对应的trace矩阵值作为权重乘到奖励上来更新Q表(这里是所有的步和整个E矩阵乘起来),之后矩阵值会衰减一下,乘以更新衰减因子\(\gamma\)和权重超参\(\lambda\)。显然\(\gamma\)为1时,就是所有的状态得到了一样的更新(因为是所有步和整个E矩阵相乘);当\(\gamma\)为0时,除了执行步元素加了1,然后整个E矩阵都置0,因此只有执行步得到了更新,即naive -Sarsa。将E矩阵的迭代展开,就可以得到与naive -sarsa一样的展开,只不过衰减的时候加了一个E(s,a)来记录某一步距离奖励的距离。 -\[ -\delta = r + \gamma Q(s \prime,a \prime) - Q(s,a) \\ -E(s,a) = E(s,a) + 1 \\ -Q = Q + \alpha \delta E \\ -E = \gamma \lambda E \\ -update \ \ s,a \\ -\]
    • -
    • 这个E矩阵就是eligibility -trace。对于某一步,如果被执行了,就增加一点值,之后慢慢衰减,直到又被执行。假如短期内被执行多次,就会上升到过高值,这时可以设置阈值来限制eligibility的增加。这个值可以解释为该步在该次迭代中对于找到最终奖励的贡献程度。
    • -
    -

    DQN

    -
      -
    • Q-learning + deep neural network
    • -
    • 神经网络用于把Q-table的更新过程参数化,输入一个状态向量,神经网络输出所有动作的价值,用神经网络的训练来替代简单的迭代更新。这样可以解决状态数过多导致的维度灾难问题。
    • -
    • 直接这么替换不容易训练,DQN引入两个技巧 -
        -
      • experience replay
      • -
      • fix q
      • -
    • -
    • 先看神经网络的输入输出和损失 -
        -
      • 有两个神经网络,一个网络参与训练(评价网络),一个网络只复制另一个网络训练得到的参数,用来生成ground -truth,即目标网络
      • -
      • 参与训练的网络输入是状态,表示为s维特征向量,输出是各个动作获得的a维价值向量,损失是这个向量和ground -truth的a维向量之间的均方误差。
      • -
    • -
    • DQN还包含一个记忆矩阵,维度是[记忆条数,$ 2 * s + 2$ -],每一条包含奖励、动作,老状态和新状态,即一步的所有信息。记忆只保存最近记忆条数次执行步。
    • -
    • 之后神经网络的输入输出从哪里来?其实是从记忆中采样一个Batch的数据,将老状态输入评价网络得到model -output,将新状态输入目标网络得到ground truth,之后计算损失。
    • -
    • 每隔一段时间目标网络才会复制评价网络,在此期间目标网络都是固定不变的,即fix -q
    • -
    • 而输入是从最近的记忆当中抽取的,即experience replay
    • -
    • 值得注意的是我们并不直接把评价网络输出价值向量用于计算损失,因为还没有采取动作。因此我们要先根据网络输出的价值向量采取动作,将价值向量里这些动作对应的价值用奖励更新,之后这个更新过的价值向量再参与损失计算。
    • -
    -

    Double DQN

    -
      -
    • Double DQN解决DQN over estimate的问题
    • -
    • 与DQN不同之处在于,评价网络不仅接受老状态产生一个输出\(q_{eval}\),还接受新状态产生一个输出\(q_{eval4next}\),之后依据\(q_{eval4next}\)选取动作更新\(q_{eval}\),而不是根据\(q_{eval}\)本身选取动作来更新。
    • -
    -

    DQN with Prioritized -Experience replay

    + Future of Computing Salon - Reading Comprehension Session + /2018/10/13/compute-future/ + 去清华的FIT听了一次轻沙龙,介绍了关于机器阅读理解的一些进展,有趣的是上午九点演讲的博士还说有一个还没公开的工作:BERT,很牛逼,很有钱,八块p100训一年,结果十点半机器之心就发了报道,下午就知乎满天飞了,说NLP新的时代到来了...... +这个沙龙是一个系列,之后可能会有机器翻译、深度贝叶斯、迁移学习和知识图谱啥的,要是有时间的话再听再记录吧

    + +

    2018.10.13 机器阅读理解

      -
    • 之前是从记忆库中随机采样一段记忆,这个随机采样会导致模型训练步数过多(随机很难保证到达最终奖励)
    • -
    • 那么自然而然想到记忆应该分配优先级,优先级高的采样概率大
    • -
    • 优先级可以用TD-error值来衡量,error大的自然要多采样多优化
    • -
    • 已知优先级分布,希望得到满足该优先级分布的一个采样序列,那么这就是一个蒙特卡洛问题了,可以用MCMC,可以用Importance -sampling,也可以用论文里提到的SumTree
    • +
    • 三场演讲,第一场是概述;第二场是当时在SQuAD2.0上拿到第一名的nlnet作者的presentation,国防科大和微软合作的成果;第三场是一位清华的博士,介绍了他关于开放领域问答中噪声过滤和信息集合的研究。
    -

    Dueling DQN

    +

    概述

      -
    • Dueling DQN细化了原始DQN的内部网络输入输出关系: \[ -Q(s,a;\theta,\alpha,\beta) = Value(s;\theta,\beta) + -Advantage(s,a;\theta,\alpha) -\]
    • -
    • 即拆分成了状态带来的价值和动作在该状态上带来的价值(advantage)
    • -
    • 为什么要单独考虑状态?因为有些状态是与动作无关的,无论采取什么动作都不会带来价值的改变
    • +
    • 现在的阅读理解和人们所期望的人工智能阅读理解差了太多,研究者把阅读理解的过程分解成了任务,例如选词、选span、生成短文本。深度学习兴起之前都是一些手工设计特征,一些Pipiline的操作,使用深度学习之后就专注于输入到输出的端到端研究,绕过了很多阅读理解过程所需要的东西。
    • +
    • 以前的关于阅读理解的研究可以作为一个测试方法,检验模型对于词法、修辞、利用知识的能力。
    • +
    • 目前的大规模机器阅读理解数据集处于很低级的推断阶段,提到了一篇论文:Efficient +and Robust Question Answering from Minimal Context over +Documents。里面讲到如果用深度学习,只用你找出的span来训练,砍掉上下文,其实结果不会差很多,因此端到端的学习并没有“通读全文掌握大意”的过程,而是“你问什么我答什么,别问我为什么这么答,背的”。提到了东京大学一份工作,建立了对模型阅读理解能力的评价指标,30多项,包括消除歧义、指代消解等等,大而简单的数据集无法体现这些特征,而设计巧妙的数据集规模不够大。
    • +
    • 还提到了一篇关于衡量模型推断能力的论文,TOWARDS AI-COMPLETE QUESTION +ANSWERING:A SET OF PREREQUISITE TOY TASKS。
    • +
    • 工业上使用阅读理解所需要解决的问题:简化模型或者加速模型,介绍了诸如SKIM-RNN之类的技巧,虽然训练的时候会变复杂,但推断时能加速。论文:NEURAL +SPEED READING VIA SKIM-RNN
    • +
    • 现在NLP的迁移学习,预训练词嵌入或者预训练语言模型,用的最多最广泛的,比如Glove和Elmo,然后就提到了BERT,4亿参数,无监督,最重要的是其模型是双向设计,且充分训练了上层参数:BERT: +Pre-training of Deep Bidirectional Transformers for Language +Understanding.另外一种迁移学习是直接将某一任务中训练好的模块做其他任务,例如直接将seq2seq中训练好的encoder拿出来计算语义表示(深度学习本来就是表示学习),记得fast +Disan就直接一个函数返回句子的向量表示,也是类似的思想。
    • +
    • 最新的研究领域:open domain question-answering和learning to +ask。前者实际上是加了一个信息检索的过程,阅读理解所需要的相关语料是通过提问检索到的。后者是将回答任务反过来做提问,演讲者提到反向可以辅助阅读理解,且有一个工业上比较有用的设计:做检索时不用query和文档(或者文档关键词)相比较,而是和针对文档生成的提问相比较,相当于两个提问之间计算相似度。
    • +
    • 演讲者提到了他关于attention的一个观点:attention是从模型中筛选信息,不代表原模型没有表示出此信息的能力。
    • +
    • 介绍了当前比较流行的几个数据集,2015之前用MCTest、ProcessBank,15到17年之间用CNNDM、SQuAD、MS +MARCO,17年之后用TriviaQA、SQuAD2.0、CoQA、QuAC、HotpotQA。(然而文摘还在用CNNDM......)
    -

    Policy Gradient

    -
      -
    • 之前介绍的都是基于值的强化学习方法,即在某状态查询各个动作带来的价值,选择最大价值动作执行
    • -
    • policy -gradient(策略梯度)通过策略网络输入状态,直接输出动作,跳过了计算价值的步骤,是基于策略的方法
    • -
    • 策略网络并不计算某种损失进行反向传播,而是依据奖励来反向传播,更新的算法如下: -\[ -\theta = \theta + \alpha \nabla _{\theta} \log \pi _{\theta} (s_t, a_t) -v_t \\ -\]
    • -
    • 需要注意以下几个关键点: +

      NLNet

        -
      • 这里的PG算法神经网络只负责接收状态作为输入,奖励作为梯度调整值,实际执行的动作作为gold -label,输出一个action vector,整个网络本身就是一个策略\(\pi\)(输入状态,输出动作概率分布)
      • -
      • 之后整个模型依然像DQN那样,借助策略(网络)按动作概率(网络输出)选择动作,转移状态,观察环境得到奖励
      • -
      • 那么第一个问题,这个策略梯度是怎么来的?可以看到梯度依然是损失对参数求导的形式,\(- \nabla _{\theta} \log \pi _{\theta} (s_t, a_t) -v_t\),哪来的损失?实际上是执行动作的概率乘以奖励,可以看作是动作概率分布和执行动作one-hot向量之间的交叉熵(交叉熵本来就有类似look -up的效果)乘以奖励。我们就看其本来的含义:执行动作的概率乘以奖励,网络本身只是一个策略,什么样的策略是好策略?假如通过这个策略选出来的动作执行之后得到了好的奖励,那么这是一个好的策略网络,也就是能选出好动作的策略网络是好网络,显然网络的目标函数就应该是执行动作的概率(网络认可的动作)乘以奖励(奖励认可的好动作)。
      • -
      • 第二个问题,对于随时能给出奖励的环境,agent可以走一步,根据奖励更新一次策略网络,那对于那些只有最后一步能够得到奖励的该咋办?事实上我们采取的是回合更新,无论是每一步都能给出奖励的环境还是只有最后一步有奖励的环境,我们都将一个回合内的所有步(s,a,r)都记录下来(除了最后一步,其余步的奖励都是0或者-1),之后每一步的奖励替换成累加奖励,并乘以一个衰减系数使得奖励随episode -steps衰减。注意不同于离散的基于值的学习,基于策略的PG在没有得到奖励的那些步也能算出一个动作概率来计算损失,因此即便是无奖励(或者负奖励),也能使得策略网络优化去让不好的动作概率降低。
      • -
    • +
    • 论文:Squad上可以看到,但是好像还没发?
    • +
    • NLNet的设计初衷是为了解决阅读理解问题中的鲁棒性和有效性,都是针对集成模型说的,所以NLNet是在集成模型的基础上加了一个蒸馏的过程,使用单模型提升效率,另外还有一个read +and +verify的过程来提升鲁棒性,所以在加入了对抗样本的SQuAD2.0数据集上表现优异,目前第一。在1.0上落后于四处碾压的BERT,但其实落后也不多。不过1.0版本中nlnet的ensemble版本要好于单模型版本,2.0中没有提交ensemble版本,就很迷......
    • +
    • 蒸馏的意思没太听明白,效果是12个模型压缩成一个模型,模型的结构完全相同,但是初始化不同。不是简单的选最优,单一的模型是训练出来的,论文里叫那12个模型为teacher,单一模型为student,student使用teacher训练的结果来指导训练。
    • +
    • 设计了一个read and +verify机制,在抽取出span回答问题之后还会根据该回答和问题计算一个置信度,置信度太低就认为是没有答案,也就是squad2.0里对抗样本的情况。感觉听下来就是有问题就加loss。
    • +
    • 听说一些选取特征的细节没有在论文中表出,而且最后用强化学习优化了一下模型?
    -

    Actor Critic

    +

    Open Domain +QA噪声过滤和信息集合

      -
    • 显然基于策略的方法抛弃了值,获得了优势(连续动作),也带来了劣势(每执行一步之后没得值可以用来估计即时奖励,只能进行回合更新),那么一个自然而然的想法就是结合这两点,选择一个基于策略的网络作为actor,训练出策略;选择一个基于值的网络作为critic,用来给策略网络提供值,估计即时奖励。
    • +
    • 论文(ACL 2018):Denoising Distantly Supervised Open-Domain +Question Answering
    • +
    • 这个噪声是指在检索文档的过程搜到了很多相关但提供的不是正确答案的文档,是对文档的过滤。这一步的过滤本来应该放在检索的过程里,但是作者最后也是用深度学习算概率加loss的方式解决了。
    • +
    • 去噪过程是一个document +selector,然后阅读理解是一个reader,作者认为对应于人做阅读理解的fast +skimming 和careful reading & summarizing。
    • +
    • 信息集合没太注意听,就是充分利用多篇文档的信息提取出答案
    ]]>
    自然语言处理 - deep learning - reinforcement learning + comprehension + NLI
    @@ -7434,1657 +7042,1879 @@ href="https://github.com/qiao/euphony">euphony

    - MediaPlayer可以用外部存储,assert,自建raw文件夹或者uri四种方式访问媒体文件并播放 - 从raw文件夹中读取可以直接用player = MediaPlayer.create(this, -R.raw.test1) - -Uri或者外部存储读取new->setDataSource->prepare->start

    -

    录制声音并重放

    -

    参考android中AudioRecord使用 -

    private class RecordTask extends AsyncTask<Void, Integer, Void> {
    @Override
    protected Void doInBackground(Void... arg0) {
    isRecording = true;
    try {
    //开通输出流到指定的文件
    DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(pcmFile)));
    //根据定义好的几个配置,来获取合适的缓冲大小
    int bufferSize = AudioRecord.getMinBufferSize(audioRate, channelConfig, audioEncoding);
    //实例化AudioRecord
    AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, audioRate, channelConfig, audioEncoding, bufferSize);
    //定义缓冲
    short[] buffer = new short[bufferSize];

    //开始录制
    record.startRecording();

    int r = 0; //存储录制进度
    //定义循环,根据isRecording的值来判断是否继续录制
    while (isRecording) {
    //从bufferSize中读取字节,返回读取的short个数
    //这里老是出现buffer overflow,不知道是什么原因,试了好几个值,都没用,TODO:待解决
    int bufferReadResult = record.read(buffer, 0, buffer.length);
    //循环将buffer中的音频数据写入到OutputStream中
    for (int i = 0; i < bufferReadResult; i++) {
    dos.writeShort(buffer[i]);
    }
    publishProgress(new Integer(r)); //向UI线程报告当前进度
    r++; //自增进度值
    }
    //录制结束
    record.stop();
    convertWaveFile();
    dos.close();
    } catch (Exception e) {
    // TODO: handle exception
    }
    return null;
    }
    }

    -

    pcm写头文件转成wav

    -

    因为录制的是裸文件,pcm格式,需要自己加上wav头

    private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate,
    int channels, long byteRate) throws IOException {
    byte[] header = new byte[45];
    header[0] = 'R'; // RIFF
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (byte) (totalDataLen & 0xff);//数据大小
    header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    header[8] = 'W';//WAVE
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    //FMT Chunk
    header[12] = 'f'; // 'fmt '
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';//过渡字节
    //数据大小
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    //编码方式 10H为PCM编码格式
    header[20] = 1; // format = 1
    header[21] = 0;
    //通道数
    header[22] = (byte) channels;
    header[23] = 0;
    //采样率,每个通道的播放速度
    header[24] = (byte) (longSampleRate & 0xff);
    header[25] = (byte) ((longSampleRate >> 8) & 0xff);
    header[26] = (byte) ((longSampleRate >> 16) & 0xff);
    header[27] = (byte) ((longSampleRate >> 24) & 0xff);
    //音频数据传送速率,采样率*通道数*采样深度/8
    header[28] = (byte) (byteRate & 0xff);
    header[29] = (byte) ((byteRate >> 8) & 0xff);
    header[30] = (byte) ((byteRate >> 16) & 0xff);
    header[31] = (byte) ((byteRate >> 24) & 0xff);
    // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数
    header[32] = (byte) (1 * 16 / 8);
    header[33] = 0;
    //每个样本的数据位数
    header[34] = 16;
    header[35] = 0;
    //Data chunk
    header[36] = 'd';//data
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (byte) (totalAudioLen & 0xff);
    header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
    header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
    header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
    header[44] = 0;
    out.write(header, 0, 45);
    }

    -

    json收发

    -

    根据我们的实际情况,发送时使用json,存三个参数和wav内容,因为录音的wav时长较短,可以把整个wav写入json中 -json发送两次,第一次发送参数和文件,拿到md5编码的时间戳,第二次把这个时间戳加入json中请求相应的midi文件 -

    private JSONObject makejson(int request, String identifycode, String data) {
    if (identifycode == "a") {
    try {
    JSONObject pack = new JSONObject();
    pack.put("request", request);
    JSONObject config = new JSONObject();
    config.put("n", lowf);
    config.put("m", highf);
    config.put("w", interval);
    pack.put("config", config);
    pack.put("data", data);
    return pack;
    } catch (JSONException e) {
    e.printStackTrace();
    }
    } else {
    try {
    JSONObject pack = new JSONObject();
    pack.put("request", request);
    pack.put("config", "");
    pack.put("data", identifycode);
    return pack;
    } catch (JSONException e) {
    e.printStackTrace();
    }

    }
    return null;
    }
    # socket通信 -单开一个线程用于启动socket,再开一个线程写两次json收发 -注意收发json时将json字符串用base64解码编码,java自己的string会存在错误 -另外因为wav字符串较长,服务器接收时分块接收,正常做法是加一个字典项存wav长度,按长度读取wav,然后这里我们偷懒直接在文件尾加了一个特殊字符段用于判断是否接收完成,"endbidou",不要问我是什么意思,做转换算法的兄弟想的 -
    private class MsgThread extends Thread {
    @Override
    public void run() {
    File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/files/Melodia.wav");
    FileInputStream reader = null;
    try {
    reader = new FileInputStream(file);
    int len = reader.available();
    byte[] buff = new byte[len];
    reader.read(buff);
    String data = Base64.encodeToString(buff, Base64.DEFAULT);
    String senda = makejson(1, "a", data).toString();
    Log.i(TAG, "request1: " + senda);
    OutputStream os = null;
    InputStream is = null;
    DataInputStream in = null;
    try {
    os = soc.getOutputStream();
    BufferedReader bra = null;
    os.write(senda.getBytes());
    os.write("endbidou1".getBytes());
    os.flush();
    Log.i(TAG, "request1 send successful");
    if (soc.isConnected()) {
    is = soc.getInputStream();
    bra = new BufferedReader(new InputStreamReader(is));
    md5 = bra.readLine();
    Log.i(TAG, "md5: " + md5);
    bra.close();
    } else
    Log.i(TAG, "socket closed while reading");
    } catch (IOException e) {
    e.printStackTrace();
    }
    soc.close();
    startflag = 1;

    StartThread st = new StartThread();
    st.start();

    while (soc.isClosed()) ;

    String sendb = makejson(2, md5, "request2").toString();
    Log.i(TAG, "request2: " + sendb);
    os = soc.getOutputStream();
    os.write(sendb.getBytes());
    os.write("endbidou1".getBytes());
    os.flush();
    Log.i(TAG, "request2 send successful");

    is = soc.getInputStream();
    byte buffer[] = new byte[1024 * 100];
    is.read(buffer);
    Log.i(TAG, "midifilecontent: " + buffer.toString());
    soc.close();
    File filemid = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/files/Melodia.mid");
    FileOutputStream writer = null;
    writer = new FileOutputStream(filemid);
    writer.write(buffer);
    writer.close();
    Message msg = myhandler.obtainMessage();
    msg.what = 1;
    myhandler.sendMessage(msg);
    } catch (IOException e) {
    e.printStackTrace();
    }


    }
    }

    -

    录音特效

    -

    录音图像动画效果来自Github:ShineButton -另外录音按钮做了个效果,按住录音,松开完成,往外滑一定距离取消 -

    fabrecord.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    uploadbt.setVisibility(View.INVISIBLE);
    if (isUploadingIcon) {
    isPressUpload = false;
    uploadbt.performClick();
    isPressUpload = true;
    isUploadingIcon = !isUploadingIcon;
    }

    Log.i(TAG, "ACTION_DOWN");
    if (!shinebtstatus) {
    shinebt.performClick();
    shinebtstatus = true;
    }
    ox = event.getX();
    oy = event.getY();

    isRecording = true;
    recLen = 0;
    recTime = 0;
    pb.setValue(0);
    fabrecord.setImageResource(R.drawable.ic_stop_white_24dp);
    Snackbar.make(fabrecord, "开始录音", Snackbar.LENGTH_SHORT)
    .setAction("Action", null).show();

    recorder = new RecordTask();
    recorder.execute();
    handler.postDelayed(runrecord, 0);

    break;
    case MotionEvent.ACTION_UP:
    handler.removeCallbacks(runrecord);
    Log.i(TAG, "ACTION_UP");
    if (shinebtstatus) {
    shinebt.performClick();
    shinebtstatus = false;
    }
    float x1 = event.getX();
    float y1 = event.getY();
    float dis1 = (x1 - ox) * (x1 - ox) + (y1 - oy) * (y1 - oy);

    isRecording = false;
    pb.setValue(0);
    fabrecord.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
    if (dis1 > 30000) {
    Snackbar.make(fabrecord, "取消录音", Snackbar.LENGTH_SHORT)
    .setAction("Action", null).show();
    } else {
    if (!isUploadingIcon) {
    uploadbt.setVisibility(View.VISIBLE);
    isPressUpload = false;
    uploadbt.performClick();
    isPressUpload = true;
    isUploadingIcon = !isUploadingIcon;
    } else {

    }

    Snackbar.make(fabrecord, "录音完成", Snackbar.LENGTH_SHORT)
    .setAction("Action", null).show();
    handler.postDelayed(runreplay, 0);
    replay();
    }
    break;
    case MotionEvent.ACTION_MOVE:
    float x2 = event.getX();
    float y2 = event.getY();
    float dis2 = (x2 - ox) * (x2 - ox) + (y2 - oy) * (y2 - oy);
    if (dis2 > 30000) {
    fabrecord.setImageResource(R.drawable.ic_cancel_white_24dp);
    } else {
    fabrecord.setImageResource(R.drawable.ic_stop_white_24dp);
    }
    break;
    }
    return true;
    }
    });
    # 展示乐谱 - -本来是想通过socket收发图片,后来觉得太麻烦于是把方案改成Apache对每一次转换生成相应的图片链接,通过时间戳md5直接在线访问,如果需要分享图片则先存到本地再分享 -
    public void init() {
    md5 = getArguments().getString("md5");
    final String imageUri = "服务器地址" + md5 + "_1.png";
    Log.i("play", "pngfile: " + imageUri);
    new Handler().postDelayed(new Runnable() {
    public void run() {
    //execute the task
    imageLoader.displayImage(imageUri, showpic);
    }
    }, 2000);

    }

    -

    与电子琴通信

    -
      -
    • 类似于上传服务器,也是socket通信,电子琴改装了之后从手机客户端接收八度、速度两个参数,arduino接收到参数就播放,并由arduino断开连接 -
      pianobt.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      if (!isconnected) {
      pianoaddr = etpianoaddr.getText().toString();
      pianoport = Integer.valueOf(etpianoport.getText().toString());
      param[0] = 0x30;
      StartThread st = new StartThread();
      st.start();
      while (!isconnected) ;
      MsgThread ms = new MsgThread();
      ms.start();
      YoYo.with(Techniques.Wobble)
      .duration(300)
      .repeat(6)
      .playOn(seekBaroctave);
      while (soc.isConnected()) ;
      try {
      soc.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      isconnected = false;
      Log.i("piano", "socket closed");
      }


      }
      });

      samplebt.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      pianoaddr = etpianoaddr.getText().toString();
      pianoport = Integer.valueOf(etpianoport.getText().toString());
      param[0] = 0x31;
      StartThread st = new StartThread();
      st.start();
      while (!isconnected) ;
      MsgThread ms = new MsgThread();
      ms.start();
      YoYo.with(Techniques.Wobble)
      .duration(300)
      .repeat(6)
      .playOn(seekBaroctave);
      while (soc.isConnected()) ;
      try {
      soc.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      isconnected = false;
      Log.i("piano", "socket closed");

      }
      });


      }

      private class StartThread extends Thread {
      @Override
      public void run() {
      try {
      soc = new Socket(pianoaddr, pianoport);
      if (soc.isConnected()) {//成功连接获取soc对象则发送成功消息
      Log.i("piano", "piano is Connected");
      if (!isconnected)
      isconnected = !isconnected;

      } else {
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      Log.i("piano", "Connect Failed");
      soc.close();
      }
      } catch (IOException e) {
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      Log.i("piano", "Connect Failed");
      e.printStackTrace();
      }
      }
      }

      private class MsgThread extends Thread {
      @Override
      public void run() {
      try {
      OutputStream os = soc.getOutputStream();
      os.write(param);
      os.flush();
      Log.i("piano", "piano msg send successful");
      Snackbar.make(pianobt, "正在启动启动电子琴教学", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();

      soc.close();
      } catch (IOException e) {
      Log.i("piano", "piano msg send successful failed");
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      e.printStackTrace();
      }

      }
      }
    • -
    -

    乐谱分享

    -
      -
    • 显示乐谱的是Github上一个魔改的ImageView:PinchImageView
    • -
    • 定义其长按事件,触发一个分享的intent
      showpic.setOnLongClickListener(new View.OnLongClickListener() {
      @Override
      public boolean onLongClick(View v) {
      Bitmap drawingCache = getViewBitmap(showpic);
      if (drawingCache == null) {
      Log.i("play", "no img to save");
      } else {
      try {
      File imageFile = new File(Environment.getExternalStorageDirectory(), "saveImageview.jpg");
      Toast toast = Toast.makeText(getActivity(),
      "", Toast.LENGTH_LONG);
      toast.setGravity(Gravity.TOP, 0, 200);
      toast.setText("分享图片");
      toast.show();
      FileOutputStream outStream;
      outStream = new FileOutputStream(imageFile);
      drawingCache.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
      outStream.flush();
      outStream.close();

      Intent sendIntent = new Intent();
      sendIntent.setAction(Intent.ACTION_SEND);
      sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
      sendIntent.setType("image/png");
      getActivity().startActivity(Intent.createChooser(sendIntent, "分享到"));

      } catch (IOException e) {
      Log.i("play", "share img wrong");
      }
      }
      return true;
      }
      });
    • -
    -]]> - - Android - - - code - android - -
    - - Glove Embedding - Mathematical Derivation - /2019/01/13/glove/ - -
      -
    • 记录一下Glove词向量的数学推导,因为原论文不是画模型得出的,而是纯数学操作计算得到的目标函数,这种设计方式非常有意思,而且还将word2vec的数学本质写出来进行了对比。
    • -
    • 原论文:GloVe: Global Vectors for Word Representation
    • -
    - -

    词向量

    -
      -
    • 无论是基于全局矩阵分解的还是基于局部窗口的词向量,其提取semantic的方式都是从词与词的共现统计信息中挖掘意义。
    • -
    • 显然,全局的方式没有利用到局部的优点:全局例如LSA等技术对于局部上下文信息不敏感,难以根据上下文挖掘近义词;局部的方式没有利用到全局的优点,它只依赖于独立的局部上下文,窗口太小的话不能有效利用整个文档乃至语料的信息。
    • -
    • Glove的思路是利用全局的词与词共现矩阵,同时利用局部上下文关系计算相关性。
    • -
    • 词向量的结果是能产生有意义的语义关系到距离关系的映射,针对这个目标,Glove设计了一个log-bilinear回归模型,并具体采用一个加权最小均方回归模型来训练词向量。
    • -
    -

    发现

    -
      -
    • 定义: -
        -
      • \(x\):为单个词。
      • -
      • \(X_{ij}\)\(x_j\) 出现在\(x_i\)的上下文中的次数。
      • -
      • \(X_i = \sum _k -x_{ik}\):所有词出现在\(x_i\)的上下文中的次数。
      • -
      • \(P_{ij} = P(j|i) = \frac {x_{ij}} -{X_i}\)\(x_j\)出现在\(x_i\)的上下文中的概率,即上下文出现频次计数概率化,论文中称之为"co-occurrence -probabilities"。
      • -
      • \(r = \frac -{P_{ik}}{P_{jk}}\):引入中间词\(x_k\),论文中叫"probe -word",通过引入这个\(x_k\)可以间接的衡量\(x_i\)\(x_j\)的关系,通过\(r\)即ratio表示。
      • -
    • -
    • \(r\)引入的作用体现在两个方面: -
        -
      • 对于要比较的\(x_i\)\(x_j\),筛除对于没有区分度的\(x_k\),也就是噪音。当\(r \approx 1\)时,\(x_k\)即为噪音。
      • -
      • 给定\(x_k\),使得\(r >> 1\)的那些\(x_i\)具有相近的词义,使得\(r << 1\)的那些\(x_j\)具有相近的词义。
      • -
    • -
    • 因此,我们可以过滤噪音,仅仅在\(r\)很大或很小的词共现数据中挖掘词义关系。
    • -
    -

    设计

    -
      -
    • 接下来,作者直接根据目标设计函数。
    • -
    • 目标是:设计出来的词向量之间的距离计算结果应该能够反映之前我们从词共现矩阵中发现的ratio,具体而言是对于三元组,词i,j和probe -word k,这三个词的词向量能够体现r
    • -
    • 那么直接设计,定义\(w_i\)\(x_i\)对应的词向量,则假设\(F\)为计算距离的函数: \[ -F(w_i,w_j,w^{*}_k) = r \\ -= \frac {P_{ik}}{P_{jk}} \\ -\]
    • -
    • 上面\(w_k\)的词向量加了星号区别于\(w_i\)\(w_j\)的词向量,因为\(w_k\)是独立的上下文词向量,与我们需要的词向量是平行的两套,类似于word2vec里面的前后词嵌入矩阵。
    • -
    • 接下来,一个自然的想法是,减少参数,即只需要词向量和上下文词向量,因为是距离计算函数且向量空间是线性空间,我们使用\(w_i\)\(w_j\)的向量差作为参数: \[ -F(w_i - w_j,w^{*}_k) = \frac {P_{ik}}{P_{jk}} \\ -\]
    • -
    • 现在函数的参数是向量,输出是张量,最简单的一个结构就是做点乘: \[ -F((w_i-w_j)^T w^{*}_k) = \frac {P_{ik}}{P_{jk}} \\ -\]
    • -
    • 接下来的一个关键点:对称。注意到虽然区分了上下文和非上下文词向量,但是由于共现矩阵\(X\)是对称的,因此两套词向量\(w\)\(w^{\*}\)应该具有相同的效果,只是由于随机初始化不同,两套词向量的值不一样,在衡量相似度时应该是一样的目标,即\(w_i^T w^{\*}_j\)\(w_j^T w^{\*}_i\)一样。
    • -
    • 由于对称性,\(x_i,x_j,x_k\)可以是语料中任意词,因此\(F\)函数的两个参数应该是可以交换位置(\(w\)\(w^{\*}\)\(X\)\(X^T\)),那这里进一步运用了一点数学技巧将函数对称化: -
        -
      • 设计: \[ -F((w_i-w_j)^T w^{*}_k) = \frac {F(w_i w^{*}_k)} {F(w_j w^{*}_k)} \\ -\]
      • -
      • 那么分子分母都是一样的形式,即 \[ -F(w_i w^{*}_k) = P_{ik} = \frac {X_{ik}} {X_i} \\ -\]
      • -
      • 要满足上面\(F\)可以拆分为两个子\(F\)的比,则\(F\)可以为\(exp\)函数,即 \[ -w_i^T w_k^{*} = log(X_{ik}) - log {X_i} \\ -\]
      • -
      • 这样k,i,j下标可互换位置且表达意思一致。由于分子分母形式一致,因此我们只要关注这个形式能够满足就行了,之后求分数自然会满足从三元组到ratio的映射。
      • -
      • 注意到上面式子当中,左边的两个向量内积,i,k符号互换值不变,而右边的两个log式子相减并不满足这种对称,因此我们补上一个\(log{x_k}\)使之对称,并将其简化为偏置\(b^{*}\),同样的道理,i,k符号互换后,补上一个\(Log{x_i}\)使之对称,即偏置\(b_i\),偏置和词向量一样,也是两套: \[ -w_i^Tw_k^{*} + b_i + b_k^{*} = log(X_{ik}) \\ -\]
      • -
      • 最后加上平滑,防止log的参数取0: \[ -w_i^Tw_k^{*} + b_i + b_k^{*} = log(1 + X_{ik}) \\ -\]
      • -
    • -
    • 到这里我们已经初步完成了\(F\)函数的设计,但这个还存在的一个问题是,它是平均加权每一个共现的,而一般语料中大部分共现都频次很低
    • -
    • Glove的解决办法是使用加权函数。加权之后将词向量的训练看成是F函数的最小均方误差回归,设计损失函数: -\[ -J = \sum _{i,j}^V f(X_{ij}) (w_i^T w_j^{*} + b_i + b_j^{*} - log (1 + -X_{ij}))^2 \\ -\]
    • -
    • 其中f为加权函数,其参数是共现频次,作者指出该函数必须满足三条性质: +R.raw.test1) - +Uri或者外部存储读取new->setDataSource->prepare->start

      +

      录制声音并重放

      +

      参考android中AudioRecord使用 +

      private class RecordTask extends AsyncTask<Void, Integer, Void> {
      @Override
      protected Void doInBackground(Void... arg0) {
      isRecording = true;
      try {
      //开通输出流到指定的文件
      DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(pcmFile)));
      //根据定义好的几个配置,来获取合适的缓冲大小
      int bufferSize = AudioRecord.getMinBufferSize(audioRate, channelConfig, audioEncoding);
      //实例化AudioRecord
      AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, audioRate, channelConfig, audioEncoding, bufferSize);
      //定义缓冲
      short[] buffer = new short[bufferSize];

      //开始录制
      record.startRecording();

      int r = 0; //存储录制进度
      //定义循环,根据isRecording的值来判断是否继续录制
      while (isRecording) {
      //从bufferSize中读取字节,返回读取的short个数
      //这里老是出现buffer overflow,不知道是什么原因,试了好几个值,都没用,TODO:待解决
      int bufferReadResult = record.read(buffer, 0, buffer.length);
      //循环将buffer中的音频数据写入到OutputStream中
      for (int i = 0; i < bufferReadResult; i++) {
      dos.writeShort(buffer[i]);
      }
      publishProgress(new Integer(r)); //向UI线程报告当前进度
      r++; //自增进度值
      }
      //录制结束
      record.stop();
      convertWaveFile();
      dos.close();
      } catch (Exception e) {
      // TODO: handle exception
      }
      return null;
      }
      }

      +

      pcm写头文件转成wav

      +

      因为录制的是裸文件,pcm格式,需要自己加上wav头

      private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate,
      int channels, long byteRate) throws IOException {
      byte[] header = new byte[45];
      header[0] = 'R'; // RIFF
      header[1] = 'I';
      header[2] = 'F';
      header[3] = 'F';
      header[4] = (byte) (totalDataLen & 0xff);//数据大小
      header[5] = (byte) ((totalDataLen >> 8) & 0xff);
      header[6] = (byte) ((totalDataLen >> 16) & 0xff);
      header[7] = (byte) ((totalDataLen >> 24) & 0xff);
      header[8] = 'W';//WAVE
      header[9] = 'A';
      header[10] = 'V';
      header[11] = 'E';
      //FMT Chunk
      header[12] = 'f'; // 'fmt '
      header[13] = 'm';
      header[14] = 't';
      header[15] = ' ';//过渡字节
      //数据大小
      header[16] = 16; // 4 bytes: size of 'fmt ' chunk
      header[17] = 0;
      header[18] = 0;
      header[19] = 0;
      //编码方式 10H为PCM编码格式
      header[20] = 1; // format = 1
      header[21] = 0;
      //通道数
      header[22] = (byte) channels;
      header[23] = 0;
      //采样率,每个通道的播放速度
      header[24] = (byte) (longSampleRate & 0xff);
      header[25] = (byte) ((longSampleRate >> 8) & 0xff);
      header[26] = (byte) ((longSampleRate >> 16) & 0xff);
      header[27] = (byte) ((longSampleRate >> 24) & 0xff);
      //音频数据传送速率,采样率*通道数*采样深度/8
      header[28] = (byte) (byteRate & 0xff);
      header[29] = (byte) ((byteRate >> 8) & 0xff);
      header[30] = (byte) ((byteRate >> 16) & 0xff);
      header[31] = (byte) ((byteRate >> 24) & 0xff);
      // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数
      header[32] = (byte) (1 * 16 / 8);
      header[33] = 0;
      //每个样本的数据位数
      header[34] = 16;
      header[35] = 0;
      //Data chunk
      header[36] = 'd';//data
      header[37] = 'a';
      header[38] = 't';
      header[39] = 'a';
      header[40] = (byte) (totalAudioLen & 0xff);
      header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
      header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
      header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
      header[44] = 0;
      out.write(header, 0, 45);
      }

      +

      json收发

      +

      根据我们的实际情况,发送时使用json,存三个参数和wav内容,因为录音的wav时长较短,可以把整个wav写入json中 +json发送两次,第一次发送参数和文件,拿到md5编码的时间戳,第二次把这个时间戳加入json中请求相应的midi文件 +

      private JSONObject makejson(int request, String identifycode, String data) {
      if (identifycode == "a") {
      try {
      JSONObject pack = new JSONObject();
      pack.put("request", request);
      JSONObject config = new JSONObject();
      config.put("n", lowf);
      config.put("m", highf);
      config.put("w", interval);
      pack.put("config", config);
      pack.put("data", data);
      return pack;
      } catch (JSONException e) {
      e.printStackTrace();
      }
      } else {
      try {
      JSONObject pack = new JSONObject();
      pack.put("request", request);
      pack.put("config", "");
      pack.put("data", identifycode);
      return pack;
      } catch (JSONException e) {
      e.printStackTrace();
      }

      }
      return null;
      }
      # socket通信 +单开一个线程用于启动socket,再开一个线程写两次json收发 +注意收发json时将json字符串用base64解码编码,java自己的string会存在错误 +另外因为wav字符串较长,服务器接收时分块接收,正常做法是加一个字典项存wav长度,按长度读取wav,然后这里我们偷懒直接在文件尾加了一个特殊字符段用于判断是否接收完成,"endbidou",不要问我是什么意思,做转换算法的兄弟想的 +
      private class MsgThread extends Thread {
      @Override
      public void run() {
      File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/files/Melodia.wav");
      FileInputStream reader = null;
      try {
      reader = new FileInputStream(file);
      int len = reader.available();
      byte[] buff = new byte[len];
      reader.read(buff);
      String data = Base64.encodeToString(buff, Base64.DEFAULT);
      String senda = makejson(1, "a", data).toString();
      Log.i(TAG, "request1: " + senda);
      OutputStream os = null;
      InputStream is = null;
      DataInputStream in = null;
      try {
      os = soc.getOutputStream();
      BufferedReader bra = null;
      os.write(senda.getBytes());
      os.write("endbidou1".getBytes());
      os.flush();
      Log.i(TAG, "request1 send successful");
      if (soc.isConnected()) {
      is = soc.getInputStream();
      bra = new BufferedReader(new InputStreamReader(is));
      md5 = bra.readLine();
      Log.i(TAG, "md5: " + md5);
      bra.close();
      } else
      Log.i(TAG, "socket closed while reading");
      } catch (IOException e) {
      e.printStackTrace();
      }
      soc.close();
      startflag = 1;

      StartThread st = new StartThread();
      st.start();

      while (soc.isClosed()) ;

      String sendb = makejson(2, md5, "request2").toString();
      Log.i(TAG, "request2: " + sendb);
      os = soc.getOutputStream();
      os.write(sendb.getBytes());
      os.write("endbidou1".getBytes());
      os.flush();
      Log.i(TAG, "request2 send successful");

      is = soc.getInputStream();
      byte buffer[] = new byte[1024 * 100];
      is.read(buffer);
      Log.i(TAG, "midifilecontent: " + buffer.toString());
      soc.close();
      File filemid = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/files/Melodia.mid");
      FileOutputStream writer = null;
      writer = new FileOutputStream(filemid);
      writer.write(buffer);
      writer.close();
      Message msg = myhandler.obtainMessage();
      msg.what = 1;
      myhandler.sendMessage(msg);
      } catch (IOException e) {
      e.printStackTrace();
      }


      }
      }

      +

      录音特效

      +

      录音图像动画效果来自Github:ShineButton +另外录音按钮做了个效果,按住录音,松开完成,往外滑一定距离取消 +

      fabrecord.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
      uploadbt.setVisibility(View.INVISIBLE);
      if (isUploadingIcon) {
      isPressUpload = false;
      uploadbt.performClick();
      isPressUpload = true;
      isUploadingIcon = !isUploadingIcon;
      }

      Log.i(TAG, "ACTION_DOWN");
      if (!shinebtstatus) {
      shinebt.performClick();
      shinebtstatus = true;
      }
      ox = event.getX();
      oy = event.getY();

      isRecording = true;
      recLen = 0;
      recTime = 0;
      pb.setValue(0);
      fabrecord.setImageResource(R.drawable.ic_stop_white_24dp);
      Snackbar.make(fabrecord, "开始录音", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();

      recorder = new RecordTask();
      recorder.execute();
      handler.postDelayed(runrecord, 0);

      break;
      case MotionEvent.ACTION_UP:
      handler.removeCallbacks(runrecord);
      Log.i(TAG, "ACTION_UP");
      if (shinebtstatus) {
      shinebt.performClick();
      shinebtstatus = false;
      }
      float x1 = event.getX();
      float y1 = event.getY();
      float dis1 = (x1 - ox) * (x1 - ox) + (y1 - oy) * (y1 - oy);

      isRecording = false;
      pb.setValue(0);
      fabrecord.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
      if (dis1 > 30000) {
      Snackbar.make(fabrecord, "取消录音", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      } else {
      if (!isUploadingIcon) {
      uploadbt.setVisibility(View.VISIBLE);
      isPressUpload = false;
      uploadbt.performClick();
      isPressUpload = true;
      isUploadingIcon = !isUploadingIcon;
      } else {

      }

      Snackbar.make(fabrecord, "录音完成", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      handler.postDelayed(runreplay, 0);
      replay();
      }
      break;
      case MotionEvent.ACTION_MOVE:
      float x2 = event.getX();
      float y2 = event.getY();
      float dis2 = (x2 - ox) * (x2 - ox) + (y2 - oy) * (y2 - oy);
      if (dis2 > 30000) {
      fabrecord.setImageResource(R.drawable.ic_cancel_white_24dp);
      } else {
      fabrecord.setImageResource(R.drawable.ic_stop_white_24dp);
      }
      break;
      }
      return true;
      }
      });
      # 展示乐谱 - +本来是想通过socket收发图片,后来觉得太麻烦于是把方案改成Apache对每一次转换生成相应的图片链接,通过时间戳md5直接在线访问,如果需要分享图片则先存到本地再分享 +
      public void init() {
      md5 = getArguments().getString("md5");
      final String imageUri = "服务器地址" + md5 + "_1.png";
      Log.i("play", "pngfile: " + imageUri);
      new Handler().postDelayed(new Runnable() {
      public void run() {
      //execute the task
      imageLoader.displayImage(imageUri, showpic);
      }
      }, 2000);

      }

      +

      与电子琴通信

        -
      • \(f(0)=0\):显然,没有出现共现则权重为0。
      • -
      • Non-decreasing:共现频次越大则权重越大。
      • -
      • relatively small for large -X:防止对于某些频次很高的常见共现加权过大,影响结果。
      • -
    • -
    • 基于以上三种性质,作者设计了截尾的加权函数,在阈值\(X_{max}\)以内: \[ -f(x) = (\frac {x}{X_{max}}) ^ {\alpha} \\ -\] 超过阈值则函数值为1.
    • +
    • 类似于上传服务器,也是socket通信,电子琴改装了之后从手机客户端接收八度、速度两个参数,arduino接收到参数就播放,并由arduino断开连接 +
      pianobt.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      if (!isconnected) {
      pianoaddr = etpianoaddr.getText().toString();
      pianoport = Integer.valueOf(etpianoport.getText().toString());
      param[0] = 0x30;
      StartThread st = new StartThread();
      st.start();
      while (!isconnected) ;
      MsgThread ms = new MsgThread();
      ms.start();
      YoYo.with(Techniques.Wobble)
      .duration(300)
      .repeat(6)
      .playOn(seekBaroctave);
      while (soc.isConnected()) ;
      try {
      soc.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      isconnected = false;
      Log.i("piano", "socket closed");
      }


      }
      });

      samplebt.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      pianoaddr = etpianoaddr.getText().toString();
      pianoport = Integer.valueOf(etpianoport.getText().toString());
      param[0] = 0x31;
      StartThread st = new StartThread();
      st.start();
      while (!isconnected) ;
      MsgThread ms = new MsgThread();
      ms.start();
      YoYo.with(Techniques.Wobble)
      .duration(300)
      .repeat(6)
      .playOn(seekBaroctave);
      while (soc.isConnected()) ;
      try {
      soc.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      isconnected = false;
      Log.i("piano", "socket closed");

      }
      });


      }

      private class StartThread extends Thread {
      @Override
      public void run() {
      try {
      soc = new Socket(pianoaddr, pianoport);
      if (soc.isConnected()) {//成功连接获取soc对象则发送成功消息
      Log.i("piano", "piano is Connected");
      if (!isconnected)
      isconnected = !isconnected;

      } else {
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      Log.i("piano", "Connect Failed");
      soc.close();
      }
      } catch (IOException e) {
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      Log.i("piano", "Connect Failed");
      e.printStackTrace();
      }
      }
      }

      private class MsgThread extends Thread {
      @Override
      public void run() {
      try {
      OutputStream os = soc.getOutputStream();
      os.write(param);
      os.flush();
      Log.i("piano", "piano msg send successful");
      Snackbar.make(pianobt, "正在启动启动电子琴教学", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();

      soc.close();
      } catch (IOException e) {
      Log.i("piano", "piano msg send successful failed");
      Snackbar.make(pianobt, "启动电子琴教学失败", Snackbar.LENGTH_SHORT)
      .setAction("Action", null).show();
      e.printStackTrace();
      }

      }
      }
    -

    与Word2vec比较

    +

    乐谱分享

      -
    • 对于Word2vec中的skip-gram模型,其目标是最大化给定上下文之后预测正确中心词的概率,一般通过softmax函数将其概率化,即: -\[ -Q_{ij} = \frac {exp (w_i^T w_j^{*})} { \sum _{k=1}^V exp(w_i^T w_k^{*})} -\\ -\]
    • -
    • 通过梯度下降求解,则整体损失函数可以写成: \[ -J = - \sum _{i \in corpus , j \in context(i)} log Q_{ij} \\ -\]
    • -
    • 将相同的\(Q_{ij}\)先分组再累加,得到: \[ -J = - \sum _{i=1}^V \sum _{j=1}^V X_{ij} log Q_{ij} \\ -\]
    • -
    • 接下来用之前定义的符号进一步变换: \[ -J = - \sum _{i=1^V} X_i \sum _{j=1}^V P_{ij} log Q_{ij} \\ -= \sum _{i=1}^V X_i H(P_i,Q_i) \\ -\]
    • -
    • 也就是说,Word2vec的损失函数实际上是加权的交叉熵,然而交叉熵只是一种可能的度量,且具有很多缺点: +
    • 显示乐谱的是Github上一个魔改的ImageView:PinchImageView
    • +
    • 定义其长按事件,触发一个分享的intent
      showpic.setOnLongClickListener(new View.OnLongClickListener() {
      @Override
      public boolean onLongClick(View v) {
      Bitmap drawingCache = getViewBitmap(showpic);
      if (drawingCache == null) {
      Log.i("play", "no img to save");
      } else {
      try {
      File imageFile = new File(Environment.getExternalStorageDirectory(), "saveImageview.jpg");
      Toast toast = Toast.makeText(getActivity(),
      "", Toast.LENGTH_LONG);
      toast.setGravity(Gravity.TOP, 0, 200);
      toast.setText("分享图片");
      toast.show();
      FileOutputStream outStream;
      outStream = new FileOutputStream(imageFile);
      drawingCache.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
      outStream.flush();
      outStream.close();

      Intent sendIntent = new Intent();
      sendIntent.setAction(Intent.ACTION_SEND);
      sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
      sendIntent.setType("image/png");
      getActivity().startActivity(Intent.createChooser(sendIntent, "分享到"));

      } catch (IOException e) {
      Log.i("play", "share img wrong");
      }
      }
      return true;
      }
      });
    • +
    +]]>
    + + Android + + + code + android + +
    + + Notes for the server of Melodia + /2017/05/26/dachuangserver/ +
      -
    • 需要归一化的概率作为参数
    • -
    • softmax计算量大,称为模型的计算瓶颈
    • -
    • 对于长尾分布,交叉熵常常分配给不太可能的项太多权重
    • -
    -
  • 解决以上问题的方法:干脆不归一化,直接用共现计数,不用交叉熵和softmax,直接用均方误差,令\(Q_{ij} = exp(w_i^T w_j^{*})\)\(P_{ij} = X_{ij}\),则: \[ -J = \sum _{i,j} X_i (P_{ij} - Q_{ij})^2 \\ -\]
  • -
  • 但是不归一化会造成数值上溢,那就再取个对数: \[ -J = \sum _{i,j} X_i (log P_{ij} - log Q_{ij})^2 \\ -= \sum _{i,j} X_i (w_i^T w_j^{*} - log X_{ij})^2 \\ -\]
  • -
  • 这样就得到了Glove最朴素的目标函数。
  • -
  • Word2vec的作者发现筛除一些常见词能够提高词向量效果,而Word2vec中的加权函数即\(f(X_i)=X_i\),因此筛除常见词等价于设计一个非降的加权函数。Glove则设计了更为精巧的加权函数。
  • -
  • 因此从数学公式推导上看,Glove简化了Word2vec的目标函数,用均方误差替换交叉熵,并重新设计了加权函数。
  • +
  • 大创项目的服务器端,大创以及客户端介绍见Melodia客户端
  • +
  • 我们大创项目的服务器承担的功能比较少,只与android设备收发文件,用Python写了一个简单的服务器端
  • -

    思路

    + +

    功能

      -
    • 该文提供了一个很好的设计模型的思路,即根据评测指标设计目标函数,反过来训练模型,得到函数的参数(副产品)作为所需的结果。
    • +
    • 从android客户端接收的数据都是json格式,base64编解码。以我们自定义的特殊字符串结尾,服务器在建立与一个终端的连接后开一个处理的线程
    • +
    • 客户端完成一次wav到midi转换需要两次通信,第一次json中request值为1,data中是wav文件,服务器负责生成md5编码的时间戳,并用时间戳命名一个wav文件存下,再调用我们的核心程序将wav转换,生成md5.mid和md5.png,即乐曲和曲谱,并回传给客户端md5值。第二次客户端发来的json中request值为2,data值为md5,服务器根据md5索引生成的midi文件回传给客户端
    • +
    +

    代码

    +
    # -*- coding:utf-8 -*- 
    # ! usr/bin/python

    from socket import *
    import time
    import threading
    import os
    import md5
    import warnings

    Host = ''
    Port = 2017
    Addr = (Host, Port)
    midi_dict = {}

    warnings.filterwarnings("ignore")


    def md5_encode(src):
    m1 = md5.new()
    m1.update(src)
    return m1.hexdigest()


    def tcplink(sock, addr):
    sessnum = 0
    music_data = ''
    while True:
    data = sock.recv(1480)
    if data[-9:]=='endbidou1':
    print 'wav recv finished'
    music_data+=data
    music_data=music_data[:-9]
    midi_data = eval(music_data)
    sessnum = midi_data['request']
    if midi_data['request'] == 1:
    flag_md5 = md5_encode(str(time.time()))
    print 'md5: ', flag_md5
    wav_name = flag_md5 + '.wav'
    with open(wav_name, 'w+') as f:
    f.write(midi_data['data'].decode('base64'))
    f.close()
    n = midi_data['config']['n'];
    m = midi_data['config']['m'];
    w = midi_data['config']['w'];
    midi_name = flag_md5 + '.mid'
    with open(midi_name, 'w') as f:
    f.close()
    shellmid = '../mldm/hum2midi.py -n '+str(n)+' -m '+str(m)+' -w '+str(w)+' -o ' + midi_name + ' ' + wav_name
    print "running wav2midi shell"
    retmid = os.system(shellmid)
    retmid >= 8
    if retmid == 0:
    print 'generate midi successful'
    shellpng = 'mono ../mlds/sheet '+midi_name+' '+flag_md5
    retpng = os.system(shellpng)
    if retpng == 0:
    sock.send(flag_md5.encode())
    print 'generate png successful'
    midi_dict[flag_md5] = midi_name
    break
    else:
    print 'generate png error'
    break
    else:
    print 'generate midi error'
    break
    elif midi_data['request'] == 2:
    flag = midi_data['data']
    if flag in midi_dict.keys():
    fo = open(flag+'.mid', 'rb')
    while True:
    filedata = fo.read(1024)
    if not filedata:
    break
    sock.send(filedata)
    print 'midi file sent'
    fo.close()
    break
    else:
    print 'can not find midi'
    break
    else:
    print 'json error'
    else:
    music_data += data
    sock.close()
    print 'session '+str(sessnum)+' for '+str(addr)+' finished'

    tcpSerSock = socket(AF_INET, SOCK_STREAM)
    tcpSerSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    tcpSerSock.bind(Addr)
    tcpSerSock.listen(5)

    while True:
    tcpCliSock, tcpCliAddr = tcpSerSock.accept()
    print 'add ', tcpCliAddr
    t = threading.Thread(target=tcplink, args=(tcpCliSock, tcpCliAddr))
    t.start()
    tcpSerSock.close()
    +]]>
    + + Python + + + code + server + linux + +
    + + DeepBayes 2018 + /2018/09/22/deepbayes2018/ + Deep-Bayes 2018 Summer Camp的习题 填不动了,就到这吧

    +

    Deep|Bayes summer school. Practical session on EM +algorithm

    +
      +
    • 第一题就是应用EM算法还原图像,人像和背景叠加在一起,灰度值的概率分布形式已知,设计人像在背景中的位置为隐变量,进行EM迭代推断。
    • +
    • 具体说明在官网和下面的notebook注释中有,实际上公式已经给出,想要完成作业就是把公式打上去,可以自己推一下公式。
    +

    One of the school organisers decided to prank us and hid all games +for our Thursday Game Night somewhere.

    +

    Let's find the prankster!

    +

    When you recognize him or +her, send: * name * reconstructed photo * this notebook with your +code (doesn't matter how awful it is :)

    +

    privately to Nadia Chirkova at Facebook +or to info@deepbayes.ru. The first three participants will receive a +present. Do not make spoilers to other participants!

    +

    Please, note that you have only one attempt to send +a message!

    +
    import numpy as np
    from matplotlib import pyplot as plt
    %matplotlib inline
    +
    DATA_FILE = "data_em"
    w = 73 # face_width
    +

    Data

    +

    We are given a set of \(K\) images +with shape \(H \times W\).

    +

    It is represented by a numpy-array with shape \(H \times W \times K\):

    +
    X = np.load(DATA_FILE)
    +
    X.shape # H, W, K
    +
    (100, 200, 1000)
    +

    Example of noisy image:

    +
    plt.imshow(X[:, :, 0], cmap="Greys_r")
    plt.axis("off")
    print(X[1,:,0])
    +
    [255. 255.  41. 255.   0.  51. 255.  15. 255.  59.   0.   0.   0. 255.
    +   0. 255. 255.   0. 175.  74. 184.   0.   0. 150. 255. 255.   0.   0.
    + 148.   0. 255. 181. 255. 255. 255.   0. 255. 255.  30.   0.   0. 255.
    +   0. 255. 255. 206. 234. 255.   0. 255. 255. 255.   0. 255.   0. 255.
    +   0. 255. 255. 175.  30. 255.   0.   0. 255.   0. 255.  48.   0.   0.
    +   0. 232. 162. 255.  26.   0.   0. 255.   0. 255. 173. 255. 255.   0.
    +   0. 255. 255. 119.   0.   0.   0.   0.   0.   0. 255. 255. 255. 255.
    +   0.   0. 248.   5. 149. 255.   0. 255. 255. 255.   0. 108.   0.   0.
    + 255.   0. 255. 255. 255.   0.   0. 193.  79.   0. 255.   0.   0.   0.
    + 233. 255.   0.  65. 255. 255. 255.   0. 255.   0.   0.   0. 255.  58.
    + 226. 255.   0. 242. 255. 255.   0. 255.   4. 255. 255.  97. 255.   0.
    +   0. 255.   0. 255.   0.   0.   0. 255.   0.  43. 219.   0. 255. 255.
    + 255. 166. 255.   0. 255.  42. 255.  44. 255. 255. 255. 255. 255. 255.
    + 255. 255.  28.   0.  52. 255.  81. 104. 255. 255.  48. 255. 255. 255.
    + 102.  25.  30.  73.]
    +
    +i0Ihiq.png + +
    +

    Goal and plan

    +

    Our goal is to find face \(F\) +(\(H \times w\)).

    +

    Also, we will find: * \(B\): +background (\(H \times W\)) * \(s\): noise standard deviation (float) * +\(a\): discrete prior over face +positions (\(W-w+1\)) * \(q(d)\): discrete posterior over face +positions for each image ((\(W-w+1\)) x +\(K\))

    +

    Implementation plan: 1. calculating \(log\, +p(X \mid d,\,F,\,B,\,s)\) 1. calculating objective 1. E-step: +finding \(q(d)\) 1. M-step: estimating +\(F,\, B, \,s, \,a\) 1. composing +EM-algorithm from E- and M-step

    +

    Implementation

    +
    ### Variables to test implementation
    tH, tW, tw, tK = 2, 3, 1, 2
    tX = np.arange(tH*tW*tK).reshape(tH, tW, tK)
    tF = np.arange(tH*tw).reshape(tH, tw)
    tB = np.arange(tH*tW).reshape(tH, tW)
    ts = 0.1
    ta = np.arange(1, (tW-tw+1)+1)
    ta = ta / ta.sum()
    tq = np.arange(1, (tW-tw+1)*tK+1).reshape(tW-tw+1, tK)
    tq = tq / tq.sum(axis=0)[np.newaxis, :]
    +

    1. Implement +calculate_log_probability

    +

    For \(k\)-th image \(X_k\) and some face position \(d_k\): \[p(X_k \mid d_k,\,F,\,B,\,s) = \prod_{ij} + \begin{cases} + \mathcal{N}(X_k[i,j]\mid F[i,\,j-d_k],\,s^2), + & \text{if}\, (i,j)\in faceArea(d_k)\\ + \mathcal{N}(X_k[i,j]\mid B[i,j],\,s^2), & \text{else} + \end{cases}\]

    +

    Important notes: * Do not forget about logarithm! * This +implementation should use no more than 1 cycle!

    +
    def calculate_log_probability(X, F, B, s):
    """
    Calculates log p(X_k|d_k, F, B, s) for all images X_k in X and
    all possible face position d_k.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.

    Returns
    -------
    ll : array, shape(W-w+1, K)
    ll[dw, k] - log-likelihood of observing image X_k given
    that the prankster's face F is located at position dw
    """
    # your code here
    H = X.shape[0]
    W = X.shape[1]
    K = X.shape[2]
    w = F.shape[1]
    ll = np.zeros((W-w+1,K))
    for k in range(K):
    X_minus_B = X[:,:,k]-B[:,:]
    XB = np.multiply(X_minus_B,X_minus_B)
    for dk in range(W-w+1):
    F_temp = np.zeros((H,W))
    F_temp[:,dk:dk+w] = F
    X_minus_F = X[:,:,k] - F_temp[:,:]
    XF = np.multiply(X_minus_F,X_minus_F)
    XB_mask = np.ones((H,W))
    XB_mask[:,dk:dk+w] = 0
    XF_mask = 1-XB_mask
    XB_temp = np.multiply(XB,XB_mask)
    XF_temp = np.multiply(XF,XF_mask)
    Sum = (np.sum(XB_temp+XF_temp))*(-1/(2*s**2))-H*W*np.log(np.sqrt(2*np.pi)*s)
    ll[dk][k]=Sum
    return ll
    +
    # run this cell to test your implementation
    expected = np.array([[-3541.69812064, -5541.69812064],
    [-4541.69812064, -6741.69812064],
    [-6141.69812064, -8541.69812064]])
    actual = calculate_log_probability(tX, tF, tB, ts)
    assert np.allclose(actual, expected)
    print("OK")
    +
    OK
    +

    2. Implement +calculate_lower_bound

    +

    \[\mathcal{L}(q, \,F, \,B,\, s,\, a) = +\sum_k \biggl (\mathbb{E} _ {q( d_k)}\bigl ( \log p( X_{k} \mid +{d}_{k} , \,F,\,B,\,s) + + \log p( d_k \mid a)\bigr) - \mathbb{E} _ {q( d_k)} \log q( +d_k)\biggr) \]

    +

    Important notes: * Use already implemented calculate_log_probability! +* Note that distributions \(q( d_k)\) +and \(p( d_k \mid a)\) are discrete. +For example, \(P(d_k=i \mid a) = +a[i]\). * This implementation should not use cycles!

    +
    def calculate_lower_bound(X, F, B, s, a, q):
    """
    Calculates the lower bound L(q, F, B, s, a) for
    the marginal log likelihood.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1)
    Estimate of prior on position of face in any image.
    q : array
    q[dw, k] - estimate of posterior
    of position dw
    of prankster's face given image Xk

    Returns
    -------
    L : float
    The lower bound L(q, F, B, s, a)
    for the marginal log likelihood.
    """
    # your code here
    K = X.shape[2]
    ll = calculate_log_probability(X,F,B,s)
    ll_expectation = np.multiply(ll,q)
    q_expectation = np.multiply(np.log(q),q)
    dk_expection = 0
    for k in range(K):
    dk_expection += np.multiply(np.log(a),q[:,k])
    L = np.sum(ll_expectation)-np.sum(q_expectation)+np.sum(dk_expection)

    return L
    +
    # run this cell to test your implementation
    expected = -12761.1875
    actual = calculate_lower_bound(tX, tF, tB, ts, ta, tq)
    assert np.allclose(actual, expected)
    print("OK")
    +
    OK
    +

    3. Implement E-step

    +

    \[q(d_k) = p(d_k \mid X_k, \,F, \,B, +\,s,\, a) = +\frac {p( X_{k} \mid {d}_{k} , \,F,\,B,\,s)\, p(d_k \mid a)} +{\sum_{d'_k} p( X_{k} \mid d'_k , \,F,\,B,\,s) \,p(d'_k +\mid a)}\]

    +

    Important notes: * Use already implemented calculate_log_probability! +* For computational stability, perform all computations with logarithmic +values and apply exp only before return. Also, we recommend using this +trick: \[\beta_i = \log{p_i(\dots)} +\quad\rightarrow \quad + \frac{e^{\beta_i}}{\sum_k e^{\beta_k}} = + \frac{e^{(\beta_i - \max_j \beta_j)}}{\sum_k e^{(\beta_k- \max_j +\beta_j)}}\] * This implementation should not use cycles!

    +
    def run_e_step(X, F, B, s, a):
    """
    Given the current esitmate of the parameters, for each image Xk
    esitmates the probability p(d_k|X_k, F, B, s, a).

    Parameters
    ----------
    X : array, shape(H, W, K)
    K images of size H x W.
    F : array_like, shape(H, w)
    Estimate of prankster's face.
    B : array shape(H, W)
    Estimate of background.
    s : float
    Eestimate of standard deviation of Gaussian noise.
    a : array, shape(W-w+1)
    Estimate of prior on face position in any image.

    Returns
    -------
    q : array
    shape (W-w+1, K)
    q[dw, k] - estimate of posterior of position dw
    of prankster's face given image Xk
    """
    # your code here
    ll = calculate_log_probability(X,F,B,s)
    K = X.shape[2]
    for k in range(K):
    max_ll = ll[:,k].max()
    ll[:,k] -= max_ll
    ll[:,k] = np.exp(ll[:,k])*a
    denominator = np.sum(ll[:,k])
    ll[:,k] /= denominator
    q = ll
    return q
    +
    # run this cell to test your implementation
    expected = np.array([[ 1., 1.],
    [ 0., 0.],
    [ 0., 0.]])
    actual = run_e_step(tX, tF, tB, ts, ta)
    assert np.allclose(actual, expected)
    print("OK")
    +
    OK
    +

    4. Implement M-step

    +

    \[a[j] = \frac{\sum_k q( d_k = j +)}{\sum_{j'} \sum_{k'} q( d_{k'} = j')}\] \[F[i, m] = \frac 1 K \sum_k \sum_{d_k} q(d_k)\, +X^k[i,\, m+d_k]\] \[B[i, j] = \frac +{\sum_k \sum_{ d_k:\, (i, \,j) \,\not\in faceArea(d_k)} q(d_k)\, X^k[i, +j]} + {\sum_k \sum_{d_k: \,(i, \,j)\, \not\in faceArea(d_k)} +q(d_k)}\] \[s^2 = \frac 1 +{HWK} \sum_k \sum_{d_k} q(d_k) + \sum_{i,\, j} (X^k[i, \,j] - Model^{d_k}[i, \,j])^2\]

    +

    where \(Model^{d_k}[i, j]\) is an +image composed from background and face located at \(d_k\).

    +

    Important notes: * Update parameters in the following order: \(a\), \(F\), \(B\), \(s\). * When the parameter is updated, its +new value is used to update other parameters. * This +implementation should use no more than 3 cycles and no embedded +cycles!

    +
    def run_m_step(X, q, w):
    """
    Estimates F, B, s, a given esitmate of posteriors defined by q.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    q :
    q[dw, k] - estimate of posterior of position dw
    of prankster's face given image Xk
    w : int
    Face mask width.

    Returns
    -------
    F : array, shape (H, w)
    Estimate of prankster's face.
    B : array, shape (H, W)
    Estimate of background.
    s : float
    Estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1)
    Estimate of prior on position of face in any image.
    """
    # your code here
    K = X.shape[2]
    W = X.shape[1]
    H = X.shape[0]

    a = np.sum(q,axis=1) / np.sum(q)

    F = np.zeros((H,w))
    for k in range(K):
    for dk in range(W-w+1):
    F+=q[dk][k]*X[:,dk:dk+w,k]
    F = F / K


    B = np.zeros((H,W))
    denominator = np.zeros((H,W))
    for k in range(K):
    for dk in range(W-w+1):
    mask = np.ones((H,W))
    mask[:,dk:dk+w] = 0
    B += np.multiply(q[dk][k]*X[:,:,k],mask)
    denominator += q[dk][k]*mask
    denominator = 1/denominator
    B = B * denominator

    s = 0
    for k in range(K):
    for dk in range(W-w+1):
    F_B = np.zeros((H,W))
    F_B[:,dk:dk+w]=F
    mask = np.ones((H,W))
    mask[:,dk:dk+w] = 0
    Model = F_B + np.multiply(B,mask)
    temp = X[:,:,k]-Model[:,:]
    temp = np.multiply(temp,temp)
    temp = np.sum(temp)
    temp *= q[dk][k]
    s += temp
    s = np.sqrt(s /(H*W*K))

    return F,B,s,a


    +
    # run this cell to test your implementation
    expected = [np.array([[ 3.27777778],
    [ 9.27777778]]),
    np.array([[ 0.48387097, 2.5 , 4.52941176],
    [ 6.48387097, 8.5 , 10.52941176]]),
    0.94868,
    np.array([ 0.13888889, 0.33333333, 0.52777778])]
    actual = run_m_step(tX, tq, tw)
    for a, e in zip(actual, expected):
    assert np.allclose(a, e)
    print("OK")
    +
    OK
    +

    5. Implement EM_algorithm

    +

    Initialize parameters, if they are not passed, and then repeat E- and +M-steps till convergence.

    +

    Please note that \(\mathcal{L}(q, \,F, \,B, +\,s, \,a)\) must increase after each iteration.

    +
    def run_EM(X, w, F=None, B=None, s=None, a=None, tolerance=0.001,
    max_iter=50):
    """
    Runs EM loop until the likelihood of observing X given current
    estimate of parameters is idempotent as defined by a fixed
    tolerance.

    Parameters
    ----------
    X : array, shape (H, W, K)
    K images of size H x W.
    w : int
    Face mask width.
    F : array, shape (H, w), optional
    Initial estimate of prankster's face.
    B : array, shape (H, W), optional
    Initial estimate of background.
    s : float, optional
    Initial estimate of standard deviation of Gaussian noise.
    a : array, shape (W-w+1), optional
    Initial estimate of prior on position of face in any image.
    tolerance : float, optional
    Parameter for stopping criterion.
    max_iter : int, optional
    Maximum number of iterations.

    Returns
    -------
    F, B, s, a : trained parameters.
    LL : array, shape(number_of_iters + 2,)
    L(q, F, B, s, a) at initial guess,
    after each EM iteration and after
    final estimate of posteriors;
    number_of_iters is actual number of iterations that was done.
    """
    H, W, N = X.shape
    if F is None:
    F = np.random.randint(0, 255, (H, w))
    if B is None:
    B = np.random.randint(0, 255, (H, W))
    if a is None:
    a = np.ones(W - w + 1)
    a /= np.sum(a)
    if s is None:
    s = np.random.rand()*pow(64,2)
    # your code here
    LL = [-100000]
    for i in range(max_iter):
    q = run_e_step(X,F,B,s,a)
    F,B,s,a = run_m_step(X,q,w)
    LL.append(calculate_lower_bound(X,F,B,s,a,q))
    if LL[-1]-LL[-2] < tolerance :
    break
    LL = np.array(LL)
    return F,B,s,a,LL


    +
    # run this cell to test your implementation
    res = run_EM(tX, tw, max_iter=10)
    LL = res[-1]
    assert np.alltrue(LL[1:] - LL[:-1] > 0)
    print("OK")
    +
    OK
    +

    Who is the prankster?

    +

    To speed up the computation, we will perform 5 iterations over small +subset of images and then gradually increase the subset.

    +

    If everything is implemented correctly, you will recognize the +prankster (remember he is the one from DeepBayes team).

    +

    Run EM-algorithm:

    +
    def show(F, i=1, n=1):
    """
    shows face F at subplot i out of n
    """
    plt.subplot(1, n, i)
    plt.imshow(F, cmap="Greys_r")
    plt.axis("off")
    +
    F, B, s, a = [None] * 4
    LL = []
    lens = [50, 100, 300, 500, 1000]
    iters = [5, 1, 1, 1, 1]
    plt.figure(figsize=(20, 5))
    for i, (l, it) in enumerate(zip(lens, iters)):
    F, B, s, a, _ = run_EM(X[:, :, :l], w, F, B, s, a, max_iter=it)
    show(F, i+1, 5)
    +
    +i0omSf.png + +
    +

    And this is the background:

    +
    show(B)
    +
    +i0I4J0.png + +
    +

    Optional part: hard-EM

    +

    If you have some time left, you can implement simplified version of +EM-algorithm called hard-EM. In hard-EM, instead of finding posterior +distribution \(p(d_k|X_k, F, B, s, A)\) +at E-step, we just remember its argmax \(\tilde d_k\) for each image \(k\). Thus, the distribution q is replaced +with a singular distribution: \[q(d_k) = +\begin{cases} 1, \, if d_k = \tilde d_k \\ 0, \, +otherwise\end{cases}\] This modification simplifies formulas for +\(\mathcal{L}\) and M-step and speeds +their computation up. However, the convergence of hard-EM is usually +slow.

    +

    If you implement hard-EM, add binary flag hard_EM to the parameters +of the following functions: * calculate_lower_bound * run_e_step * +run_m_step * run_EM

    +

    After implementation, compare overall computation time for EM and +hard-EM till recognizable F.

    ]]>
    - 机器学习 + 数学 math - glove - word embedding + machine learning + bayes
    - Debates between GPTs - /2023/06/05/gpt-debate/ - -
      -
    • 基于ChatGPT-Shortcut改了一个网页,展示了一些GPT自己与自己发生的有趣辩论。
    • -
    • 体验地址在
    • -
    • A webpage based on ChatGPT-Shortcut -that shows some interesting debates that took place between GPTs.
    • -
    • The experience website is here
    • -
    + Easy Reinforcement Learning Notes + /2019/09/23/easyrl/ + 极简风格 - Q-learning - Sarsa - Sarsa(\(\lambda\)) - DQN - Double DQN - DQN with +Prioritized Experience replay - Dueling DQN - Policy Gradient

    -

    Intro

    +

    定义

      -
    • 这是一个基于ChatGPT-Shortcut更改的项目,展示一些GPT自己和自己辩论的记录。这是一个纯前端展示页面,不包含任何的模型、数据、训练过程,也不是一个平台,没有ChatGPT-Shortcut的登录和平台共享功能。
    • -
    • 这只是一个爱好、偏收集的项目,没有研究目的和商业目的。此类项目也已经有很多不错的尝试,比如b站上的AI-talk或者油管上的Watch GPT-4 Debate -with Itself! (About whether it is an AGI)
    • -
    • 网址在
    • -
    • This is a project based on ChatGPT-Shortcut -to showcase some of GPT's own records of debates with themselves. This -is a pure front-end display page, containing no models, data, training -process, nor is it a platform with the login and platform sharing -features of ChatGPT-Shortcut.
    • -
    • This is just a hobby, collective-favour project, with no research -purpose or commercial purpose. There have been many good attempts at -such projects, such as AI-talk on bilibili or -Watch GPT-4 Debate -with Itself! (About whether it is an AGI) on YouTube
    • -
    • The website is here
    • +
    • agent:智能体,智能体处在某一状态下,依据某种策略(policy),采取一个动作,到达下一个状态
    • +
    • s:status,状态
    • +
    • a:action,动作
    • +
    • r:reward,奖励
    • +
    • s,a:可以称之为一步。智能体的行为可以描述为一系列步。强化学习里agent的行为可以用DP(决策过程)表示,s是DP里的节点状态,a是状态之间的转移路径
    • +
    • Q:Q表,Q(s,a)即状态s下执行动作a的价值(infer时的可能性),用奖励期望来估计
    -

    Prompt

    +

    Q-learning

      -
    • 以单句辩论为例,给予GPT的background -prompt类似于:"你是一个具有顶尖水平的专业辩手。现在你参加了一个特殊的辩论,每次发言不能超过一句话。你将会得到一个辩题和你方观点,你需要引经据典,整理语言,逻辑严谨的为这个辩题辩护。你需要首先阐述观点,之后你会得到多轮对方的阐释,你需要不断驳斥他直到说服对方。记住,每次发言不能超过一句话。所有回答以中文呈现。"
    • -
    • 之后给出论点:“辩题为:{}.你方观点是支持/反对。”
    • -
    • 之后在两个GPT bots之间传递观点:“对方发言:“ -{}”,请反驳他,依然发言不超过一句。不要重复你方观点。不要重复之前的发言。尽可能找出对方观点漏洞。尽可能提出新证据攻击对方。”
    • -
    • Take the example of a one-sentence debate, where the background -prompt given to the GPT is something like: "You are a professional -debater at the top of your game. Now you are taking part in a special -debate where you can speak no more than one sentence at a time. You will -be given a topic and your side of the argument, and you will be required -to defend it logically, using quotations from the classics and -organising your language. You will be given several rounds of -elucidation from your opponent, and you will have to refute him until -you are convinced. Remember, no more than one sentence per statement. -All responses will be presented in Chinese."
    • -
    • The argument is then given: "The debate is entitled: {}. Your side's -argument is for/against."
    • -
    • Then pass the argument between the two GPT bots: "The other side -speaks:" {}", please rebut him, still speaking in no more than one -sentence. Do not repeat your side of the argument. Do not repeat what -you have said before. Find as many holes in the other person's argument -as possible. Present new evidence to attack the other person whenever -possible."
    • +
    • 随机Q表,初始化状态,开始迭代,\(\epsilon\)贪心
    • +
    • 在状态s采取动作a,观察到奖励r和状态\(s +\prime\)
    • +
    • 关键迭代公式: \[ +Q(s,a) = Q(s,a) + \alpha [r + \gamma max_{a \prime}Q(s \prime,a \prime) +- Q(s,a)] \\ +\]
    • +
    • Q的更新包括两部分,一部分自然是奖励(假如这一步得到奖励的话),另一部分是时间差值,即TD-error,是现实和估计之间的差值。这里的现实是在新状态采取了最好动作后得到的奖励,这里的估计是指我们所有的奖励,除了最终步得到的真实奖励,其余中间步都是用Q表值来估计现实奖励,因此Q表的更新应该是加上(现实-估计),即让Q表更加贴近现实。
    • +
    • 值得注意的是,只有最后一步得到奖励时(假如我们只有终点一个奖励),现实才真的是现实的奖励,否则还是用Q表估计的。
    • +
    • 这里Q表的更新只与未来的状态和动作有关,在最开始,应该除了真正有奖励的最后一步,其余步骤的更新都是不确定的(因为现实也是用Q表估计的,只有最后一步现实才是现实),但第一次迭代之后最后一步的价值更新是确定的(在宝藏边上还是知道怎么走向宝藏),且与LSTM那种时间序列不同,它不是从最后一个时间步往前BPTT,而是更新了一个状态的转移价值(取哪个动作好),这个状态可能出现在每一次迭代的多个时间步上(或者说和时间步无关),接下来与该状态相邻的状态更新时,用Q表估计的现实就会准确一些,慢慢的整个算法达到收敛。
    -

    Discovery

    -
      -
    • 该项目想通过辩论这一极具挑战和思辨的语言应用来探索一下GPT的语言能力、逻辑能力,以及探索人类的思想究竟是否可以被概率所拟合
    • -
    • 可以设计许多有意思的场景,观察GPT如何给出他的最优解,例如: +

      Sarsa

        -
      • 限制每次只能发言一句进行辩论
      • -
      • 设计一个反事实的辩题
      • -
      • 引入第三个gpt作为裁判
      • -
      • 三方乃至n方辩论
      • -
      • 只提供背景,gpt自己设计辩题
      • -
      • 何时一个GPT bot才会被另一个GPT bot说服
      • -
      • and more
      • -
    • -
    • The project aims to explore the linguistic and logical capabilities -of the GPT through the challenging and discursive use of language in -debate, and to explore whether human thought can be fitted to -probabilities.
    • -
    • A number of interesting scenarios can be devised to see how the GPT -gives his optimal solution, for example +
    • Q-learning是off-policy的,因为存在着现实和估计的差距,我们朝着现实优化,而实际采取的是根据Q表估计的现实,即异步的(off)。
    • +
    • Sarsa是on-policy的,与Q-learning在算法上的区别:
        -
      • Limit debate to one sentence at a time
      • -
      • devising a counterfactual debate question
      • -
      • Introducing a third GPT as a referee
      • -
      • Three-way or even n-way debates
      • -
      • Provide only the background, the gpt designs his own debate
      • -
      • When will one GPT bot be convinced by another GPT bot
      • -
      • and more
      • +
      • Q-learning:根据Q表选动作-执行动作观察到奖励和新状态-更新Q表-更新状态
      • +
      • Sarsa:执行动作观察到奖励和新状态-更新状态-根据Q表在新状态上选动作,在迭代之前先来一次根据Q表选动作
    • +
    • 可以看到Sarsa更改了学习算法的步骤顺序,这种更改带来了什么效果?效果就是将新状态和新动作的选取提前到Q表更新之前,这样Q表更新时,差距里现实的部分不用\(max_{a \prime}Q(s \prime,a +\prime)\)来估计,而直接用新状态和新动作: \[ +Q(s,a) = Q(s,a) + \alpha [r + \gamma Q(s \prime,a \prime) - Q(s,a)] \\ +\]
    • +
    • 也就是说现实和估计采用的是同一策略(确定的动作,而不是给定状态选最大价值),然后依然使用这个差距来更新。
    • +
    • 在更新的过程中,sarsa说到做到(因为现实采用的就是新状态和新动作,agent一定会按照这样更新),而Q-learning则比较乐观(因为现实采用的是新状态下的最大价值,但实际走不一定会采取最大价值的行动,有\(\epsilon\)的扰动)。Sarsa更为保守(每一步都想走好),而Q-learning更为激进(先rush到再说)。
    -]]>
    - - 自然语言处理 - - - GPT - NLP - LLM - -
    - - Note for Heterogeneous Information Network - /2019/10/30/heterogeneous/ - 记录近年来对于异构信息网络的一些处理 - PathSim - HGNN - HGAN - HGAN -for text classification - 带属性,Attributed Multiplex Heterogeneous -Network - Meta-graph Guided Random Walks - TBD

    - -

    PathSim: -Meta Path-Based Top-K Similarity Search in Heterogeneous Information -Networks

    +

    Sarsa(\(\lambda\))

      -
    • 较早的一篇论文(作者都是大神),定义清楚了meta -path中的很多概念,提出了衡量异构信息网络中节点相似度的一种方法。
    • -
    • 传统的相似度衡量方法存在偏差,基于路径数统计和随机游走的方法存在偏差,偏向度数较多的节点;pair-wise的随机游走偏向具有较多离群点邻居的节点
    • -
    • PathSim的想法是,两个相似的节点不仅仅应该相互强链接,还需要share -comparable visibility
    • -
    • 在给定对称的meta path \(P\)下,两个同类型节点\(x,y\)的PathSim定义为: \[ -s(x, y)=\frac{2 \times\left|\left\{p_{x \leadsto y}: p_{x \sim y} \in -\mathcal{P}\right\}\right|}{\left|\left\{p_{x \leadsto x}: p_{x -\hookrightarrow x} \in \mathcal{P}\right\}\right|+\left|\left\{p_{y -\leadsto y}: p_{y \leadsto y} \in \mathcal{P}\right\}\right|} +
    • naive版本的Sarsa可以看成是Sarsa(0),因为每走一步就更新了Q表,即\(Q(s \prime,a \prime)\)只会带来上一步\(Q(s,a)\)的价值更新。假如我们考虑对所有步的更新,且离最终奖励近的步权重大,离最终奖励远的步权重小,那么调整这个权重的超参就是\(\lambda\),权重为0就是不考虑之前的步数,即naive +Sarsa。
    • +
    • 具体实现是添加一个trace矩阵E(矩阵中每一个元素对应一步(s,a))保存所有步在该次路径中的权重,离最终奖励越近,权重越大,因此每走一步,执行的那一步元素对应矩阵值加1,然后用对应的trace矩阵值作为权重乘到奖励上来更新Q表(这里是所有的步和整个E矩阵乘起来),之后矩阵值会衰减一下,乘以更新衰减因子\(\gamma\)和权重超参\(\lambda\)。显然\(\gamma\)为1时,就是所有的状态得到了一样的更新(因为是所有步和整个E矩阵相乘);当\(\gamma\)为0时,除了执行步元素加了1,然后整个E矩阵都置0,因此只有执行步得到了更新,即naive +Sarsa。将E矩阵的迭代展开,就可以得到与naive +sarsa一样的展开,只不过衰减的时候加了一个E(s,a)来记录某一步距离奖励的距离。 +\[ +\delta = r + \gamma Q(s \prime,a \prime) - Q(s,a) \\ +E(s,a) = E(s,a) + 1 \\ +Q = Q + \alpha \delta E \\ +E = \gamma \lambda E \\ +update \ \ s,a \\ \]
    • -
    • 实际分母的节点回归概率就是visibility,作者在传统的pathcount上除以visibility,所有的路径都由edge -weight累乘得到。
    • -
    • 类似于对节点的度做了对称归一化。
    • +
    • 这个E矩阵就是eligibility +trace。对于某一步,如果被执行了,就增加一点值,之后慢慢衰减,直到又被执行。假如短期内被执行多次,就会上升到过高值,这时可以设置阈值来限制eligibility的增加。这个值可以解释为该步在该次迭代中对于找到最终奖励的贡献程度。
    • +
    +

    DQN

    +
      +
    • Q-learning + deep neural network
    • +
    • 神经网络用于把Q-table的更新过程参数化,输入一个状态向量,神经网络输出所有动作的价值,用神经网络的训练来替代简单的迭代更新。这样可以解决状态数过多导致的维度灾难问题。
    • +
    • 直接这么替换不容易训练,DQN引入两个技巧 +
        +
      • experience replay
      • +
      • fix q
      • +
    • +
    • 先看神经网络的输入输出和损失 +
        +
      • 有两个神经网络,一个网络参与训练(评价网络),一个网络只复制另一个网络训练得到的参数,用来生成ground +truth,即目标网络
      • +
      • 参与训练的网络输入是状态,表示为s维特征向量,输出是各个动作获得的a维价值向量,损失是这个向量和ground +truth的a维向量之间的均方误差。
      • +
    • +
    • DQN还包含一个记忆矩阵,维度是[记忆条数,$ 2 * s + 2$ +],每一条包含奖励、动作,老状态和新状态,即一步的所有信息。记忆只保存最近记忆条数次执行步。
    • +
    • 之后神经网络的输入输出从哪里来?其实是从记忆中采样一个Batch的数据,将老状态输入评价网络得到model +output,将新状态输入目标网络得到ground truth,之后计算损失。
    • +
    • 每隔一段时间目标网络才会复制评价网络,在此期间目标网络都是固定不变的,即fix +q
    • +
    • 而输入是从最近的记忆当中抽取的,即experience replay
    • +
    • 值得注意的是我们并不直接把评价网络输出价值向量用于计算损失,因为还没有采取动作。因此我们要先根据网络输出的价值向量采取动作,将价值向量里这些动作对应的价值用奖励更新,之后这个更新过的价值向量再参与损失计算。
    -

    Heterogeneous Graph Neural -Network

    -
      -
    • 任务:图表示学习
    • -
    • 异构类型:节点异构、边异构、节点多属性
    • -
    • 解决办法: +

      Double DQN

        -
      • 四步走:异构邻居采样、多属性编码、同类型邻居聚合、不同类型聚合
      • -
      • 异构邻居采样:基于重启的随机游走,先随机游走,且有一定概率p返回初始节点(重启),直到采样了一定数量的邻域节点。每种类型的邻域节点有上限值以确保所有类型的邻居都能采样到。再等比例缩小,对每个邻域节点类型\(t\),只取\(K_t\)个邻域节点,分好组。
      • -
      • 多属性编码:根据多模态内容,预先编好码,例如文本用paragraph2vec,图像用CNN,同一邻域节点的不同属性信息用BiLSTM编码
      • -
      • 同类型邻居聚合:用BiLSTM聚合同类型下多个邻域节点的特征
      • -
      • 不同类型聚合:再用一个注意力机制聚合不同类型的特征
      • -
    • +
    • Double DQN解决DQN over estimate的问题
    • +
    • 与DQN不同之处在于,评价网络不仅接受老状态产生一个输出\(q_{eval}\),还接受新状态产生一个输出\(q_{eval4next}\),之后依据\(q_{eval4next}\)选取动作更新\(q_{eval}\),而不是根据\(q_{eval}\)本身选取动作来更新。
    -

    Heterogeneous Graph -Attention Network

    +

    DQN with Prioritized +Experience replay

      -
    • 任务:图表示学习
    • -
    • 异构类型:节点异构
    • -
    • 解决办法: +
    • 之前是从记忆库中随机采样一段记忆,这个随机采样会导致模型训练步数过多(随机很难保证到达最终奖励)
    • +
    • 那么自然而然想到记忆应该分配优先级,优先级高的采样概率大
    • +
    • 优先级可以用TD-error值来衡量,error大的自然要多采样多优化
    • +
    • 已知优先级分布,希望得到满足该优先级分布的一个采样序列,那么这就是一个蒙特卡洛问题了,可以用MCMC,可以用Importance +sampling,也可以用论文里提到的SumTree
    • +
    +

    Dueling DQN

      -
    • 实现node-level和metapath-level的双层注意力。
    • -
    • 需要在所有的metapath neighbour里加上自身,类似于GCN里的内环。
    • -
    • node-level注意力,对一条metapath上的不同节点进行注意力加权。因为不同类型的节点特征表示空间不同,因此针对每一种类型对应一个特征转换矩阵,将不同类型节点映射到同一空间,之后通过自注意力机制对节点进行注意力的计算和加权(其中\(\phi\)代表metapath): \[ -h_i^{\prime} = M_{\phi _i} \cdot h_i \\ -e^{\phi}_{ij} = attn_{node}(h^{\prime}_i,h^{\prime}_j;\phi) \\ -\] -在计算attention需要做mask,只对邻域节点计算attention并做softmax。值得注意的是这里的自注意力的非对称性对异构图来说很重要,因为在一个节点对里,两个节点的邻域不同,相互的影响不是等量的。简单来说,对某一个节点,计算其在某一类metapath下所有邻域节点的注意力权重,输入是两个节点的h以及metapath -specific的一个参数向量,输出注意力权重,然后对某一节点,加权求和其某一类metapath下所有邻域节点的h,得到该节点的某一metapath的表示。 -\[ -\alpha_{i j}^{\Phi}=\operatorname{softmax}_{j}\left(e_{i -j}^{\Phi}\right)=\frac{\exp -\left(\sigma\left(\mathbf{a}_{\Phi}^{\mathrm{T}} -\cdot\left[\mathbf{h}_{i}^{\prime} \| -\mathbf{h}_{j}^{\prime}\right]\right)\right)}{\sum_{k \in -\mathcal{N}_{i}^{\mathrm{\Phi}}} \exp -\left(\sigma\left(\mathbf{a}_{\Phi}^{\mathrm{T}} -\cdot\left[\mathbf{h}_{i}^{\prime} \| -\mathbf{h}_{k}^{\prime}\right]\right)\right)} \\ -\] 计算出注意力之后对变换后的metapath邻域节点特征加权: Dueling DQN细化了原始DQN的内部网络输入输出关系: \[ -\mathbf{z}_{i}^{\Phi}=\sigma\left(\sum_{j \in \mathcal{N}_{i}^{\Phi}} -\alpha_{i j}^{\Phi} \cdot \mathbf{h}_{j}^{\prime}\right) -\]
    • -
    • 在实际加权的时候作者参考了multi-head的做法,计算了k个attention加权特征并拼接起来
    • -
    • metapath-level的attention即对某一节点所有不同类的metapath -embedding进行加权。先将每一条metapath的embedding变换到同一隐空间,然后参数化计算出注意力权重并softmax。需要注意的是softmax之前的attention -logit是在所有节点上计算某一类型metapath的平均,分母是节点数,分子是包含该类型metapath的节点的metapath -embedding累加,而之前的node-level是针对某一节点某一metapath下所有的邻域节点平均: -\[ -w_{\Phi_{i}}=\frac{1}{|\mathcal{V}|} \sum_{i \in \mathcal{V}} -\mathbf{q}^{\mathrm{T}} \cdot \tanh \left(\mathbf{W} \cdot -\mathbf{z}_{i}^{\Phi}+\mathbf{b}\right) +Q(s,a;\theta,\alpha,\beta) = Value(s;\theta,\beta) + +Advantage(s,a;\theta,\alpha) \]
    • -
    • 之后再在所有metapath类型上做softmax,得到权重,加权每个节点不同metapath -embedding得到最终embedding
    • -
    • 整个双层attention的logit以及softmax的范围有点绕,时而局部时而全局,需要仔细考虑清楚。
    • -
    -
  • 可以看到整个过程是可以在节点层次并行化计算的
  • -
  • 从结果来看效果达到了SOTA,而且可视化的结果可以看到节点embedding的聚类效果更好,attention也带来了一定可解释性。
  • +
  • 即拆分成了状态带来的价值和动作在该状态上带来的价值(advantage)
  • +
  • 为什么要单独考虑状态?因为有些状态是与动作无关的,无论采取什么动作都不会带来价值的改变
  • -

    Heterogeneous -Graph Attention Networks for Semi-supervised Short Text -Classification

    -
      -
    • 任务:节点分类
    • -
    • 异构类型:节点异构,包含三类节点,文本、实体、主题
    • -
    • 解决办法: +

      Policy Gradient

        -
      • 最朴素:扩充节点的特征空间,将三类节点的特征向量拼接起来,对于具体的某一节点,其不包含的特征向量位置全设为0
      • -
      • 异构图卷积:将相同节点类型的子图分离,每个子图单独做卷积,不同的子图通过参数变换矩阵投影到相同隐空间并相加激活作为下一层,具体而言,原始GCN为: +
      • 之前介绍的都是基于值的强化学习方法,即在某状态查询各个动作带来的价值,选择最大价值动作执行
      • +
      • policy +gradient(策略梯度)通过策略网络输入状态,直接输出动作,跳过了计算价值的步骤,是基于策略的方法
      • +
      • 策略网络并不计算某种损失进行反向传播,而是依据奖励来反向传播,更新的算法如下: \[ -H^{(l+1)}=\sigma\left(\tilde{A} \cdot H^{(l)} \cdot W^{(l)}\right) -\] 而异构GCN为: \[ -H^{(l+1)}=\sigma\left(\sum_{\tau \in \mathcal{T}} \tilde{A}_{\tau} \cdot -H_{\tau}^{(l)} \cdot W_{\tau}^{(l)}\right) -\] 其中\(\tilde{A}_{\tau}\)的行是所有节点,列是某一类型的所有节点,这样就抽离出了同构的连接子图,即对于每个节点,我们分别考虑他的邻域里类型a的节点,做信息聚合得到编码a,再考虑邻域里类型b的节点,做信息聚合得到编码b,编码a和b通过各自的变换矩阵变换到同一隐空间再相加。这样的设计是符合逻辑的。
      • -
      • 作者还考虑了以下情况:对于某一节点,不同类型的邻域节点的贡献不一样,同一类型下不同的邻域节点贡献也不一样。显然这里需要注意力。作者就提出了对偶注意力(即双层注意力),一层是type -level的,一层是node level的,先用某一类型邻域节点embedding的均值作为type -embedding,然后根据当前节点embedding与type embedding 计算出type -attention -weight,同理用具体的邻域节点embedding和当前节点embedding再加上type -attention得到node attention,利用计算出的node -attention替换GCN里的对称归一化邻接矩阵。
      • -
    • -
    -

    Representation -Learning for Attributed Multiplex Heterogeneous Network

    -
      -
    • 任务:图表示学习
    • -
    • 异构类型:节点异构、边异构、节点多属性
    • -
    • 解决办法: +\theta = \theta + \alpha \nabla _{\theta} \log \pi _{\theta} (s_t, a_t) +v_t \\ +\]
    • +
    • 需要注意以下几个关键点:
        -
      • 考虑某一节点在不同类型边连接下有不同的embedding,将节点总的overall -embedding拆成与边无关的base embedding和与边相关的edge embedding
      • -
      • edge -embedding与边类型相关,通过相同类型的边相连的邻域节点aggregate得到,这里的aggreagator -function可以采用GraphSage里的做法。
      • -
      • 经过k层聚合之后,对于每个节点都得到了k种边类型的edge -embedding,通过self attention将这些edge -embedding加权求和,乘上比例再加上base embedding就得到了最终的overall -embedding
      • -
      • 以上是直推式(transductive)模型,对于未观测数据,需要归纳式(inductive)的方法。具体做法很简单,将base -embedding和edge -embedding参数化为节点attribute的函数,而不是随机初始化之后完全根据已有的图学习。这样即便有图中没看见的节点,只要节点有属性,一样可以进行overall -embedding的提取
      • -
      • 最后做基于meta-path的random walk得到训练对,使用skip -gram训练,加入了负采样。
      • +
      • 这里的PG算法神经网络只负责接收状态作为输入,奖励作为梯度调整值,实际执行的动作作为gold +label,输出一个action vector,整个网络本身就是一个策略\(\pi\)(输入状态,输出动作概率分布)
      • +
      • 之后整个模型依然像DQN那样,借助策略(网络)按动作概率(网络输出)选择动作,转移状态,观察环境得到奖励
      • +
      • 那么第一个问题,这个策略梯度是怎么来的?可以看到梯度依然是损失对参数求导的形式,\(- \nabla _{\theta} \log \pi _{\theta} (s_t, a_t) +v_t\),哪来的损失?实际上是执行动作的概率乘以奖励,可以看作是动作概率分布和执行动作one-hot向量之间的交叉熵(交叉熵本来就有类似look +up的效果)乘以奖励。我们就看其本来的含义:执行动作的概率乘以奖励,网络本身只是一个策略,什么样的策略是好策略?假如通过这个策略选出来的动作执行之后得到了好的奖励,那么这是一个好的策略网络,也就是能选出好动作的策略网络是好网络,显然网络的目标函数就应该是执行动作的概率(网络认可的动作)乘以奖励(奖励认可的好动作)。
      • +
      • 第二个问题,对于随时能给出奖励的环境,agent可以走一步,根据奖励更新一次策略网络,那对于那些只有最后一步能够得到奖励的该咋办?事实上我们采取的是回合更新,无论是每一步都能给出奖励的环境还是只有最后一步有奖励的环境,我们都将一个回合内的所有步(s,a,r)都记录下来(除了最后一步,其余步的奖励都是0或者-1),之后每一步的奖励替换成累加奖励,并乘以一个衰减系数使得奖励随episode +steps衰减。注意不同于离散的基于值的学习,基于策略的PG在没有得到奖励的那些步也能算出一个动作概率来计算损失,因此即便是无奖励(或者负奖励),也能使得策略网络优化去让不好的动作概率降低。
    -

    Semi-supervised -Learning over Heterogeneous Information Networks by Ensemble of -Meta-graph Guided Random Walks

    +

    Actor Critic

      -
    • 任务:节点分类
    • -
    • 异构类型:节点异构,包含三类节点,文本、实体、主题
    • -
    • 解决办法:meta-path guided random walk
    • +
    • 显然基于策略的方法抛弃了值,获得了优势(连续动作),也带来了劣势(每执行一步之后没得值可以用来估计即时奖励,只能进行回合更新),那么一个自然而然的想法就是结合这两点,选择一个基于策略的网络作为actor,训练出策略;选择一个基于值的网络作为critic,用来给策略网络提供值,估计即时奖励。
    -

    Joint -Embedding of Meta-Path and Meta-Graph for Heterogeneous Information -Networks

    ]]>
    自然语言处理 - graph neural network deep learning - natural language processing - heterogeneous information network + reinforcement learning
    - Note for Graph-based Summarization - /2019/10/03/graph-summarization/ - 基于图的自动摘要相关论文选读 - AMR 生成式摘要 - AMR 多文档摘要两篇 - -pagerank in encoder attention - 基于主题建模构建图,使用ILP做抽取式摘要 -- 基于GCN的多文档抽取式摘要 - STRUCTURED NEURAL SUMMARIZATION -

    -

    Toward -Abstractive Summarization Using Semantic Representations

    -
      -
    • 探讨了如何从原文的AMR图构建摘要的AMR图,即graph summarization
    • -
    • 三步走,source graph construction, subgraph prediction, text -generation
    • -
    -

    Source Graph Construction

    -
      -
    • 这一步是将多句graph合并为source graph,一些concept node需要合并
    • -
    • 首先AMR不会重复建模提到的concept,而是将提到的频次作为特征补充进node -embedding当中
    • -
    • 节点合并包含两步:把一些节点的子树合并,接着把相同的概念节点合并
    • -
    • 子树合并之后的节点名称里包含了所有子树节点的信息,之后只有完全相同的节点才能合并,因此经过一次子树合并之后的节点很难再次合并(很难完全相同),这里需要做一些共指消解的工作(future -work)
    • -
    • 一些节点之间会有多条边,取出现次数最多的两个边的label,合并,抛弃其他边
    • -
    • 相同的概念节点直接合并
    • -
    • 加一个总的root节点连接各个句子的root节点
    • -
    • 这样连接出来的source graph对于gold summary -graph的边覆盖度不高,因此对于source -graph还后处理一下,将所有节点之间加入null 边,提高覆盖率
    • -
    -

    Subgraph Prediction

    -
      -
    • 子图预测问题是一个structured prediction problem
    • -
    • 作者构建子图打分函数为模型参数线性加权边和节点的特征: \[ -\operatorname{score}\left(V^{\prime}, E^{\prime} ; \boldsymbol{\theta}, -\boldsymbol{\psi}\right)=\sum_{v \in V^{\prime}} -\boldsymbol{\theta}^{\top} \mathbf{f}(v)+\sum_{e \in E^{\prime}} -\boldsymbol{\psi}^{\top} \mathbf{g}(e) -\]
    • -
    • decoding:基于ILP选出得分最大的子图。这里的约束条件是选出的子图必须合法且是联通的,可以通过指示函数v,e和流量f来描述。\(v_i=1\)即第i个节点被选中,\(e_{i,j}=1\)即i,j两个节点之间的边被选中,\(f_{i,j}\)代表从i流向j的流量,那么合法即: -\[ -v_{i}-e_{i, j} \geq 0, \quad v_{j}-e_{i, j} \geq 0, \quad \forall i, j -\leq N -\]
    • -
    • 联通即:从根流出的流量到达选中的每一个概念节点,每一个概念节点消耗一个流量,只有边被选中时流量才可能通过,这三个约束用数学描述为: -\[ -\begin{array}{r}{\sum_{i} f_{0, i}-\sum_{i} v_{i}=0} \\ {\sum_{i} f_{i, -j}-\sum_{k} f_{j, k}-v_{j}=0, \quad \forall j \leq N} \\ {N \cdot e_{i, -j}-f_{i, j} \geq 0, \quad \forall i, j \leq N}\end{array} -\]
    • -
    • 另外作者只假设了每一个概念只有一个父节点,即构建为树的形式 \[ -\sum _j e_{i,j} \leq 1, \quad \forall i, j \leq N -\]
    • -
    • 这种形式的ILP在sentence compression和dependency -parsing中都出现过,作者使用gurobi的ILP算法完成最优化
    • -
    • 可以附加一个约束来限制摘要的长度,例如选中的边总数不大于L
    • -
    • 以上是decoding,即选子图,但选图基于分数,而分数由参数加权,因此还包含了一个参数的优化。我们需要一个损失函数来衡量decoded -graph和gold summary graph之间的差距,然而gold summary -graph可能不在source graph当中,作者借鉴了机器翻译中的ramp -loss,作者对比了感知机所用的perceptron loss, structured SVM中的hinge -loss以及ramp loss,其中\(G\)是source -graph,\(G^{*}\) 是gold summary graph: -\[ -\begin{array}{ll}{\text {perceptron loss: }} & {-\text { score -}\left(G^{*}\right)+\max _{G} \text { score }(G)} \\ {\text {hinge loss: -}} & {-\text { score(G^{*} ) }+\max _{G}\left(\text -{score}(G)+\operatorname{cost}\left(G ; G^{*}\right)\right)} \\ {\text -{ramp loss: }} & {-\max _{G}\left(\text -{score}(G)-\operatorname{cost}\left(G ; G^{*}\right)\right)+\max -_{G}\left(\text {score}(G)+\operatorname{cost}\left(G ; -G^{*}\right)\right)}\end{array} -\]
    • -
    • cost对多余的边惩罚
    • -
    • perceptron loss很简单,就是希望缩小gold graph与decoded -graph之间的分数差距
    • -
    • hinge loss在ILP中加入对多余边的惩罚,使得decoded -graph的分数尽可能大,而不仅仅是和gold -graph接近,这里decoded的graph会比直接计算分数得到的graph分值上差一点
    • -
    • ramp loss相比hinge loss就是在前面一项加了一个反向的惩罚,实际ramp -loss依然是在缩小两个图的分数差距,只不过一个图比best decoded -graph分值高一点,另一个比best decoded graph低一点,放宽松了条件
    • -
    -

    Generation

    + Glove Embedding - Mathematical Derivation + /2019/01/13/glove/ +
      -
    • 作者目前只统计了decoded graph中概念节点对应的text -span,并没有生成可读的摘要,因此只计算了ROUGE-1
    • +
    • 记录一下Glove词向量的数学推导,因为原论文不是画模型得出的,而是纯数学操作计算得到的目标函数,这种设计方式非常有意思,而且还将word2vec的数学本质写出来进行了对比。
    • +
    • 原论文:GloVe: Global Vectors for Word Representation
    -

    Abstract -Meaning Representation for Multi-Document Summarization

    + +

    词向量

      -
    • 这是上一篇的扩展
    • -
    • 用AMR构建有根有向无环图,节点是概念,边是语义关系: +
    • 无论是基于全局矩阵分解的还是基于局部窗口的词向量,其提取semantic的方式都是从词与词的共现统计信息中挖掘意义。
    • +
    • 显然,全局的方式没有利用到局部的优点:全局例如LSA等技术对于局部上下文信息不敏感,难以根据上下文挖掘近义词;局部的方式没有利用到全局的优点,它只依赖于独立的局部上下文,窗口太小的话不能有效利用整个文档乃至语料的信息。
    • +
    • Glove的思路是利用全局的词与词共现矩阵,同时利用局部上下文关系计算相关性。
    • +
    • 词向量的结果是能产生有意义的语义关系到距离关系的映射,针对这个目标,Glove设计了一个log-bilinear回归模型,并具体采用一个加权最小均方回归模型来训练词向量。
    • +
    +

    发现

      -
    • 节点:可能是PropBank里的一个frameset(命题),一个普通英语单词,一个特殊类别词,一个字符串,
    • -
    • 边:可以是PropBank里的命题关系,或者魔改之后的关系
    • -
    -
  • 整个系统三个部分 +
  • 定义:
      -
    • source sentence -selection:输入一系列文章,然后挑出关于某一主题不同方面的句子
    • -
    • content planning:输入一系列句子,输出摘要图
    • -
    • surface realization:将图转换为可读的摘要句
    • +
    • \(x\):为单个词。
    • +
    • \(X_{ij}\)\(x_j\) 出现在\(x_i\)的上下文中的次数。
    • +
    • \(X_i = \sum _k +x_{ik}\):所有词出现在\(x_i\)的上下文中的次数。
    • +
    • \(P_{ij} = P(j|i) = \frac {x_{ij}} +{X_i}\)\(x_j\)出现在\(x_i\)的上下文中的概率,即上下文出现频次计数概率化,论文中称之为"co-occurrence +probabilities"。
    • +
    • \(r = \frac +{P_{ik}}{P_{jk}}\):引入中间词\(x_k\),论文中叫"probe +word",通过引入这个\(x_k\)可以间接的衡量\(x_i\)\(x_j\)的关系,通过\(r\)即ratio表示。
  • -
  • 三个组件可分别用领域内小语料优化
  • - -

    Source Sentence Selection

    -
      -
    • 因为是多文档摘要,因此对每一个输入样例(多篇文档),做谱聚类,每个簇再挑若干句子
    • -
    • 这样就有多个句子组,之后和更改了输入的摘要模型一样,需要重新构造训练对,这里是要构造接下来提供给content -planning的训练对,即句子组和对应的gold summary的AMR graph。就对gold -summary里的每一句,和句子组算一个平均相似度,选相似度大的作为训练对里的句子组。平均相似度有: +
    • \(r\)引入的作用体现在两个方面:
        -
      • LCS
      • -
      • VSM
      • -
      • Smatch方法,参考了论文Smatch: an evaluation metric for semantic -feature structures
      • -
      • Concept Coverage,即最大覆盖gold summary AMR graph里的concept
      • +
      • 对于要比较的\(x_i\)\(x_j\),筛除对于没有区分度的\(x_k\),也就是噪音。当\(r \approx 1\)时,\(x_k\)即为噪音。
      • +
      • 给定\(x_k\),使得\(r >> 1\)的那些\(x_i\)具有相近的词义,使得\(r << 1\)的那些\(x_j\)具有相近的词义。
    • -
    • 四种相似度也做了ablation
    • +
    • 因此,我们可以过滤噪音,仅仅在\(r\)很大或很小的词共现数据中挖掘词义关系。
    -

    Content Planning

    -
      -
    • 训练对是句子组和summary的AMR -graph,自然这个部分就是学习这个转换过程
    • -
    • 首先要把句子组里的summary转成AMR graph,作者试用了两种AMR -Parser,JAMR和CAMR
    • -
    • 之后把句子组里的每一句也转成AMR -graph,并且做合并(这一部分论文描述并不清楚) +

      设计

        -
      • 相同概念节点合并?
      • -
      • 做共指消解,把相同指代概念节点合并
      • -
      • 一些特殊节点需要把子树整合进节点信息里,叫mega-node,其实就是取消不必要的展开,将展开的具体信息直接写进节点里,例如date -entity :year 2002 :month 1 :day -5。这些mega-node只有完全相同时才能合并
      • -
      • 最后生成一个root节点,把各个子图的root节点连起来
      • -
      • 通过最后一个操作貌似相同概念节点合并是同一子图内相同节点合并?
      • -
    • -
    • 接下来设计算法,从源AMR graph中识别出摘要的AMR graph,包含两部分 +
    • 接下来,作者直接根据目标设计函数。
    • +
    • 目标是:设计出来的词向量之间的距离计算结果应该能够反映之前我们从词共现矩阵中发现的ratio,具体而言是对于三元组,词i,j和probe +word k,这三个词的词向量能够体现r
    • +
    • 那么直接设计,定义\(w_i\)\(x_i\)对应的词向量,则假设\(F\)为计算距离的函数: \[ +F(w_i,w_j,w^{*}_k) = r \\ += \frac {P_{ik}}{P_{jk}} \\ +\]
    • +
    • 上面\(w_k\)的词向量加了星号区别于\(w_i\)\(w_j\)的词向量,因为\(w_k\)是独立的上下文词向量,与我们需要的词向量是平行的两套,类似于word2vec里面的前后词嵌入矩阵。
    • +
    • 接下来,一个自然的想法是,减少参数,即只需要词向量和上下文词向量,因为是距离计算函数且向量空间是线性空间,我们使用\(w_i\)\(w_j\)的向量差作为参数: \[ +F(w_i - w_j,w^{*}_k) = \frac {P_{ik}}{P_{jk}} \\ +\]
    • +
    • 现在函数的参数是向量,输出是张量,最简单的一个结构就是做点乘: \[ +F((w_i-w_j)^T w^{*}_k) = \frac {P_{ik}}{P_{jk}} \\ +\]
    • +
    • 接下来的一个关键点:对称。注意到虽然区分了上下文和非上下文词向量,但是由于共现矩阵\(X\)是对称的,因此两套词向量\(w\)\(w^{\*}\)应该具有相同的效果,只是由于随机初始化不同,两套词向量的值不一样,在衡量相似度时应该是一样的目标,即\(w_i^T w^{\*}_j\)\(w_j^T w^{\*}_i\)一样。
    • +
    • 由于对称性,\(x_i,x_j,x_k\)可以是语料中任意词,因此\(F\)函数的两个参数应该是可以交换位置(\(w\)\(w^{\*}\)\(X\)\(X^T\)),那这里进一步运用了一点数学技巧将函数对称化:
        -
      • graph -decoding:通过整数线性规划(ILP)识别出一个最优摘要图:首先构造一个参数化的图打分函数,将每一个节点特征和边特征通过参数加权并累加得到分数,这里的特征是手工构造,参考Fei -Liu他的一系列AMR -summarization的论文;接下来做一个ILP,要求找一个子图,使得得分最大,限制为L个节点而且子图是连接的。
      • -
      • parameter update:最小化系统解码出的摘要图和gold -summary图之间的差距。这一步优化的是上一步打分函数中的特征加权参数。构造损失函数来衡量decoded -graph和gold graph之间的差距。有时gold graph不能从source -graph中解码出来,这时就采用structed ramp -loss,不仅仅考虑score,还考虑cost,即gold graph和decoded -graph就是否将某个节点或者边加入摘要达成一致的程度 设计: \[ +F((w_i-w_j)^T w^{*}_k) = \frac {F(w_i w^{*}_k)} {F(w_j w^{*}_k)} \\ +\]
      • +
      • 那么分子分母都是一样的形式,即 \[ +F(w_i w^{*}_k) = P_{ik} = \frac {X_{ik}} {X_i} \\ +\]
      • +
      • 要满足上面\(F\)可以拆分为两个子\(F\)的比,则\(F\)可以为\(exp\)函数,即 \[ +w_i^T w_k^{*} = log(X_{ik}) - log {X_i} \\ +\]
      • +
      • 这样k,i,j下标可互换位置且表达意思一致。由于分子分母形式一致,因此我们只要关注这个形式能够满足就行了,之后求分数自然会满足从三元组到ratio的映射。
      • +
      • 注意到上面式子当中,左边的两个向量内积,i,k符号互换值不变,而右边的两个log式子相减并不满足这种对称,因此我们补上一个\(log{x_k}\)使之对称,并将其简化为偏置\(b^{*}\),同样的道理,i,k符号互换后,补上一个\(Log{x_i}\)使之对称,即偏置\(b_i\),偏置和词向量一样,也是两套: \[ -L_{ramp}(\theta, \phi) = max_G (score(G)+cost(G;G_{gold})) - -max_G(score(G) - cost(G;G_{gold})) +w_i^Tw_k^{*} + b_i + b_k^{*} = log(X_{ik}) \\ +\]
      • +
      • 最后加上平滑,防止log的参数取0: \[ +w_i^Tw_k^{*} + b_i + b_k^{*} = log(1 + X_{ik}) \\ \]
    • -
    -

    Surface Realization

    -
      -
    • 将图转成句子
    • -
    • AMR图并不好转成句子,因为图并不包含语法信息,一个图可能生成多句不合法的句子,作者两步走,先将AMR图转成PENMAN形式,然后用现有的AMR-to-text来将PENMAN转成句子
    • -
    -

    Towards -a Neural Network Approach to Abstractive Multi-Document -Summarization

    -
      -
    • 这篇论文是上篇论文的扩展,从单文档摘要扩展到多文档摘要,主要是如何将大规模单文档摘要数据集上预训练好的模型迁移到多文档摘要任务上
    • -
    • 相比单文档模型,编码端又加了一层文档级别的编码,文档之间并没有依存或者顺序关系,因此没必要用RNN,作者直接用了线性加权,值得注意的是这个加权的权重不应该是固定或者直接学习出来的,而应该根据文档本身决定,因此作者给权重加了一个依赖关系学习出来,依赖文档本身和文档集的关系: +
    • 到这里我们已经初步完成了\(F\)函数的设计,但这个还存在的一个问题是,它是平均加权每一个共现的,而一般语料中大部分共现都频次很低
    • +
    • Glove的解决办法是使用加权函数。加权之后将词向量的训练看成是F函数的最小均方误差回归,设计损失函数: \[ -w_{m}=\frac{\mathbf{q}^{T}\left[\mathbf{d}_{m} ; -\mathbf{d}_{\Sigma}\right]}{\sum_{m} \mathbf{q}^{T}\left[\mathbf{d}_{m} -; \mathbf{d}_{\Sigma}\right]} +J = \sum _{i,j}^V f(X_{ij}) (w_i^T w_j^{*} + b_i + b_j^{*} - log (1 + +X_{ij}))^2 \\ \]
    • -
    • 注意力的机制基本不变,decoder的初始状态从单文档变成多文档编码,注意力加权从单篇文档句子数量到多篇文档句子数量。这里带来的一个问题是多文档的句子数量太大了,很多注意力被分散的很均匀,加权之后包含的信息量太大。因此作者将global -soft attention给截断了一下,只有top -k个句子可以用权重加权,其余的句子直接在编码中被抛弃
    • -
    • 单文档到多文档的迁移其实并不是论文的重点,作者在CNN/DM上训练单文档的模型部分,之后在少量DUC数据集上训练多文档的部分,但是这两个数据集挺一致的,很多工作在CNNDM上训练在DUC上测试也能取得不错的效果。
    • -
    • 论文的ablation做的非常详细,对比了多种功能图模型方法下的效果,包括Textrank,Lexrank,Centroid
    • -
    • 值得注意的是作者使用了编辑距离来衡量文摘的抽象程度
    • -
    -

    Abstractive -Document Summarization with a Graph-Based Attentional Neural Model

    -
      -
    • 万老师团队的一篇论文,想法非常的好,重要的部分在两点: +
    • 其中f为加权函数,其参数是共现频次,作者指出该函数必须满足三条性质:
        -
      • hierarchical encoder and -decoder:由于需要在句子级别上做编解码以适应图打分的操作,所以采用了分层的seq2seq,无论编码解码都是word-level加sentence-level
      • -
      • graph-attention:这里用的图是其实是pagerank里的全连接图,相似度直接用enc-dec的隐层向量内积来衡量,然后利用topic-aware -pagerank来重新计算句子级别注意力权重。
      • +
      • \(f(0)=0\):显然,没有出现共现则权重为0。
      • +
      • Non-decreasing:共现频次越大则权重越大。
      • +
      • relatively small for large +X:防止对于某些频次很高的常见共现加权过大,影响结果。
    • -
    • 在编解码阶段,我们利用隐层来计算相似度,这和原始的attention是一样的,只不过原始的attention加了一个参数矩阵(现代的attention连参数矩阵都懒得加了)使得这个相似度能够体现出注意力权重(分数),那么graph-attention就是在这个相似度上直接计算pagerank的markov链迭代,认为马氏链的稳定分布\(f\)就是重新rank之后的句子分数,这里有一点论文里没讲,作者做了一个假设,即编解码时拿到的已经是稳定状态,而不是从头迭代,因此可以令\(f(t+1)=f(t)=f\),直接算出稳定分布: 基于以上三种性质,作者设计了截尾的加权函数,在阈值\(X_{max}\)以内: \[ -\mathbf{f}(t+1)=\lambda W D^{-1} \mathbf{f}(t)+(1-\lambda) \mathbf{y} \\ -\mathbf{f}=(1-\lambda)\left(I-\lambda W D^{-1}\right)^{-1} \mathbf{y} \\ +f(x) = (\frac {x}{X_{max}}) ^ {\alpha} \\ +\] 超过阈值则函数值为1.
    • +
    +

    与Word2vec比较

    +
      +
    • 对于Word2vec中的skip-gram模型,其目标是最大化给定上下文之后预测正确中心词的概率,一般通过softmax函数将其概率化,即: +\[ +Q_{ij} = \frac {exp (w_i^T w_j^{*})} { \sum _{k=1}^V exp(w_i^T w_k^{*})} +\\ \]
    • -
    • 基本形式与pagerank一致,一部分是基于相似矩阵的salience分配,另一部分补上一个均匀分布\(y\)保证马氏链收敛(这里感觉应该是简略了了,把均匀转移矩阵乘以f直接写成了均匀分布),值得注意的是这是在sentence-level的编解码隐层状态做的计算,因此是计算给定某解码句下,各个编码句的graph -attention score,如何体现这个给定某解码句?那就是用topic-aware -pagerank,将解码句看成topic,把这个topic句加入pagerank的图里,并且y从均匀分布改成one-hot分布,即保证了解码句在graph中的影响力,并借此影响其他句子。
    • -
    • 之后借鉴了distraction attention使得注意力不重复: 通过梯度下降求解,则整体损失函数可以写成: \[ -\alpha_{i}^{j}=\frac{\max \left(f_{i}^{j}-f_{i}^{j-1}, -0\right)}{\sum_{l}\left(\max \left(f_{l}^{j}-f_{l}^{j-1}, -0\right)\right)} +J = - \sum _{i \in corpus , j \in context(i)} log Q_{ij} \\ \]
    • -
    • 在解码端也做了一些小技巧,包括: -
        -
      • OOV的处理,用@entity+单词长度来作为标签替换所有容易成为OOV的实体,并尝试把解码句中生成的实体标签还原,根据单词长度在原文中查找
      • -
      • hierarchical beam search:word-level的beam search打分考虑了attend -to的原文句子和当前生成部分的bigram -overlap,希望这个overlap越大越好;sentence-level的beam -search则希望生成每一句时attend -to的原文句子不相同,这一段描述不是很清楚,应该是生成每一句时会attend -N个不同的原文句产生N个不同的decoded sentence
      • -
    • -
    • 本文的层次编解码其实起到了很关键的作用,作者并没有一股脑用单词级别的注意力,还是根据句子关系构件图并重排序,在beam -search也充分利用了两个层次的信息
    • -
    • 从ablation来看,graph attention和sentence -beam的效果其实不大,影响ROUGE分数最大的是考虑了bigram -overlap的word-level beam -search,这也暴露了ROUGE的问题,即我们之前工作中提到的OTR问题
    • -
    -

    Topical -Coherence for Graph-based Extractive Summarization

    +
  • 将相同的\(Q_{ij}\)先分组再累加,得到: \[ +J = - \sum _{i=1}^V \sum _{j=1}^V X_{ij} log Q_{ij} \\ +\]
  • +
  • 接下来用之前定义的符号进一步变换: \[ +J = - \sum _{i=1^V} X_i \sum _{j=1}^V P_{ij} log Q_{ij} \\ += \sum _{i=1}^V X_i H(P_i,Q_i) \\ +\]
  • +
  • 也就是说,Word2vec的损失函数实际上是加权的交叉熵,然而交叉熵只是一种可能的度量,且具有很多缺点:
      -
    • 基于主题建模构建图,使用ILP做抽取式摘要
    • -
    • 作者使用了二分图,一边是句子节点,一边是主题节点,两组节点之间用边连接,边的权值是句子中所有单词在某一主题下概率的对数和,除以句子长度做归一化
    • -
    • 使用HITS算法在二分图上计算句子的重要程度
    • +
    • 需要归一化的概率作为参数
    • +
    • softmax计算量大,称为模型的计算瓶颈
    • +
    • 对于长尾分布,交叉熵常常分配给不太可能的项太多权重
    • +
  • +
  • 解决以上问题的方法:干脆不归一化,直接用共现计数,不用交叉熵和softmax,直接用均方误差,令\(Q_{ij} = exp(w_i^T w_j^{*})\)\(P_{ij} = X_{ij}\),则: \[ +J = \sum _{i,j} X_i (P_{ij} - Q_{ij})^2 \\ +\]
  • +
  • 但是不归一化会造成数值上溢,那就再取个对数: \[ +J = \sum _{i,j} X_i (log P_{ij} - log Q_{ij})^2 \\ += \sum _{i,j} X_i (w_i^T w_j^{*} - log X_{ij})^2 \\ +\]
  • +
  • 这样就得到了Glove最朴素的目标函数。
  • +
  • Word2vec的作者发现筛除一些常见词能够提高词向量效果,而Word2vec中的加权函数即\(f(X_i)=X_i\),因此筛除常见词等价于设计一个非降的加权函数。Glove则设计了更为精巧的加权函数。
  • +
  • 因此从数学公式推导上看,Glove简化了Word2vec的目标函数,用均方误差替换交叉熵,并重新设计了加权函数。
  • -

    Graph-based -Neural Multi-Document Summarization

    -
      -
    • 用GCN做抽取式摘要,在这里GCN起到了一个特征补充的作用,原始的做法就是一个two-level -GRU,documents -cluster做一个embedding,其中每一个sentence有一个embedding,然后类似IR,拿sentence -embedding和documents embedding做一个比较算出salience -score,之后再用一个贪心的方法根据分数抽句子,大框架依然是打分-抽取的思路
    • -
    • GCN加进了两层GRU之间,即句子的embedding在一个句子关系图下做了三层GCN,之后再由documents层次的GRU生成documents -embedding
    • -
    • 这里就关注两点:句子关系图如何构建
    • -
    • 句子关系图作者试了三种: +

      思路

        -
      • 最naive的,tfidf的cosine距离
      • -
      • Towards Coherent Multi-Document Summarization一文中的ADG
      • -
      • 作者在ADG上改进的PDG
      • -
    • -
    • 之后直接套GCN传播就行了
    • +
    • 该文提供了一个很好的设计模型的思路,即根据评测指标设计目标函数,反过来训练模型,得到函数的参数(副产品)作为所需的结果。
    ]]>
    - 自然语言处理 + 机器学习 - graph neural network - deep learning - summarization - natural language processing + math + glove + word embedding
    - Note for Hierarchical Latent Dirichlet Allocation - /2019/11/15/hlda/ - 记录 Hierarchical Latent Dirichlet -Allocation,层次主题模型的学习笔记。 -依然大量参考了徐亦达老师的教程。

    - -

    hLDA改进了什么

    -
      -
    • 改进了两点

      + Debates between GPTs + /2023/06/05/gpt-debate/ +
        -
      • 引入了Dirichlet Process

      • -
      • 引入了层次结构

      • -
    • +
    • 基于ChatGPT-Shortcut改了一个网页,展示了一些GPT自己与自己发生的有趣辩论。
    • +
    • 体验地址在
    • +
    • A webpage based on ChatGPT-Shortcut +that shows some interesting debates that took place between GPTs.
    • +
    • The experience website is here
    -

    DP

    -
      -
    • Dirichlet Process将Dirichlet -Distribution的概念扩展到随机过程,一般依概率采样会得到一个样本,一个值,而依据随机过程采样得到的是一个函数,是一个分布。给定DP的超参\(\alpha\),给定度量空间\(\theta\),以及该度量空间上的一个测度\(H\)(称为基分布, Base Distribution),\(DP(\alpha,H)\)中采样得到的就是一个在\(\theta\)上的无限维离散分布\(G\),假如对这个无限维(无限个离散点)做\(\theta\)上的任意一种划分\(A_1,...,A_n\),那么划分之后的\(G\)分布依然满足对应Dirichlet -Distribution在超参上的划分: \[ -(G(A_1,...,A_n)) \sim Dir(\alpha H(A_1),...,\alpha H(A_n)) -\] \(G\)定义为Dirichlet -Process的一个sample path/function/realization,即\(G=DP(t,w_0) \sim \ -DP(\alpha,H)\)。Dirichelt -Process的一个realization是一个概率测度,是一个函数,定义域在度量空间\(\theta\)上,函数输出即概率。注意因为是无限维,因此不能预先设置\(\alpha\)的维数,只能设置为一样的\(\alpha\),对比LDA,可以看到DP的超参\(\alpha\)是一个concentration -parameter,只能控制G分布趋于均匀分布的确定性,而不能控制G分布趋于怎样的分布,趋于怎样的分布由划分\(A\)决定。

    • -
    • 这里可以看到和LDA使用Dir -Distribution的区别:DP是直接采样生成了一个概率测度,可以进而生成离散的概率分布;而LDA中对Dir -Distribution采样只能得到一个样本,但是这个样本作为了多项式分布的参数,确定了一个多项式分布(也是离散的)。

    • -
    • DP可以用于描述混合模型,在混合组件数量不确定的情况下,通过DP来构造一个组件分配。放在GMM的场景里,假如有n个样本,但我不知道有几个GM来生成这n个样本,那么对样本i,我将其分配给某一个GM,称这个样本i所在GM的参数为\(\theta _i\),那么这个\(\theta\)服从一个基分布\(H(\theta)\),假如\(H\)是连续分布,那么两个样本取到相同的\(\theta\)的概率趋于零,相当于n个样本对应n个GM,那么我们可以把这个\(H\)离散化为G,离散的方式为\(G \sim DP(\alpha,H)\)\(\alpha\)越小越离散,越大则\(G\)越趋近于\(H\)。注意\(H\)也可以是离散的。

    • -
    • DP的两个参数,\(H\)\(\alpha\),前者决定了\(G\)的每一个离散点的位置,即\(\theta -_i\)具体的值;后者决定了离散程度,或者理解为\(\theta\)有多分散,有多不重复,即概率分布是集中的还是分散的,这个Dirichlet -Distribution里的\(\alpha\)是一致的。

    • -
    • 由于G满足Dirichlet -Distribution,因此有很多好的性质,包括对于多项式分布的conjugate,collapsing和splitting,以及renormalization。

      -
        -
      • \(E[G(A_i)]=H(A_i)\)

      • -
      • \(Var[G(A_i)]=\frac -{H(A_i)[1-H(A_i)]}{\alpha + 1}\)

      • -
      • 可以看到\(\alpha\)取极端时,方差分别退化为0或者伯努利分布的方差,对应着之前我们说的G去离散化H的两种极端情况。

      • -
    • -
    • 那么我们想用DP做什么,做一个生成式模型:我们想得到一个概率测度\(G \sim \ DP(H,\alpha)\),根据\(G\)得到每一个样本点i所属的组对应的参数(Group -Parameter)\(x_i \sim -\ G\),之后根据这个参数和函数\(F\)生成样本点i:\(p_i \sim \ F(x_i)\)

    • -
    • 接下来可以用中国餐馆过程(CRP)、折棒过程(Stick Breaking)和Polya -Urm模型来细化这个\(x_i\),即将和样本点i对应组的参数拆成样本点i对应的组和每组的参数,写成\(x_i=\phi _{g_i}\),其中\(g\)是样本点的组分配,\(\phi\)是组参数。

    • -
    • 接下来套用echen大佬的描述来描述三个模型如何细化\(x_i\)的:

    • -
    • In the Chinese Restaurant Process:

      -
        -
      • We generate table assignments \(g_1, -\ldots, g_n \sim CRP(\alpha)\) according to a Chinese Restaurant -Process. (\(g_i\) is the table assigned -to datapoint \(i\).)

      • -
      • We generate table parameters \(\phi_1, -\ldots, \phi_m \sim G_0\) according to the base distribution -\(G_0\), where \(\phi_k\) is the parameter for the kth -distinct group.

      • -
      • Given table assignments and table parameters, we generate each -datapoint \(p_i \sim F(\phi_{g_i})\) -from a distribution \(F\) with the -specified table parameters. (For example, \(F\) could be a Gaussian, and \(\phi_i\) could be a parameter vector -specifying the mean and standard deviation).

      • -
    • -
    • In the Polya Urn Model:

      -
        -
      • We generate colors \(\phi_1, \ldots, -\phi_n \sim Polya(G_0, \alpha)\) according to a Polya Urn Model. -(\(\phi_i\) is the color of the ith -ball.)

      • -
      • Given ball colors, we generate each datapoint \(p_i \sim F(\phi_i)\).

      • -
    • -
    • In the Stick-Breaking Process:

      + +

      Intro

        -
      • We generate group probabilities (stick lengths) \(w_1, \ldots, w_{\infty} \sim -Stick(\alpha)\) according to a Stick-Breaking process.

      • -
      • We generate group parameters \(\phi_1, -\ldots, \phi_{\infty} \sim G_0\) from \(G_0\), where \(\phi_k\) is the parameter for the kth -distinct group.

      • -
      • We generate group assignments \(g_1, -\ldots, g_n \sim Multinomial(w_1, \ldots, w_{\infty})\) for each -datapoint.

      • -
      • Given group assignments and group parameters, we generate each -datapoint \(p_i \sim -F(\phi_{g_i})\).

      • -
    • -
    • In the Dirichlet Process:

      +
    • 这是一个基于ChatGPT-Shortcut更改的项目,展示一些GPT自己和自己辩论的记录。这是一个纯前端展示页面,不包含任何的模型、数据、训练过程,也不是一个平台,没有ChatGPT-Shortcut的登录和平台共享功能。
    • +
    • 这只是一个爱好、偏收集的项目,没有研究目的和商业目的。此类项目也已经有很多不错的尝试,比如b站上的AI-talk或者油管上的Watch GPT-4 Debate +with Itself! (About whether it is an AGI)
    • +
    • 网址在
    • +
    • This is a project based on ChatGPT-Shortcut +to showcase some of GPT's own records of debates with themselves. This +is a pure front-end display page, containing no models, data, training +process, nor is it a platform with the login and platform sharing +features of ChatGPT-Shortcut.
    • +
    • This is just a hobby, collective-favour project, with no research +purpose or commercial purpose. There have been many good attempts at +such projects, such as AI-talk on bilibili or +Watch GPT-4 Debate +with Itself! (About whether it is an AGI) on YouTube
    • +
    • The website is here
    • +
    +

    Prompt

      -
    • We generate a distribution \(G \sim -DP(G_0, \alpha)\) from a Dirichlet Process with base distribution -\(G_0\) and dispersion parameter \(\alpha\).

    • -
    • We generate group-level parameters \(x_i \sim G\) from \(G\), where \(x_i\) is the group parameter for the ith -datapoint. (Note: this is not the same as \(\phi_i\). \(x_i\) is the parameter associated to the -group that the ith datapoint belongs to, whereas \(\phi_k\) is the parameter of the kth -distinct group.)

    • -
    • Given group-level parameters \(x_i\), we generate each datapoint \(p_i \sim F(x_i)\).

    • -
    +
  • 以单句辩论为例,给予GPT的background +prompt类似于:"你是一个具有顶尖水平的专业辩手。现在你参加了一个特殊的辩论,每次发言不能超过一句话。你将会得到一个辩题和你方观点,你需要引经据典,整理语言,逻辑严谨的为这个辩题辩护。你需要首先阐述观点,之后你会得到多轮对方的阐释,你需要不断驳斥他直到说服对方。记住,每次发言不能超过一句话。所有回答以中文呈现。"
  • +
  • 之后给出论点:“辩题为:{}.你方观点是支持/反对。”
  • +
  • 之后在两个GPT bots之间传递观点:“对方发言:“ +{}”,请反驳他,依然发言不超过一句。不要重复你方观点。不要重复之前的发言。尽可能找出对方观点漏洞。尽可能提出新证据攻击对方。”
  • +
  • Take the example of a one-sentence debate, where the background +prompt given to the GPT is something like: "You are a professional +debater at the top of your game. Now you are taking part in a special +debate where you can speak no more than one sentence at a time. You will +be given a topic and your side of the argument, and you will be required +to defend it logically, using quotations from the classics and +organising your language. You will be given several rounds of +elucidation from your opponent, and you will have to refute him until +you are convinced. Remember, no more than one sentence per statement. +All responses will be presented in Chinese."
  • +
  • The argument is then given: "The debate is entitled: {}. Your side's +argument is for/against."
  • +
  • Then pass the argument between the two GPT bots: "The other side +speaks:" {}", please rebut him, still speaking in no more than one +sentence. Do not repeat your side of the argument. Do not repeat what +you have said before. Find as many holes in the other person's argument +as possible. Present new evidence to attack the other person whenever +possible."
  • -

    折棒过程

    +

    Discovery

      -
    • 折棒过程提供了一种在\(\theta\)上的无限划分,依然令DP的参数为\(\alpha\),折棒过程如下:

      +
    • 该项目想通过辩论这一极具挑战和思辨的语言应用来探索一下GPT的语言能力、逻辑能力,以及探索人类的思想究竟是否可以被概率所拟合
    • +
    • 可以设计许多有意思的场景,观察GPT如何给出他的最优解,例如:
        -
      • \(\beta _1 \sim -Beta(1,\alpha)\)

      • -
      • \(A_1 = \beta _1\)

      • -
      • \(\beta _2 \sim -Beta(1,\alpha)\)

      • -
      • \(A_2 = (1-\pi _1) * \beta -_2\)

      • +
      • 限制每次只能发言一句进行辩论
      • +
      • 设计一个反事实的辩题
      • +
      • 引入第三个gpt作为裁判
      • +
      • 三方乃至n方辩论
      • +
      • 只提供背景,gpt自己设计辩题
      • +
      • 何时一个GPT bot才会被另一个GPT bot说服
      • +
      • and more
    • -
    • 这样每次从Beta分布中得到[0,1]上的一个划分,将整个\(\theta\)切成两部分,第一部分作为\(\theta\)上的第一个划分,剩下的部分看成下一次折棒的整体,接着从上面切两部分,第一部分作为\(\theta\)上的第二个划分,像一个棒不断被折断,每次从剩下的部分里折,最后折成的分段就是划分。

    • -
    -

    DP2CRP

    +
  • The project aims to explore the linguistic and logical capabilities +of the GPT through the challenging and discursive use of language in +debate, and to explore whether human thought can be fitted to +probabilities.
  • +
  • A number of interesting scenarios can be devised to see how the GPT +gives his optimal solution, for example
      -
    • 引入一个示性函数,假如两个样本点i,j他们被分配的组件相同,则他们的示性函数\(z\)相同,也就是表征每一个样本属于哪一个组件,\(x_i \sim Component(\theta -_{z_i})\)

    • -
    • 那么对于混合分布,比如GMM,我们希望得到的是predictive -distribution,即已知数据的组件分配情况下,新来了一个未知数据,我想知道他属于哪个组件: -\[ -p(z_i=m|z_{not \ i}) -\]

    • -
    • 结合定义可以知道这个概率应该是和\(H\)无关的,因为我不在乎\(\theta\)具体的值,我只在乎是哪一个\(\theta\),所以predictive -distribution与\(\alpha\)密切相关。将其展开: \[ -p(z_i=m|z_{not \ i}) = \frac {p(z_i=m,z_{not \ i})}{p(z_{not \ i})} \\ -\]

    • -
    • 由于在DP里是划分的类别数可以到无穷多个,因此这里采用了一个小技巧,我们先假设有k类,之后在把k趋于无穷 -\[ -= \frac {\int _{p_1...p_k} p(z_i=m, z_{not \ -i}|p_1...p_k)p(p_1...p_k)}{\int _{p_1...p_k} p(z_{not \ -i}|p_1...p_k)p(p_1...p_k)} -\]

    • -
    • 这里的k个类的概率是符合Dirichlet Distribution的,假设这里的Base -Distribution是均匀分布,则 \[ -= \frac {\int _{p_1...p_k} p(z_i=m, z_{not \ i}|p_1...p_k)Dir(\frac -{\alpha}{k} ... \frac {\alpha}{k})}{\int _{p_1...p_k} p(z_{not \ -i}|p_1...p_k)Dir(\frac {\alpha}{k} ... \frac{\alpha}{k})} -\]

    • -
    • 上面无论分子分母,积分内其实都是一个多项式分布乘以一个Dirichlet分布,根据共轭我们知道后验应该还是一个Dirichlet分布,我们推导一下多项式分布与Dirichlet分布相乘的积分: -\[ -\int _{p_1...p_k} p(n_1...n_k|p_1...p_k) p(p_1...p_k|\alpha _1 ... -\alpha _k) \\ -\] \[ -= \int _{p_1...p_k} Mul(n_1...n_k|p_1...p_k) Dir(p_1...p_k|\alpha _1 ... -\alpha _k) \\ -\] \[ -= \int _{p_1...p_k} (\frac {n!}{n_1!...n_k!} \prod _{i=1}^k p_i ^{n_i}) -\frac {\Gamma(\sum \alpha _i)}{\prod \Gamma (\alpha _i)} \prod _{i=1}^k -p_i^{\alpha _i -1} \\ -\] \[ -= \frac {n!}{n_1!...n_k!} \frac {\Gamma(\sum \alpha _i)}{\prod \Gamma -(\alpha _i)} \int _{p_1...p_k} \prod _{i=1}^k p_i^{n_i+\alpha _i -1} \\ -\]

    • -
    • 其中积分式内实际上是一个Dirichelt Distribution\(Dir(\alpha _1 + n_1 ... \alpha _k + -n_k)\)排除了常数部分,因此积分的结果就是1/常数,即: \[ -= \frac {n!}{n_1!...n_k!} \frac {\Gamma(\sum \alpha _i)}{\prod \Gamma -(\alpha _i)} \frac { \prod \Gamma (\alpha _i + n_i)}{\Gamma (n + \sum -\alpha _i)} -\]

    • -
    • 上式包括了三个部分,第一部分的一堆n,它是由多项式分布引入的,代表我们只看划分后每个集合的大小,而不看划分之后每个集合具体的内容,这和我们的需求是不一样的,因此不需要这个常数;第二个部分,是由Dir分布先验产生的,而在predictive -distribution中,分布先验都相同,因此抵消了,所以我们主要关注第三部分,回代入predictive -distribution那个分式当中。

    • -
    • 首先定义一个辅助变量\(n_{l , not \ i} = -Count(z_{not \ i} == l)\),那么: \[ -n_1 = n_{1,not \ i} \\ -\] \[ -... \\ -\] \[ -n_k = n_{k,not \ i} \\ -\]

    • -
    • 因为我们是是在求\(p(z_i=m, z_{not \ -i})\),那么肯定除了第m类,其余类的数量早已由除了第i个样本以外的样本确定,那么第m类呢? -\[ -n_m = n_{m,not \ i} + 1 -\]

    • -
    • 这样我们就完成了从指示函数表示的概率到多项式分布的转换,分子部分代入之前得到的第三部分有: -\[ -\frac {\Gamma(n_{m,not \ i} + \frac {\alpha}{k} + 1) \prod _{l=1,l \neq -m}^k Gamma(n_{l,not \ i})}{\Gamma (\alpha + n)} -\]

    • -
    • 同理计算分子,分子不用考虑第i个样本分给第m类,因此不用在累乘里单独拎出来第m项,形式要简单一些: -\[ -\frac {\prod _{l=1}^k \Gamma(n_{l,not \ i})}{\Gamma(\alpha +n -1)} -\]

    • -
    • 将上面两式相除,再利用Gamma函数\(\Gamma(x) = (x-1) \Gamma -(x-1)\)的性质简化,得到: \[ -= \frac {n_{m,not \ i} + \frac {\alpha}{k}}{n + \alpha - 1} -\]

    • -
    • 再令k趋于无穷,得到: \[ -= \frac {n_{m,not \ i}}{n + \alpha - 1} -\]

    • -
    • 但是上面这个式子对所有的类别从1到m求和并不为1,而是\(\frac {n-1}{n + \alpha --1}\),剩下一部分概率就设为取一个新类别的概率,这样我们的predictive -distribution就算完成了,而且可以发现,这个概率,实际上就对应着中国餐馆过程。

    • +
    • Limit debate to one sentence at a time
    • +
    • devising a counterfactual debate question
    • +
    • Introducing a third GPT as a referee
    • +
    • Three-way or even n-way debates
    • +
    • Provide only the background, the gpt designs his own debate
    • +
    • When will one GPT bot be convinced by another GPT bot
    • +
    • and more
    • +
  • -

    CRP

    +]]>
    + + 自然语言处理 + + + GPT + NLP + LLM + +
    + + Notes for NLP with Graph-Structured Representations + /2020/04/05/graph-doc-thesis/ + 阅读来自University of Alberta 的Bang Liu博士的论文Natural Language +Processing and Text Mining with Graph-Structured +Representations,做一些笔记

    +

    基于图结构表示的自然语言处理

      -
    • 中国餐馆过程的经典描述就是把n个人,一个一个人来,分到不确定张数目的桌子上,做一个整数集合上的划分。假设集合每个元素是一位顾客,第n位顾客走进了一家参观,则他按照以下概率去选择某一张已经有人的桌子坐下,或者找一张没人的新桌子坐下: -\[ -\begin{aligned} p(\text { occupied table } i | \text { previous -customers }) &=\frac{n_{i}}{\alpha +n-1} \\ p(\text { next -unoccupied table } | \text { previous customers }) &=\frac{\alpha -}{\alpha +n-1} \end{aligned} -\]

    • -
    • 其中\(n_i\)是第i张桌子上已经有的人数,$$是超参数。这样人到桌子的分配就对应了整数集合上的划分。

    • -
    • 分析一下,若是选择已经有人的桌子,则顾客倾向于选择人多的桌子;若是在有人的桌子与新桌子之间纠结,则依赖于超参$$

    • -
    • 那根据之前的推导,这个\(\alpha\)其实就是Dirichlet -Distribution的超参数,且效果完全吻合。由于在CRP中我们base -distribution选的是均匀分布,那对应的Dirichlet -Distribution选择对称超参,各个\(alpha -_i\)相同。那么\(\alpha\)越大,以Dirichlet -Distritbuion为参数先验的多项式分布里,取得各个项等概率的可能就越大,在中国餐馆过程中对应着每个顾客进来都想选择一张新桌子,因此每个桌子都只有一个人,等量分配;反之\(\alpha\)越小则越不确定,在中国餐馆过程中桌子的分配也不确定

    • -
    • 可以得到第m个人选择之后,桌子数量的期望是\(E(K_m|\alpha ) = O(\alpha \log -m)\),具体而言是\(E(K_m|\alpha ) = -\alpha (\Psi (\alpha + n) - \Psi (\alpha )) \approx \alpha \log (1 + -\frac{n}{\alpha })\), -也就是聚类数的增加与样本数的对数成线性关系。我们可以根据数据量和想要聚类的数量来反估计超参\(\alpha\)的设置。

    • -
    -

    nCRP

    +
  • 论文主要囊括了主要包含四个方向的工作:
      -
    • 以上仅仅完成了一个利用了DP的不确定数目聚类,我们可以认为餐馆里每个桌子是一个主题,人就是单词,主题模型就是把词分配到主题,把人分配到桌子,但是这样的话和LDA一样,主题之间没有关联。为了建立主题之间的层次关系,Blei提出了嵌套餐馆过程。

    • -
    • 在嵌套餐馆过程中,我们统一了餐馆和桌子的概念,餐馆就是桌子,桌子就是餐馆!为什么这么说?首先我们设置一个餐馆作为root餐馆(显然我们要建立一棵树了),然后根据中国餐馆过程选择root餐馆里的一个桌子,餐馆里的每个桌子上都有一张纸条指示顾客第二天去某一个餐馆,因此第二天顾客来到这个餐馆,接着根据CRP选个桌子,同时知晓了自己第三天该去哪个参观。因此桌子对应着餐馆,父节点餐馆的桌子对应着子节点餐馆,每一天就是树的每一层,这样就建立了一个层次结构的中国餐馆过程。

    • +
    • 事件抽取、故事生成
    • +
    • 语义匹配
    • +
    • 推荐
    • +
    • 阅读理解
    • +
  • -

    hLDA

    +

    相关领域及方法论

      -
    • 接下来我们可以在nCRP的框架上描述hLDA

    • -
    • 定义符号

      +
    • 在NLP当中构图的相关工作
    • +
    • 词作为节点
        -
      • \(z\):主题,假设有\(K\)

      • -
      • \(\beta\):主题到词分布的参数,Dir先验参数

      • -
      • \(w\):词

      • -
      • \(\theta\):文档到主题的分布

      • -
      • \(\alpha\):文档到主题分布的参数,Dir先验参数

      • +
      • syntactic信息作为边:Learning substructures of document semantic +graphs for document summarization
      • +
      • 共现信息作为边: Graph-of-word and tw-idf: new approach to ad hoc +ir; Shortest-path graph kernels for document similarity;Directional +skip-gram: Explicitly distinguishing left and right context for word +embeddings;
    • -
    • 那么可以简单定义LDA: \[ -p(w | \beta) \sim Dir(\beta) \\ -p(\theta | \alpha) \sim Dir(\alpha) \\ -\theta \sim p(\theta | \alpha) \\ -w \sim p(w | \theta , \beta) = \sum _{i=1}^K \theta _i p(w|z=i, \beta -_i) \\ -\]

    • -
    • hLDA流程如下:

      +
    • 句子、段落、文档作为节点
        -
      • 根据nCRP获得一条从root到leaf的长为\(L\)的路径

      • -
      • 根据一个\(L\)维的Dirichlet采样一个在路径上的主题分布

      • -
      • 根据这L个主题混合生成一个词

      • +
      • 词共现、位置作为边:Textrank: Bringing order into texts;
      • +
      • 相似度作为边:Evaluating text coherence based on semantic similarity +graph;
      • +
      • 链接作为边:Pagerank
      • +
      • 混合:Graph methods for multilingual framenets
      • +
    • +
    • 方法论 +
        +
      • 明确输入输出、决定语义的细粒度、构图(定义节点和边,抽取节点和边的特征)、基于图的表示重构问题、进行实验
      • +
      • 在NLP中引入图的关键是引入结构信息和关系信息。
      • +
      • 基于图的表示重构问题,例如 +
          +
        • 语义匹配:树或者图的匹配
        • +
        • 事件发现:社区发现
        • +
        • phrase挖掘:节点分类和排序
        • +
        • ontology creation: 关系鉴别
        • +
        • 问题生成:节点选择 GG2kes.png
        • +
    • -
    • 详细描述如下:

    • -
    • 概率图如下,其中\(c\)是餐馆,这里把nCRP单独拎出来了,实际上\(c\)决定了主题\(z\),另外\(\gamma\)是nCRP中CRP对应DP的concentration -paramter:

    -

    Gibbs Sampling in hLDA

    +

    事件抽取及故事生成

    +

    相关工作

      -
    • 定义变量:

      +
    • 文本聚类
        -
      • \(w_{m,n}\):第m篇文档里的第n个词

      • -
      • \(c_{m,l}\):第m篇文档里路径上第l层选择的主题对应的餐馆,需要采样计算

      • -
      • \(z_{m,n}\):第m篇文档里第n个词分配的主题,需要采样计算

      • +
      • 基于相似度的方法,需要指定聚类数目
      • +
      • 基于密度的方法,不太适合文本这样的高维稀疏空间
      • +
      • 基于非负矩阵分解的方法(谱聚类)
      • +
      • 基于概率模型,例如PLSA,LDA,GMM
    • -
    • 从后验分布中采样的公式分为两部分,第一部分是得到路径,这一部分就会利用到之前的predictive -distribution;第二部分是已知路径,剩下的部分就是普通的LDA,最终采样公式为: -\[ -p\left(\mathbf{w}_{m} | \mathbf{c}, \mathbf{w}_{-m}, -\mathbf{z}\right)=\prod_{\ell=1}^{L}\left(\frac{\Gamma\left(n_{c_{m, -\ell},-m}^{(\cdot)}+W \eta\right)}{\prod_{w} \Gamma\left(n_{c_{m, -e},-m}^{(w)}+\eta\right)} \frac{\prod_{w} \Gamma\left(n_{c_{m, -\ell},-m}^{(w)}+n_{c_{m, \ell}, -m}^{(w)}+\eta\right)}{\Gamma\left(n_{c_{m, \ell},-m}^{(\cdot)}+n_{c_{m, -\ell}, m}^{(\cdot)}+W \eta\right)}\right) -\]

    • -
    -]]>
    - - 机器学习 - - - math - topic model - lda - -
    - - Incremental Decoding - /2020/03/17/incremental-decoding/ - 记录一下Fairseq当中对于CNN -seq2seq,Transformer之类的并行解码模型,在推理阶段的增量解码处理。

    - -

    Fairseq架构

    +
  • 故事结构生成
      -
    • 在Facebook推出的seq2seq库Fairseq当中,所有模型继承FairseqEncdoerDecoder类,所有的Encoder继承FairseqEncoder类,所有的Decoder继承FairseqIncrementalDecoder类,而FairseqIncrementalDecoder继承自FairseqDecoder类。
    • -
    • FairseqEncoder类只定义了forward,reorder_encoder_out,max_positions,upgrade_state_dict,最重要的就是forward,即定义编码的前向传播过程。reorder其实在decoder中更重要,但是这里也定义了。
    • -
    • FairseqDecoder类定义了forward,extract_features,output_layer,get_normalized_probs,max_positions,upgrade_state_dict,prepare_for_onnx_export_。forward=extract_features+output_layer,即forward定义了解码出序列的整个前向过程,而extract_features只定义到获得整个decoder的state -sequence。
    • -
    • Incremental -Decoder额外定义了reorder_incremental_state,set_beam_size。reorder是和incremental以及beam -search密切相关的,后文将详细介绍。
    • +
    • 持续的将新事件归类到已有聚类当中
    • +
    • 想要为一系列时序事件生成故事总结,传统的基于summarization的方法不能持续生成,现在多采用基于贝叶斯模型的方法,但是gibbs +sampling太耗时
    • +
  • +
  • 作者提出了EventX方法,构建了Story +Forest系统,与以上两个路线相关,做的是开放域新闻文档事件抽取
  • -

    训练并行,推理增量

    +

    Story +Forest: Extracting Events and Telling Stories from Breaking +News(TKDD)

      -
    • 像CNN seq2seq, -Transformer之类的模型打破了RNN模型的顺序性,使得seq2seq架构中的编码器和解码器在训练是都可以并行训练。
    • -
    • 编码器并行训练非常显然,而解码器实际上是一个语言模型,之所以可以并行是因为在训练时采用了teacher -forcing,因此语言模型的每一时间步输入在训练时我们假设是已知的,就可以一整个(Batch,Length,Hidden)的decoder -input输入模型,直接训练。
    • -
    • 但是在测试(推理)阶段,每一时间步的输入由上一时间步的输出决定,无法并行操作,如果反复运行整个decoder,那么就要运行Length次,且第i次只有前i个位置的信息是有用的,剩下部分的计算完全浪费掉了,推理的效率大大降低。
    • -
    • 这个时候就需要incremental -decoding,即在推理阶段,无论是CNN还是Transformer,都想RNN一样一步一步解码,每一步使用之前推理得到的信息,而不是完全从头开始计算。
    • -
    -

    CNN

    +
  • Story Forest:从新闻中抽取事件,生成故事
  • +
  • 定义:一个topic相当于一个story forest,包含多个story tree;每个story +tree的节点是一个event,event作为最小处理单元,实际上是关于某一个event的多篇新闻文档。本系统假设每篇文章只报道一个event
  • +
  • 整体架构:
  • +
  • 主要关注EventX中如何做cluster events,是一个两层聚类
      -
    • 对于CNN,可以发现,decoder无论哪一层,第i个位置都只需要该层[i-k,i)位置上内的信息,其中k为一维卷积的窗长。因此,只需要维护一个长度为k的队列,保存各层计算出来的state,就可以复用模型之前推理得到的信息,之后再把当前的state更新到队列中。
    • -
    • 每次计算时只需要对第i个位置进行decoding,即操作(Batch,1,Hidden)的数据Length次。
    • -
    • 在代码里,FConvDecoder将输入x和incremental_state一起传给了LinearizedConvolution,这里的介绍是 -
      """An optimized version of nn.Conv1d.
      At training time, this module uses ConvTBC, which is an optimized version
      of Conv1d. At inference time, it optimizes incremental generation (i.e.,
      one time step at a time) by replacing the convolutions with linear layers.
      Note that the input order changes from training to inference.
      """
    • -
    • 即训练时使用Time-First的形式组织数据进行卷积,充分利用GPU的并行性能,在推断时,将卷积层换成相同效果的线性层,逐帧进行推断 -
      if incremental_state is None:
      output = super().forward(input) # 这里 LinearizedConvolution的父类是ConvTBC,即没有推断时,直接将整个序列送入ConvTBC
      if self.kernel_size[0] > 1 and self.padding[0] > 0:
      # remove future timesteps added by padding
      output = output[:-self.padding[0], :, :]
      return output
    • -
    • 否则,就逐层用线性层推断,并更新input -buffer进而更新incremental_state
      # reshape weight
      weight = self._get_linearized_weight()
      kw = self.kernel_size[0]
      bsz = input.size(0) # input: bsz x len x dim
      if kw > 1:
      input = input.data
      input_buffer = self._get_input_buffer(incremental_state)
      if input_buffer is None:
      input_buffer = input.new(bsz, kw, input.size(2)).zero_()
      self._set_input_buffer(incremental_state, input_buffer)
      else:
      # shift buffer
      input_buffer[:, :-1, :] = input_buffer[:, 1:, :].clone()
      # append next input
      input_buffer[:, -1, :] = input[:, -1, :]
      input = input_buffer
      with torch.no_grad():
      output = F.linear(input.view(bsz, -1), weight, self.bias)
      return output.view(bsz, 1, -1)
    • +
    • 构建一个keyword co-occurrence +graph,节点是keyword,建边考虑两点:单篇文档内的相关性,即同一篇文档内共现次数超过阈值就建边;语料上的相关性,即条件概率超过阈值: +\[ +\operatorname{Pr}\left\{w_{i} | w_{j}\right\}=\frac{D F_{i, j}}{D F_{j}} +\]
    • +
    • 在这个keyword graph上做community +detection,将keyword做一次聚类,认为每个类的Keyword描述同一个topic。这样每个topic是一系列keywords的集合,相当于一个文档(bag +of words)
    • +
    • 计算每篇文档和每个topic之间的相似度,将文档分配给具有最大相似度的topic,这样就完成了第一层:文档按主题聚类
    • +
    • 将文档按topic分开之后,每个topic下还要细分event,这就是第二层聚类,event +cluster的大小通常严重不均衡,作者提出了一种基于监督学习指导的聚类方法
    • +
    • 现在将每篇文档看成节点,希望谈论同一个event的文档之间建边,这里不太好人为设计规则,就使用了监督学习,训练了一个SVM来判断是否描述同一个event,获得document +graph之后接着做community detection,完成第二层聚类
    • +
  • -

    Transformer

    +

    语义匹配

    +

    相关工作

      -
    • 同样的,我们看基于自注意力的模型如何去维护一个incremental state
    • -
    • 显然,在推断第i个位置的token时,不像CNN只与窗口大小的history相关,而是与前i-1个位置相关,但是注意,前i-1个位置计算出来的key和value是不变的,是可以复用的,第i位置只生成该位置的key,value以及query,并用query查询自己以及前i-1个位置复用的key,value,因此,incremental -state应该包含了key与value的信息,且维护的不是窗口大小,而是整个序列。
    • -
    • 在代码里,TransformerDecoder将当前层输入和encoder输出传给TransformerDecoderLayer,更新buffer -
      if prev_self_attn_state is not None:
      prev_key, prev_value = prev_self_attn_state[:2]
      saved_state: Dict[str, Optional[Tensor]] = {
      "prev_key": prev_key,
      "prev_value": prev_value,
      }
      if len(prev_self_attn_state) >= 3:
      saved_state["prev_key_padding_mask"] = prev_self_attn_state[2]
      assert incremental_state is not None
      self.self_attn._set_input_buffer(incremental_state, saved_state)
      _self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state)
    • -
    • 并在MultiHeadAttention里,假如incremental_state存在,将key和value设为None,后面的计算判断为None时就跳过计算 -
      if incremental_state is not None:
      saved_state = self._get_input_buffer(incremental_state)
      if saved_state is not None and "prev_key" in saved_state:
      # previous time steps are cached - no need to recompute
      # key and value if they are static
      if static_kv:
      assert self.encoder_decoder_attention and not self.self_attention
      key = value = None
    • -
    • 之后读取、计算、更新,代码写的很详细。
      if saved_state is not None:
      # saved states are stored with shape (bsz, num_heads, seq_len, head_dim)
      if "prev_key" in saved_state:
      _prev_key = saved_state["prev_key"]
      assert _prev_key is not None
      prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim)
      if static_kv:
      k = prev_key
      else:
      assert k is not None
      k = torch.cat([prev_key, k], dim=1)
      if "prev_value" in saved_state:
      _prev_value = saved_state["prev_value"]
      assert _prev_value is not None
      prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim)
      if static_kv:
      v = prev_value
      else:
      assert v is not None
      v = torch.cat([prev_value, v], dim=1)
      prev_key_padding_mask: Optional[Tensor] = None
      if "prev_key_padding_mask" in saved_state:
      prev_key_padding_mask = saved_state["prev_key_padding_mask"]
      assert k is not None and v is not None
      key_padding_mask = MultiheadAttention._append_prev_key_padding_mask(
      key_padding_mask=key_padding_mask,
      prev_key_padding_mask=prev_key_padding_mask,
      batch_size=bsz,
      src_len=k.size(1),
      static_kv=static_kv,
      )

      saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim)
      saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim)
      saved_state["prev_key_padding_mask"] = key_padding_mask
      # In this branch incremental_state is never None
      assert incremental_state is not None
      incremental_state = self._set_input_buffer(incremental_state, saved_state)
    • -
    -

    Generate

    +
  • 文档级别的语义匹配,相关工作:文本匹配、文档图结构表示
  • +
  • 文本匹配
      -
    • Fairseq的模型定义了所有前向过程,至于具体选择哪个前向过程则依据训练还是推断来决定。推断使用了fairseq-generate。
    • -
    • 要完成一次seq2seq,需要指定task和model,以及其他学习超参数。其中task确定了数据集参数,建立评价指标、词典、data_batch、实例化模型等等。
    • -
    • 其中最重要的就是train_step和inference_step,我们看看inference_step -
      def inference_step(self, generator, models, sample, prefix_tokens=None):
      with torch.no_grad():
      return generator.generate(models, sample, prefix_tokens=prefix_tokens)
    • -
    • 这里的generator是一个sequence_generator对象,其中生成的部分 -
      for step in range(max_len + 1):  # one extra step for EOS marker
      # reorder decoder internal states based on the prev choice of beams
      if reorder_state is not None:
      if batch_idxs is not None:
      # update beam indices to take into account removed sentences
      corr = batch_idxs - torch.arange(batch_idxs.numel()).type_as(batch_idxs)
      reorder_state.view(-1, beam_size).add_(corr.unsqueeze(-1) * beam_size)
      model.reorder_incremental_state(reorder_state)
      encoder_outs = model.reorder_encoder_out(encoder_outs, reorder_state)

      lprobs, avg_attn_scores = model.forward_decoder(
      tokens[:, :step + 1], encoder_outs, temperature=self.temperature,
      )
    • -
    • 这里做了一层emsemble -model的包装,假如我们只有一个decoder模型,那么实际上forward_decoder执行的是 -
      def _decode_one(
      self, tokens, model, encoder_out, incremental_states, log_probs,
      temperature=1.,
      ):
      if self.incremental_states is not None:
      decoder_out = list(model.forward_decoder(
      tokens,
      encoder_out=encoder_out,
      incremental_state=self.incremental_states[model],
      ))
      else:
      decoder_out = list(model.forward_decoder(tokens, encoder_out=encoder_out))
    • -
    • 这里可以看到是用incremental decoding逐步解码出句子
    • +
    • 交互放在最后,先通过孪生网络提取embedding,然后待匹配的embedding +pair进行score
    • +
    • 交互提前,先提取pair-wise的交互作为特征,然后通过神经网络聚合交互,最后score
    • +
  • +
  • 文档图结构表示 +
      +
    • word +graph:通过句法剖析得到spo三元组构图,还可以通过wordnet扩展合并;基于窗口的方法,nodes +represent unique terms and directed edges represent co-occurrences +between the terms within a fixed-size sliding +window;将依存关系作为边;基于超链接的构图;
    • +
    • text +graph:节点是句子、段落、文档,边基于词级别的相似度、位置、共现建立。
    • +
    • concept +graph:基于知识图谱,提取文档中的实体作为节点,例如DBpedia,然后通过最多两跳在知识图谱中进行dfs,找出outgoing +relation and entity,构图;或者基于wordnet,verbnet,找出semantic +role,用semantic/syntactic relation建边
    • +
    • hybrid graph:即异构图,多种节点以及多种边,lexical,tokens, +syntactic structure nodes, part of speech nodes
    • +
  • -

    Reorder

    +

    Matching +Article Pairs with Graphical Decomposition and Convolutions(ACL +2019)

      -
    • 更多的详细信息可以参考这篇博文,写的非常好,甚至被官方钦点加入了代码注释里understanding-incremental-decoding-in-fairseq
    • -
    • 还有一点,就是decoder中的reorder,在这篇博文里也有提到。
    • -
    • 在推断时和训练不同的另一点就是beam -search。因此我们不止维护一个缓存队列,而是beam_size个队列。
    • -
    • 那么在挑选第i个词的时候,第k个beam缓存队列的存的输入token可能是第i-1个位置时第j个beam缓存队列beam -search出来的,因此需要重新排序保证一致。
    • +
    • 作者在文本匹配和文档图结构表示方向的工作是提出了一种文档建图的方式,然后用GCN提取文档特征,进行文档级别的匹配
    • +
    • 这一部分可以改进上一个工作中两篇文档是否讨论同一个event的部分。
    • +
    • 整体流程:
    • +
    • 构图:Concept Interaction Graph +
        +
      • 先构建key +graph,抽取文章中的keywords和实体作为节点,假如两个节点出现在同一句中就建边
      • +
      • 可以将key graph中的节点直接作为concept,也可以在key +graph上做一个overlapping community detection,将Key +graph切分成多个相交的子图,子图作为concept节点,相交就建边
      • +
      • 现在concept 和 sentence都是bag of +words,就可以计算相似度,将句子分配到concept
      • +
      • 现在concept是句子的集合,将其看成bag of +words,concept之间就可以根据句子集合之间的tfidf vector +similarity建边
      • +
      • 很关键的一点,由于是做matching,输入是句子对,在这一步变成了图对,作者将两个CIG合并成一个大CIG,将描述同一个concept的两篇文章的句子集合放在一个concept +节点中
      • +
    • +
    • 构建matching network with GCN +
        +
      • 得到一个大的CIG之后,两篇文档之间的matching变成了大CIG当中每一个节点里来自两篇文档的sentence +set之间的matching
      • +
      • 构建了一个端到端的流程:用孪生网络提取节点特征、用GCN做节点直接的特征交互、聚合所有特征做预测
      • +
      • 这里每个节点包含了两个句子集,将其拼接成两个长句,进孪生网络,分别用bilstm或者cnn提取到特征,再进行一个特征的聚合: +\[ +\mathbf{m}_{A +B}(v)=\left(\left|\mathbf{c}_{A}(v)-\mathbf{c}_{B}(v)\right|, +\mathbf{c}_{A}(v) \circ \mathbf{c}_{B}(v)\right) +\]
      • +
      • 这样就得到每个节点上的matching +vector,可以理解为在该节点(concept)上两篇文档的相似度相关特征。此外作者还提取了一些传统特征相似度(tfidf,bm25,jaccard,Ochiai)的值拼接到matching +vector当中
      • +
      • 接下来过GCN
      • +
      • 聚合所有节点特征就是一个简单的mean +pooling,然后过一个线性层做分类(0,1)
      • +
    • +
    • 在长篇新闻语料上(avg 734 token),graph +matching的效果远好于传统的双塔模型(DUET,DSSM,ARC都在50~60的f1,graph +model达到了70~80)
    +

    Matching +Natural Language Sentences with Hierarchical Sentence Factorization(WWW +2018)

    +

    - +句子对语义匹配任务,主要利用的是AMR剖析得到的句子结构 - 五个步骤 - AMR +parsing and +alignment:AMR将句子表示为有向无环图,如果将有多个父节点的节点复制拆分,则可以将有向无环图转换为树。AMR的叶子节点代表一个概念,其余的是关系,代表概念之间的关联或者某个概念是另外一个概念的参数。得到AMR图之后还需要对齐,将句子中具体的token和概念建立连接。作者使用了现有的工具JAMR +- AMR +purification:一个token可能与多个概念建立连接,作者只选择最浅层的概念建立连接,之后将关系的内容删去,只保留边不保留边的label,得到简化之后的AMR +tree,如上图所示 - Index mapping:加入root节点,重设节点坐标 - Node +completion:类似于padding,保证两个句子的树的深度一样 - Node +traversal:做一次dfs,使得每个非叶子节点的内容拼接了其子树的内容 - +这样root节点就得到原句子的一个重新组织方式,类似于predicate-argument的形式,即谓语接谓语操作的词,类似于最初始的AMR +purification得到的只保留概念的N叉树先做后序遍历再逆序,作者的意思大致是这样可以统一的表达两个句子,避免原文表示中各种因词序和其他不那么重要的词(助词介词)的现象导致接下来语义匹配中产生错误。 +- 接下来使用Ordered Word Mover +Distance。如下式,D代表传输的cost(embedding距离),T代表传输量(词占比),\(\alpha,\beta\)代表两个句子中各个词的词频向量,这里作者直接用均匀分布替代。传统的WMD没有考虑词的顺序,作者引入了两个惩罚项,当T主要集中在对角线上时I较大,P是T的一个理想分布,其第i行第j列个元素满足i,j到对角线位置的距离的标准高斯分布,也是希望T是一个对角阵。对角阵的意义就是会在传输时考虑顺序,不发生相对距离较远的传输。 +\[ +\begin{array}{ll} +\underset{T \in \mathbb{R}_{+}^{M \mathrm{XN}}}{\operatorname{minimize}} +& \sum_{i, j} T_{i j} D_{i j}-\lambda_{1} I(T)+\lambda_{2} K L(T \| +P) \\ +\text { subject to } & \sum_{i=1}^{M} T_{i j}=\beta_{j}^{\prime} +\quad 1 \leq j \leq N^{\prime} \\ +& \sum_{j=1}^{N} T_{i j}=\alpha_{i}^{\prime} \quad 1 \leq i \leq +M^{\prime} +\end{array} \\ +\] \[ +I(T)=\sum_{i=1}^{M^{\prime}} \sum_{j=1}^{N^{\prime}} \frac{T_{i +j}}{\left(\frac{i}{M^{\prime}}-\frac{j}{N^{\prime}}\right)^{2}+1} \\ +\] \[ +P_{i j}=\frac{1}{\sigma \sqrt{2 \pi}} e^{-\frac{l^{2}(i, j)}{2 +\sigma^{2}}} \\ +\] \[ +l(i, j)=\frac{\left|i / M^{\prime}-j / N^{\prime}\right|}{\sqrt{1 / +M^{\prime 2}+1 / N^{\prime 2}}} \\ +\] - +通过上述方法就能得到针对两个句子AMR表示的OWMD距离,完成无监督的文本相似度计算。也可以充分利用AMR +Tree来完成监督学习。 - +注意到在AMR树中,不同层的节点其实代表了整句不同粒度的语义切分,例如第0层是整句,第一层是短句"Jerry +little",第二层是单一的概念"Jerry",作者选取前三层,将每一层不同粒度的语义单元之间输入context +layer,同一语义单元内的token +embedding相加作为单一embedding,并假设每一层的子节点最多k个,不足的padding。 +

    +

    推荐

    +

    相关工作

    +

    A +User-Centered Concept Mining System for Query and Document Understanding +at Tencent(KDD 2019)

    +

    Scalable +Creation of a Web-scale Ontology(SIGMOD 2020)

    +

    阅读理解

    +

    Learning +to Generate Questions by Learning What not to Generate(WWW 2019)

    +

    Asking +Questions the Human Way: Scalable Question-Answer Generation from Text +Corpus(WWW 2020)

    ]]>
    - - 自然语言处理 - math - inference - seq2seq + gnn + graph
    - Notes for NLP with Graph-Structured Representations - /2020/04/05/graph-doc-thesis/ - 阅读来自University of Alberta 的Bang Liu博士的论文Natural Language -Processing and Text Mining with Graph-Structured -Representations,做一些笔记

    -

    基于图结构表示的自然语言处理

    + Note for Graph-based Summarization + /2019/10/03/graph-summarization/ + 基于图的自动摘要相关论文选读 - AMR 生成式摘要 - AMR 多文档摘要两篇 - +pagerank in encoder attention - 基于主题建模构建图,使用ILP做抽取式摘要 +- 基于GCN的多文档抽取式摘要 - STRUCTURED NEURAL SUMMARIZATION +

    +

    Toward +Abstractive Summarization Using Semantic Representations

      -
    • 论文主要囊括了主要包含四个方向的工作: +
    • 探讨了如何从原文的AMR图构建摘要的AMR图,即graph summarization
    • +
    • 三步走,source graph construction, subgraph prediction, text +generation
    • +
    +

    Source Graph Construction

      -
    • 事件抽取、故事生成
    • -
    • 语义匹配
    • -
    • 推荐
    • -
    • 阅读理解
    • -
    +
  • 这一步是将多句graph合并为source graph,一些concept node需要合并
  • +
  • 首先AMR不会重复建模提到的concept,而是将提到的频次作为特征补充进node +embedding当中
  • +
  • 节点合并包含两步:把一些节点的子树合并,接着把相同的概念节点合并
  • +
  • 子树合并之后的节点名称里包含了所有子树节点的信息,之后只有完全相同的节点才能合并,因此经过一次子树合并之后的节点很难再次合并(很难完全相同),这里需要做一些共指消解的工作(future +work)
  • +
  • 一些节点之间会有多条边,取出现次数最多的两个边的label,合并,抛弃其他边
  • +
  • 相同的概念节点直接合并
  • +
  • 加一个总的root节点连接各个句子的root节点
  • +
  • 这样连接出来的source graph对于gold summary +graph的边覆盖度不高,因此对于source +graph还后处理一下,将所有节点之间加入null 边,提高覆盖率
  • -

    相关领域及方法论

    +

    Subgraph Prediction

      -
    • 在NLP当中构图的相关工作
    • -
    • 词作为节点 +
    • 子图预测问题是一个structured prediction problem
    • +
    • 作者构建子图打分函数为模型参数线性加权边和节点的特征: \[ +\operatorname{score}\left(V^{\prime}, E^{\prime} ; \boldsymbol{\theta}, +\boldsymbol{\psi}\right)=\sum_{v \in V^{\prime}} +\boldsymbol{\theta}^{\top} \mathbf{f}(v)+\sum_{e \in E^{\prime}} +\boldsymbol{\psi}^{\top} \mathbf{g}(e) +\]
    • +
    • decoding:基于ILP选出得分最大的子图。这里的约束条件是选出的子图必须合法且是联通的,可以通过指示函数v,e和流量f来描述。\(v_i=1\)即第i个节点被选中,\(e_{i,j}=1\)即i,j两个节点之间的边被选中,\(f_{i,j}\)代表从i流向j的流量,那么合法即: +\[ +v_{i}-e_{i, j} \geq 0, \quad v_{j}-e_{i, j} \geq 0, \quad \forall i, j +\leq N +\]
    • +
    • 联通即:从根流出的流量到达选中的每一个概念节点,每一个概念节点消耗一个流量,只有边被选中时流量才可能通过,这三个约束用数学描述为: +\[ +\begin{array}{r}{\sum_{i} f_{0, i}-\sum_{i} v_{i}=0} \\ {\sum_{i} f_{i, +j}-\sum_{k} f_{j, k}-v_{j}=0, \quad \forall j \leq N} \\ {N \cdot e_{i, +j}-f_{i, j} \geq 0, \quad \forall i, j \leq N}\end{array} +\]
    • +
    • 另外作者只假设了每一个概念只有一个父节点,即构建为树的形式 \[ +\sum _j e_{i,j} \leq 1, \quad \forall i, j \leq N +\]
    • +
    • 这种形式的ILP在sentence compression和dependency +parsing中都出现过,作者使用gurobi的ILP算法完成最优化
    • +
    • 可以附加一个约束来限制摘要的长度,例如选中的边总数不大于L
    • +
    • 以上是decoding,即选子图,但选图基于分数,而分数由参数加权,因此还包含了一个参数的优化。我们需要一个损失函数来衡量decoded +graph和gold summary graph之间的差距,然而gold summary +graph可能不在source graph当中,作者借鉴了机器翻译中的ramp +loss,作者对比了感知机所用的perceptron loss, structured SVM中的hinge +loss以及ramp loss,其中\(G\)是source +graph,\(G^{*}\) 是gold summary graph: +\[ +\begin{array}{ll}{\text {perceptron loss: }} & {-\text { score +}\left(G^{*}\right)+\max _{G} \text { score }(G)} \\ {\text {hinge loss: +}} & {-\text { score(G^{*} ) }+\max _{G}\left(\text +{score}(G)+\operatorname{cost}\left(G ; G^{*}\right)\right)} \\ {\text +{ramp loss: }} & {-\max _{G}\left(\text +{score}(G)-\operatorname{cost}\left(G ; G^{*}\right)\right)+\max +_{G}\left(\text {score}(G)+\operatorname{cost}\left(G ; +G^{*}\right)\right)}\end{array} +\]
    • +
    • cost对多余的边惩罚
    • +
    • perceptron loss很简单,就是希望缩小gold graph与decoded +graph之间的分数差距
    • +
    • hinge loss在ILP中加入对多余边的惩罚,使得decoded +graph的分数尽可能大,而不仅仅是和gold +graph接近,这里decoded的graph会比直接计算分数得到的graph分值上差一点
    • +
    • ramp loss相比hinge loss就是在前面一项加了一个反向的惩罚,实际ramp +loss依然是在缩小两个图的分数差距,只不过一个图比best decoded +graph分值高一点,另一个比best decoded graph低一点,放宽松了条件
    • +
    +

    Generation

      -
    • syntactic信息作为边:Learning substructures of document semantic -graphs for document summarization
    • -
    • 共现信息作为边: Graph-of-word and tw-idf: new approach to ad hoc -ir; Shortest-path graph kernels for document similarity;Directional -skip-gram: Explicitly distinguishing left and right context for word -embeddings;
    • +
    • 作者目前只统计了decoded graph中概念节点对应的text +span,并没有生成可读的摘要,因此只计算了ROUGE-1
    • +
    +

    Abstract +Meaning Representation for Multi-Document Summarization

    +
      +
    • 这是上一篇的扩展
    • +
    • 用AMR构建有根有向无环图,节点是概念,边是语义关系: +
        +
      • 节点:可能是PropBank里的一个frameset(命题),一个普通英语单词,一个特殊类别词,一个字符串,
      • +
      • 边:可以是PropBank里的命题关系,或者魔改之后的关系
    • -
    • 句子、段落、文档作为节点 +
    • 整个系统三个部分
        -
      • 词共现、位置作为边:Textrank: Bringing order into texts;
      • -
      • 相似度作为边:Evaluating text coherence based on semantic similarity -graph;
      • -
      • 链接作为边:Pagerank
      • -
      • 混合:Graph methods for multilingual framenets
      • +
      • source sentence +selection:输入一系列文章,然后挑出关于某一主题不同方面的句子
      • +
      • content planning:输入一系列句子,输出摘要图
      • +
      • surface realization:将图转换为可读的摘要句
    • -
    • 方法论 +
    • 三个组件可分别用领域内小语料优化
    • +
    +

    Source Sentence Selection

      -
    • 明确输入输出、决定语义的细粒度、构图(定义节点和边,抽取节点和边的特征)、基于图的表示重构问题、进行实验
    • -
    • 在NLP中引入图的关键是引入结构信息和关系信息。
    • -
    • 基于图的表示重构问题,例如 +
    • 因为是多文档摘要,因此对每一个输入样例(多篇文档),做谱聚类,每个簇再挑若干句子
    • +
    • 这样就有多个句子组,之后和更改了输入的摘要模型一样,需要重新构造训练对,这里是要构造接下来提供给content +planning的训练对,即句子组和对应的gold summary的AMR graph。就对gold +summary里的每一句,和句子组算一个平均相似度,选相似度大的作为训练对里的句子组。平均相似度有:
        -
      • 语义匹配:树或者图的匹配
      • -
      • 事件发现:社区发现
      • -
      • phrase挖掘:节点分类和排序
      • -
      • ontology creation: 关系鉴别
      • -
      • 问题生成:节点选择 GG2kes.png
      • -
    • +
    • LCS
    • +
    • VSM
    • +
    • Smatch方法,参考了论文Smatch: an evaluation metric for semantic +feature structures
    • +
    • Concept Coverage,即最大覆盖gold summary AMR graph里的concept
    +
  • 四种相似度也做了ablation
  • -

    事件抽取及故事生成

    -

    相关工作

    +

    Content Planning

      -
    • 文本聚类 +
    • 训练对是句子组和summary的AMR +graph,自然这个部分就是学习这个转换过程
    • +
    • 首先要把句子组里的summary转成AMR graph,作者试用了两种AMR +Parser,JAMR和CAMR
    • +
    • 之后把句子组里的每一句也转成AMR +graph,并且做合并(这一部分论文描述并不清楚)
        -
      • 基于相似度的方法,需要指定聚类数目
      • -
      • 基于密度的方法,不太适合文本这样的高维稀疏空间
      • -
      • 基于非负矩阵分解的方法(谱聚类)
      • -
      • 基于概率模型,例如PLSA,LDA,GMM
      • +
      • 相同概念节点合并?
      • +
      • 做共指消解,把相同指代概念节点合并
      • +
      • 一些特殊节点需要把子树整合进节点信息里,叫mega-node,其实就是取消不必要的展开,将展开的具体信息直接写进节点里,例如date +entity :year 2002 :month 1 :day +5。这些mega-node只有完全相同时才能合并
      • +
      • 最后生成一个root节点,把各个子图的root节点连起来
      • +
      • 通过最后一个操作貌似相同概念节点合并是同一子图内相同节点合并?
    • -
    • 故事结构生成 +
    • 接下来设计算法,从源AMR graph中识别出摘要的AMR graph,包含两部分
        -
      • 持续的将新事件归类到已有聚类当中
      • -
      • 想要为一系列时序事件生成故事总结,传统的基于summarization的方法不能持续生成,现在多采用基于贝叶斯模型的方法,但是gibbs -sampling太耗时
      • +
      • graph +decoding:通过整数线性规划(ILP)识别出一个最优摘要图:首先构造一个参数化的图打分函数,将每一个节点特征和边特征通过参数加权并累加得到分数,这里的特征是手工构造,参考Fei +Liu他的一系列AMR +summarization的论文;接下来做一个ILP,要求找一个子图,使得得分最大,限制为L个节点而且子图是连接的。
      • +
      • parameter update:最小化系统解码出的摘要图和gold +summary图之间的差距。这一步优化的是上一步打分函数中的特征加权参数。构造损失函数来衡量decoded +graph和gold graph之间的差距。有时gold graph不能从source +graph中解码出来,这时就采用structed ramp +loss,不仅仅考虑score,还考虑cost,即gold graph和decoded +graph就是否将某个节点或者边加入摘要达成一致的程度 \[ +L_{ramp}(\theta, \phi) = max_G (score(G)+cost(G;G_{gold})) - +max_G(score(G) - cost(G;G_{gold})) +\]
    • -
    • 作者提出了EventX方法,构建了Story -Forest系统,与以上两个路线相关,做的是开放域新闻文档事件抽取
    -

    Story -Forest: Extracting Events and Telling Stories from Breaking -News(TKDD)

    +

    Surface Realization

      -
    • Story Forest:从新闻中抽取事件,生成故事
    • -
    • 定义:一个topic相当于一个story forest,包含多个story tree;每个story -tree的节点是一个event,event作为最小处理单元,实际上是关于某一个event的多篇新闻文档。本系统假设每篇文章只报道一个event
    • -
    • 整体架构:
    • -
    • 主要关注EventX中如何做cluster events,是一个两层聚类 +
    • 将图转成句子
    • +
    • AMR图并不好转成句子,因为图并不包含语法信息,一个图可能生成多句不合法的句子,作者两步走,先将AMR图转成PENMAN形式,然后用现有的AMR-to-text来将PENMAN转成句子
    • +
    +

    Towards +a Neural Network Approach to Abstractive Multi-Document +Summarization

      -
    • 构建一个keyword co-occurrence -graph,节点是keyword,建边考虑两点:单篇文档内的相关性,即同一篇文档内共现次数超过阈值就建边;语料上的相关性,即条件概率超过阈值: +
    • 这篇论文是上篇论文的扩展,从单文档摘要扩展到多文档摘要,主要是如何将大规模单文档摘要数据集上预训练好的模型迁移到多文档摘要任务上
    • +
    • 相比单文档模型,编码端又加了一层文档级别的编码,文档之间并没有依存或者顺序关系,因此没必要用RNN,作者直接用了线性加权,值得注意的是这个加权的权重不应该是固定或者直接学习出来的,而应该根据文档本身决定,因此作者给权重加了一个依赖关系学习出来,依赖文档本身和文档集的关系: \[ -\operatorname{Pr}\left\{w_{i} | w_{j}\right\}=\frac{D F_{i, j}}{D F_{j}} +w_{m}=\frac{\mathbf{q}^{T}\left[\mathbf{d}_{m} ; +\mathbf{d}_{\Sigma}\right]}{\sum_{m} \mathbf{q}^{T}\left[\mathbf{d}_{m} +; \mathbf{d}_{\Sigma}\right]} \]
    • -
    • 在这个keyword graph上做community -detection,将keyword做一次聚类,认为每个类的Keyword描述同一个topic。这样每个topic是一系列keywords的集合,相当于一个文档(bag -of words)
    • -
    • 计算每篇文档和每个topic之间的相似度,将文档分配给具有最大相似度的topic,这样就完成了第一层:文档按主题聚类
    • -
    • 将文档按topic分开之后,每个topic下还要细分event,这就是第二层聚类,event -cluster的大小通常严重不均衡,作者提出了一种基于监督学习指导的聚类方法
    • -
    • 现在将每篇文档看成节点,希望谈论同一个event的文档之间建边,这里不太好人为设计规则,就使用了监督学习,训练了一个SVM来判断是否描述同一个event,获得document -graph之后接着做community detection,完成第二层聚类
    • -
    +
  • 注意力的机制基本不变,decoder的初始状态从单文档变成多文档编码,注意力加权从单篇文档句子数量到多篇文档句子数量。这里带来的一个问题是多文档的句子数量太大了,很多注意力被分散的很均匀,加权之后包含的信息量太大。因此作者将global +soft attention给截断了一下,只有top +k个句子可以用权重加权,其余的句子直接在编码中被抛弃
  • +
  • 单文档到多文档的迁移其实并不是论文的重点,作者在CNN/DM上训练单文档的模型部分,之后在少量DUC数据集上训练多文档的部分,但是这两个数据集挺一致的,很多工作在CNNDM上训练在DUC上测试也能取得不错的效果。
  • +
  • 论文的ablation做的非常详细,对比了多种功能图模型方法下的效果,包括Textrank,Lexrank,Centroid
  • +
  • 值得注意的是作者使用了编辑距离来衡量文摘的抽象程度
  • -

    语义匹配

    -

    相关工作

    +

    Abstractive +Document Summarization with a Graph-Based Attentional Neural Model

      -
    • 文档级别的语义匹配,相关工作:文本匹配、文档图结构表示
    • -
    • 文本匹配 +
    • 万老师团队的一篇论文,想法非常的好,重要的部分在两点:
        -
      • 交互放在最后,先通过孪生网络提取embedding,然后待匹配的embedding -pair进行score
      • -
      • 交互提前,先提取pair-wise的交互作为特征,然后通过神经网络聚合交互,最后score
      • +
      • hierarchical encoder and +decoder:由于需要在句子级别上做编解码以适应图打分的操作,所以采用了分层的seq2seq,无论编码解码都是word-level加sentence-level
      • +
      • graph-attention:这里用的图是其实是pagerank里的全连接图,相似度直接用enc-dec的隐层向量内积来衡量,然后利用topic-aware +pagerank来重新计算句子级别注意力权重。
    • -
    • 文档图结构表示 +
    • 在编解码阶段,我们利用隐层来计算相似度,这和原始的attention是一样的,只不过原始的attention加了一个参数矩阵(现代的attention连参数矩阵都懒得加了)使得这个相似度能够体现出注意力权重(分数),那么graph-attention就是在这个相似度上直接计算pagerank的markov链迭代,认为马氏链的稳定分布\(f\)就是重新rank之后的句子分数,这里有一点论文里没讲,作者做了一个假设,即编解码时拿到的已经是稳定状态,而不是从头迭代,因此可以令\(f(t+1)=f(t)=f\),直接算出稳定分布: \[ +\mathbf{f}(t+1)=\lambda W D^{-1} \mathbf{f}(t)+(1-\lambda) \mathbf{y} \\ +\mathbf{f}=(1-\lambda)\left(I-\lambda W D^{-1}\right)^{-1} \mathbf{y} \\ +\]
    • +
    • 基本形式与pagerank一致,一部分是基于相似矩阵的salience分配,另一部分补上一个均匀分布\(y\)保证马氏链收敛(这里感觉应该是简略了了,把均匀转移矩阵乘以f直接写成了均匀分布),值得注意的是这是在sentence-level的编解码隐层状态做的计算,因此是计算给定某解码句下,各个编码句的graph +attention score,如何体现这个给定某解码句?那就是用topic-aware +pagerank,将解码句看成topic,把这个topic句加入pagerank的图里,并且y从均匀分布改成one-hot分布,即保证了解码句在graph中的影响力,并借此影响其他句子。
    • +
    • 之后借鉴了distraction attention使得注意力不重复: \[ +\alpha_{i}^{j}=\frac{\max \left(f_{i}^{j}-f_{i}^{j-1}, +0\right)}{\sum_{l}\left(\max \left(f_{l}^{j}-f_{l}^{j-1}, +0\right)\right)} +\]
    • +
    • 在解码端也做了一些小技巧,包括:
        -
      • word -graph:通过句法剖析得到spo三元组构图,还可以通过wordnet扩展合并;基于窗口的方法,nodes -represent unique terms and directed edges represent co-occurrences -between the terms within a fixed-size sliding -window;将依存关系作为边;基于超链接的构图;
      • -
      • text -graph:节点是句子、段落、文档,边基于词级别的相似度、位置、共现建立。
      • -
      • concept -graph:基于知识图谱,提取文档中的实体作为节点,例如DBpedia,然后通过最多两跳在知识图谱中进行dfs,找出outgoing -relation and entity,构图;或者基于wordnet,verbnet,找出semantic -role,用semantic/syntactic relation建边
      • -
      • hybrid graph:即异构图,多种节点以及多种边,lexical,tokens, -syntactic structure nodes, part of speech nodes
      • +
      • OOV的处理,用@entity+单词长度来作为标签替换所有容易成为OOV的实体,并尝试把解码句中生成的实体标签还原,根据单词长度在原文中查找
      • +
      • hierarchical beam search:word-level的beam search打分考虑了attend +to的原文句子和当前生成部分的bigram +overlap,希望这个overlap越大越好;sentence-level的beam +search则希望生成每一句时attend +to的原文句子不相同,这一段描述不是很清楚,应该是生成每一句时会attend +N个不同的原文句产生N个不同的decoded sentence
    • +
    • 本文的层次编解码其实起到了很关键的作用,作者并没有一股脑用单词级别的注意力,还是根据句子关系构件图并重排序,在beam +search也充分利用了两个层次的信息
    • +
    • 从ablation来看,graph attention和sentence +beam的效果其实不大,影响ROUGE分数最大的是考虑了bigram +overlap的word-level beam +search,这也暴露了ROUGE的问题,即我们之前工作中提到的OTR问题
    -

    Matching -Article Pairs with Graphical Decomposition and Convolutions(ACL -2019)

    +

    Topical +Coherence for Graph-based Extractive Summarization

      -
    • 作者在文本匹配和文档图结构表示方向的工作是提出了一种文档建图的方式,然后用GCN提取文档特征,进行文档级别的匹配
    • -
    • 这一部分可以改进上一个工作中两篇文档是否讨论同一个event的部分。
    • -
    • 整体流程:
    • -
    • 构图:Concept Interaction Graph +
    • 基于主题建模构建图,使用ILP做抽取式摘要
    • +
    • 作者使用了二分图,一边是句子节点,一边是主题节点,两组节点之间用边连接,边的权值是句子中所有单词在某一主题下概率的对数和,除以句子长度做归一化
    • +
    • 使用HITS算法在二分图上计算句子的重要程度
    • +
    +

    Graph-based +Neural Multi-Document Summarization

      -
    • 先构建key -graph,抽取文章中的keywords和实体作为节点,假如两个节点出现在同一句中就建边
    • -
    • 可以将key graph中的节点直接作为concept,也可以在key -graph上做一个overlapping community detection,将Key -graph切分成多个相交的子图,子图作为concept节点,相交就建边
    • -
    • 现在concept 和 sentence都是bag of -words,就可以计算相似度,将句子分配到concept
    • -
    • 现在concept是句子的集合,将其看成bag of -words,concept之间就可以根据句子集合之间的tfidf vector -similarity建边
    • -
    • 很关键的一点,由于是做matching,输入是句子对,在这一步变成了图对,作者将两个CIG合并成一个大CIG,将描述同一个concept的两篇文章的句子集合放在一个concept -节点中
    • -
    -
  • 构建matching network with GCN +
  • 用GCN做抽取式摘要,在这里GCN起到了一个特征补充的作用,原始的做法就是一个two-level +GRU,documents +cluster做一个embedding,其中每一个sentence有一个embedding,然后类似IR,拿sentence +embedding和documents embedding做一个比较算出salience +score,之后再用一个贪心的方法根据分数抽句子,大框架依然是打分-抽取的思路
  • +
  • GCN加进了两层GRU之间,即句子的embedding在一个句子关系图下做了三层GCN,之后再由documents层次的GRU生成documents +embedding
  • +
  • 这里就关注两点:句子关系图如何构建
  • +
  • 句子关系图作者试了三种:
      -
    • 得到一个大的CIG之后,两篇文档之间的matching变成了大CIG当中每一个节点里来自两篇文档的sentence -set之间的matching
    • -
    • 构建了一个端到端的流程:用孪生网络提取节点特征、用GCN做节点直接的特征交互、聚合所有特征做预测
    • -
    • 这里每个节点包含了两个句子集,将其拼接成两个长句,进孪生网络,分别用bilstm或者cnn提取到特征,再进行一个特征的聚合: -\[ -\mathbf{m}_{A -B}(v)=\left(\left|\mathbf{c}_{A}(v)-\mathbf{c}_{B}(v)\right|, -\mathbf{c}_{A}(v) \circ \mathbf{c}_{B}(v)\right) -\]
    • -
    • 这样就得到每个节点上的matching -vector,可以理解为在该节点(concept)上两篇文档的相似度相关特征。此外作者还提取了一些传统特征相似度(tfidf,bm25,jaccard,Ochiai)的值拼接到matching -vector当中
    • -
    • 接下来过GCN
    • -
    • 聚合所有节点特征就是一个简单的mean -pooling,然后过一个线性层做分类(0,1)
    • +
    • 最naive的,tfidf的cosine距离
    • +
    • Towards Coherent Multi-Document Summarization一文中的ADG
    • +
    • 作者在ADG上改进的PDG
  • -
  • 在长篇新闻语料上(avg 734 token),graph -matching的效果远好于传统的双塔模型(DUET,DSSM,ARC都在50~60的f1,graph -model达到了70~80)
  • +
  • 之后直接套GCN传播就行了
  • -

    Matching -Natural Language Sentences with Hierarchical Sentence Factorization(WWW -2018)

    -

    - -句子对语义匹配任务,主要利用的是AMR剖析得到的句子结构 - 五个步骤 - AMR -parsing and -alignment:AMR将句子表示为有向无环图,如果将有多个父节点的节点复制拆分,则可以将有向无环图转换为树。AMR的叶子节点代表一个概念,其余的是关系,代表概念之间的关联或者某个概念是另外一个概念的参数。得到AMR图之后还需要对齐,将句子中具体的token和概念建立连接。作者使用了现有的工具JAMR -- AMR -purification:一个token可能与多个概念建立连接,作者只选择最浅层的概念建立连接,之后将关系的内容删去,只保留边不保留边的label,得到简化之后的AMR -tree,如上图所示 - Index mapping:加入root节点,重设节点坐标 - Node -completion:类似于padding,保证两个句子的树的深度一样 - Node -traversal:做一次dfs,使得每个非叶子节点的内容拼接了其子树的内容 - -这样root节点就得到原句子的一个重新组织方式,类似于predicate-argument的形式,即谓语接谓语操作的词,类似于最初始的AMR -purification得到的只保留概念的N叉树先做后序遍历再逆序,作者的意思大致是这样可以统一的表达两个句子,避免原文表示中各种因词序和其他不那么重要的词(助词介词)的现象导致接下来语义匹配中产生错误。 -- 接下来使用Ordered Word Mover -Distance。如下式,D代表传输的cost(embedding距离),T代表传输量(词占比),\(\alpha,\beta\)代表两个句子中各个词的词频向量,这里作者直接用均匀分布替代。传统的WMD没有考虑词的顺序,作者引入了两个惩罚项,当T主要集中在对角线上时I较大,P是T的一个理想分布,其第i行第j列个元素满足i,j到对角线位置的距离的标准高斯分布,也是希望T是一个对角阵。对角阵的意义就是会在传输时考虑顺序,不发生相对距离较远的传输。 -\[ -\begin{array}{ll} -\underset{T \in \mathbb{R}_{+}^{M \mathrm{XN}}}{\operatorname{minimize}} -& \sum_{i, j} T_{i j} D_{i j}-\lambda_{1} I(T)+\lambda_{2} K L(T \| -P) \\ -\text { subject to } & \sum_{i=1}^{M} T_{i j}=\beta_{j}^{\prime} -\quad 1 \leq j \leq N^{\prime} \\ -& \sum_{j=1}^{N} T_{i j}=\alpha_{i}^{\prime} \quad 1 \leq i \leq -M^{\prime} -\end{array} \\ -\] \[ -I(T)=\sum_{i=1}^{M^{\prime}} \sum_{j=1}^{N^{\prime}} \frac{T_{i -j}}{\left(\frac{i}{M^{\prime}}-\frac{j}{N^{\prime}}\right)^{2}+1} \\ -\] \[ -P_{i j}=\frac{1}{\sigma \sqrt{2 \pi}} e^{-\frac{l^{2}(i, j)}{2 -\sigma^{2}}} \\ -\] \[ -l(i, j)=\frac{\left|i / M^{\prime}-j / N^{\prime}\right|}{\sqrt{1 / -M^{\prime 2}+1 / N^{\prime 2}}} \\ -\] - -通过上述方法就能得到针对两个句子AMR表示的OWMD距离,完成无监督的文本相似度计算。也可以充分利用AMR -Tree来完成监督学习。 - -注意到在AMR树中,不同层的节点其实代表了整句不同粒度的语义切分,例如第0层是整句,第一层是短句"Jerry -little",第二层是单一的概念"Jerry",作者选取前三层,将每一层不同粒度的语义单元之间输入context -layer,同一语义单元内的token -embedding相加作为单一embedding,并假设每一层的子节点最多k个,不足的padding。 -

    -

    推荐

    -

    相关工作

    -

    A -User-Centered Concept Mining System for Query and Document Understanding -at Tencent(KDD 2019)

    -

    Scalable -Creation of a Web-scale Ontology(SIGMOD 2020)

    -

    阅读理解

    -

    Learning -to Generate Questions by Learning What not to Generate(WWW 2019)

    -

    Asking -Questions the Human Way: Scalable Question-Answer Generation from Text -Corpus(WWW 2020)

    ]]>
    + + 自然语言处理 + - gnn - math - graph + graph neural network + deep learning + summarization + natural language processing
    - Interview Summary for NLP - /2019/08/09/interview201906/ - 总结一下六月份的面试经验

    + Note for Heterogeneous Information Network + /2019/10/30/heterogeneous/ + 记录近年来对于异构信息网络的一些处理 - PathSim - HGNN - HGAN - HGAN +for text classification - 带属性,Attributed Multiplex Heterogeneous +Network - Meta-graph Guided Random Walks - TBD

    -

    投简历

    +

    PathSim: +Meta Path-Based Top-K Similarity Search in Heterogeneous Information +Networks

      -
    • 在六月初投的暑期实习岗位,自然语言处理实习生。其实这个时间点很不好,处于暑期和春招之间青黄不接的时候,当我拿到offer快六月下旬的时候一大批hc就放出来了,而我当时主要在学校论坛上找内推或者直招,这种一般看当时公司的需求,我投了20份,大部分都是三四月份时发的帖,到六月份可能又缺一个名额才被顶上来,这种情况很难被捞到简历。
    • -
    • 最后是四家给了面试机会,京东广告、新浪微博、滴滴AI -LAB、头条搜索。头条因为通知的太晚就没去了,而且当时完全是去裸面,没有任何准备,想想自己这么菜还是算了。
    • -
    • 平时刷题还是很重要(虽然我依然很懒不想刷),当时我一直忙着论文,忙完休息了个周末就直接投了,结果快的第二天就叫我去面试,实在是尴尬。
    • -
    • 面试一般都是两轮,大概一到两个小时。
    • +
    • 较早的一篇论文(作者都是大神),定义清楚了meta +path中的很多概念,提出了衡量异构信息网络中节点相似度的一种方法。
    • +
    • 传统的相似度衡量方法存在偏差,基于路径数统计和随机游走的方法存在偏差,偏向度数较多的节点;pair-wise的随机游走偏向具有较多离群点邻居的节点
    • +
    • PathSim的想法是,两个相似的节点不仅仅应该相互强链接,还需要share +comparable visibility
    • +
    • 在给定对称的meta path \(P\)下,两个同类型节点\(x,y\)的PathSim定义为: \[ +s(x, y)=\frac{2 \times\left|\left\{p_{x \leadsto y}: p_{x \sim y} \in +\mathcal{P}\right\}\right|}{\left|\left\{p_{x \leadsto x}: p_{x +\hookrightarrow x} \in \mathcal{P}\right\}\right|+\left|\left\{p_{y +\leadsto y}: p_{y \leadsto y} \in \mathcal{P}\right\}\right|} +\]
    • +
    • 实际分母的节点回归概率就是visibility,作者在传统的pathcount上除以visibility,所有的路径都由edge +weight累乘得到。
    • +
    • 类似于对节点的度做了对称归一化。
    • +
    +

    Heterogeneous Graph Neural +Network

    +
      +
    • 任务:图表示学习
    • +
    • 异构类型:节点异构、边异构、节点多属性
    • +
    • 解决办法: +
        +
      • 四步走:异构邻居采样、多属性编码、同类型邻居聚合、不同类型聚合
      • +
      • 异构邻居采样:基于重启的随机游走,先随机游走,且有一定概率p返回初始节点(重启),直到采样了一定数量的邻域节点。每种类型的邻域节点有上限值以确保所有类型的邻居都能采样到。再等比例缩小,对每个邻域节点类型\(t\),只取\(K_t\)个邻域节点,分好组。
      • +
      • 多属性编码:根据多模态内容,预先编好码,例如文本用paragraph2vec,图像用CNN,同一邻域节点的不同属性信息用BiLSTM编码
      • +
      • 同类型邻居聚合:用BiLSTM聚合同类型下多个邻域节点的特征
      • +
      • 不同类型聚合:再用一个注意力机制聚合不同类型的特征
      • +
    • +
    +

    Heterogeneous Graph +Attention Network

    +
      +
    • 任务:图表示学习
    • +
    • 异构类型:节点异构
    • +
    • 解决办法: +
        +
      • 实现node-level和metapath-level的双层注意力。
      • +
      • 需要在所有的metapath neighbour里加上自身,类似于GCN里的内环。
      • +
      • node-level注意力,对一条metapath上的不同节点进行注意力加权。因为不同类型的节点特征表示空间不同,因此针对每一种类型对应一个特征转换矩阵,将不同类型节点映射到同一空间,之后通过自注意力机制对节点进行注意力的计算和加权(其中\(\phi\)代表metapath): \[ +h_i^{\prime} = M_{\phi _i} \cdot h_i \\ +e^{\phi}_{ij} = attn_{node}(h^{\prime}_i,h^{\prime}_j;\phi) \\ +\] +在计算attention需要做mask,只对邻域节点计算attention并做softmax。值得注意的是这里的自注意力的非对称性对异构图来说很重要,因为在一个节点对里,两个节点的邻域不同,相互的影响不是等量的。简单来说,对某一个节点,计算其在某一类metapath下所有邻域节点的注意力权重,输入是两个节点的h以及metapath +specific的一个参数向量,输出注意力权重,然后对某一节点,加权求和其某一类metapath下所有邻域节点的h,得到该节点的某一metapath的表示。 +\[ +\alpha_{i j}^{\Phi}=\operatorname{softmax}_{j}\left(e_{i +j}^{\Phi}\right)=\frac{\exp +\left(\sigma\left(\mathbf{a}_{\Phi}^{\mathrm{T}} +\cdot\left[\mathbf{h}_{i}^{\prime} \| +\mathbf{h}_{j}^{\prime}\right]\right)\right)}{\sum_{k \in +\mathcal{N}_{i}^{\mathrm{\Phi}}} \exp +\left(\sigma\left(\mathbf{a}_{\Phi}^{\mathrm{T}} +\cdot\left[\mathbf{h}_{i}^{\prime} \| +\mathbf{h}_{k}^{\prime}\right]\right)\right)} \\ +\] 计算出注意力之后对变换后的metapath邻域节点特征加权: \[ +\mathbf{z}_{i}^{\Phi}=\sigma\left(\sum_{j \in \mathcal{N}_{i}^{\Phi}} +\alpha_{i j}^{\Phi} \cdot \mathbf{h}_{j}^{\prime}\right) +\]
      • +
      • 在实际加权的时候作者参考了multi-head的做法,计算了k个attention加权特征并拼接起来
      • +
      • metapath-level的attention即对某一节点所有不同类的metapath +embedding进行加权。先将每一条metapath的embedding变换到同一隐空间,然后参数化计算出注意力权重并softmax。需要注意的是softmax之前的attention +logit是在所有节点上计算某一类型metapath的平均,分母是节点数,分子是包含该类型metapath的节点的metapath +embedding累加,而之前的node-level是针对某一节点某一metapath下所有的邻域节点平均: +\[ +w_{\Phi_{i}}=\frac{1}{|\mathcal{V}|} \sum_{i \in \mathcal{V}} +\mathbf{q}^{\mathrm{T}} \cdot \tanh \left(\mathbf{W} \cdot +\mathbf{z}_{i}^{\Phi}+\mathbf{b}\right) +\]
      • +
      • 之后再在所有metapath类型上做softmax,得到权重,加权每个节点不同metapath +embedding得到最终embedding
      • +
      • 整个双层attention的logit以及softmax的范围有点绕,时而局部时而全局,需要仔细考虑清楚。
      • +
    • +
    • 可以看到整个过程是可以在节点层次并行化计算的
    • +
    • 从结果来看效果达到了SOTA,而且可视化的结果可以看到节点embedding的聚类效果更好,attention也带来了一定可解释性。
    -

    京东广告

    +

    Heterogeneous +Graph Attention Networks for Semi-supervised Short Text +Classification

      -
    • 一面着重问了简历上的内容,包括我做的几项评测和论文,讨论论文的动机、解决方法,对面也用类似的方法在做文本生成,就问了文本生成该如何评估质量、decoder训练如何保证不看到未来的信息,深度学习中常见的训练trick。
    • -
    • 抽取式文摘怎么构造特征,怎么抽取。
    • -
    • 讲述seq2seq的原理,分词的做法。讲述attention的作用及其变种。
    • -
    • 二面就让手写中序遍历的递归和非递归版本。
    • +
    • 任务:节点分类
    • +
    • 异构类型:节点异构,包含三类节点,文本、实体、主题
    • +
    • 解决办法: +
        +
      • 最朴素:扩充节点的特征空间,将三类节点的特征向量拼接起来,对于具体的某一节点,其不包含的特征向量位置全设为0
      • +
      • 异构图卷积:将相同节点类型的子图分离,每个子图单独做卷积,不同的子图通过参数变换矩阵投影到相同隐空间并相加激活作为下一层,具体而言,原始GCN为: +\[ +H^{(l+1)}=\sigma\left(\tilde{A} \cdot H^{(l)} \cdot W^{(l)}\right) +\] 而异构GCN为: \[ +H^{(l+1)}=\sigma\left(\sum_{\tau \in \mathcal{T}} \tilde{A}_{\tau} \cdot +H_{\tau}^{(l)} \cdot W_{\tau}^{(l)}\right) +\] 其中\(\tilde{A}_{\tau}\)的行是所有节点,列是某一类型的所有节点,这样就抽离出了同构的连接子图,即对于每个节点,我们分别考虑他的邻域里类型a的节点,做信息聚合得到编码a,再考虑邻域里类型b的节点,做信息聚合得到编码b,编码a和b通过各自的变换矩阵变换到同一隐空间再相加。这样的设计是符合逻辑的。
      • +
      • 作者还考虑了以下情况:对于某一节点,不同类型的邻域节点的贡献不一样,同一类型下不同的邻域节点贡献也不一样。显然这里需要注意力。作者就提出了对偶注意力(即双层注意力),一层是type +level的,一层是node level的,先用某一类型邻域节点embedding的均值作为type +embedding,然后根据当前节点embedding与type embedding 计算出type +attention +weight,同理用具体的邻域节点embedding和当前节点embedding再加上type +attention得到node attention,利用计算出的node +attention替换GCN里的对称归一化邻接矩阵。
      • +
    -

    新浪微博

    +

    Representation +Learning for Attributed Multiplex Heterogeneous Network

      -
    • 只有leader一个人问,同样先问了简历上的内容
    • -
    • 手写最基础的attention和self attention过程,画一下bert的大致结构
    • -
    • 手写decoder生成每一个字的过程
    • -
    • 因为这边业务比较依赖bert,问了比较多bert的内容,例如如何用bert做文本分类,如何根据业务需求修改bert
    • -
    • 手写算法,链表判断环
    • +
    • 任务:图表示学习
    • +
    • 异构类型:节点异构、边异构、节点多属性
    • +
    • 解决办法: +
        +
      • 考虑某一节点在不同类型边连接下有不同的embedding,将节点总的overall +embedding拆成与边无关的base embedding和与边相关的edge embedding
      • +
      • edge +embedding与边类型相关,通过相同类型的边相连的邻域节点aggregate得到,这里的aggreagator +function可以采用GraphSage里的做法。
      • +
      • 经过k层聚合之后,对于每个节点都得到了k种边类型的edge +embedding,通过self attention将这些edge +embedding加权求和,乘上比例再加上base embedding就得到了最终的overall +embedding
      • +
      • 以上是直推式(transductive)模型,对于未观测数据,需要归纳式(inductive)的方法。具体做法很简单,将base +embedding和edge +embedding参数化为节点attribute的函数,而不是随机初始化之后完全根据已有的图学习。这样即便有图中没看见的节点,只要节点有属性,一样可以进行overall +embedding的提取
      • +
      • 最后做基于meta-path的random walk得到训练对,使用skip +gram训练,加入了负采样。
      • +
    -

    滴滴AILAB

    +

    Semi-supervised +Learning over Heterogeneous Information Networks by Ensemble of +Meta-graph Guided Random Walks

      -
    • 滴滴是问的最详细最久的一个,也是两个人面,一面理论一面工程
    • -
    • 不知道是不是因为有做AI研究的需求,一面面试官把我的论文问的很详细,包括DPPs的计算过程,如何整合进seq2seq,为什么会出现OTR现象,这个现象有没有可能不是论文里分析的原因那样,而是由于encoder的过拟合导致的等等,感觉就像在做论文的rebut
    • -
    • 同样也问了seq2seq和attention的原理
    • -
    • 简单说明一下LDA的原理,如何用LDA做聚类,如何衡量LDA聚类的质量
    • -
    • 问了评测中三个任务:content linking, facet classification, -extractive summarization具体是怎么做的
    • -
    • 写出一个简单DNN的前向后向过程
    • -
    • 问了git、awk、sed的一些操作
    • -
    • 算法手写归并排序
    • +
    • 任务:节点分类
    • +
    • 异构类型:节点异构,包含三类节点,文本、实体、主题
    • +
    • 解决办法:meta-path guided random walk
    +

    Joint +Embedding of Meta-Path and Meta-Graph for Heterogeneous Information +Networks

    ]]>
    - 面试 + 自然语言处理 + graph neural network + deep learning natural language processing - machine learning - interview + heterogeneous information network
    - K-Means and KNN - /2017/03/16/kmeans/ - -
  • 以简单的Iris数据集做测试,实现了K-means++聚类算法,并与sklearn中自带的KNN算法进行比较
  • -
  • 标题本来是K-Means&KNN,把&改成了和,因为标题中出现特殊符号&会导致我的sitemap生成错误...... -***
  • - + Note for Hierarchical Latent Dirichlet Allocation + /2019/11/15/hlda/ + 记录 Hierarchical Latent Dirichlet +Allocation,层次主题模型的学习笔记。 +依然大量参考了徐亦达老师的教程。

    -
    -i0onl8.jpg - -
    -

    简介

    +

    hLDA改进了什么

    +
      +
    • 改进了两点

      +
        +
      • 引入了Dirichlet Process

      • +
      • 引入了层次结构

      • +
    • +
    +

    DP

    +
      +
    • Dirichlet Process将Dirichlet +Distribution的概念扩展到随机过程,一般依概率采样会得到一个样本,一个值,而依据随机过程采样得到的是一个函数,是一个分布。给定DP的超参\(\alpha\),给定度量空间\(\theta\),以及该度量空间上的一个测度\(H\)(称为基分布, Base Distribution),\(DP(\alpha,H)\)中采样得到的就是一个在\(\theta\)上的无限维离散分布\(G\),假如对这个无限维(无限个离散点)做\(\theta\)上的任意一种划分\(A_1,...,A_n\),那么划分之后的\(G\)分布依然满足对应Dirichlet +Distribution在超参上的划分: \[ +(G(A_1,...,A_n)) \sim Dir(\alpha H(A_1),...,\alpha H(A_n)) +\] \(G\)定义为Dirichlet +Process的一个sample path/function/realization,即\(G=DP(t,w_0) \sim \ +DP(\alpha,H)\)。Dirichelt +Process的一个realization是一个概率测度,是一个函数,定义域在度量空间\(\theta\)上,函数输出即概率。注意因为是无限维,因此不能预先设置\(\alpha\)的维数,只能设置为一样的\(\alpha\),对比LDA,可以看到DP的超参\(\alpha\)是一个concentration +parameter,只能控制G分布趋于均匀分布的确定性,而不能控制G分布趋于怎样的分布,趋于怎样的分布由划分\(A\)决定。

    • +
    • 这里可以看到和LDA使用Dir +Distribution的区别:DP是直接采样生成了一个概率测度,可以进而生成离散的概率分布;而LDA中对Dir +Distribution采样只能得到一个样本,但是这个样本作为了多项式分布的参数,确定了一个多项式分布(也是离散的)。

    • +
    • DP可以用于描述混合模型,在混合组件数量不确定的情况下,通过DP来构造一个组件分配。放在GMM的场景里,假如有n个样本,但我不知道有几个GM来生成这n个样本,那么对样本i,我将其分配给某一个GM,称这个样本i所在GM的参数为\(\theta _i\),那么这个\(\theta\)服从一个基分布\(H(\theta)\),假如\(H\)是连续分布,那么两个样本取到相同的\(\theta\)的概率趋于零,相当于n个样本对应n个GM,那么我们可以把这个\(H\)离散化为G,离散的方式为\(G \sim DP(\alpha,H)\)\(\alpha\)越小越离散,越大则\(G\)越趋近于\(H\)。注意\(H\)也可以是离散的。

    • +
    • DP的两个参数,\(H\)\(\alpha\),前者决定了\(G\)的每一个离散点的位置,即\(\theta +_i\)具体的值;后者决定了离散程度,或者理解为\(\theta\)有多分散,有多不重复,即概率分布是集中的还是分散的,这个Dirichlet +Distribution里的\(\alpha\)是一致的。

    • +
    • 由于G满足Dirichlet +Distribution,因此有很多好的性质,包括对于多项式分布的conjugate,collapsing和splitting,以及renormalization。

      +
        +
      • \(E[G(A_i)]=H(A_i)\)

      • +
      • \(Var[G(A_i)]=\frac +{H(A_i)[1-H(A_i)]}{\alpha + 1}\)

      • +
      • 可以看到\(\alpha\)取极端时,方差分别退化为0或者伯努利分布的方差,对应着之前我们说的G去离散化H的两种极端情况。

      • +
    • +
    • 那么我们想用DP做什么,做一个生成式模型:我们想得到一个概率测度\(G \sim \ DP(H,\alpha)\),根据\(G\)得到每一个样本点i所属的组对应的参数(Group +Parameter)\(x_i \sim +\ G\),之后根据这个参数和函数\(F\)生成样本点i:\(p_i \sim \ F(x_i)\)

    • +
    • 接下来可以用中国餐馆过程(CRP)、折棒过程(Stick Breaking)和Polya +Urm模型来细化这个\(x_i\),即将和样本点i对应组的参数拆成样本点i对应的组和每组的参数,写成\(x_i=\phi _{g_i}\),其中\(g\)是样本点的组分配,\(\phi\)是组参数。

    • +
    • 接下来套用echen大佬的描述来描述三个模型如何细化\(x_i\)的:

    • +
    • In the Chinese Restaurant Process:

      +
        +
      • We generate table assignments \(g_1, +\ldots, g_n \sim CRP(\alpha)\) according to a Chinese Restaurant +Process. (\(g_i\) is the table assigned +to datapoint \(i\).)

      • +
      • We generate table parameters \(\phi_1, +\ldots, \phi_m \sim G_0\) according to the base distribution +\(G_0\), where \(\phi_k\) is the parameter for the kth +distinct group.

      • +
      • Given table assignments and table parameters, we generate each +datapoint \(p_i \sim F(\phi_{g_i})\) +from a distribution \(F\) with the +specified table parameters. (For example, \(F\) could be a Gaussian, and \(\phi_i\) could be a parameter vector +specifying the mean and standard deviation).

      • +
    • +
    • In the Polya Urn Model:

      +
        +
      • We generate colors \(\phi_1, \ldots, +\phi_n \sim Polya(G_0, \alpha)\) according to a Polya Urn Model. +(\(\phi_i\) is the color of the ith +ball.)

      • +
      • Given ball colors, we generate each datapoint \(p_i \sim F(\phi_i)\).

      • +
    • +
    • In the Stick-Breaking Process:

      +
        +
      • We generate group probabilities (stick lengths) \(w_1, \ldots, w_{\infty} \sim +Stick(\alpha)\) according to a Stick-Breaking process.

      • +
      • We generate group parameters \(\phi_1, +\ldots, \phi_{\infty} \sim G_0\) from \(G_0\), where \(\phi_k\) is the parameter for the kth +distinct group.

      • +
      • We generate group assignments \(g_1, +\ldots, g_n \sim Multinomial(w_1, \ldots, w_{\infty})\) for each +datapoint.

      • +
      • Given group assignments and group parameters, we generate each +datapoint \(p_i \sim +F(\phi_{g_i})\).

      • +
    • +
    • In the Dirichlet Process:

        -
      • K-Means是简单的基于划分的聚类方法,要解决的问题是,现在有n个样本(点集X),将他们的特征向量投射到高维空间中,根据空间分布可以大致划分成几个子空间,每个子空间中的点属于同一类,现在需要计算出每个点所在的类,大致思想就是随机选择k个点(中心点集C)作为中心点,其余的点自己站队:离k个中心点里哪个点最近就站那个点的队,即和那个中心点划分到同一类中,这样就能形成k个类,重复上过程,期间引入一个损失评估,比如以各个类中的点到这个类中心点距离的和作为评估指标,当指标小于某一程度或者指标变化小于某一程度就停止重复
      • -
      • KNN则比较简单粗暴,其思想类似于民主投票。KNN不训练数据,选定一个值K,对于每一个需要预测的向量,在已知类别的数据集中找到与这个向量最近的K,这K个点中拥有最多点个数的类别就是预测类别,即让离某个点最近的K个点投票决定这个点的类别,哪个类别的点票数多就是哪个类别
      • +
      • We generate a distribution \(G \sim +DP(G_0, \alpha)\) from a Dirichlet Process with base distribution +\(G_0\) and dispersion parameter \(\alpha\).

      • +
      • We generate group-level parameters \(x_i \sim G\) from \(G\), where \(x_i\) is the group parameter for the ith +datapoint. (Note: this is not the same as \(\phi_i\). \(x_i\) is the parameter associated to the +group that the ith datapoint belongs to, whereas \(\phi_k\) is the parameter of the kth +distinct group.)

      • +
      • Given group-level parameters \(x_i\), we generate each datapoint \(p_i \sim F(x_i)\).

      • +
    -

    K-means++

    +

    折棒过程

      -
    • k-means++在k-means上优化了初始k个点的选择。原始算法是随机取k个点,显然这样随机不确定性太大,比较好的k个点的选择方案应该是他们离彼此尽量远,但不能太远。尽量远,就能尽可能贴近最终理想中心点分布;不能太远,是为了防止将一些错误点孤立点作为中心点
    • -
    • 算法上的实现是先随机从X集中取第一个中心点,之后反复以下过程取中心点 +
    • 折棒过程提供了一种在\(\theta\)上的无限划分,依然令DP的参数为\(\alpha\),折棒过程如下:

        -
      • 计算每个点\(c_i\)到已经选出的中心点\(k_1,k_2...\)的距离,选取最小的一个距离作为\(c_i\)的距离,这个距离的意义即\(c_i\)作为下一个中心点时离其他中心点至少有多远
      • -
      • \(c_1,c_2,c_3......\)的距离归一化,并排成一条线
      • -
      • 这条线长度为1,分成了许多段,每一段的长度就代表了这一段所代表的点的距离在归一化中所占的比例,距离越大,比例越大
      • -
      • 在(0,1)之间随机取一个数,这个数所在的段区间所代表的点就是下一个中心点,将其加入中心点集C,接着重复找下一个中心点
      • +
      • \(\beta _1 \sim +Beta(1,\alpha)\)

      • +
      • \(A_1 = \beta _1\)

      • +
      • \(\beta _2 \sim +Beta(1,\alpha)\)

      • +
      • \(A_2 = (1-\pi _1) * \beta +_2\)

    • -
    • 可以看出,如果距离够远,在线上被随机抽到的可能越大,符合我们的需求
    • +
    • 这样每次从Beta分布中得到[0,1]上的一个划分,将整个\(\theta\)切成两部分,第一部分作为\(\theta\)上的第一个划分,剩下的部分看成下一次折棒的整体,接着从上面切两部分,第一部分作为\(\theta\)上的第二个划分,像一个棒不断被折断,每次从剩下的部分里折,最后折成的分段就是划分。

    -

    K-Means代码实现

    -

    数据检视

    +

    DP2CRP

      -
    • Iris是鸢尾花分类数据集,150个样本,均匀分成3类,每一个样本有4个属性 -
    • +
    • 引入一个示性函数,假如两个样本点i,j他们被分配的组件相同,则他们的示性函数\(z\)相同,也就是表征每一个样本属于哪一个组件,\(x_i \sim Component(\theta +_{z_i})\)

    • +
    • 那么对于混合分布,比如GMM,我们希望得到的是predictive +distribution,即已知数据的组件分配情况下,新来了一个未知数据,我想知道他属于哪个组件: +\[ +p(z_i=m|z_{not \ i}) +\]

    • +
    • 结合定义可以知道这个概率应该是和\(H\)无关的,因为我不在乎\(\theta\)具体的值,我只在乎是哪一个\(\theta\),所以predictive +distribution与\(\alpha\)密切相关。将其展开: \[ +p(z_i=m|z_{not \ i}) = \frac {p(z_i=m,z_{not \ i})}{p(z_{not \ i})} \\ +\]

    • +
    • 由于在DP里是划分的类别数可以到无穷多个,因此这里采用了一个小技巧,我们先假设有k类,之后在把k趋于无穷 +\[ += \frac {\int _{p_1...p_k} p(z_i=m, z_{not \ +i}|p_1...p_k)p(p_1...p_k)}{\int _{p_1...p_k} p(z_{not \ +i}|p_1...p_k)p(p_1...p_k)} +\]

    • +
    • 这里的k个类的概率是符合Dirichlet Distribution的,假设这里的Base +Distribution是均匀分布,则 \[ += \frac {\int _{p_1...p_k} p(z_i=m, z_{not \ i}|p_1...p_k)Dir(\frac +{\alpha}{k} ... \frac {\alpha}{k})}{\int _{p_1...p_k} p(z_{not \ +i}|p_1...p_k)Dir(\frac {\alpha}{k} ... \frac{\alpha}{k})} +\]

    • +
    • 上面无论分子分母,积分内其实都是一个多项式分布乘以一个Dirichlet分布,根据共轭我们知道后验应该还是一个Dirichlet分布,我们推导一下多项式分布与Dirichlet分布相乘的积分: +\[ +\int _{p_1...p_k} p(n_1...n_k|p_1...p_k) p(p_1...p_k|\alpha _1 ... +\alpha _k) \\ +\] \[ += \int _{p_1...p_k} Mul(n_1...n_k|p_1...p_k) Dir(p_1...p_k|\alpha _1 ... +\alpha _k) \\ +\] \[ += \int _{p_1...p_k} (\frac {n!}{n_1!...n_k!} \prod _{i=1}^k p_i ^{n_i}) +\frac {\Gamma(\sum \alpha _i)}{\prod \Gamma (\alpha _i)} \prod _{i=1}^k +p_i^{\alpha _i -1} \\ +\] \[ += \frac {n!}{n_1!...n_k!} \frac {\Gamma(\sum \alpha _i)}{\prod \Gamma +(\alpha _i)} \int _{p_1...p_k} \prod _{i=1}^k p_i^{n_i+\alpha _i -1} \\ +\]

    • +
    • 其中积分式内实际上是一个Dirichelt Distribution\(Dir(\alpha _1 + n_1 ... \alpha _k + +n_k)\)排除了常数部分,因此积分的结果就是1/常数,即: \[ += \frac {n!}{n_1!...n_k!} \frac {\Gamma(\sum \alpha _i)}{\prod \Gamma +(\alpha _i)} \frac { \prod \Gamma (\alpha _i + n_i)}{\Gamma (n + \sum +\alpha _i)} +\]

    • +
    • 上式包括了三个部分,第一部分的一堆n,它是由多项式分布引入的,代表我们只看划分后每个集合的大小,而不看划分之后每个集合具体的内容,这和我们的需求是不一样的,因此不需要这个常数;第二个部分,是由Dir分布先验产生的,而在predictive +distribution中,分布先验都相同,因此抵消了,所以我们主要关注第三部分,回代入predictive +distribution那个分式当中。

    • +
    • 首先定义一个辅助变量\(n_{l , not \ i} = +Count(z_{not \ i} == l)\),那么: \[ +n_1 = n_{1,not \ i} \\ +\] \[ +... \\ +\] \[ +n_k = n_{k,not \ i} \\ +\]

    • +
    • 因为我们是是在求\(p(z_i=m, z_{not \ +i})\),那么肯定除了第m类,其余类的数量早已由除了第i个样本以外的样本确定,那么第m类呢? +\[ +n_m = n_{m,not \ i} + 1 +\]

    • +
    • 这样我们就完成了从指示函数表示的概率到多项式分布的转换,分子部分代入之前得到的第三部分有: +\[ +\frac {\Gamma(n_{m,not \ i} + \frac {\alpha}{k} + 1) \prod _{l=1,l \neq +m}^k Gamma(n_{l,not \ i})}{\Gamma (\alpha + n)} +\]

    • +
    • 同理计算分子,分子不用考虑第i个样本分给第m类,因此不用在累乘里单独拎出来第m项,形式要简单一些: +\[ +\frac {\prod _{l=1}^k \Gamma(n_{l,not \ i})}{\Gamma(\alpha +n -1)} +\]

    • +
    • 将上面两式相除,再利用Gamma函数\(\Gamma(x) = (x-1) \Gamma +(x-1)\)的性质简化,得到: \[ += \frac {n_{m,not \ i} + \frac {\alpha}{k}}{n + \alpha - 1} +\]

    • +
    • 再令k趋于无穷,得到: \[ += \frac {n_{m,not \ i}}{n + \alpha - 1} +\]

    • +
    • 但是上面这个式子对所有的类别从1到m求和并不为1,而是\(\frac {n-1}{n + \alpha +-1}\),剩下一部分概率就设为取一个新类别的概率,这样我们的predictive +distribution就算完成了,而且可以发现,这个概率,实际上就对应着中国餐馆过程。

    -

    初始化数据

    +

    CRP

      -
    • 初始化数据
      def init():
      iris = load_iris()
      X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=33)
      ss = StandardScaler()
      X_train = ss.fit_transform(X_train)
      X_test = ss.fit_transform(X_test)
      return X_train, X_test, y_train, y_test, iris

    • +
    • 中国餐馆过程的经典描述就是把n个人,一个一个人来,分到不确定张数目的桌子上,做一个整数集合上的划分。假设集合每个元素是一位顾客,第n位顾客走进了一家参观,则他按照以下概率去选择某一张已经有人的桌子坐下,或者找一张没人的新桌子坐下: +\[ +\begin{aligned} p(\text { occupied table } i | \text { previous +customers }) &=\frac{n_{i}}{\alpha +n-1} \\ p(\text { next +unoccupied table } | \text { previous customers }) &=\frac{\alpha +}{\alpha +n-1} \end{aligned} +\]

    • +
    • 其中\(n_i\)是第i张桌子上已经有的人数,$$是超参数。这样人到桌子的分配就对应了整数集合上的划分。

    • +
    • 分析一下,若是选择已经有人的桌子,则顾客倾向于选择人多的桌子;若是在有人的桌子与新桌子之间纠结,则依赖于超参$$

    • +
    • 那根据之前的推导,这个\(\alpha\)其实就是Dirichlet +Distribution的超参数,且效果完全吻合。由于在CRP中我们base +distribution选的是均匀分布,那对应的Dirichlet +Distribution选择对称超参,各个\(alpha +_i\)相同。那么\(\alpha\)越大,以Dirichlet +Distritbuion为参数先验的多项式分布里,取得各个项等概率的可能就越大,在中国餐馆过程中对应着每个顾客进来都想选择一张新桌子,因此每个桌子都只有一个人,等量分配;反之\(\alpha\)越小则越不确定,在中国餐馆过程中桌子的分配也不确定

    • +
    • 可以得到第m个人选择之后,桌子数量的期望是\(E(K_m|\alpha ) = O(\alpha \log +m)\),具体而言是\(E(K_m|\alpha ) = +\alpha (\Psi (\alpha + n) - \Psi (\alpha )) \approx \alpha \log (1 + +\frac{n}{\alpha })\), +也就是聚类数的增加与样本数的对数成线性关系。我们可以根据数据量和想要聚类的数量来反估计超参\(\alpha\)的设置。

    -

    k-means++初始化k个点

    +

    nCRP

      -
    • D2是每个点的距离(即之前定义的里其他中心点至少有多远)
    • -
    • probs归一化
    • -
    • cumprobs将归一化的概率累加,排列成一条线
      def initk(X_train, k):
      C = [X_train[0]]
      for i in range(1, k):
      D2 = scipy.array([min([scipy.inner(c - x, c - x) for c in C]) for x in X_train])
      probs = D2 / D2.sum()
      cumprobs = probs.cumsum()
      r = scipy.rand()
      for j, p in enumerate(cumprobs):
      if r < p:
      i = j
      break
      C.append(X_train[i])
      return C

    • +
    • 以上仅仅完成了一个利用了DP的不确定数目聚类,我们可以认为餐馆里每个桌子是一个主题,人就是单词,主题模型就是把词分配到主题,把人分配到桌子,但是这样的话和LDA一样,主题之间没有关联。为了建立主题之间的层次关系,Blei提出了嵌套餐馆过程。

    • +
    • 在嵌套餐馆过程中,我们统一了餐馆和桌子的概念,餐馆就是桌子,桌子就是餐馆!为什么这么说?首先我们设置一个餐馆作为root餐馆(显然我们要建立一棵树了),然后根据中国餐馆过程选择root餐馆里的一个桌子,餐馆里的每个桌子上都有一张纸条指示顾客第二天去某一个餐馆,因此第二天顾客来到这个餐馆,接着根据CRP选个桌子,同时知晓了自己第三天该去哪个参观。因此桌子对应着餐馆,父节点餐馆的桌子对应着子节点餐馆,每一天就是树的每一层,这样就建立了一个层次结构的中国餐馆过程。

    -

    损失评估

    +

    hLDA

      -
    • 在这里用每个类内点到中心点距离平方和的总和作为损失评估 -
      def evaluate(C, X_train, y_predict):
      sum = 0
      for i in range(len(X_train)):
      c = C[y_predict[i]]
      sum += scipy.inner(c - X_train[i], c - X_train[i])
      return sum
    • +
    • 接下来我们可以在nCRP的框架上描述hLDA

    • +
    • 定义符号

      +
        +
      • \(z\):主题,假设有\(K\)

      • +
      • \(\beta\):主题到词分布的参数,Dir先验参数

      • +
      • \(w\):词

      • +
      • \(\theta\):文档到主题的分布

      • +
      • \(\alpha\):文档到主题分布的参数,Dir先验参数

      • +
    • +
    • 那么可以简单定义LDA: \[ +p(w | \beta) \sim Dir(\beta) \\ +p(\theta | \alpha) \sim Dir(\alpha) \\ +\theta \sim p(\theta | \alpha) \\ +w \sim p(w | \theta , \beta) = \sum _{i=1}^K \theta _i p(w|z=i, \beta +_i) \\ +\]

    • +
    • hLDA流程如下:

      +
        +
      • 根据nCRP获得一条从root到leaf的长为\(L\)的路径

      • +
      • 根据一个\(L\)维的Dirichlet采样一个在路径上的主题分布

      • +
      • 根据这L个主题混合生成一个词

      • +
    • +
    • 详细描述如下:

    • +
    • 概率图如下,其中\(c\)是餐馆,这里把nCRP单独拎出来了,实际上\(c\)决定了主题\(z\),另外\(\gamma\)是nCRP中CRP对应DP的concentration +paramter:

    -

    聚类

    +

    Gibbs Sampling in hLDA

      -
    • 初始化k个中心点后,所有的点就可以分类
    • -
    • 重新在每个类中取中心点,在这里取一个类中所有点坐标平均作为中心点坐标 -
      def cluster(C, X_train, y_predict, k):
      sum = [0, 0, 0, 0] * k
      count = [0] * k
      newC = []
      for i in range(len(X_train)):
      min = 32768
      minj = -1
      for j in range(k):
      if scipy.inner(C[j] - X_train[i], C[j] - X_train[i]) < min:
      min = scipy.inner(C[j] - X_train[i], C[j] - X_train[i])
      minj = j
      y_predict[i] = (minj + 1) % k
      for i in range(len(X_train)):
      sum[y_predict[i]] += X_train[i]
      count[y_predict[i]] += 1
      for i in range(k):
      newC.append(sum[i] / count[i])
      return y_predict, newC
    • +
    • 定义变量:

      +
        +
      • \(w_{m,n}\):第m篇文档里的第n个词

      • +
      • \(c_{m,l}\):第m篇文档里路径上第l层选择的主题对应的餐馆,需要采样计算

      • +
      • \(z_{m,n}\):第m篇文档里第n个词分配的主题,需要采样计算

      • +
    • +
    • 从后验分布中采样的公式分为两部分,第一部分是得到路径,这一部分就会利用到之前的predictive +distribution;第二部分是已知路径,剩下的部分就是普通的LDA,最终采样公式为: +\[ +p\left(\mathbf{w}_{m} | \mathbf{c}, \mathbf{w}_{-m}, +\mathbf{z}\right)=\prod_{\ell=1}^{L}\left(\frac{\Gamma\left(n_{c_{m, +\ell},-m}^{(\cdot)}+W \eta\right)}{\prod_{w} \Gamma\left(n_{c_{m, +e},-m}^{(w)}+\eta\right)} \frac{\prod_{w} \Gamma\left(n_{c_{m, +\ell},-m}^{(w)}+n_{c_{m, \ell}, +m}^{(w)}+\eta\right)}{\Gamma\left(n_{c_{m, \ell},-m}^{(\cdot)}+n_{c_{m, +\ell}, m}^{(\cdot)}+W \eta\right)}\right) +\]

    -

    主函数

    +]]>
    + + 机器学习 + + + math + topic model + lda + +
    + + Incremental Decoding + /2020/03/17/incremental-decoding/ + 记录一下Fairseq当中对于CNN +seq2seq,Transformer之类的并行解码模型,在推理阶段的增量解码处理。

    + +

    Fairseq架构

      -
    • 计算损失,更新k个中心点,再站队(聚类)一次
    • -
    • 重复,直到损失变化小于10%
    • -
    • 每次迭代显示新旧损失,显示损失变化
    • -
    • 最后输出分类结果
      def main():
      X_train, X_test, y_train, y_test, iris = init()
      k = 3
      total = len(y_train)
      y_predict = [0] * total
      C = initk(X_train, k)
      oldeval = evaluate(C, X_train, y_predict)
      while (1):
      y_predict, C = cluster(C, X_train, y_predict, k)
      neweval = evaluate(C, X_train, y_predict)
      ratio = (oldeval - neweval) / oldeval * 100
      print(oldeval, " -> ", neweval, "%f %%" % ratio)
      oldeval = neweval
      if ratio < 0.1:
      break

      print(y_train)
      print(y_predict)
      n = 0
      m = 0
      for i in range(len(y_train)):
      m += 1
      if y_train[i] == y_predict[i]:
      n += 1
      print(n / m)
      print(classification_report(y_train, y_predict, target_names=iris.target_names))

    • +
    • 在Facebook推出的seq2seq库Fairseq当中,所有模型继承FairseqEncdoerDecoder类,所有的Encoder继承FairseqEncoder类,所有的Decoder继承FairseqIncrementalDecoder类,而FairseqIncrementalDecoder继承自FairseqDecoder类。
    • +
    • FairseqEncoder类只定义了forward,reorder_encoder_out,max_positions,upgrade_state_dict,最重要的就是forward,即定义编码的前向传播过程。reorder其实在decoder中更重要,但是这里也定义了。
    • +
    • FairseqDecoder类定义了forward,extract_features,output_layer,get_normalized_probs,max_positions,upgrade_state_dict,prepare_for_onnx_export_。forward=extract_features+output_layer,即forward定义了解码出序列的整个前向过程,而extract_features只定义到获得整个decoder的state +sequence。
    • +
    • Incremental +Decoder额外定义了reorder_incremental_state,set_beam_size。reorder是和incremental以及beam +search密切相关的,后文将详细介绍。
    -

    KNN代码

    +

    训练并行,推理增量

      -
    • 直接使用了sklearn中的KNeighborsClassifier
      from sklearn.datasets import load_iris
      from sklearn.preprocessing import StandardScaler
      from sklearn.neighbors import KNeighborsClassifier
      from sklearn.model_selection import train_test_split
      from sklearn.metrics import classification_report


      def init():
      iris = load_iris()
      X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=33)
      ss = StandardScaler()
      X_train = ss.fit_transform(X_train)
      X_test = ss.fit_transform(X_test)
      return X_train, X_test, y_train, y_test, iris


      def KNN(X_train, X_test, y_train, y_test, iris):
      knc = KNeighborsClassifier()
      knc.fit(X_train, y_train)
      y_predict = knc.predict(X_test)
      print(knc.score(X_test, y_test))
      print(classification_report(y_test, y_predict, target_names=iris.target_names))


      def main():
      X_train, X_test, y_train, y_test, iris = init()
      KNN(X_train, X_test, y_train, y_test, iris)

      if __name__ == "__main__":
      main()
    • +
    • 像CNN seq2seq, +Transformer之类的模型打破了RNN模型的顺序性,使得seq2seq架构中的编码器和解码器在训练是都可以并行训练。
    • +
    • 编码器并行训练非常显然,而解码器实际上是一个语言模型,之所以可以并行是因为在训练时采用了teacher +forcing,因此语言模型的每一时间步输入在训练时我们假设是已知的,就可以一整个(Batch,Length,Hidden)的decoder +input输入模型,直接训练。
    • +
    • 但是在测试(推理)阶段,每一时间步的输入由上一时间步的输出决定,无法并行操作,如果反复运行整个decoder,那么就要运行Length次,且第i次只有前i个位置的信息是有用的,剩下部分的计算完全浪费掉了,推理的效率大大降低。
    • +
    • 这个时候就需要incremental +decoding,即在推理阶段,无论是CNN还是Transformer,都想RNN一样一步一步解码,每一步使用之前推理得到的信息,而不是完全从头开始计算。
    -

    预测结果

    +

    CNN

      -
    • 指标说明 -对于二分类,四种情况的总数:对的预测成对的TP;对的预测成错的FN;错的预测成对的FP;错的预测成错的TN -\[ -精确率:P=\frac{TP}{TP+FP} \\ -召回率:R=\frac{TP}{TP+FN} \\ -1F值:\frac {2}{F_1}=\frac1P+\frac1R \\ -\]

    • -
    • K-Means程序输出 预测正确率:88.39% 平均精确率:89% 召回率:0.88 -F1指标:0.88

    • -
    • KNN程序输出 预测正确率:71.05% 平均精确率:86% 召回率:0.71 -F1指标:0.70

    • -
    • 原始分类 可以看到这个数据集本身在空间上就比较方便聚类划分

    • -
    • 预测分类

    • +
    • 对于CNN,可以发现,decoder无论哪一层,第i个位置都只需要该层[i-k,i)位置上内的信息,其中k为一维卷积的窗长。因此,只需要维护一个长度为k的队列,保存各层计算出来的state,就可以复用模型之前推理得到的信息,之后再把当前的state更新到队列中。
    • +
    • 每次计算时只需要对第i个位置进行decoding,即操作(Batch,1,Hidden)的数据Length次。
    • +
    • 在代码里,FConvDecoder将输入x和incremental_state一起传给了LinearizedConvolution,这里的介绍是 +
      """An optimized version of nn.Conv1d.
      At training time, this module uses ConvTBC, which is an optimized version
      of Conv1d. At inference time, it optimizes incremental generation (i.e.,
      one time step at a time) by replacing the convolutions with linear layers.
      Note that the input order changes from training to inference.
      """
    • +
    • 即训练时使用Time-First的形式组织数据进行卷积,充分利用GPU的并行性能,在推断时,将卷积层换成相同效果的线性层,逐帧进行推断 +
      if incremental_state is None:
      output = super().forward(input) # 这里 LinearizedConvolution的父类是ConvTBC,即没有推断时,直接将整个序列送入ConvTBC
      if self.kernel_size[0] > 1 and self.padding[0] > 0:
      # remove future timesteps added by padding
      output = output[:-self.padding[0], :, :]
      return output
    • +
    • 否则,就逐层用线性层推断,并更新input +buffer进而更新incremental_state
      # reshape weight
      weight = self._get_linearized_weight()
      kw = self.kernel_size[0]
      bsz = input.size(0) # input: bsz x len x dim
      if kw > 1:
      input = input.data
      input_buffer = self._get_input_buffer(incremental_state)
      if input_buffer is None:
      input_buffer = input.new(bsz, kw, input.size(2)).zero_()
      self._set_input_buffer(incremental_state, input_buffer)
      else:
      # shift buffer
      input_buffer[:, :-1, :] = input_buffer[:, 1:, :].clone()
      # append next input
      input_buffer[:, -1, :] = input[:, -1, :]
      input = input_buffer
      with torch.no_grad():
      output = F.linear(input.view(bsz, -1), weight, self.bias)
      return output.view(bsz, 1, -1)
    -

    改进

    -

    未知k的情况

    +

    Transformer

      -
    • 以上是我们已知鸢尾花会分成3类,加入我们不知道有几类呢?毕竟k-means是无监督学习,可以在无标签的情况下计算,自然标签的个数我们也极有可能不知道,那么如何确定k?
    • -
    • 一种方式是canopy算法
    • -
    • 待补充
    • +
    • 同样的,我们看基于自注意力的模型如何去维护一个incremental state
    • +
    • 显然,在推断第i个位置的token时,不像CNN只与窗口大小的history相关,而是与前i-1个位置相关,但是注意,前i-1个位置计算出来的key和value是不变的,是可以复用的,第i位置只生成该位置的key,value以及query,并用query查询自己以及前i-1个位置复用的key,value,因此,incremental +state应该包含了key与value的信息,且维护的不是窗口大小,而是整个序列。
    • +
    • 在代码里,TransformerDecoder将当前层输入和encoder输出传给TransformerDecoderLayer,更新buffer +
      if prev_self_attn_state is not None:
      prev_key, prev_value = prev_self_attn_state[:2]
      saved_state: Dict[str, Optional[Tensor]] = {
      "prev_key": prev_key,
      "prev_value": prev_value,
      }
      if len(prev_self_attn_state) >= 3:
      saved_state["prev_key_padding_mask"] = prev_self_attn_state[2]
      assert incremental_state is not None
      self.self_attn._set_input_buffer(incremental_state, saved_state)
      _self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state)
    • +
    • 并在MultiHeadAttention里,假如incremental_state存在,将key和value设为None,后面的计算判断为None时就跳过计算 +
      if incremental_state is not None:
      saved_state = self._get_input_buffer(incremental_state)
      if saved_state is not None and "prev_key" in saved_state:
      # previous time steps are cached - no need to recompute
      # key and value if they are static
      if static_kv:
      assert self.encoder_decoder_attention and not self.self_attention
      key = value = None
    • +
    • 之后读取、计算、更新,代码写的很详细。
      if saved_state is not None:
      # saved states are stored with shape (bsz, num_heads, seq_len, head_dim)
      if "prev_key" in saved_state:
      _prev_key = saved_state["prev_key"]
      assert _prev_key is not None
      prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim)
      if static_kv:
      k = prev_key
      else:
      assert k is not None
      k = torch.cat([prev_key, k], dim=1)
      if "prev_value" in saved_state:
      _prev_value = saved_state["prev_value"]
      assert _prev_value is not None
      prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim)
      if static_kv:
      v = prev_value
      else:
      assert v is not None
      v = torch.cat([prev_value, v], dim=1)
      prev_key_padding_mask: Optional[Tensor] = None
      if "prev_key_padding_mask" in saved_state:
      prev_key_padding_mask = saved_state["prev_key_padding_mask"]
      assert k is not None and v is not None
      key_padding_mask = MultiheadAttention._append_prev_key_padding_mask(
      key_padding_mask=key_padding_mask,
      prev_key_padding_mask=prev_key_padding_mask,
      batch_size=bsz,
      src_len=k.size(1),
      static_kv=static_kv,
      )

      saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim)
      saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim)
      saved_state["prev_key_padding_mask"] = key_padding_mask
      # In this branch incremental_state is never None
      assert incremental_state is not None
      incremental_state = self._set_input_buffer(incremental_state, saved_state)
    -

    空类的处理

    +

    Generate

      -
    • 待补充
    • +
    • Fairseq的模型定义了所有前向过程,至于具体选择哪个前向过程则依据训练还是推断来决定。推断使用了fairseq-generate。
    • +
    • 要完成一次seq2seq,需要指定task和model,以及其他学习超参数。其中task确定了数据集参数,建立评价指标、词典、data_batch、实例化模型等等。
    • +
    • 其中最重要的就是train_step和inference_step,我们看看inference_step +
      def inference_step(self, generator, models, sample, prefix_tokens=None):
      with torch.no_grad():
      return generator.generate(models, sample, prefix_tokens=prefix_tokens)
    • +
    • 这里的generator是一个sequence_generator对象,其中生成的部分 +
      for step in range(max_len + 1):  # one extra step for EOS marker
      # reorder decoder internal states based on the prev choice of beams
      if reorder_state is not None:
      if batch_idxs is not None:
      # update beam indices to take into account removed sentences
      corr = batch_idxs - torch.arange(batch_idxs.numel()).type_as(batch_idxs)
      reorder_state.view(-1, beam_size).add_(corr.unsqueeze(-1) * beam_size)
      model.reorder_incremental_state(reorder_state)
      encoder_outs = model.reorder_encoder_out(encoder_outs, reorder_state)

      lprobs, avg_attn_scores = model.forward_decoder(
      tokens[:, :step + 1], encoder_outs, temperature=self.temperature,
      )
    • +
    • 这里做了一层emsemble +model的包装,假如我们只有一个decoder模型,那么实际上forward_decoder执行的是 +
      def _decode_one(
      self, tokens, model, encoder_out, incremental_states, log_probs,
      temperature=1.,
      ):
      if self.incremental_states is not None:
      decoder_out = list(model.forward_decoder(
      tokens,
      encoder_out=encoder_out,
      incremental_state=self.incremental_states[model],
      ))
      else:
      decoder_out = list(model.forward_decoder(tokens, encoder_out=encoder_out))
    • +
    • 这里可以看到是用incremental decoding逐步解码出句子
    -

    不同距离计算方式

    +

    Reorder

      -
    • 待补充
    • +
    • 更多的详细信息可以参考这篇博文,写的非常好,甚至被官方钦点加入了代码注释里understanding-incremental-decoding-in-fairseq
    • +
    • 还有一点,就是decoder中的reorder,在这篇博文里也有提到。
    • +
    • 在推断时和训练不同的另一点就是beam +search。因此我们不止维护一个缓存队列,而是beam_size个队列。
    • +
    • 那么在挑选第i个词的时候,第k个beam缓存队列的存的输入token可能是第i-1个位置时第j个beam缓存队列beam +search出来的,因此需要重新排序保证一致。
    -

    ANN算法

    ]]>
    - 机器学习 + 自然语言处理 - machine learning - code + math + inference + seq2seq
    @@ -9116,2821 +8946,3593 @@ class="math inline">\(p(\theta)\)
  • 很多时候我们并没有先验知识,这时一般采用平坦的、分散的分布作为先验分布,例如范围很大的均匀分布,或者方差很大的正态分布
  • 有时我们并不需要知道整个后验分布,而仅仅做点估计或者区间估计
  • -

    Markov Chain Monte Carlo

    +

    Markov Chain Monte Carlo

    +
      +
    • MCMC,前一个MC代表如何采样,使得采样点满足分布,后一个MC代表用随机采样来估计分布的参数
    • +
    • 最大似然估计和EM算法都是点估计,而MCMC是通过采样找出完整的后验分布
    • +
    • 蒙特卡洛单纯做抽样,是已知分布,但无法直接求得某些函数在此分布上的统计量,因此间接的通过对此分布随机抽样产生样本,通过样本计算统计量
    • +
    • 蒙特卡洛做推断,则是分布未知,已知样本(数据),通过样本反推分布(?待确定)
    • +
    +

    采样

    +
      +
    • 直接通过分布函数很难(或者分布未知)推出一些统计量,我们可以通过产生一系列符合这个分布的样本,通过样本统计计算统计量,即随机采样的方式获得统计量
    • +
    • 在参数推断中,我们可以随机采样出一系列满足参数的后验分布的样本,从而依靠样本估计参数
    • +
    • 最简单的采样:从累计分布函数的逆采样,也就是先从[0,1]做一个均匀分布的采样,然后这个值作为cdf函数的输出值,采样值即cdf的输入值: +\[ +u = U(0,1) \\ +x= cdf ^{-1} (u) \\ +\]
    • +
    +

    拒绝采样

    +
      +
    • 但是不是所有分布的累积分布函数取逆都容易得到。另外一种采样方法叫做rejection +sampling
    • +
    • 对于一个概率密度函数,我们无法直接采样,那么就做一个处处大于概率密度函数的分布,包围着这个函数,如图中红色线包住了绿色线 +
    • +
    • 我们计算出每个点到红线和绿线的距离,将其分为接受和拒绝区域,这样,我们先从红色分布采样得到样本,然后做一个[0,1]均匀分布采样,如果落在接收区域则接收该采样,否则拒接
    • +
    • 显然红色分布处处比绿色大是不可能的,积分不为1,因此需要按比例放缩一下,乘以一个系数M,算法如下: +
      i=0
      while i!= N
      x(i)~q(x) and u~U(0,1)
      if u< p(x(i))/Mq(x(i)) then
      accept x(i)
      i=i+1
      else
      reject x(i)
      end
      end
    • +
    • rejection +sampling效率太低,因为若红色分布选择不好,不能紧紧包住绿色分布时,接受率太低,大部分采样会被拒绝。
    • +
    +

    适应性拒绝采样

    +
      +
    • 当分布是log-concave的时候,我们能够有效的构造绿色分布的包络,也就是红色分布比较贴近绿色分布,接受率较高
    • +
    • 基本思想是,将要采样的绿色分布分为k个区域,每个区域最左边的点作为起始点,如果在每个区域能够用绿色分布在起始点的切线来包络的话,我们就可以用这个k个区域上的切线来组成红色区域
    • +
    • 但是这要求在各个区域内原始分布是凹的,但是例如高斯分布的概率密度函数并不是凹函数,但是高斯分布取对数之后是凹的,也就是所谓log-concave,因此我们先取对数,作出切线,然后计算指数还原到原分布,得到原分布的k段切线。 +
    • +
    +

    重要性采样

    +
      +
    • 上面提到的采样算法是从简单分布(提议分布)采样,通过简单分布和复杂分布之间的关系计算每个样本的接受率,拒绝掉一些样本,使得剩下的样本满足复杂分布
    • +
    • importance +sampling的思路是对样本点加权而不是简单粗暴的拒绝或者接收,这样可以充分利用每个样本点。
    • +
    • 例如我们希望通过采样得到某个分布的期望 \[ +E_{p(x)}(f(x)) = \int _x f(x)p(x)dx \\ +E_{p(x)}(f(x)) = \int _x f(x) \frac{p(x)}{q(x)} q(x) dx \\ +E_{p(x)}(f(x)) = \int _x g(x)q(x)dx \\ +\]
    • +
    • p(x)难以采样,我们就转化为从q(x)采样。其中\(\frac{p(x)}{q(x)}\)就是importance +weight。
    • +
    • 这样我们消除了红色分布必须包络住绿色分布的限制,只要计算出重要性权重,对采样出的样本点进行重要性加权,就可以得到绿色分布下的一些统计量。
    • +
    +

    马尔可夫蒙特卡洛和Metropolis-Hasting算法

    +
      +
    • mcmc是另一种采样方法,他将样本序列看作马尔可夫链,通过mcmc采样出的样本之间不是独立的,下一个样本的概率分布与上一个样本有关
    • +
    • 不同于普通采样的接收或者拒绝的概念,在每采样一个样本之后,mcmc会计算在当前样本的前提下,下一个样本的位置的概率分布,也就是关键的转移概率。
    • +
    • 我们抽样一个样本之后,按照转移概率我们抽下一个,得到一系列样本,符合给定的分布,显然这个转移概率是需要和给定分布相关的。我们利用马尔可夫链的收敛性,希望收敛之后的分布\(\pi\)就是给定分布,假定转移概率为\(k(x^{'} | x)\),从样本\(x\)转移到样本\(x^{'}\)
    • +
    • 在马尔可夫链中,有如下Chapman-Kologronvo等式: \[ +\pi _t (x^{'}) = \int _x \pi _{t-1}(x) k(x^{'} | x) dx +\]
    • +
    • 这个公式的意义显而易见。我们希望得到马氏链收敛,收敛之后无论怎么转移,得到的一系列样本都满足同一给定分布,则要求: +\[ +\pi _t (x) = \pi _{t-1} (x) +\]
    • +
    • 实际使用时我们依赖于另一个重要的公式,叫做细致平稳条件,the detailed +balance: \[ +\pi (x) k(x^{'} | x) = \pi (x^{'}) k(x | x^{'}) +\]
    • +
    • 由detailed balance可以推出Chapman-Kologronvo等式,反之不一定。
    • +
    • 当满足细致平稳条件时,马氏链是收敛的
    • +
    • 在LDA的博客里介绍了mh和gibbs,Metropolis-Hasting就是基本mcmc将一边的接受率提到1的结果: +
    • +
    • 在mh中,我们没有改变转移矩阵来适应给定分布,而是用给定分布来修正转移矩阵,因此,转移矩阵是我们自己设计的。一般将转移矩阵(提议分布)设计为以当前状态为中心的高斯分布,对于这个高斯分布,当方差很小时,概率集中在本次采样点附近,那么转移到下次采样时大概率位置不会变动很多,接受率高(因为本次采样点就是通过了接收得到的,大概率是处于高接受率的位置),但这会造成随机游走缓慢;如果方差很大,到处走,接受率就会降低。
    • +
    • 尽管一边的样本接受率提到了1,但总有一边低于1,如果被拒绝,则mcmc会原地重复采样一次,再继续。
    • +
    • 而gibbs则将两边的接受率都提到了1,可以看出,gibbs是mh的一种特例。mh没有修改转移概率,而是添加了接受率,将原先的转移概率和需要采样的分布联系起来。但是显然如果我们自己选择转移概率,且使得转移概率和原始分布的联系越密切,那效果越好,gibbs就是这样的思路。
    • +
    +

    Hybrid Metropolis-Hasting

    +
      +
    • 待补充
    • +
    +

    吉布斯采样

    +
      +
    • 吉布斯采样的一个动机:对于多个参数的联合分布,很难直接采样,但是如果固定其他参数作为条件,仅仅对一个参数的条件分布做采样,这时采样会简单许多,且可以证明收敛之后这样采样出来的样本满足联合分布
    • +
    • 先看直觉上为啥吉布斯采样通过条件概率迭代抽样的过程中不改变联合概率分布。首先在排除第i个参数计算条件概率时,这被排除的n-1个变量的边缘分布与真实联合概率分布针对这n-1个变量的边缘分布是一样的,因为它们的值没有改变;条件概率依据的条件相比真实分布是不变的,那条件概率分布也是不变的。边缘分布和条件概率分布都是不变(真实)的,那相乘得到的联合分布自然也是不变的,因此每一步迭代里都是按照真实分布采样且迭代不会改变这个分布。
    • +
    • 吉本斯采样是类似变分推断的coordinate +descent方法,一次更新样本的一个分量,依据的转移概率是在给定其他分量情况下当前更新分量所在维度的条件概率: +
    • +
    • 工业上吉布斯采样用的很广,因为它快,事实上这样一种迭代算法不能并行,但是利用collapsed +gibbs +sampling可以并行化迭代。其原理是将几个分量看成一个整体,collapse成一个分量,当其他分量用这组分量更新时,看成独立的(存在疑问,另一种关于collapse的说法是忽略一些条件变量,基本的gibbs采样就是collapsed +gibbs sampling,而这种几个分量看成一个整体的做法是blocked gibbs +sampling):
      u~p(u|x,y,z)
      x,y,z~p(x,y,z|u)
      =p(x|u)p(y|u)p(z|u)
    • +
    • 上面关于x,y,z的三个条件概率可以并行计算。
    • +
    • 现在我们证明gibbs是mh的一种特例且接受率为1,先看看mh的接受率 \[ +\alpha = min(1,\frac{\pi (x^{'}),q(x| x^{'})}{\pi (x) +q(x^{'} | x)}) +\]
    • +
    • 在gibbs中 \[ +q(x|x^{'})=\pi (x_i | x_{¬i}^{'}) \\ +q(x^{'}|x)=\pi (x_i ^{'} | x_{¬i}) \\ +\]
    • +
    • 而且实际上从\(x_{¬i}\)\(x_{¬i}^{'}\),只有第i个分量变了,除了第i个分量之外的其他分量没有改变,因此 +\[ +x_{¬i}^{'}=x_{¬i} +\]
    • +
    • 接下来看看gibbs的接受率 \[ +\alpha _{gibbs} = min(1,\frac{\pi (x^{'}) \pi (x_i | +x_{¬i}^{'})}{\pi (x) (x_i ^{'} | x_{¬i})}) \\ +\] \[ += min(1,\frac{\pi (x^{'}) \pi (x_i | x_{¬i})}{\pi (x) (x_i ^{'} +| x_{¬i})}) \\ +\] \[ += min(1,\frac{\pi (x^{'} | x_{¬i}^{'}) \pi( x_{¬i}^{'}) \pi +(x_i | x_{¬i})}{\pi (x_i | x_{¬i}) \pi( x_{¬i}) (x_i ^{'} | +x_{¬i})}) \\ +\] \[ += min(1,\frac{\pi (x^{'} | x_{¬i}) \pi( x_{¬i}) \pi (x_i | +x_{¬i})}{\pi (x_i | x_{¬i}) \pi( x_{¬i}) (x_i ^{'} | x_{¬i})}) \\ +\] \[ += min(1,1) \\ +\] \[ += 1 \\ +\]
    • +
    +

    Expectation Maximization

    +

    更新

    +
      +
    • 看毛子的deep|bayes2018,提到了用随机梯度下降做EM的M步骤,因为是随机的,所以E步骤只针对一部分数据进行,开销小,可以实现大规模数据上的隐变量模型推断,当时应用在word2vec上,为每一个词添加了一个定性隐变量,指示该词多个意思当中的一个,以期解决歧义问题,甚至还可以用中国餐馆过程将词意个数参数化。有时间再详细看。
    • +
    +

    公式

    +
      +
    • 对于简单的分布,我们想要做参数推断,只需要做最大似然估计,先求对数似然:
    • +
    +

    \[ +\theta=\mathop{argmax}_{\theta} L(X | \theta) \\ +=\mathop{argmax}_{\theta} \log \prod p(x_i | \theta) \\ +=\mathop{argmax}_{\theta} \sum \log p(x_i | \theta) \\ +\]

      -
    • MCMC,前一个MC代表如何采样,使得采样点满足分布,后一个MC代表用随机采样来估计分布的参数
    • -
    • 最大似然估计和EM算法都是点估计,而MCMC是通过采样找出完整的后验分布
    • -
    • 蒙特卡洛单纯做抽样,是已知分布,但无法直接求得某些函数在此分布上的统计量,因此间接的通过对此分布随机抽样产生样本,通过样本计算统计量
    • -
    • 蒙特卡洛做推断,则是分布未知,已知样本(数据),通过样本反推分布(?待确定)
    • +
    • 之后对这个对数似然求导计算极值即可,但是对于复杂的分布,可能并不方便求导
    • +
    • 这时我们可以用EM算法迭代求解。EM算法考虑了概率生成模型当中的隐变量,并为其分配概率,每次迭代更新其概率分布并同时更新参数\(\theta\),可以证明,每一次迭代之后得到的\(\theta\)都会使对数似然增加。
    • +
    • 每一次迭代分为两个部分,E和M,也就求期望和最大化 +
        +
      • 求期望,是求\(\log +p(x,z|\theta)\)在分布\(p(z|x,\theta +^{(t)})\)上的期望,其中\(\theta +^{(t)}\)是第t次迭代时计算出的参数
      • +
      • 最大化,也就是求使这个期望最大的\(\theta\),作为本次参数迭代更新的结果
      • +
    • +
    • 合起来就得到EM算法的公式: \[ +\theta ^{(t+1)} = \mathop{argmax} _{\theta} \int p(z|x,\theta ^{(t)}) +\log p(x,z|\theta) dz +\] ## 为何有效
    • +
    • 也就是证明,每次迭代后最大似然会增加
    • +
    • 要证明: \[ +\log p(x|\theta ^{(t+1)}) \geq \log p(x|\theta ^{(t)}) +\]
    • +
    • 先改写对数似然 \[ +\log p(x|\theta) = \log p(x,z|\theta) - \log p(z|x,\theta) \\ +\]
    • +
    • 两边对分布\(p(z|x,\theta +^{(t)})\)求期望,注意到等式左边与z无关,因此求期望之后不变: +\[ +\log p(x|\theta) = \int _z \log p(x,z|\theta) p(z|x,\theta ^{(t)}) dz - +\int _z \log p(z|x,\theta) p(z|x,\theta ^{(t)}) dz \\ +=Q(\theta,\theta ^{(t)})-H(\theta,\theta ^{(t)}) \\ +\]
    • +
    • 其中Q部分就是EM算法中的E部分,注意在这里\(\theta\)是变量,\(\theta ^{(t)}\)是常量
    • +
    • 迭代之后,由于EM算法中M部分作用,Q部分肯定变大了(大于等于),那么使Q部分变大的这个迭代之后新的\(\theta\),代入H部分,H部分会怎么变化呢?
    • +
    • 我们先计算,假如H部分的\(\theta\)不变,直接用上一次的\(\theta ^{(t)}\)带入,即\(H(\theta ^{(t)},\theta ^{(t)})\) \[ +H(\theta ^{(t)},\theta ^{(t)})-H(\theta,\theta ^{(t)})= \\ +\] \[ +\int _z \log p(z|x,\theta ^{(t)}) p(z|x,\theta ^{(t)}) dz - \int _z \log +p(z|x,\theta) p(z|x,\theta ^{(t)}) dz \\ +\] \[ += \int _z \log (\frac {p(z|x,\theta ^{(t)})} {p(z|x,\theta)} ) +p(z|x,\theta ^{(t)}) dz \\ +\] \[ += - \int _z \log (\frac {p(z|x,\theta)} {p(z|x,\theta ^{(t)})} ) +p(z|x,\theta ^{(t)}) dz \\ +\] \[ +\geq - \log \int _z (\frac {p(z|x,\theta)} {p(z|x,\theta ^{(t)})} ) +p(z|x,\theta ^{(t)}) dz \\ +\] \[ += - \log 1 \\ +\] \[ += 0 \\ +\]
    • +
    • 其中那个不等式是利用了Jensen不等式。也就是说,直接用上一次的\(\theta ^{(t)}\)作为\(\theta\)代入H,就是H的最大值!那么无论新的由argmax +Q部分得到的\(\theta +^{(t+1)}\)是多少,带入 +H,H部分都会减小(小于等于)!被减数变大,减数变小,那么得到的结果就是对数似然肯定变大,也就证明了EM算法的有效性
    -

    采样

    +

    从ELBO的角度理解

      -
    • 直接通过分布函数很难(或者分布未知)推出一些统计量,我们可以通过产生一系列符合这个分布的样本,通过样本统计计算统计量,即随机采样的方式获得统计量
    • -
    • 在参数推断中,我们可以随机采样出一系列满足参数的后验分布的样本,从而依靠样本估计参数
    • -
    • 最简单的采样:从累计分布函数的逆采样,也就是先从[0,1]做一个均匀分布的采样,然后这个值作为cdf函数的输出值,采样值即cdf的输入值: +
    • 我们还可以从ELBO(Evidence Lower Bound)的角度推出EM算法的公式
    • +
    • 在之前改写对数似然时我们得到了两个式子\(p(x,z|\theta)\)\(p(z|x,\theta)\),我们引入隐变量的一个分布\(q(z)\),对这个两个式子做其与\(q(z)\)之间的KL散度,可以证明对数似然是这两个KL散度之差: \[ -u = U(0,1) \\ -x= cdf ^{-1} (u) \\ +KL(q(z)||p(z|x,\theta)) = \int q(z) [\log q(z) - \log p(z|x,\theta)] dz +\\ +\] \[ += \int q(z) [\log q(z) - \log p(x|z,\theta) - \log (z|\theta) + \log +p(x|\theta)] dz \\ +\] \[ += \int q(z) [\log q(z) - \log p(x|z,\theta) - \log (z|\theta)] dz + \log +p(x|\theta) \\ +\] \[ += \int q(z) [\log q(z) - \log p(x,z|\theta)] dz + \log p(x|\theta) \\ +\] \[ += KL(q(z)||p(x,z|\theta)) + \log p(x|\theta) \\ +\]
    • +
    • 也就是 \[ +\log p(x|\theta) = - KL(q(z)||p(x,z|\theta)) + KL(q(z)||p(z|x,\theta)) +\]
    • +
    • 其中\(- +KL(q(z)||p(x,z|\theta))\)就是ELBO,因为$ KL(q(z)||p(z|x,)) +$,因此ELBO是对数似然的下界。我们可以通过最大化这个下界来最大化对数似然
    • +
    • 可以看到,ELBO有两个参数,\(q\)\(\theta\),首先我们固定\(\theta ^{(t-1)}\),找到使ELBO最大化的\(q^{(t)}\),这一步实际上是EM算法的E步骤,接下来固定\(q^{(t)}\),找到使ELBO最大化的\(\theta +^{(t)}\),这一步对应的就是EM算法的M步骤
    • +
    • 我们把\(\theta = \theta +^{(t-1)}\)带入ELBO的表达式: \[ +ELBO=\log p(x|\theta ^{(t-1)}) - KL(q(z)||p(z|x,\theta ^{(t-1)})) +\]
    • +
    • q取什么值时ELBO最大?显然当KL散度为0时,ELBO取到最大值,也就是下界达到对数似然本身,这时\(q(z)=p(z|x,\theta +^{(t-1)})\),接下来我们固定\(q\),求使ELBO最大的\(\theta\),先把ELBO的定义式改写: \[ +ELBO = - KL(q(z)||p(x,z|\theta)) \\ +\] \[ += \int q^{(t)}(z) [ \log p(x,z|\theta) - \log q^{(t)}(z)] dz \\ +\] \[ += - \int q^{(t)}(z) \log p(x,z|\theta) - q^{(t)}(z) \log q^{(t)}(z) dz +\\ +\]
    • +
    • 其中第二项与\(\theta\)无关,因此: +\[ +\theta ^{(t)} = \mathop{argmax} _{\theta} \int q^{(t)}(z) \log +p(x,z|\theta) dz \\ +\]
    • +
    • 代入上一步得到的\(q(z)=p(z|x,\theta +^{(t-1)})\),得到 \[ +\theta ^{(t)} = \mathop{argmax} _{\theta} \int \log +p(x,z|\theta)p(z|x,\theta ^{(t-1)}) dz \]
    • +
    • 同样得到了EM算法的迭代公式
    • +
    • 下面两张图截取自Christopher M. Bishop的Pattern Recognition and +Machine +Learning,说明了E步骤和M步骤实际在做什么:E步骤将下界ELBO提高到对数似然,但是这时只更新了隐变量,因此对数似然没有变化,而当利用更新的隐变量更新参数\(\theta\),也就是M步骤执行后,我们继续获得了更高的ELBO,以及其对应的对数似然,此时q没有变化,但p发生改变,因此KL不为0,对数似然一定大于ELBO,也就是会提升。直观的来说,我们在E和M步骤都提高了ELBO,E步骤先一口气将ELBO提满到对数似然,之后M步骤依然可以提高ELBO,但对数似然肯定会大于等于(在M步骤时实际上是大于)ELBO,因此对数似然就被M步骤提升的ELBO给“顶上去了”。 +i0oZfP.png +
    • +
    • 剩下的问题就是,如何选择z以及q,在混合模型中,可以将z作为示性函数引入,其他在设计时包含隐变量的概率模型里,可以直接将隐变量引入
    -

    拒绝采样

    +

    从假设隐变量为可观察的角度

      -
    • 但是不是所有分布的累积分布函数取逆都容易得到。另外一种采样方法叫做rejection -sampling
    • -
    • 对于一个概率密度函数,我们无法直接采样,那么就做一个处处大于概率密度函数的分布,包围着这个函数,如图中红色线包住了绿色线 -
    • -
    • 我们计算出每个点到红线和绿线的距离,将其分为接受和拒绝区域,这样,我们先从红色分布采样得到样本,然后做一个[0,1]均匀分布采样,如果落在接收区域则接收该采样,否则拒接
    • -
    • 显然红色分布处处比绿色大是不可能的,积分不为1,因此需要按比例放缩一下,乘以一个系数M,算法如下: -
      i=0
      while i!= N
      x(i)~q(x) and u~U(0,1)
      if u< p(x(i))/Mq(x(i)) then
      accept x(i)
      i=i+1
      else
      reject x(i)
      end
      end
    • -
    • rejection -sampling效率太低,因为若红色分布选择不好,不能紧紧包住绿色分布时,接受率太低,大部分采样会被拒绝。
    • +
    • 这种理解来自Chuong B Do & Serafim Batzoglou的tutorial:What is +the expectation maximization algorithm?
    • +
    • EM用于包含不可观察隐变量的概率模型推断,事实上,如果我们将隐变量从不可观察变为可观察,针对隐变量每一种可能的取值做最大似然估计,一样可以得到结果,但其时间代价是相当高的。
    • +
    • EM则改进了这种朴素的算法。一种对EM算法的理解是:EM算法在每次迭代中先猜想一种隐变量的取值概率分布,创造一个考虑了所有隐变量取值可能的加权的训练集,然后在这上面做一个魔改版本的最大似然估计。
    • +
    • 猜想一种隐变量的取值概率分布就是E步骤,但是我们不需要知道具体的概率分布,我们只需要求充分统计量在这个分布上的期望(Expectation)。
    • +
    • 所以说EM算法是最大似然估计在包含隐变量的数据(或者说包含部分不可观察样本的数据)上的自然泛化。
    -

    适应性拒绝采样

    +

    从假设隐变量为缺失值的角度

      -
    • 当分布是log-concave的时候,我们能够有效的构造绿色分布的包络,也就是红色分布比较贴近绿色分布,接受率较高
    • -
    • 基本思想是,将要采样的绿色分布分为k个区域,每个区域最左边的点作为起始点,如果在每个区域能够用绿色分布在起始点的切线来包络的话,我们就可以用这个k个区域上的切线来组成红色区域
    • -
    • 但是这要求在各个区域内原始分布是凹的,但是例如高斯分布的概率密度函数并不是凹函数,但是高斯分布取对数之后是凹的,也就是所谓log-concave,因此我们先取对数,作出切线,然后计算指数还原到原分布,得到原分布的k段切线。 -
    • +
    • 一般如何处理缺失值?用随机值、平均值、0值、聚类中心值代替等等
    • +
    • EM相当于用均值代替缺失值,也就是隐变量,但是利用了更多的信息:这个均值是在已知的x分布上求期望得到
    • +
    • EM的迭代就是反复处理缺失值(隐变量),然后基于完整的数据再调整x的分布,再将隐变量看成缺失值进行调整
    -

    重要性采样

    +

    EM算法与K-means

      -
    • 上面提到的采样算法是从简单分布(提议分布)采样,通过简单分布和复杂分布之间的关系计算每个样本的接受率,拒绝掉一些样本,使得剩下的样本满足复杂分布
    • -
    • importance -sampling的思路是对样本点加权而不是简单粗暴的拒绝或者接收,这样可以充分利用每个样本点。
    • -
    • 例如我们希望通过采样得到某个分布的期望 \[ -E_{p(x)}(f(x)) = \int _x f(x)p(x)dx \\ -E_{p(x)}(f(x)) = \int _x f(x) \frac{p(x)}{q(x)} q(x) dx \\ -E_{p(x)}(f(x)) = \int _x g(x)q(x)dx \\ -\]
    • -
    • p(x)难以采样,我们就转化为从q(x)采样。其中\(\frac{p(x)}{q(x)}\)就是importance -weight。
    • -
    • 这样我们消除了红色分布必须包络住绿色分布的限制,只要计算出重要性权重,对采样出的样本点进行重要性加权,就可以得到绿色分布下的一些统计量。
    • +
    • K-means是一种Hard-EM算法,它一样对隐变量的各种可能做出假设(样本属于的类),但是他并不是在类上计算概率和期望,而是比较Hard,只指定一个类作为样本的类,只有这个类概率为1,其余均为0。
    -

    马尔可夫蒙特卡洛和Metropolis-Hasting算法

    +

    隐变量引入的好处

      -
    • mcmc是另一种采样方法,他将样本序列看作马尔可夫链,通过mcmc采样出的样本之间不是独立的,下一个样本的概率分布与上一个样本有关
    • -
    • 不同于普通采样的接收或者拒绝的概念,在每采样一个样本之后,mcmc会计算在当前样本的前提下,下一个样本的位置的概率分布,也就是关键的转移概率。
    • -
    • 我们抽样一个样本之后,按照转移概率我们抽下一个,得到一系列样本,符合给定的分布,显然这个转移概率是需要和给定分布相关的。我们利用马尔可夫链的收敛性,希望收敛之后的分布\(\pi\)就是给定分布,假定转移概率为\(k(x^{'} | x)\),从样本\(x\)转移到样本\(x^{'}\)
    • -
    • 在马尔可夫链中,有如下Chapman-Kologronvo等式: 其实应该反过来说,很多时候我们凭借逻辑设计了隐变量,然后利用EM算法推断隐变量,而不是刻意设计隐变量来简化运算。
    • +
    • 对于GMM来说,引入隐变量的一个好处是化简了最大似然估计的计算(当然这是假设我们已知隐变量的情况下),将log与求和运算交换,参考了pluskid大神的博客:漫谈 Clustering (番外篇): +Expectation Maximization
    • +
    • 对于GMM,引入隐变量作为示性函数之前,最大似然估计是: \[ -\pi _t (x^{'}) = \int _x \pi _{t-1}(x) k(x^{'} | x) dx +\sum _{i=1}^N \log (\sum _{k=1}^K \pi _k N(x_i | \mu _k , \Sigma _k)) \]
    • -
    • 这个公式的意义显而易见。我们希望得到马氏链收敛,收敛之后无论怎么转移,得到的一系列样本都满足同一给定分布,则要求: +
    • 引入隐变量之后,令第i个样本\(x_i\)对应的示性函数为\(z_i\),这是一个k维one-hot向量,代表第i个样本属于k个高斯模型中哪一个,假设属于第m个模型,则\(z_i^m\)等于1,其余等于0。现在最大似然估计是: \[ -\pi _t (x) = \pi _{t-1} (x) +\log \prod _{i=1}^N p(x_i,z_i) \\ +\] \[ += \log \prod _{i=1}^N p(z_i) \prod _{k=1}^K N(x_i | \mu _k , \Sigma +_k)^{z_i^k} \\ +\] \[ += \log \prod _{i=1}^N \prod _{k=1}^K \pi _k ^{z_i^k} \prod _{k=1}^K +N(x_i | \mu _k , \Sigma _k)^{z_i^k} \\ +\] \[ += \log \prod _{i=1}^N \prod _{k=1}^K ( \pi _k N(x_i | \mu _k , \Sigma +_k)) ^{z_i^k} \\ +\] \[ += \sum _{i=1}^N \sum _{k=1}^K z_i^k(\log \pi _k + \log N(x_i | \mu _k , +\Sigma _k)) \\ \]
    • -
    • 实际使用时我们依赖于另一个重要的公式,叫做细致平稳条件,the detailed -balance: \[ -\pi (x) k(x^{'} | x) = \pi (x^{'}) k(x | x^{'}) +
    +

    在EM算法中应用蒙特卡罗方法

    +
      +
    • 当E步骤无法解析的计算时,可以使用蒙特卡洛近似M步骤的积分: \[ +\theta ^{(t+1)} = \mathop{argmax} _{\theta} \int p(z|x,\theta ^{(t)}) +\log p(x,z|\theta) dz +\]
    • +
    • 我们根据现在得到的隐变量后验估计\(p(z|x,\theta ^{(t)})\)来采样有限个\(Z^l\),之后将这些\(Z^l\)代入\(\log +p(x,z|\theta)\)来近似积分: \[ +\theta ^{(t+1)} = \mathop{argmax} _{\theta} \approx \frac 1L +\sum_{l=1}^L \log p(x,Z^l|\theta) +\]
    • +
    • 蒙特卡洛EM算法的一个极端的例子是随机EM算法,相当于每次迭代只在E步骤只采样一个样本点。在混合模型求解中,隐变量作为示性函数,只采样一个隐变量意味着hard +assignment,每个样本点以1概率分配到某个component,
    • +
    • 蒙特卡洛EM算法推广到贝叶斯框架,就得到IP算法 +
        +
      • I步骤: \[ +p(Z|X)=\int p(Z | \theta ,X)p(\theta | X)d\theta +\] 先从\(p(\theta | +X)\)中采样\(\theta +^l\),再将其代入,接着从\(p(Z | \theta +^l ,X)\)中采样\(Z^l\)
      • +
      • P步骤: 从I步骤采样得到的\(Z^l\)用于估计参数后验: \[ +p(\theta | X) = \int p(\theta | Z,X)p(Z|X) dZ \\ +\approx \frac 1L \sum _{l=1}^L p(\theta | Z^l,X) \\ \]
      • -
      • 由detailed balance可以推出Chapman-Kologronvo等式,反之不一定。
      • -
      • 当满足细致平稳条件时,马氏链是收敛的
      • -
      • 在LDA的博客里介绍了mh和gibbs,Metropolis-Hasting就是基本mcmc将一边的接受率提到1的结果: -
      • -
      • 在mh中,我们没有改变转移矩阵来适应给定分布,而是用给定分布来修正转移矩阵,因此,转移矩阵是我们自己设计的。一般将转移矩阵(提议分布)设计为以当前状态为中心的高斯分布,对于这个高斯分布,当方差很小时,概率集中在本次采样点附近,那么转移到下次采样时大概率位置不会变动很多,接受率高(因为本次采样点就是通过了接收得到的,大概率是处于高接受率的位置),但这会造成随机游走缓慢;如果方差很大,到处走,接受率就会降低。
      • -
      • 尽管一边的样本接受率提到了1,但总有一边低于1,如果被拒绝,则mcmc会原地重复采样一次,再继续。
      • -
      • 而gibbs则将两边的接受率都提到了1,可以看出,gibbs是mh的一种特例。mh没有修改转移概率,而是添加了接受率,将原先的转移概率和需要采样的分布联系起来。但是显然如果我们自己选择转移概率,且使得转移概率和原始分布的联系越密切,那效果越好,gibbs就是这样的思路。
      • +
    -

    Hybrid Metropolis-Hasting

    +

    广义EM算法

      -
    • 待补充
    • +
    • 不会鸽
    -

    吉布斯采样

    +

    Wake-Sleep算法

      -
    • 吉布斯采样的一个动机:对于多个参数的联合分布,很难直接采样,但是如果固定其他参数作为条件,仅仅对一个参数的条件分布做采样,这时采样会简单许多,且可以证明收敛之后这样采样出来的样本满足联合分布
    • -
    • 先看直觉上为啥吉布斯采样通过条件概率迭代抽样的过程中不改变联合概率分布。首先在排除第i个参数计算条件概率时,这被排除的n-1个变量的边缘分布与真实联合概率分布针对这n-1个变量的边缘分布是一样的,因为它们的值没有改变;条件概率依据的条件相比真实分布是不变的,那条件概率分布也是不变的。边缘分布和条件概率分布都是不变(真实)的,那相乘得到的联合分布自然也是不变的,因此每一步迭代里都是按照真实分布采样且迭代不会改变这个分布。
    • -
    • 吉本斯采样是类似变分推断的coordinate -descent方法,一次更新样本的一个分量,依据的转移概率是在给定其他分量情况下当前更新分量所在维度的条件概率: -
    • -
    • 工业上吉布斯采样用的很广,因为它快,事实上这样一种迭代算法不能并行,但是利用collapsed -gibbs -sampling可以并行化迭代。其原理是将几个分量看成一个整体,collapse成一个分量,当其他分量用这组分量更新时,看成独立的(存在疑问,另一种关于collapse的说法是忽略一些条件变量,基本的gibbs采样就是collapsed -gibbs sampling,而这种几个分量看成一个整体的做法是blocked gibbs -sampling):
      u~p(u|x,y,z)
      x,y,z~p(x,y,z|u)
      =p(x|u)p(y|u)p(z|u)
    • -
    • 上面关于x,y,z的三个条件概率可以并行计算。
    • -
    • 现在我们证明gibbs是mh的一种特例且接受率为1,先看看mh的接受率 鸽德哲学
    • +
    +

    广义EM算法与吉布斯采样

    +
      +
    • 当你认为我不会鸽的时候鸽了,亦是一种不鸽
    • +
    +

    Variational Inference

    +

    ELBO

    +
      +
    • 接下来介绍变分推断,可以看到,EM算法可以推广到变分推断
    • +
    • 重新推出ELBO与对数似然的关系: \[ +\log p(x) = \log p(x,z) - \log p(z|x) \\ += \log \frac{p(x,z)}{q(z)} - \log \frac{p(z|x)}{q(z)} \\ += \log p(x,z) - \log q(z) - \log \frac{p(z|x)}{q(z)} \\ +\]
    • +
    • 两边对隐分布\(q(z)\)求期望 \[ -\alpha = min(1,\frac{\pi (x^{'}),q(x| x^{'})}{\pi (x) -q(x^{'} | x)}) +\log p(x) = \\ +[ \int _z q(z) \log p(x,z)dz - \int _z q(z) \log q(z)dz ] + [- \int _z +\log \frac{p(z|x)}{q(z)} q(z) dz ]\\ += ELBO+KL(q||p(z|x)) \\ \]
    • -
    • 在gibbs中 \[ -q(x|x^{'})=\pi (x_i | x_{¬i}^{'}) \\ -q(x^{'}|x)=\pi (x_i ^{'} | x_{¬i}) \\ +
    • 我们希望推断隐变量\(z\)的后验分布\(p(z|x)\),为此我们引入一个分布\(q(z)\)来近似这个后验。当目前观测量也就是对数似然确定的前提下,近似后验等价于使得\(q(z)\)\(p(z|x)\)的KL散度最小,由上式可以看出,当ELBO最大时,KL散度最小。
    • +
    • 接下来就是讨论如何使得ELBO最大化
    • +
    +

    任意分布上的变分推断

    +
      +
    • 对任意分布使用,一次选取隐变量一个分量更新,比如第j个分量
    • +
    • 我们自己选取的\(q(z)\)当然要比近似的分布简单,这里假设分布是独立的,隐变量是\(M\)维的: \[ +q(z)=\prod _{i=1}^M q_i(z_i) \]
    • -
    • 而且实际上从\(x_{¬i}\)\(x_{¬i}^{'}\),只有第i个分量变了,除了第i个分量之外的其他分量没有改变,因此 +
    • 因此ELBO可以写成两部分 \[ +ELBO=\int \prod q_i(z_i) \log p(x,z) dz - \int \prod q_j(z_j) \sum \log +q_j(z_j) dz \\ +=part1-part2 \\ +\]
    • +
    • 其中part1可以写成对隐变量各个维度求多重积分的形式,我们挑出第j个维度将其改写成 \[ -x_{¬i}^{'}=x_{¬i} +part1=\int \prod q_i(z_i) \log p(x,z) dz \\ +\] \[ += \int _{z_1} \int _{z_2} ... \int _{z_M} \prod _{i=1}^M q_i(z_i) \log +p(x,z) d z_1 , d z_2 , ... ,d z_M \\ +\] \[ += \int _{z_j} q_j(z_j) ( \int _{z_{i \neq j}} \log (p(x,z)) \prod _{z_{i +\neq j}} q_i(z_i) d z_i) d z_j \\ +\] \[ += \int _{z_j} q_j(z_j) [E_{i \neq j} [\log (p(x,z))]] d z_j \\ \]
    • -
    • 接下来看看gibbs的接受率 \[ -\alpha _{gibbs} = min(1,\frac{\pi (x^{'}) \pi (x_i | -x_{¬i}^{'})}{\pi (x) (x_i ^{'} | x_{¬i})}) \\ +
    • 在此我们定义一种伪分布的形式,一种分布的伪分布就是对其对数求积分再求指数: +\[ +p_j(z_j) = \int _{i \neq j} p(z_1,...,z_i) d z_1 , d z_2 ,..., d z_i \\ \] \[ -= min(1,\frac{\pi (x^{'}) \pi (x_i | x_{¬i})}{\pi (x) (x_i ^{'} -| x_{¬i})}) \\ +p_j^{'}(z_j) = exp \int _{i \neq j} \log p(z_1,...,z_i) d z_1 , d +z_2 ,..., d z_i \\ \] \[ -= min(1,\frac{\pi (x^{'} | x_{¬i}^{'}) \pi( x_{¬i}^{'}) \pi -(x_i | x_{¬i})}{\pi (x_i | x_{¬i}) \pi( x_{¬i}) (x_i ^{'} | -x_{¬i})}) \\ +\log p_j^{'}(z_j) = \int _{i \neq j} \log p(z_1,...,z_i) d z_1 , d +z_2 ,..., d z_i \\ +\]
    • +
    • 这样part1用伪分布的形式可以改写成 \[ +part1= \int _{z_j} q_j(z_j) \log p_j^{'}(x,z_j) \\ +\]
    • +
    • part2中因为隐变量各个分量独立,可以把函数的和在联合分布上的期望改写成各个函数在边缘分布上的期望的和,在这些和中我们关注第j个变量,其余看成常量: +\[ +part2=\int \prod q_j(z_j) \sum \log q_j(z_j) dz \\ \] \[ -= min(1,\frac{\pi (x^{'} | x_{¬i}) \pi( x_{¬i}) \pi (x_i | -x_{¬i})}{\pi (x_i | x_{¬i}) \pi( x_{¬i}) (x_i ^{'} | x_{¬i})}) \\ += \sum ( \int q_i(z_i) \log (q_i(z_i)) d z_i ) \\ \] \[ -= min(1,1) \\ += \int q_j(z_j) \log (q_j(z_j)) d z_j + const \\ +\]
    • +
    • 再把part1和part2合起来,得到ELBO关于分量j的形式: \[ +ELBO = \int _{z_j} \log \log p_j^{'}(x,z_j) - \int q_j(z_j) \log +(q_j(z_j)) d z_j + const \\ \] \[ -= 1 \\ += \int _{z_j} q_j(z_j) \log \frac{p_j^{'}(x,z_j)}{q_j(z_j)} + const +\\ +\] \[ += - KL(p_j^{'}(x,z_j) || q_j(z_j)) + const\\ \]
    • +
    • 也就是将ELBO写成了伪分布和近似分布之间的负KL散度,最大化ELBO就是最小化这个KL散度
    • +
    • 何时这个KL散度最小?也就是: \[ +q_j(z_j) = p_j^{'}(x,z_j) \\ +\log q_j(z_j) = E_{i \neq j} [\log (p(x,z))] \\ +\]
    • +
    • 到此我们就得到了变分推断下对于隐变量单一分量的近似分布迭代公式,在计算第j个分量的概率时,用到了\(\log (p(x,z))\)在其他所有分量\(q_i(z_i)\)上的期望,之后这个新的第j个分量的概率就参与下一次迭代,计算出其他分量的概率。
    -

    Expectation Maximization

    -

    更新

    -
      -
    • 看毛子的deep|bayes2018,提到了用随机梯度下降做EM的M步骤,因为是随机的,所以E步骤只针对一部分数据进行,开销小,可以实现大规模数据上的隐变量模型推断,当时应用在word2vec上,为每一个词添加了一个定性隐变量,指示该词多个意思当中的一个,以期解决歧义问题,甚至还可以用中国餐馆过程将词意个数参数化。有时间再详细看。
    • -
    -

    公式

    -
      -
    • 对于简单的分布,我们想要做参数推断,只需要做最大似然估计,先求对数似然:
    • -
    -

    \[ -\theta=\mathop{argmax}_{\theta} L(X | \theta) \\ -=\mathop{argmax}_{\theta} \log \prod p(x_i | \theta) \\ -=\mathop{argmax}_{\theta} \sum \log p(x_i | \theta) \\ -\]

    +

    指数家族分布

      -
    • 之后对这个对数似然求导计算极值即可,但是对于复杂的分布,可能并不方便求导
    • -
    • 这时我们可以用EM算法迭代求解。EM算法考虑了概率生成模型当中的隐变量,并为其分配概率,每次迭代更新其概率分布并同时更新参数\(\theta\),可以证明,每一次迭代之后得到的\(\theta\)都会使对数似然增加。
    • -
    • 每一次迭代分为两个部分,E和M,也就求期望和最大化 +
    • 定义指数家族分布: \[ +p(x | \theta)=h(x) exp(\eta (\theta) \cdot T(x)-A(\theta)) \\ +\]
    • +
    • 其中
        -
      • 求期望,是求\(\log -p(x,z|\theta)\)在分布\(p(z|x,\theta -^{(t)})\)上的期望,其中\(\theta -^{(t)}\)是第t次迭代时计算出的参数
      • -
      • 最大化,也就是求使这个期望最大的\(\theta\),作为本次参数迭代更新的结果
      • +
      • \(T(x)\):sufficient statistics
      • +
      • \(\theta\):parameter of the +family
      • +
      • \(\eta\):natural parameter
      • +
      • \(h(x)\):underlying measure
      • +
      • \(A(\theta)\):log normalizer / +partition function
    • -
    • 合起来就得到EM算法的公式: \[ -\theta ^{(t+1)} = \mathop{argmax} _{\theta} \int p(z|x,\theta ^{(t)}) -\log p(x,z|\theta) dz -\] ## 为何有效
    • -
    • 也就是证明,每次迭代后最大似然会增加
    • -
    • 要证明: \[ -\log p(x|\theta ^{(t+1)}) \geq \log p(x|\theta ^{(t)}) -\]
    • -
    • 先改写对数似然 \[ -\log p(x|\theta) = \log p(x,z|\theta) - \log p(z|x,\theta) \\ -\]
    • -
    • 两边对分布\(p(z|x,\theta -^{(t)})\)求期望,注意到等式左边与z无关,因此求期望之后不变: -\[ -\log p(x|\theta) = \int _z \log p(x,z|\theta) p(z|x,\theta ^{(t)}) dz - -\int _z \log p(z|x,\theta) p(z|x,\theta ^{(t)}) dz \\ -=Q(\theta,\theta ^{(t)})-H(\theta,\theta ^{(t)}) \\ +
    • 注意parameter of the family和natural +parameter都是向量,当指数家族分布处于标量化参数形式,即\(\eta _i (\theta) = \theta +_i\)的时候,指数家族分布可以写成: \[ +p(x | \eta)=h(x) exp(\eta (T(x) ^T \eta - A(\eta)) \]
    • -
    • 其中Q部分就是EM算法中的E部分,注意在这里\(\theta\)是变量,\(\theta ^{(t)}\)是常量
    • -
    • 迭代之后,由于EM算法中M部分作用,Q部分肯定变大了(大于等于),那么使Q部分变大的这个迭代之后新的\(\theta\),代入H部分,H部分会怎么变化呢?
    • -
    • 我们先计算,假如H部分的\(\theta\)不变,直接用上一次的\(\theta ^{(t)}\)带入,即\(H(\theta ^{(t)},\theta ^{(t)})\) 当我们把概率密度函数写成指数家族形式,求最大对数似然时,有: \[ -H(\theta ^{(t)},\theta ^{(t)})-H(\theta,\theta ^{(t)})= \\ -\] \[ -\int _z \log p(z|x,\theta ^{(t)}) p(z|x,\theta ^{(t)}) dz - \int _z \log -p(z|x,\theta) p(z|x,\theta ^{(t)}) dz \\ +\eta = \mathop{argmax} _ {\eta} [\log p(X | \eta)] \\ \] \[ -= \int _z \log (\frac {p(z|x,\theta ^{(t)})} {p(z|x,\theta)} ) -p(z|x,\theta ^{(t)}) dz \\ += \mathop{argmax} _ {\eta} [\log \prod p(x_i | \eta)] \\ \] \[ -= - \int _z \log (\frac {p(z|x,\theta)} {p(z|x,\theta ^{(t)})} ) -p(z|x,\theta ^{(t)}) dz \\ += \mathop{argmax} _ {\eta} [\log [\prod h(x_i) exp [(\sum T(x_i))^T \eta +- n A(\eta)]]] \\ \] \[ -\geq - \log \int _z (\frac {p(z|x,\theta)} {p(z|x,\theta ^{(t)})} ) -p(z|x,\theta ^{(t)}) dz \\ += \mathop{argmax} _ {\eta} (\sum T(x_i))^T \eta - n A(\eta)] \\ \] \[ -= - \log 1 \\ += \mathop{argmax} _ {\eta} L(\eta) \\ +\]
    • +
    • 继续求极值,我们就可以得到指数家族分布关于log normalizer和sufficient +statistics的很重要的一个性质: \[ +\frac{\partial L (\eta)}{\partial \eta} = \sum T(x_i) - n +A^{'}(\eta) =0 \\ \] \[ -= 0 \\ +A^{'}(\eta) = \sum \frac{T(x_i)}{n} \\ \]
    • -
    • 其中那个不等式是利用了Jensen不等式。也就是说,直接用上一次的\(\theta ^{(t)}\)作为\(\theta\)代入H,就是H的最大值!那么无论新的由argmax -Q部分得到的\(\theta -^{(t+1)}\)是多少,带入 -H,H部分都会减小(小于等于)!被减数变大,减数变小,那么得到的结果就是对数似然肯定变大,也就证明了EM算法的有效性
    • -
    -

    从ELBO的角度理解

    -
      -
    • 我们还可以从ELBO(Evidence Lower Bound)的角度推出EM算法的公式
    • -
    • 在之前改写对数似然时我们得到了两个式子\(p(x,z|\theta)\)\(p(z|x,\theta)\),我们引入隐变量的一个分布\(q(z)\),对这个两个式子做其与\(q(z)\)之间的KL散度,可以证明对数似然是这两个KL散度之差: -\[ -KL(q(z)||p(z|x,\theta)) = \int q(z) [\log q(z) - \log p(z|x,\theta)] dz -\\ +
    • 举个例子,高斯分布写成指数家族分布形式: \[ +p(x) = exp[- \frac{1}{2 \sigma ^2}x^2 + \frac{\mu}{\sigma ^2}x - +\frac{\mu ^2}{2 \sigma ^2} - \frac 12 \log(2 \pi \sigma ^2)] \\ \] \[ -= \int q(z) [\log q(z) - \log p(x|z,\theta) - \log (z|\theta) + \log -p(x|\theta)] dz \\ +=exp ( [x \ x^2] [\frac{\mu}{\sigma ^2} \ \frac{-1}{2 \sigma ^2}] ^T - +\frac{\mu ^2}{2 \sigma ^2} - \frac 12 \log(2 \pi \sigma ^2) ) +\]
    • +
    • 用自然参数去替代方差和均值,写成指数家族分布形式: \[ +p(x) = exp( [x \ x^2] [ \eta _1 \ \eta _2] ^T + \frac{\eta _1 ^2}{4 \eta +_2} + \frac 12 \log (-2 \eta _2 ) - \frac 12 \log (2 \pi)) +\]
    • +
    • 其中: +
        +
      • \(T(x)\):\([x \ x^2]\)
      • +
      • \(\eta\):\([ \eta _1 \ \eta _2] ^T\)
      • +
      • \(-A(\eta)\):\(\frac{\eta _1 ^2}{4 \eta _2} + \frac 12 \log (-2 +\eta _2 )\)
      • +
    • +
    • 接下来我们利用指数家族的性质来快速计算均值和方差 \[ +A^{'}(\eta) = \sum \frac{T(x_i)}{n} \\ \] \[ -= \int q(z) [\log q(z) - \log p(x|z,\theta) - \log (z|\theta)] dz + \log -p(x|\theta) \\ +[\frac{\partial A}{\eta _1} \ \frac{\partial A}{\eta _2}] = [\frac{- +\eta _1}{2 \eta _2} \ \frac{\eta _1 ^2 }{2 \eta _2}-\frac{1}{2 \eta _2}] +\\ \] \[ -= \int q(z) [\log q(z) - \log p(x,z|\theta)] dz + \log p(x|\theta) \\ += [\frac{\sum x_i}{n} \ \frac{\sum x_i^2}{n}] \\ \] \[ -= KL(q(z)||p(x,z|\theta)) + \log p(x|\theta) \\ -\]
    • -
    • 也就是 \[ -\log p(x|\theta) = - KL(q(z)||p(x,z|\theta)) + KL(q(z)||p(z|x,\theta)) += [\mu \ \mu ^2 + \sigma ^2] \\ \]
    • -
    • 其中\(- -KL(q(z)||p(x,z|\theta))\)就是ELBO,因为$ KL(q(z)||p(z|x,)) -$,因此ELBO是对数似然的下界。我们可以通过最大化这个下界来最大化对数似然
    • -
    • 可以看到,ELBO有两个参数,\(q\)\(\theta\),首先我们固定\(\theta ^{(t-1)}\),找到使ELBO最大化的\(q^{(t)}\),这一步实际上是EM算法的E步骤,接下来固定\(q^{(t)}\),找到使ELBO最大化的\(\theta -^{(t)}\),这一步对应的就是EM算法的M步骤
    • -
    • 我们把\(\theta = \theta -^{(t-1)}\)带入ELBO的表达式: \[ -ELBO=\log p(x|\theta ^{(t-1)}) - KL(q(z)||p(z|x,\theta ^{(t-1)})) +
    • 为什么\(A(\eta)\)叫做log +normalizer?因为把概率密度的指数族分布积分有: \[ +\int _x \frac{h(x)exp(T(x)^T \eta)}{exp(A(\eta))} = 1 \\ +\] \[ +A(\eta) = \log \int _x h(x)exp(T(x)^T \eta) \\ \]
    • -
    • q取什么值时ELBO最大?显然当KL散度为0时,ELBO取到最大值,也就是下界达到对数似然本身,这时\(q(z)=p(z|x,\theta -^{(t-1)})\),接下来我们固定\(q\),求使ELBO最大的\(\theta\),先把ELBO的定义式改写: 下面讨论指数族分布的共轭关系,假设似然和先验均是指数族分布: \[ -ELBO = - KL(q(z)||p(x,z|\theta)) \\ +p(\beta | x) ∝ p(x | \beta) p(\beta) \\ \] \[ -= \int q^{(t)}(z) [ \log p(x,z|\theta) - \log q^{(t)}(z)] dz \\ +∝ h(x) exp(T(x) \beta ^T - A_l (\beta)) h(\beta) exp(T(\beta) \alpha ^T +- A(\alpha)) \\ +\]
    • +
    • 用向量组的方式改写: \[ +T(\beta) = [\beta \ -g(\beta)] \\ \] \[ -= - \int q^{(t)}(z) \log p(x,z|\theta) - q^{(t)}(z) \log q^{(t)}(z) dz -\\ +\alpha = [\alpha _1 \ \alpha _2] \\ \]
    • -
    • 其中第二项与\(\theta\)无关,因此: +
    • 原式中关于\(\beta\)\(h(x)\)\(A(\alpha)\)都是常数,从正比式中消去,带入向量组有: \[ -\theta ^{(t)} = \mathop{argmax} _{\theta} \int q^{(t)}(z) \log -p(x,z|\theta) dz \\ +∝ h(\beta) exp(T(x) \beta - A_l(\beta) + \alpha _1 \beta - \alpha _2 +g(\beta)) \\ \]
    • -
    • 代入上一步得到的\(q(z)=p(z|x,\theta -^{(t-1)})\),得到 \[ -\theta ^{(t)} = \mathop{argmax} _{\theta} \int \log -p(x,z|\theta)p(z|x,\theta ^{(t-1)}) dz +
    • 我们注意到,如果令\(-g(\beta)=-A_l +(\beta)\),原式就可以写成: \[ +∝ h(\beta) exp((T(x)+\alpha _1)\beta - (1+\alpha _2) A_l (\beta)) \\ +\] \[ +∝ h(\beta) exp(\alpha _1 ^{'} \beta - \alpha _2 ^{'} A_l +(\beta)) \\ \]
    • -
    • 同样得到了EM算法的迭代公式
    • -
    • 下面两张图截取自Christopher M. Bishop的Pattern Recognition and -Machine -Learning,说明了E步骤和M步骤实际在做什么:E步骤将下界ELBO提高到对数似然,但是这时只更新了隐变量,因此对数似然没有变化,而当利用更新的隐变量更新参数\(\theta\),也就是M步骤执行后,我们继续获得了更高的ELBO,以及其对应的对数似然,此时q没有变化,但p发生改变,因此KL不为0,对数似然一定大于ELBO,也就是会提升。直观的来说,我们在E和M步骤都提高了ELBO,E步骤先一口气将ELBO提满到对数似然,之后M步骤依然可以提高ELBO,但对数似然肯定会大于等于(在M步骤时实际上是大于)ELBO,因此对数似然就被M步骤提升的ELBO给“顶上去了”。 -i0oZfP.png -
    • -
    • 剩下的问题就是,如何选择z以及q,在混合模型中,可以将z作为示性函数引入,其他在设计时包含隐变量的概率模型里,可以直接将隐变量引入
    • -
    -

    从假设隐变量为可观察的角度

    -
      -
    • 这种理解来自Chuong B Do & Serafim Batzoglou的tutorial:What is -the expectation maximization algorithm?
    • -
    • EM用于包含不可观察隐变量的概率模型推断,事实上,如果我们将隐变量从不可观察变为可观察,针对隐变量每一种可能的取值做最大似然估计,一样可以得到结果,但其时间代价是相当高的。
    • -
    • EM则改进了这种朴素的算法。一种对EM算法的理解是:EM算法在每次迭代中先猜想一种隐变量的取值概率分布,创造一个考虑了所有隐变量取值可能的加权的训练集,然后在这上面做一个魔改版本的最大似然估计。
    • -
    • 猜想一种隐变量的取值概率分布就是E步骤,但是我们不需要知道具体的概率分布,我们只需要求充分统计量在这个分布上的期望(Expectation)。
    • -
    • 所以说EM算法是最大似然估计在包含隐变量的数据(或者说包含部分不可观察样本的数据)上的自然泛化。
    • -
    -

    从假设隐变量为缺失值的角度

    -
      -
    • 一般如何处理缺失值?用随机值、平均值、0值、聚类中心值代替等等
    • -
    • EM相当于用均值代替缺失值,也就是隐变量,但是利用了更多的信息:这个均值是在已知的x分布上求期望得到
    • -
    • EM的迭代就是反复处理缺失值(隐变量),然后基于完整的数据再调整x的分布,再将隐变量看成缺失值进行调整
    • -
    -

    EM算法与K-means

    -
      -
    • K-means是一种Hard-EM算法,它一样对隐变量的各种可能做出假设(样本属于的类),但是他并不是在类上计算概率和期望,而是比较Hard,只指定一个类作为样本的类,只有这个类概率为1,其余均为0。
    • +
    • 这样先验和后验形式一致,也就是共轭
    • +
    • 这样我们用统一的形式写下似然和先验 \[ +p(\beta | x, \alpha) ∝ p(x | \beta) p(\beta | \alpha) \\ +\] \[ +∝ h(x)exp[T(x)^T\beta - A_l(\beta)] h(\beta) exp[T(\beta)^T\alpha - +A_l(\alpha)] \\ +\]
    • +
    • 这里我们可以计算log +normalizer关于参数求导的结果,注意,这是计算得到,不同于之前求指数族分布的最大似然估计得到的关于log +normalizer和sufficient statistics的性质: \[ +\frac{\partial A_l(\beta)}{\partial \beta}=\int _x T(x) p(x | \beta)dx +\\ +\] \[ += E_{p(x|\beta)} [T(x)] \\ +\]
    • +
    • 上式可以通过指数族分布积分为1,积分对\(\beta\)求导为0,将这个等式变换证明。
    -

    隐变量引入的好处

    +

    指数族分布下的变分推断

      -
    • 其实应该反过来说,很多时候我们凭借逻辑设计了隐变量,然后利用EM算法推断隐变量,而不是刻意设计隐变量来简化运算。
    • -
    • 对于GMM来说,引入隐变量的一个好处是化简了最大似然估计的计算(当然这是假设我们已知隐变量的情况下),将log与求和运算交换,参考了pluskid大神的博客:漫谈 Clustering (番外篇): -Expectation Maximization
    • -
    • 对于GMM,引入隐变量作为示性函数之前,最大似然估计是: 接下来我们将ELBO中的参数后验写成指数族分布形式,可以看到最后的迭代公式相当简洁
    • +
    • 我们假定要优化的参数有两个,x和z,我们用\(\lambda\)\(\phi\)来近似\(\eta(z,x)\)\(\eta(\beta +,x)\),依然是要使ELBO最大,这时调整的参数是\(q(\lambda , \phi)\),实际上是\(\lambda\)\(\phi\)
    • +
    • 我们采用固定一个参数,优化另一个参数的方法,相互迭代使得ELBO变大
    • +
    • 首先我们改写ELBO,注意\(q(z,\beta)=q(z)q(\beta)\)\[ -\sum _{i=1}^N \log (\sum _{k=1}^K \pi _k N(x_i | \mu _k , \Sigma _k)) +ELBO=E_{q(z,\beta)}[\log p(x,z,\beta)] - E_{q(z,\beta)}[\log p(z,\beta)] +\\ +\] \[ += E_{q(z,\beta)}[\log p(\beta | x,z) + \log p(z | x) + \log p(x)] - +E_{q(z,\beta)}[\log q(\beta)] - E_{q(z,\beta)}[\log q(z)] \\ \]
    • -
    • 引入隐变量之后,令第i个样本\(x_i\)对应的示性函数为\(z_i\),这是一个k维one-hot向量,代表第i个样本属于k个高斯模型中哪一个,假设属于第m个模型,则\(z_i^m\)等于1,其余等于0。现在最大似然估计是: -\[ -\log \prod _{i=1}^N p(x_i,z_i) \\ +
    • 其中后验为指数家族分布,且q分布用简单的参数\(\lambda\)\(\phi\)去近似: \[ +p(\beta | x,z) = h(\beta) exp [ T(\beta) ^T \eta (z,x) - A_g +(\eta(z,x))] \\ \] \[ -= \log \prod _{i=1}^N p(z_i) \prod _{k=1}^K N(x_i | \mu _k , \Sigma -_k)^{z_i^k} \\ +\approx q(\beta | \lambda) \\ \] \[ -= \log \prod _{i=1}^N \prod _{k=1}^K \pi _k ^{z_i^k} \prod _{k=1}^K -N(x_i | \mu _k , \Sigma _k)^{z_i^k} \\ += h(\beta) exp [ T(\beta) ^T \eta (\lambda - A_g (\eta(\lambda))] \\ \] \[ -= \log \prod _{i=1}^N \prod _{k=1}^K ( \pi _k N(x_i | \mu _k , \Sigma -_k)) ^{z_i^k} \\ +p(z | x,\beta) = h(z) exp [ T(z) ^T \eta (\beta,x) - A_l +(\eta(\beta,x))] \\ \] \[ -= \sum _{i=1}^N \sum _{k=1}^K z_i^k(\log \pi _k + \log N(x_i | \mu _k , -\Sigma _k)) \\ +\approx q(\beta | \phi) \\ +\] \[ += h(z) exp [ T(z) ^T \eta (\phi - A_l (\eta(\phi))] \\ \]
    • -
    -

    在EM算法中应用蒙特卡罗方法

    -
      -
    • 当E步骤无法解析的计算时,可以使用蒙特卡洛近似M步骤的积分: 现在我们固定\(\phi\),优化\(\lambda\),将ELBO中无关常量除去,有: \[ -\theta ^{(t+1)} = \mathop{argmax} _{\theta} \int p(z|x,\theta ^{(t)}) -\log p(x,z|\theta) dz +ELBO_{\lambda} = E_{q(z,\beta)}[\log p(\beta | x,z)] - +E_{q(z,\beta)}[\log q(\beta)] \\ \]
    • -
    • 我们根据现在得到的隐变量后验估计\(p(z|x,\theta ^{(t)})\)来采样有限个\(Z^l\),之后将这些\(Z^l\)代入\(\log -p(x,z|\theta)\)来近似积分: \[ -\theta ^{(t+1)} = \mathop{argmax} _{\theta} \approx \frac 1L -\sum_{l=1}^L \log p(x,Z^l|\theta) +
    • 代入指数家族分布,消去无关常量\(- +E_{q(z)}[A_g(\eta(x,z))]\),化简得到: \[ +ELBO_{\lambda} = E_{q(\beta)}[T(\beta)^T] +E_{q(z)}[\eta(z,x)] -E_{q(\beta)} [T(\beta)^T \lambda] + A_g(\lambda) \]
    • -
    • 蒙特卡洛EM算法的一个极端的例子是随机EM算法,相当于每次迭代只在E步骤只采样一个样本点。在混合模型求解中,隐变量作为示性函数,只采样一个隐变量意味着hard -assignment,每个样本点以1概率分配到某个component,
    • -
    • 蒙特卡洛EM算法推广到贝叶斯框架,就得到IP算法 +
    • 利用之前log normalizer关于参数求导的结论,有: \[ +ELBO_{\lambda} = A_g^{'}(\lambda)^T[E_{q(z)}[\eta(z,x)]] - \lambda +A_g^{'}(\lambda) ^T + A_g (\lambda) +\]
    • +
    • 对上式求导,令其为0,有: \[ +A_g^{''}(\lambda)^T[E_{q(z)}[\eta(z,x)]] - +A_g^{'}(\lambda)-\lambda A_g^{''}(\lambda) ^T + A_g^{} +(\lambda) = 0 \\ +\lambda = E_{q(z)}[\eta(z,x)] \\ +\]
    • +
    • 我们就得到了\(\lambda\)的迭代式!同理可以得到: \[ +\phi = E_{q(\beta)}[\eta(\beta,x)] \\ +\]
    • +
    • 写完整应该是: \[ +\lambda = E_{q(z | \phi)}[\eta(z,x)] \\ +\phi = E_{q(\beta | \lambda)}[\eta(\beta,x)] \\ +\]
    • +
    • 观察这两个迭代式,变量更新的路径是: \[ +\lambda \rightarrow q(\beta | \lambda) \rightarrow \phi \rightarrow q(z +| \phi) \rightarrow \lambda +\]
    • +
    +]]> + + 机器学习 + + + math + inference + mcmc + variational inference + em + +
    + + Interview Summary for NLP + /2019/08/09/interview201906/ + 总结一下六月份的面试经验

    + +

    投简历

      -
    • I步骤: \[ -p(Z|X)=\int p(Z | \theta ,X)p(\theta | X)d\theta -\] 先从\(p(\theta | -X)\)中采样\(\theta -^l\),再将其代入,接着从\(p(Z | \theta -^l ,X)\)中采样\(Z^l\)
    • -
    • P步骤: 从I步骤采样得到的\(Z^l\)用于估计参数后验: \[ -p(\theta | X) = \int p(\theta | Z,X)p(Z|X) dZ \\ -\approx \frac 1L \sum _{l=1}^L p(\theta | Z^l,X) \\ -\]
    • -
    +
  • 在六月初投的暑期实习岗位,自然语言处理实习生。其实这个时间点很不好,处于暑期和春招之间青黄不接的时候,当我拿到offer快六月下旬的时候一大批hc就放出来了,而我当时主要在学校论坛上找内推或者直招,这种一般看当时公司的需求,我投了20份,大部分都是三四月份时发的帖,到六月份可能又缺一个名额才被顶上来,这种情况很难被捞到简历。
  • +
  • 最后是四家给了面试机会,京东广告、新浪微博、滴滴AI +LAB、头条搜索。头条因为通知的太晚就没去了,而且当时完全是去裸面,没有任何准备,想想自己这么菜还是算了。
  • +
  • 平时刷题还是很重要(虽然我依然很懒不想刷),当时我一直忙着论文,忙完休息了个周末就直接投了,结果快的第二天就叫我去面试,实在是尴尬。
  • +
  • 面试一般都是两轮,大概一到两个小时。
  • -

    广义EM算法

    +

    京东广告

      -
    • 不会鸽
    • +
    • 一面着重问了简历上的内容,包括我做的几项评测和论文,讨论论文的动机、解决方法,对面也用类似的方法在做文本生成,就问了文本生成该如何评估质量、decoder训练如何保证不看到未来的信息,深度学习中常见的训练trick。
    • +
    • 抽取式文摘怎么构造特征,怎么抽取。
    • +
    • 讲述seq2seq的原理,分词的做法。讲述attention的作用及其变种。
    • +
    • 二面就让手写中序遍历的递归和非递归版本。
    -

    Wake-Sleep算法

    +

    新浪微博

      -
    • 鸽德哲学
    • +
    • 只有leader一个人问,同样先问了简历上的内容
    • +
    • 手写最基础的attention和self attention过程,画一下bert的大致结构
    • +
    • 手写decoder生成每一个字的过程
    • +
    • 因为这边业务比较依赖bert,问了比较多bert的内容,例如如何用bert做文本分类,如何根据业务需求修改bert
    • +
    • 手写算法,链表判断环
    -

    广义EM算法与吉布斯采样

    +

    滴滴AILAB

      -
    • 当你认为我不会鸽的时候鸽了,亦是一种不鸽
    • +
    • 滴滴是问的最详细最久的一个,也是两个人面,一面理论一面工程
    • +
    • 不知道是不是因为有做AI研究的需求,一面面试官把我的论文问的很详细,包括DPPs的计算过程,如何整合进seq2seq,为什么会出现OTR现象,这个现象有没有可能不是论文里分析的原因那样,而是由于encoder的过拟合导致的等等,感觉就像在做论文的rebut
    • +
    • 同样也问了seq2seq和attention的原理
    • +
    • 简单说明一下LDA的原理,如何用LDA做聚类,如何衡量LDA聚类的质量
    • +
    • 问了评测中三个任务:content linking, facet classification, +extractive summarization具体是怎么做的
    • +
    • 写出一个简单DNN的前向后向过程
    • +
    • 问了git、awk、sed的一些操作
    • +
    • 算法手写归并排序
    -

    Variational Inference

    -

    ELBO

    +]]>
    + + 面试 + + + natural language processing + machine learning + interview + +
    + + Paper reading on Knowledge Graphs + /2019/11/13/kg/ + 知识图谱专辑 - 跨语言知识图谱中的实体对齐 - Knowledge Graph Language +Model - 动态知识图谱对话生成 - Graph2Seq - Graph Matching Network - +动态更新知识图谱 - Attention-based Embeddings for Relation +Prediction

    + +

    Cross-lingual +Knowledge Graph Alignment via Graph Matching Neural Network

      -
    • 接下来介绍变分推断,可以看到,EM算法可以推广到变分推断
    • -
    • 重新推出ELBO与对数似然的关系: \[ -\log p(x) = \log p(x,z) - \log p(z|x) \\ -= \log \frac{p(x,z)}{q(z)} - \log \frac{p(z|x)}{q(z)} \\ -= \log p(x,z) - \log q(z) - \log \frac{p(z|x)}{q(z)} \\ -\]
    • -
    • 两边对隐分布\(q(z)\)求期望

      研究:跨语言知识图谱中实体的对齐

    • +
    • 一般的做法,在各自语言的知识图谱中投影到低维向量,然后学习到一个相似度计算函数

    • +
    • 问题在于,上面的做法依赖于相同实体在不同语言知识图谱下的邻域结构相同这一假设,但这一假设并不总是成立,因此传统的做法对少对齐邻域节点/少邻域节点的实体不友好

    • +
    • 作者提出主题实体图来编码实体节点的上下文信息,将节点embedding之间的Match转换为主题实体图之间的图Match

    • +
    • 这里的主题实体指的是需要对齐的实体,主题实体图即主题实体周围一跳邻域实体与本体一同构建的子图,假如在原知识图谱里这两个实体没有直接相连的话就在知识图谱里添加一条边

    • +
    • 得到主题实体图之后,经过四层网络计算出两个主题实体图之间的相似度:

      +
        +
      • 输入表示层:对主题实体图中的每一个实体学习到embedding。首先用word-level +lstm学习到初始embedding,然后因为是有向图,因此需要将邻域节点区分为输入和输出邻居,分别做聚合(FFN+mean +pooling),拼接到上一次得到的实体embedding并更新(FFN),迭代K次

      • +
      • 节点级别的局部匹配层:两个图互相匹配所有实体节点,这里用了基于注意力的Matching,即先用cosine距离得到主题实体图1里某个节点i和主题实体图2所有节点之间的相似度,用这个相似度作为注意力权重去加权主题实体图2所有节点得到图2的graph +embedding,然后用这个graph embedding和图1的query entity +embedding之间计算一个多角度cosine距离作为local match +score,这个多角度是指l个角度用l个加权向量(d维,同embedding维度)表示。一个角度下的cosine距离就用一个加权向量(逐元素相乘)加权两个embedding再计算cosine距离,l个角度合在一起就是一个\(W \in R^{l*d}\)的矩阵,如下: \[ -\log p(x) = \\ -[ \int _z q(z) \log p(x,z)dz - \int _z q(z) \log q(z)dz ] + [- \int _z -\log \frac{p(z|x)}{q(z)} q(z) dz ]\\ -= ELBO+KL(q||p(z|x)) \\ -\]

      • -
      • 我们希望推断隐变量\(z\)的后验分布\(p(z|x)\),为此我们引入一个分布\(q(z)\)来近似这个后验。当目前观测量也就是对数似然确定的前提下,近似后验等价于使得\(q(z)\)\(p(z|x)\)的KL散度最小,由上式可以看出,当ELBO最大时,KL散度最小。
      • -
      • 接下来就是讨论如何使得ELBO最大化
      • +score_{perspective_k} = cosine(W_k \cdot embedding_1, W_k \cdot +embedding_2) +\]

        +
      • 全局匹配层:局部匹配层存在着之前提到的对少共现邻居节点不友好的问题,这里就需要全局匹配。具体做法是,再用一个GCN将局部的match +embedding(上一层多角度cosine +score得到的向量)传递到整个主题实体图,之后在整个图上做一个FFN + +max/mean pooling,得到两个图的graph matching vector

      • +
      • 预测层:将两个主题实体图的graph matching +vector拼接送入一个softmax预测

      • +
    • +
    • 训练时,对每一个正样本启发式的生成了20个负样本,两个方向各十个,这里直接基于word-level +average embedding作为实体的特征向量,匹配十个最相似的实体

    -

    任意分布上的变分推断

    +

    Barack’s +Wife Hillary: Using Knowledge Graphs for Fact-Aware Language +Modeling

      -
    • 对任意分布使用,一次选取隐变量一个分量更新,比如第j个分量
    • -
    • 我们自己选取的\(q(z)\)当然要比近似的分布简单,这里假设分布是独立的,隐变量是\(M\)维的: \[ -q(z)=\prod _{i=1}^M q_i(z_i) -\]
    • -
    • 因此ELBO可以写成两部分 \[ -ELBO=\int \prod q_i(z_i) \log p(x,z) dz - \int \prod q_j(z_j) \sum \log -q_j(z_j) dz \\ -=part1-part2 \\ -\]
    • -
    • 其中part1可以写成对隐变量各个维度求多重积分的形式,我们挑出第j个维度将其改写成 -\[ -part1=\int \prod q_i(z_i) \log p(x,z) dz \\ -\] \[ -= \int _{z_1} \int _{z_2} ... \int _{z_M} \prod _{i=1}^M q_i(z_i) \log -p(x,z) d z_1 , d z_2 , ... ,d z_M \\ -\] \[ -= \int _{z_j} q_j(z_j) ( \int _{z_{i \neq j}} \log (p(x,z)) \prod _{z_{i -\neq j}} q_i(z_i) d z_i) d z_j \\ -\] \[ -= \int _{z_j} q_j(z_j) [E_{i \neq j} [\log (p(x,z))]] d z_j \\ -\]
    • -
    • 在此我们定义一种伪分布的形式,一种分布的伪分布就是对其对数求积分再求指数: +
    • 作者希望在语言模型当中维持一个local knowledge +graph来管理已经探测到的事实,并利用该图谱来查询未知的事实用于文本生成,称之为KGLM(Knowledge +Graph Language Model)

    • +
    • 假设实体集合为\(\xi\),则KGLM要预测的是 \[ +p(x_t,\xi _t|x_{1,t-1},\xi_ {1,t-1}) +\]

    • +
    • 生成下一个词的流程可以拆分如下:

      +
        +
      • 下一个词不是实体:那就正常词典范围上计算概率

      • +
      • 下一个词是全新实体:在正常词典以及所有实体范围上计算概率

      • +
      • 下一个词是与已经看见的实体相关的实体:先挑出一个已经看见的实体作为父节点,再挑出一个子节点,之后在正常词典以及该子节点的所有别名上计算概率

      • +
    • +
    • 作者使用LSTM作为LM的基础模型,所有的挑选:挑新实体、挑父节点、挑子节点,均利用LSTM的隐状态(切分为三部分),并加上实体和关系的预训练embedding作为输入依赖,之后通过softmax计算概率

    • +
    • 为了实现这样的模型数据集应该提供实体信息,作者提出了Linked +WikiText2数据集,该数据集的构建流程如下:

      +
        +
      • 根据维基百科上的链接创造实体之间的链接,借助neural-el来识别wikidata数据库中额外的链接,使用stanford +corenlp来做共指消解。

      • +
      • 构造local knowledge graph:接下来需要建立实体之间的parents +relation,每遇到一个实体a,将其在wikidata中相关联的所有实体{b}加入matching的候选,加入相关联的某一实体b在之后的文段中出现了,则将实体a作为实体b的父节点

      • +
      • 以上的做法只是构建了初始集合,需要不断扩展,作者还对日期、量词等做了alias +table

      • +
      • 以下是一句话在Linked WikiText2中的表示,相比WikiText使用api +query构造的方法,Linked +WikiText2直接对原始html操作,保留了更多链接信息:

      • +
    • +
    • Train and +Inference:首先对实体和关系使用TransE算法做一个Pretraining,给定三元组(p,r,e),目标是最小化距离: \[ -p_j(z_j) = \int _{i \neq j} p(z_1,...,z_i) d z_1 , d z_2 ,..., d z_i \\ -\] \[ -p_j^{'}(z_j) = exp \int _{i \neq j} \log p(z_1,...,z_i) d z_1 , d -z_2 ,..., d z_i \\ -\] \[ -\log p_j^{'}(z_j) = \int _{i \neq j} \log p(z_1,...,z_i) d z_1 , d -z_2 ,..., d z_i \\ -\]

    • -
    • 这样part1用伪分布的形式可以改写成 \[ -part1= \int _{z_j} q_j(z_j) \log p_j^{'}(x,z_j) \\ -\]
    • -
    • part2中因为隐变量各个分量独立,可以把函数的和在联合分布上的期望改写成各个函数在边缘分布上的期望的和,在这些和中我们关注第j个变量,其余看成常量: +\delta\left(\mathbf{v}_{p}, \mathbf{v}_{r}, +\mathbf{v}_{e}\right)=\left\|\mathbf{v}_{p}+\mathbf{v}_{r}-\mathbf{v}_{e}\right\|^{2} +\] 采用Hinge Loss,使得正负样本得分之差不超过\(\gamma\): \[ +\mathcal{L}=\max \left(0, \gamma+\delta\left(\mathbf{v}_{p}, +\mathbf{v}_{r}, +\mathbf{v}_{e}\right)-\delta\left(\mathbf{v}_{p}^{\prime}, +\mathbf{v}_{r}, \mathbf{v}_{e}^{\prime}\right)\right) +\]

    • +
    • 虽然整个过程是生成式的,但是所有变量均可见,因此可以端到端的直接训练,对于有多个父节点的实体节点,需要对概率做归一化

    • +
    • 在推理过程中,我们没有标注信息,我们希望计算的也是单词\(x\)在实体\(\xi\)求和得到的边缘概率,而不是联合概率(我们只希望得到词,词的实体信息被marginalize了),然而实体太多,不可能对所有实体计算联合概率再求和,因此作者采用了重要性采样: \[ -part2=\int \prod q_j(z_j) \sum \log q_j(z_j) dz \\ -\] \[ -= \sum ( \int q_i(z_i) \log (q_i(z_i)) d z_i ) \\ -\] \[ -= \int q_j(z_j) \log (q_j(z_j)) d z_j + const \\ -\]

    • -
    • 再把part1和part2合起来,得到ELBO关于分量j的形式: \[ -ELBO = \int _{z_j} \log \log p_j^{'}(x,z_j) - \int q_j(z_j) \log -(q_j(z_j)) d z_j + const \\ -\] \[ -= \int _{z_j} q_j(z_j) \log \frac{p_j^{'}(x,z_j)}{q_j(z_j)} + const -\\ -\] \[ -= - KL(p_j^{'}(x,z_j) || q_j(z_j)) + const\\ -\]
    • -
    • 也就是将ELBO写成了伪分布和近似分布之间的负KL散度,最大化ELBO就是最小化这个KL散度
    • -
    • 何时这个KL散度最小?也就是: \[ -q_j(z_j) = p_j^{'}(x,z_j) \\ -\log q_j(z_j) = E_{i \neq j} [\log (p(x,z))] \\ -\]
    • -
    • 到此我们就得到了变分推断下对于隐变量单一分量的近似分布迭代公式,在计算第j个分量的概率时,用到了\(\log (p(x,z))\)在其他所有分量\(q_i(z_i)\)上的期望,之后这个新的第j个分量的概率就参与下一次迭代,计算出其他分量的概率。
    • +\begin{aligned} p(\mathbf{x}) &=\sum_{\mathcal{E}} p(\mathbf{x}, +\mathcal{E})=\sum_{\mathcal{E}} \frac{p(\mathbf{x}, +\mathcal{E})}{q(\mathcal{E} | \mathbf{x})} q(\mathcal{E} | \mathbf{x}) +\\ & \approx \frac{1}{N} \sum_{\mathcal{E} \sim q} +\frac{p(\mathbf{x}, \mathcal{E})}{q(\mathcal{E} | \mathbf{x})} +\end{aligned} +\] 其中proposed +distribution使用判别式的KGLM得到,即另外训练一个KGLM判断当前token的annotation

      +
    • 结果非常漂亮,KGLM仅仅用了LSTM,参数量也不大,和超大规模的GPT-2模型相比,在实体词的预测上有着明显优势。

    • +
    +

    DyKgChat: +Benchmarking Dialogue Generation Grounding on Dynamic Knowledge +Graphs

    +
      +
    • 本文作者提出了一个新的任务,动态知识图谱对话生成,也就是希望抓住图谱中的关系,来将基于知识图谱的对话生成推广到zero-shot

    • +
    • 任务的详细描述分为两步:

      +
        +
      • 每轮对话t,给定输入x和图谱K,希望生成正确的回答y,而且包含正确的知识图谱实体

      • +
      • 当知识图谱更新之后(这里只可能更新关系和受体),回答y能够相应更改回答。

      • +
    • +
    • 为了有效衡量动态知识图谱对话的质量,作者提出了两类指标:

      +
        +
      • 知识实体建模:包括已知要预测实体,实体词命中的准确率;判别要预测实体还是通用词的TP;整个知识图谱所有实体的TP

      • +
      • 图自适应:作者提出了三种改变图的方法,包括shuffle和随即替换实体,观察生成的序列是否替换且替换正确

      • +
    • +
    • 作者提出了一个平行语料库,包含中英两个电视剧的语料,并做了详细的处理

    • +
    • 作者提出的模型Qadpt在seq2seq的基础上修改,首先将decoder的当前状态\(d_t\)生成一个controller\(c_t\)来决定是从KG里挑实体还是从generic +vocab里生成一般词汇。和copy +mechanism一样这个选择不是hard,而是分别计算概率,最后将两部分词表拼到一起,最后依概率选择: +\[ +\begin{aligned} P\left(\{K B, \mathcal{W}\} | y_{1} y_{2} \ldots +y_{t-1}, \mathbf{e}(x)\right) +\\=\operatorname{softmax}\left(\phi\left(\mathbf{d}_{t}\right)\right) \\ +\mathbf{w}_{t}=P\left(\mathcal{W} | y_{1} y_{2} \ldots y_{t-1}, +\mathbf{e}(x)\right) \\ c_{t}=P\left(K B | y_{1} y_{2} \ldots y_{t-1}, +\mathbf{e}(x)\right) \\ \mathbf{o}_{t}=\left\{c_{t} \mathbf{k}_{t} ; +\mathbf{w}_{t}\right\} \end{aligned} +\]

    • +
    • 至于如何产生实体候选列表,就是在知识图谱上做reasoning,不同于一般的attention +based graph embedding的做法,作者采用了multi-hop reasoning

      +
        +
      • 首先将path matrix和adjacency matrix合成transition matrix,其中的path +matrix是指用\(d_t\)学习到的每个实体选择每一种关系的概率,之后依概率选择受体节点:
      -

      指数家族分布

      +

      \[ +\begin{aligned} \mathbf{R}_{t} +&=\operatorname{softmax}\left(\theta\left(\mathbf{d}_{t}\right)\right) +\\ \mathbf{A}_{i, j, \gamma} &=\left\{\begin{array}{ll}{1,} & +{\left(h_{i}, r_{j}, t_{\gamma}\right) \in \mathcal{K}} \\ {0,} & +{\left(h_{i}, r_{j}, t_{\gamma}\right) \notin +\mathcal{K}}\end{array}\right.\\ \mathbf{T}_{t}=\mathbf{R}_{t} +\mathbf{A} \end{aligned} +\]

        -
      • 定义指数家族分布: \[ -p(x | \theta)=h(x) exp(\eta (\theta) \cdot T(x)-A(\theta)) \\ -\]
      • -
      • 其中 +
      • 之后取一个初始向量\(s\)(均匀分布?),用transition +matrix做n次transform,得到每个实体出现的概率并提供给controller计算,这里会使用one +hot ground truth计算一个交叉熵作为辅助损失
      • +
    • +
    +

    Graph2Seq: +Graph to Sequence Learning with Attention-based Neural Networks

      -
    • \(T(x)\):sufficient statistics
    • -
    • \(\theta\):parameter of the -family
    • -
    • \(\eta\):natural parameter
    • -
    • \(h(x)\):underlying measure
    • -
    • \(A(\theta)\):log normalizer / -partition function
    • +
    • 顾名思义,输入为图结构组织的数据,生成的是序列

    • +
    • 以往的做法,将图编码成固定长度的序列,再用Seq2Seq,作者认为这样存在信息丢失,本身Enc +Seq 2 Dec Seq就存在信息丢失,现在Graph 2 Enc +Seq会再丢失一层信息

    • +
    • 因此比较自然的做法应该是,解码器在编码的图节点上做attention,直接利用图的信息

    • +
    • 首先是图编码器,参考了GraphSage的做法,值得注意的是作者处理的是有向图,因此将邻居节点按两个方向做了区分,分别做Aggregate和Update的操作,做了k跳之后再拼接回来

    • +
    • 作者试了Mean、LSTM、Pooling三种,由于邻居是无序的,因此LSTM没有时序上的效果,作者直接随机排列邻居用LSTM +Aggregate

    • +
    • 作者认为传给解码器的不只node embedding还需要graph +embedding。作者采用了两种方法获取graph embedding

      +
        +
      • Pooling-based:先将所有的node +embedding经过一个全连接层,然后逐元素做max、min、average +pooling,作者发现三种方法的实际效果相差不大,就使用max +pooling作为默认的池化方法

      • +
      • Node-based:在图中加入一个超级节点,该节点与图中其他所有节点相连,用该节点经过图编码之后的embedding作为Graph +embedding

    • -
    • 注意parameter of the family和natural -parameter都是向量,当指数家族分布处于标量化参数形式,即\(\eta _i (\theta) = \theta -_i\)的时候,指数家族分布可以写成: \[ -p(x | \eta)=h(x) exp(\eta (T(x) ^T \eta - A(\eta)) -\]
    • -
    • 当我们把概率密度函数写成指数家族形式,求最大对数似然时,有: \[ -\eta = \mathop{argmax} _ {\eta} [\log p(X | \eta)] \\ -\] \[ -= \mathop{argmax} _ {\eta} [\log \prod p(x_i | \eta)] \\ -\] \[ -= \mathop{argmax} _ {\eta} [\log [\prod h(x_i) exp [(\sum T(x_i))^T \eta -- n A(\eta)]]] \\ -\] \[ -= \mathop{argmax} _ {\eta} (\sum T(x_i))^T \eta - n A(\eta)] \\ -\] \[ -= \mathop{argmax} _ {\eta} L(\eta) \\ -\]
    • -
    • 继续求极值,我们就可以得到指数家族分布关于log normalizer和sufficient -statistics的很重要的一个性质: \[ -\frac{\partial L (\eta)}{\partial \eta} = \sum T(x_i) - n -A^{'}(\eta) =0 \\ -\] \[ -A^{'}(\eta) = \sum \frac{T(x_i)}{n} \\ -\]
    • -
    • 举个例子,高斯分布写成指数家族分布形式: \[ -p(x) = exp[- \frac{1}{2 \sigma ^2}x^2 + \frac{\mu}{\sigma ^2}x - -\frac{\mu ^2}{2 \sigma ^2} - \frac 12 \log(2 \pi \sigma ^2)] \\ -\] \[ -=exp ( [x \ x^2] [\frac{\mu}{\sigma ^2} \ \frac{-1}{2 \sigma ^2}] ^T - -\frac{\mu ^2}{2 \sigma ^2} - \frac 12 \log(2 \pi \sigma ^2) ) -\]
    • -
    • 用自然参数去替代方差和均值,写成指数家族分布形式: \[ -p(x) = exp( [x \ x^2] [ \eta _1 \ \eta _2] ^T + \frac{\eta _1 ^2}{4 \eta -_2} + \frac 12 \log (-2 \eta _2 ) - \frac 12 \log (2 \pi)) -\]
    • -
    • 其中: +
    • 基于注意力的解码器:graph +embedding作为解码器的初始状态输入,之后decoder每一步生成在所有node +embedding上的attention并加权作为该时间步decoder的隐状态

    • +
    • 重点关注NLG task,作者测试了SQL2Text任务,首先将SQL +Query建图,然后使用Graph2Seq。效果显著好于SQL +Query到Text的Seq2seq

    • +
    • 另外在Aggregate的比对实验中发现,Mean +Pooling的效果最好,对于Graph Embedding,Pooling based的效果显著好于Node +based

    • +
    +

    Graph +Matching Networks for Learning the Similarity of Graph Structured +Objects

      -
    • \(T(x)\):\([x \ x^2]\)
    • -
    • \(\eta\):\([ \eta _1 \ \eta _2] ^T\)
    • -
    • \(-A(\eta)\):\(\frac{\eta _1 ^2}{4 \eta _2} + \frac 12 \log (-2 -\eta _2 )\)
    • +
    • google出品,实验和可视化结果一如既往的丰富
    • +
    • 两点贡献: +
        +
      • 证明了GNN可以产生用于相似度计算的graph embedding
      • +
      • 提出了attention based的Graph Matching +Networks,并超越了baseline
    • -
    • 接下来我们利用指数家族的性质来快速计算均值和方差 \[ -A^{'}(\eta) = \sum \frac{T(x_i)}{n} \\ -\] \[ -[\frac{\partial A}{\eta _1} \ \frac{\partial A}{\eta _2}] = [\frac{- -\eta _1}{2 \eta _2} \ \frac{\eta _1 ^2 }{2 \eta _2}-\frac{1}{2 \eta _2}] -\\ -\] \[ -= [\frac{\sum x_i}{n} \ \frac{\sum x_i^2}{n}] \\ -\] \[ -= [\mu \ \mu ^2 + \sigma ^2] \\ -\]
    • -
    • 为什么\(A(\eta)\)叫做log -normalizer?因为把概率密度的指数族分布积分有: \[ -\int _x \frac{h(x)exp(T(x)^T \eta)}{exp(A(\eta))} = 1 \\ -\] \[ -A(\eta) = \log \int _x h(x)exp(T(x)^T \eta) \\ +
    +

    Graph Embedding Model

    +
      +
    • baseline:Graph Embedding +Model,一个简单的encode-propagation-aggregate模型
    • +
    • encode:将点和边的特征通过MLP编码得到embedding
    • +
    • proprgation:将中心点,邻接点,邻接边的embedding传递到下一层的中心点embedding +\[ +\begin{aligned} \mathbf{m}_{j \rightarrow i} &=f_{\text {message +}}\left(\mathbf{h}_{i}^{(t)}, \mathbf{h}_{j}^{(t)}, \mathbf{e}_{i +j}\right) \\ \mathbf{h}_{i}^{(t+1)} &=f_{\text {node +}}\left(\mathbf{h}_{i}^{(t)}, \sum_{j:(j, i) \in E} \mathbf{m}_{j +\rightarrow i}\right) \end{aligned} \]
    • -
    • 下面讨论指数族分布的共轭关系,假设似然和先验均是指数族分布: \[ -p(\beta | x) ∝ p(x | \beta) p(\beta) \\ -\] \[ -∝ h(x) exp(T(x) \beta ^T - A_l (\beta)) h(\beta) exp(T(\beta) \alpha ^T -- A(\alpha)) \\ +
    • aggregate:作者用门控的方式将各个节点的embedding加权求和得到最后的graph +embedding \[ +\mathbf{h}_{G}=\operatorname{MLP}_{G}\left(\sum_{i \in V} +\sigma\left(\operatorname{MLP}_{\operatorname{gate}}\left(\mathbf{h}_{i}^{(T)}\right)\right) +\odot \operatorname{MLP}\left(\mathbf{h}_{i}^{(T)}\right)\right) \]
    • -
    • 用向量组的方式改写: \[ -T(\beta) = [\beta \ -g(\beta)] \\ -\] \[ -\alpha = [\alpha _1 \ \alpha _2] \\ +
    +

    Graph Matching Networks

    +
      +
    • GMN并不像Baseline一样分别对两个图先生成embedding再match,而是接受两个图作为输入直接输出similarity +score。 \[ +\begin{aligned} \mathbf{m}_{j \rightarrow i} &=f_{\text {message +}}\left(\mathbf{h}_{i}^{(t)}, \mathbf{h}_{j}^{(t)}, \mathbf{e}_{i +j}\right), \forall(i, j) \in E_{1} \cup E_{2} \\ \boldsymbol{\mu}_{j +\rightarrow i} &=f_{\text {match }}\left(\mathbf{h}_{i}^{(t)}, +\mathbf{h}_{j}^{(t)}\right) \\ \forall i \in V_{1}, j & \in V_{2}, +\text { or } i \in V_{2}, j \in V_{1} \\ \mathbf{h}_{i}^{(t+1)} +&=f_{\text {node }}\left(\mathbf{h}_{i}^{(t)}, \sum_{j} +\mathbf{m}_{j \rightarrow i}, \sum_{j^{\prime}} \mu_{j^{\prime} +\rightarrow i}\right) \\ \mathbf{h}_{G_{1}} +&=f_{G}\left(\left\{\mathbf{h}_{i}^{(T)}\right\}_{i \in +V_{1}}\right) \\ \mathbf{h}_{G_{2}} +&=f_{G}\left(\left\{\mathbf{h}_{i}^{(T)}\right\}_{i \in +V_{2}}\right) \\ s &=f_{s}\left(\mathbf{h}_{G_{1}}, +\mathbf{h}_{G_{2}}\right) \end{aligned} \]
    • -
    • 原式中关于\(\beta\)\(h(x)\)\(A(\alpha)\)都是常数,从正比式中消去,带入向量组有: +
    • 从上面的公式可以看到,在propagation阶段,GMN做出了两点改动 +
        +
      • 因为一次性输入一对图,因此第一步的邻域节点是从两张图的范围内找。但是一般而言两张图之间是没有节点连接的,除非两张图里的相同节点共享邻域?
      • +
      • 除了邻域信息的传递之外,作者还计算了两张图之间的match,这里用了一个最简单的attention机制,用待匹配两个节点embedding的距离加权两个节点embedding之间的差: \[ -∝ h(\beta) exp(T(x) \beta - A_l(\beta) + \alpha _1 \beta - \alpha _2 -g(\beta)) \\ +\begin{aligned} a_{j \rightarrow i} &=\frac{\exp +\left(s_{h}\left(\mathbf{h}_{i}^{(t)}, +\mathbf{h}_{j}^{(t)}\right)\right)}{\sum_{j^{\prime}} \exp +\left(s_{h}\left(\mathbf{h}_{i}^{(t)}, +\mathbf{h}_{j^{\prime}}^{(t)}\right)\right)} \\ \boldsymbol{\mu}_{j +\rightarrow i} &=a_{j \rightarrow +i}\left(\mathbf{h}_{i}^{(t)}-\mathbf{h}_{j}^{(t)}\right) \end{aligned} \]
      • -
      • 我们注意到,如果令\(-g(\beta)=-A_l -(\beta)\),原式就可以写成: \[ -∝ h(\beta) exp((T(x)+\alpha _1)\beta - (1+\alpha _2) A_l (\beta)) \\ -\] \[ -∝ h(\beta) exp(\alpha _1 ^{'} \beta - \alpha _2 ^{'} A_l -(\beta)) \\ +
      • 这样在update到下一层节点embedding时,match的那部分实际上计算了a图某一结点与b图所有节点的加权距离: +\[ +\sum_{j} \boldsymbol{\mu}_{j \rightarrow i}=\sum_{j} a_{j \rightarrow +i}\left(\mathbf{h}_{i}^{(t)}-\mathbf{h}_{j}^{(t)}\right)=\mathbf{h}_{i}^{(t)}-\sum_{j} +a_{j \rightarrow i} \mathbf{h}_{j}^{(t)} \]
      • -
      • 这样先验和后验形式一致,也就是共轭
      • -
      • 这样我们用统一的形式写下似然和先验 \[ -p(\beta | x, \alpha) ∝ p(x | \beta) p(\beta | \alpha) \\ -\] \[ -∝ h(x)exp[T(x)^T\beta - A_l(\beta)] h(\beta) exp[T(\beta)^T\alpha - -A_l(\alpha)] \\ +
      • 这样计算的复杂度就升到了\(O(V(G_1)V(G_2))\),但正是这逐点的比较能够区分那些细微的变化,而且可视化更加具有可解释性。所以该算法的使用场景应该是小图且对区分精度要求高
      • +
    • +
    • 对于这样的匹配问题可以用pair 或者triplet +loss,前者比较相似不相似,后者比较和两个候选相比跟哪个更相似,作者分别给出了两种形式下的margin +loss: \[ +L_{\text {pair }}=\mathbb{E}_{\left(G_{1}, G_{2}, t\right)}\left[\max +\left\{0, \gamma-t\left(1-d\left(G_{1}, +G_{2}\right)\right)\right\}\right] \\ +L_{\text {triplet }}=\mathbb{E}_{\left(G_{1}, G_{2}, +G_{3}\right)}\left[\max \left\{0, d\left(G_{1}, +G_{2}\right)-d\left(G_{1}, G_{3}\right)+\gamma\right\}\right] \\ \]
    • -
    • 这里我们可以计算log -normalizer关于参数求导的结果,注意,这是计算得到,不同于之前求指数族分布的最大似然估计得到的关于log -normalizer和sufficient statistics的性质: \[ -\frac{\partial A_l(\beta)}{\partial \beta}=\int _x T(x) p(x | \beta)dx +
    • 作者还特意提到,为了加速运算,可以对Graph +Embedding做二值化处理,这样在衡量距离的时候就是用汉明距离,牺牲掉了一些欧式空间的部分,具体做法是将整个向量过tanh并作平均内积用作训练时的图相似度,并设计损失将正样本对的汉明距离推向1,负样本对的汉明距离推向-1,假如在推断检索下使用汉明距离进行检索,这样的损失设计比margin +loss更加稳定: \[ +s\left(G_{1}, G_{2}\right)=\frac{1}{H} \sum_{i=1}^{H} \tanh +\left(h_{G_{1} i}\right) \cdot \tanh \left(h_{G_{2} i}\right) \\ +L_{\text {pair }}=\mathbb{E}_{\left(G_{1}, G_{2}, +t\right)}\left[\left(t-s\left(G_{1}, G_{2}\right)\right)^{2}\right] / 4 \\ -\] \[ -= E_{p(x|\beta)} [T(x)] \\ -\]
    • -
    • 上式可以通过指数族分布积分为1,积分对\(\beta\)求导为0,将这个等式变换证明。
    • +\begin{aligned} L_{\text {triplet }}=\mathbb{E}_{\left(G_{1}, G_{2}, +G_{3}\right)}\left[\left(s\left(G_{1}, +G_{2}\right)-1\right)^{2}+\right.\\\left.\left(s\left(G_{1}, +G_{3}\right)+1\right)^{2}\right] / 8 \end{aligned} \\ +\] 其中除以4或者除以8是为了约束损失的范围在[0,1]区间内。
    -

    指数族分布下的变分推断

    +

    Learning to +Update Knowledge Graphs by Reading News

      -
    • 接下来我们将ELBO中的参数后验写成指数族分布形式,可以看到最后的迭代公式相当简洁
    • -
    • 我们假定要优化的参数有两个,x和z,我们用\(\lambda\)\(\phi\)来近似\(\eta(z,x)\)\(\eta(\beta -,x)\),依然是要使ELBO最大,这时调整的参数是\(q(\lambda , \phi)\),实际上是\(\lambda\)\(\phi\)
    • -
    • 我们采用固定一个参数,优化另一个参数的方法,相互迭代使得ELBO变大
    • -
    • 首先我们改写ELBO,注意\(q(z,\beta)=q(z)q(\beta)\)\[ -ELBO=E_{q(z,\beta)}[\log p(x,z,\beta)] - E_{q(z,\beta)}[\log p(z,\beta)] -\\ -\] \[ -= E_{q(z,\beta)}[\log p(\beta | x,z) + \log p(z | x) + \log p(x)] - -E_{q(z,\beta)}[\log q(\beta)] - E_{q(z,\beta)}[\log q(z)] \\ -\]
    • -
    • 其中后验为指数家族分布,且q分布用简单的参数\(\lambda\)\(\phi\)去近似: EMNLP2019的一项工作,作者肯定是个篮球迷,举了一个很恰当的NBA转会的例子来说明本文要解决的问题:知识图谱更新
    • +
    • 比如发生了球员转俱乐部,则相关的两个俱乐部的球员图谱就会发生变化,作者提出了两个重点,如文中图1所示: +
        +
      • 知识图谱的更新只发生在text subgraph而不是1-hop subgraph
      • +
      • 传统方法不能从文本中获取隐藏的图谱更新信息,例如球员转会之后,这个球员的队友就会发生变化,这是文中没提但是可以推断出来的
      • +
    • +
    • 整体的结构是一个基于R-GCN和GAT的encoder和一个基于DistMult的decoder,基本上就是把RGCN改成了attention +based,decoder依然不变,做链接预测任务
    • +
    +

    encoder

    +
      +
    • encoder:RGCN+GAT=RGAT,在RGCN中前向过程为: \[ -p(\beta | x,z) = h(\beta) exp [ T(\beta) ^T \eta (z,x) - A_g -(\eta(z,x))] \\ -\] \[ -\approx q(\beta | \lambda) \\ -\] \[ -= h(\beta) exp [ T(\beta) ^T \eta (\lambda - A_g (\eta(\lambda))] \\ -\] \[ -p(z | x,\beta) = h(z) exp [ T(z) ^T \eta (\beta,x) - A_l -(\eta(\beta,x))] \\ -\] \[ -\approx q(\beta | \phi) \\ -\] \[ -= h(z) exp [ T(z) ^T \eta (\phi - A_l (\eta(\phi))] \\ +\mathbf{H}^{l+1}=\sigma\left(\sum_{r \in \mathbf{R}} +\hat{\mathbf{A}}_{r}^{l} \mathbf{H}^{l} \mathbf{W}_{r}^{l}\right) \]
    • -
    • 现在我们固定\(\phi\),优化\(\lambda\),将ELBO中无关常量除去,有: \[ -ELBO_{\lambda} = E_{q(z,\beta)}[\log p(\beta | x,z)] - -E_{q(z,\beta)}[\log q(\beta)] \\ +
    • 即对异构的边分给予一个参数矩阵,独立的计算之后求和再激活。 +将邻接矩阵改为注意力矩阵,注意力计算为: \[ +a_{i j}^{l r}=\left\{\begin{array}{ll}{\frac{\exp \left(a t t^{l +r}\left(\mathbf{h}_{i}^{l}, \mathbf{h}_{j}^{l}\right)\right)}{\sum_{k +\in \mathcal{N}_{i}^{r}} \exp \left(a t t^{l} r\left(\mathbf{h}_{i}^{l}, +\mathbf{h}_{k}^{l}\right)\right)}} & {, j \in \mathcal{N}_{i}^{r}} +\\ {0} & {, \text { otherwise }}\end{array}\right. \]
    • -
    • 代入指数家族分布,消去无关常量\(- -E_{q(z)}[A_g(\eta(x,z))]\),化简得到: \[ -ELBO_{\lambda} = E_{q(\beta)}[T(\beta)^T] -E_{q(z)}[\eta(z,x)] -E_{q(\beta)} [T(\beta)^T \lambda] + A_g(\lambda) +
    • 其中注意力函数\(attn\)基于文本计算 +
        +
      • 首先用双向GRU对序列编码\(u\)
      • +
      • 再利用序列注意力得到上下文表示 \[ +b_{t}^{l r}=\frac{\exp \left(\mathbf{u}_{t}^{T} \mathbf{g}_{t e x t}^{l +r}\right)}{\sum_{k=1}^{|S|} \exp \left(\mathbf{u}_{k}^{T} \mathbf{g}_{t +e x t}^{l r}\right)} \\ +\mathbf{c}^{l r}=\sum_{t=1}^{|S|} b_{t}^{l r} \mathbf{u}_{t} \\ \]
      • -
      • 利用之前log normalizer关于参数求导的结论,有: \[ -ELBO_{\lambda} = A_g^{'}(\lambda)^T[E_{q(z)}[\eta(z,x)]] - \lambda -A_g^{'}(\lambda) ^T + A_g (\lambda) +
      • 之后利用注意力的时候,trainable guidance vector\(g\)就利用了这个上下文表示,利用一个简单的线性插值引入 +\[ +\mathbf{g}_{f i n}^{l r}=\alpha^{l r} \mathbf{g}_{g r a p h}^{l +r}+\left(1-\alpha^{l r}\right) \mathbf{U}^{l r} \mathbf{c}^{l r} \\ +a t t^{l r}(\mathbf{h}_{i}^{l}, \mathbf{h}_{j}^{l}) =\mathbf{g}_{f i +n}^{l r}[\mathbf{h}_{i}^{l} | \mathbf{h}_{j}^{l}] \\ \]
      • -
      • 对上式求导,令其为0,有: \[ -A_g^{''}(\lambda)^T[E_{q(z)}[\eta(z,x)]] - -A_g^{'}(\lambda)-\lambda A_g^{''}(\lambda) ^T + A_g^{} -(\lambda) = 0 \\ -\lambda = E_{q(z)}[\eta(z,x)] \\ +
    • +
    • 在实际应用到作者想要完成的kg update任务中,作者还引入了几个小技巧 +
        +
      • RGCN/RGAT中的参数量随着边(关系)的类别数量成线性增长,为了减少参数量,作者利用了basis-decomposition,也就是k类关系,存在k套参数,这k套参数用b套参数线性组合而成,而b小于k,这样来减少参数
      • +
      • 实际数据集里实体之间的关系很稀疏,一两层的RGAT聚合不到消息,因此在构造数据集时首先对图中所有实体之间人为添加一个叫SHORTCUT的关系,并使用现成的信息抽取工具将SHORTCUT细化为add,delete和other,用来初步的判定人员的转会(从一个俱乐部delete,add到另一个俱乐部)关系
      • +
    • +
    +

    decoder

    +
      +
    • 在EMBEDDING ENTITIES AND RELATIONS FOR LEARNING AND INFERENCE IN +KNOWLEDGE +BASES一文中总结了知识图谱中的关系embedding学习问题,可以归结为不同的线性/双线性参数矩阵搭配不同的打分函数,计算margin +triplet loss:
    • +
    • DistMult即最简单的,将双线性参数矩阵换成对角阵,即最后的分数是两个实体embedding逐元素相乘并加权求和得到,权重与关系相关,在本文中的具体实现为: +\[ +P(y)=\operatorname{sigmoid}\left(\mathbf{h}_{i}^{T}\left(\mathbf{r}_{k} +\circ \mathbf{h}_{j}\right)\right) \]
    • -
    • 我们就得到了\(\lambda\)的迭代式!同理可以得到: \[ -\phi = E_{q(\beta)}[\eta(\beta,x)] \\ +
    +

    result

    +
      +
    • 对比几个Baseline:RGCN,PCNN,感觉作者使用了GRU这样data-hungry的网络提取语义计算相似度,数据集偏小,当然最后结果还是很好看,可以看到数据集明显不平衡,但是在add和delete这些小样本类上RGAT比RGCN提升了一倍的准确率。
    • +
    • 值得称赞的是论文将链接预测问题包装的很好,一个update突出了持续学习持续更新的想法,最后简化问题为链接预测,模型没有太多改进,但是效果达到了。
    • +
    +

    Learning +Attention-based Embeddings for Relation Prediction in Knowledge +Graphs

    +
      +
    • 依然是做链接预测,依然是基于GAT
    • +
    • 作者认为在KG当中关系非常重要,但是又不好给边加特征,因此就曲线救国,将边的特征融入到节点的特征当中
    • +
    • 一图胜千言
    • +
    • 从左到右 +
        +
      • 输入,依然是节点特征输入GAT,只不过每个节点特征是与其相关的三元组特征做self +attention得到,而三元组特征由节点和关系特征拼接得到,绿色为输入关系特征,黄色为输入节点特征: +\[ +c_{i j k}=\mathbf{W}_{1}\left[\vec{h}_{i}\left\|\vec{h}_{j}\right\| +\vec{g}_{k}\right] \\ +\begin{aligned} \alpha_{i j k} &=\operatorname{softmax}_{j +k}\left(b_{i j k}\right) \\ &=\frac{\exp \left(b_{i j +k}\right)}{\sum_{n \in \mathcal{N}_{i}} \sum_{r \in \mathcal{R}_{i n}} +\exp \left(b_{i n r}\right)} \end{aligned} \\ +\overrightarrow{h_{i}^{\prime}}=\|_{m=1}^{M} \sigma\left(\sum_{j \in +\mathcal{N}_{i}} \alpha_{i j k}^{m} c_{i j k}^{m}\right) \\ \]
      • -
      • 写完整应该是: \[ -\lambda = E_{q(z | \phi)}[\eta(z,x)] \\ -\phi = E_{q(\beta | \lambda)}[\eta(\beta,x)] \\ +
      • 之后经过GAT,得到灰色的中间层节点特征,两个3维灰色拼接是指GAT里multi-head +attention的拼接,之后两个6维灰色与绿色做变换之后拼接是指依然用三元组表示每个节点
      • +
      • 最后一层,不做拼接了,做average +pooling,并且加入了输入节点特征,再拼接上关系特征,计算损失
      • +
      • 损失依然用三元组距离,即subject+predicate-object,margin triplet +loss,负采样时随机替换subject或者object
      • +
    • +
    • 以上是encoder部分,decoder用ConvKB \[ +f\left(t_{i j}^{k}\right)=\left(\prod_{m=1}^{\Omega} +\operatorname{ReLU}\left(\left[\vec{h}_{i}, \vec{g}_{k}, +\vec{h}_{j}\right] * \omega^{m}\right)\right) \mathbf{. W} \\ \]
    • -
    • 观察这两个迭代式,变量更新的路径是: \[ -\lambda \rightarrow q(\beta | \lambda) \rightarrow \phi \rightarrow q(z -| \phi) \rightarrow \lambda +
    • 损失为soft-margin loss(好像1和-1写反了?) \[ +\begin{array}{l}{\mathcal{L}=\sum_{t_{i j}^{k} \in\left\{S \cup +S^{\prime}\right\}} \log \left(1+\exp \left(l_{t_{i j}^{k}} * +f\left(t_{i +j}^{k}\right)\right)\right)+\frac{\lambda}{2}\|\mathbf{W}\|_{2}^{2}} \\ +{\text { where } l_{t_{i j}^{k}}=\left\{\begin{array}{ll}{1} & +{\text { for } t_{i j}^{k} \in S} \\ {-1} & {\text { for } t_{i +j}^{k} \in S^{\prime}}\end{array}\right.}\end{array} \]
    • +
    • 另外作者还为2跳距离的节点之间加入了边
    • +
    • 结果非常好,在FB15K-237和WN18RR上取得了SOTA。作者并没有试图将边的特征直接整合进GAT的message +passing,而是就把特征当成待训练的输入,用encoder专注于训练特征,并且在模型的每一层都直接输入的初始特征来保证梯度能够传递到原始输入。
    • +
    +]]>
    + + 自然语言处理 + + + deep learning + natural language processing + machine learning + knowledge graph + +
    + + K-Means and KNN + /2017/03/16/kmeans/ + +
  • 以简单的Iris数据集做测试,实现了K-means++聚类算法,并与sklearn中自带的KNN算法进行比较
  • +
  • 标题本来是K-Means&KNN,把&改成了和,因为标题中出现特殊符号&会导致我的sitemap生成错误...... +***
  • + + +
    +i0onl8.jpg + +
    +

    简介

    +
      +
    • K-Means是简单的基于划分的聚类方法,要解决的问题是,现在有n个样本(点集X),将他们的特征向量投射到高维空间中,根据空间分布可以大致划分成几个子空间,每个子空间中的点属于同一类,现在需要计算出每个点所在的类,大致思想就是随机选择k个点(中心点集C)作为中心点,其余的点自己站队:离k个中心点里哪个点最近就站那个点的队,即和那个中心点划分到同一类中,这样就能形成k个类,重复上过程,期间引入一个损失评估,比如以各个类中的点到这个类中心点距离的和作为评估指标,当指标小于某一程度或者指标变化小于某一程度就停止重复
    • +
    • KNN则比较简单粗暴,其思想类似于民主投票。KNN不训练数据,选定一个值K,对于每一个需要预测的向量,在已知类别的数据集中找到与这个向量最近的K,这K个点中拥有最多点个数的类别就是预测类别,即让离某个点最近的K个点投票决定这个点的类别,哪个类别的点票数多就是哪个类别
    • +
    +

    K-means++

    +
      +
    • k-means++在k-means上优化了初始k个点的选择。原始算法是随机取k个点,显然这样随机不确定性太大,比较好的k个点的选择方案应该是他们离彼此尽量远,但不能太远。尽量远,就能尽可能贴近最终理想中心点分布;不能太远,是为了防止将一些错误点孤立点作为中心点
    • +
    • 算法上的实现是先随机从X集中取第一个中心点,之后反复以下过程取中心点 +
        +
      • 计算每个点\(c_i\)到已经选出的中心点\(k_1,k_2...\)的距离,选取最小的一个距离作为\(c_i\)的距离,这个距离的意义即\(c_i\)作为下一个中心点时离其他中心点至少有多远
      • +
      • \(c_1,c_2,c_3......\)的距离归一化,并排成一条线
      • +
      • 这条线长度为1,分成了许多段,每一段的长度就代表了这一段所代表的点的距离在归一化中所占的比例,距离越大,比例越大
      • +
      • 在(0,1)之间随机取一个数,这个数所在的段区间所代表的点就是下一个中心点,将其加入中心点集C,接着重复找下一个中心点
      • +
    • +
    • 可以看出,如果距离够远,在线上被随机抽到的可能越大,符合我们的需求
    • +
    +

    K-Means代码实现

    +

    数据检视

    +
      +
    • Iris是鸢尾花分类数据集,150个样本,均匀分成3类,每一个样本有4个属性 +
    • +
    +

    初始化数据

    +
      +
    • 初始化数据
      def init():
      iris = load_iris()
      X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=33)
      ss = StandardScaler()
      X_train = ss.fit_transform(X_train)
      X_test = ss.fit_transform(X_test)
      return X_train, X_test, y_train, y_test, iris

    • +
    +

    k-means++初始化k个点

    +
      +
    • D2是每个点的距离(即之前定义的里其他中心点至少有多远)
    • +
    • probs归一化
    • +
    • cumprobs将归一化的概率累加,排列成一条线
      def initk(X_train, k):
      C = [X_train[0]]
      for i in range(1, k):
      D2 = scipy.array([min([scipy.inner(c - x, c - x) for c in C]) for x in X_train])
      probs = D2 / D2.sum()
      cumprobs = probs.cumsum()
      r = scipy.rand()
      for j, p in enumerate(cumprobs):
      if r < p:
      i = j
      break
      C.append(X_train[i])
      return C

    • +
    +

    损失评估

    +
      +
    • 在这里用每个类内点到中心点距离平方和的总和作为损失评估 +
      def evaluate(C, X_train, y_predict):
      sum = 0
      for i in range(len(X_train)):
      c = C[y_predict[i]]
      sum += scipy.inner(c - X_train[i], c - X_train[i])
      return sum
    • +
    +

    聚类

    +
      +
    • 初始化k个中心点后,所有的点就可以分类
    • +
    • 重新在每个类中取中心点,在这里取一个类中所有点坐标平均作为中心点坐标 +
      def cluster(C, X_train, y_predict, k):
      sum = [0, 0, 0, 0] * k
      count = [0] * k
      newC = []
      for i in range(len(X_train)):
      min = 32768
      minj = -1
      for j in range(k):
      if scipy.inner(C[j] - X_train[i], C[j] - X_train[i]) < min:
      min = scipy.inner(C[j] - X_train[i], C[j] - X_train[i])
      minj = j
      y_predict[i] = (minj + 1) % k
      for i in range(len(X_train)):
      sum[y_predict[i]] += X_train[i]
      count[y_predict[i]] += 1
      for i in range(k):
      newC.append(sum[i] / count[i])
      return y_predict, newC
    • +
    +

    主函数

    +
      +
    • 计算损失,更新k个中心点,再站队(聚类)一次
    • +
    • 重复,直到损失变化小于10%
    • +
    • 每次迭代显示新旧损失,显示损失变化
    • +
    • 最后输出分类结果
      def main():
      X_train, X_test, y_train, y_test, iris = init()
      k = 3
      total = len(y_train)
      y_predict = [0] * total
      C = initk(X_train, k)
      oldeval = evaluate(C, X_train, y_predict)
      while (1):
      y_predict, C = cluster(C, X_train, y_predict, k)
      neweval = evaluate(C, X_train, y_predict)
      ratio = (oldeval - neweval) / oldeval * 100
      print(oldeval, " -> ", neweval, "%f %%" % ratio)
      oldeval = neweval
      if ratio < 0.1:
      break

      print(y_train)
      print(y_predict)
      n = 0
      m = 0
      for i in range(len(y_train)):
      m += 1
      if y_train[i] == y_predict[i]:
      n += 1
      print(n / m)
      print(classification_report(y_train, y_predict, target_names=iris.target_names))

    • +
    +

    KNN代码

    +
      +
    • 直接使用了sklearn中的KNeighborsClassifier
      from sklearn.datasets import load_iris
      from sklearn.preprocessing import StandardScaler
      from sklearn.neighbors import KNeighborsClassifier
      from sklearn.model_selection import train_test_split
      from sklearn.metrics import classification_report


      def init():
      iris = load_iris()
      X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=33)
      ss = StandardScaler()
      X_train = ss.fit_transform(X_train)
      X_test = ss.fit_transform(X_test)
      return X_train, X_test, y_train, y_test, iris


      def KNN(X_train, X_test, y_train, y_test, iris):
      knc = KNeighborsClassifier()
      knc.fit(X_train, y_train)
      y_predict = knc.predict(X_test)
      print(knc.score(X_test, y_test))
      print(classification_report(y_test, y_predict, target_names=iris.target_names))


      def main():
      X_train, X_test, y_train, y_test, iris = init()
      KNN(X_train, X_test, y_train, y_test, iris)

      if __name__ == "__main__":
      main()
    • +
    +

    预测结果

    +
      +
    • 指标说明 +对于二分类,四种情况的总数:对的预测成对的TP;对的预测成错的FN;错的预测成对的FP;错的预测成错的TN +\[ +精确率:P=\frac{TP}{TP+FP} \\ +召回率:R=\frac{TP}{TP+FN} \\ +1F值:\frac {2}{F_1}=\frac1P+\frac1R \\ +\]

    • +
    • K-Means程序输出 预测正确率:88.39% 平均精确率:89% 召回率:0.88 +F1指标:0.88

    • +
    • KNN程序输出 预测正确率:71.05% 平均精确率:86% 召回率:0.71 +F1指标:0.70

    • +
    • 原始分类 可以看到这个数据集本身在空间上就比较方便聚类划分

    • +
    • 预测分类

    • +
    +

    改进

    +

    未知k的情况

    +
      +
    • 以上是我们已知鸢尾花会分成3类,加入我们不知道有几类呢?毕竟k-means是无监督学习,可以在无标签的情况下计算,自然标签的个数我们也极有可能不知道,那么如何确定k?
    • +
    • 一种方式是canopy算法
    • +
    • 待补充
    • +
    +

    空类的处理

    +
      +
    • 待补充
    +

    不同距离计算方式

    +
      +
    • 待补充
    • +
    +

    ANN算法

    ]]>
    机器学习 - math - inference - mcmc - variational inference - em + machine learning + code
    - Paper reading on Knowledge Graphs - /2019/11/13/kg/ - 知识图谱专辑 - 跨语言知识图谱中的实体对齐 - Knowledge Graph Language -Model - 动态知识图谱对话生成 - Graph2Seq - Graph Matching Network - -动态更新知识图谱 - Attention-based Embeddings for Relation -Prediction

    + Note for Latent Dirichlet Allocation + /2018/07/23/lda/ + +

    Latent Dirichlet Allocation 文档主题生成模型学习笔记 +本文主要归纳自《LDA数学八卦》,原文写的非常精彩(建议先阅读原文),有许多抛砖引玉之处,本文梳理了其一步一步推出LDA的脉络,删除了不相关的一些扩展,比较大白话的总结一下LDA。

    -

    Cross-lingual -Knowledge Graph Alignment via Graph Matching Neural Network

    -
      -
    • 研究:跨语言知识图谱中实体的对齐

    • -
    • 一般的做法,在各自语言的知识图谱中投影到低维向量,然后学习到一个相似度计算函数

    • -
    • 问题在于,上面的做法依赖于相同实体在不同语言知识图谱下的邻域结构相同这一假设,但这一假设并不总是成立,因此传统的做法对少对齐邻域节点/少邻域节点的实体不友好

    • -
    • 作者提出主题实体图来编码实体节点的上下文信息,将节点embedding之间的Match转换为主题实体图之间的图Match

    • -
    • 这里的主题实体指的是需要对齐的实体,主题实体图即主题实体周围一跳邻域实体与本体一同构建的子图,假如在原知识图谱里这两个实体没有直接相连的话就在知识图谱里添加一条边

    • -
    • 得到主题实体图之后,经过四层网络计算出两个主题实体图之间的相似度:

      +
      +i0oNlT.jpg + +
      +

      LDA用来做什么

        -
      • 输入表示层:对主题实体图中的每一个实体学习到embedding。首先用word-level -lstm学习到初始embedding,然后因为是有向图,因此需要将邻域节点区分为输入和输出邻居,分别做聚合(FFN+mean -pooling),拼接到上一次得到的实体embedding并更新(FFN),迭代K次

      • -
      • 节点级别的局部匹配层:两个图互相匹配所有实体节点,这里用了基于注意力的Matching,即先用cosine距离得到主题实体图1里某个节点i和主题实体图2所有节点之间的相似度,用这个相似度作为注意力权重去加权主题实体图2所有节点得到图2的graph -embedding,然后用这个graph embedding和图1的query entity -embedding之间计算一个多角度cosine距离作为local match -score,这个多角度是指l个角度用l个加权向量(d维,同embedding维度)表示。一个角度下的cosine距离就用一个加权向量(逐元素相乘)加权两个embedding再计算cosine距离,l个角度合在一起就是一个\(W \in R^{l*d}\)的矩阵,如下: \[ -score_{perspective_k} = cosine(W_k \cdot embedding_1, W_k \cdot -embedding_2) -\]

      • -
      • 全局匹配层:局部匹配层存在着之前提到的对少共现邻居节点不友好的问题,这里就需要全局匹配。具体做法是,再用一个GCN将局部的match -embedding(上一层多角度cosine -score得到的向量)传递到整个主题实体图,之后在整个图上做一个FFN + -max/mean pooling,得到两个图的graph matching vector

      • -
      • 预测层:将两个主题实体图的graph matching -vector拼接送入一个softmax预测

      • -
    • -
    • 训练时,对每一个正样本启发式的生成了20个负样本,两个方向各十个,这里直接基于word-level -average embedding作为实体的特征向量,匹配十个最相似的实体

    • +
    • LDA是一种主题模型,问题实际上是主题模型是用来做什么?用来表示文档 +。在这里将文档看成一个词袋。
    • +
    • 如果将词典里每一个词看成一个特征,tfidf值作为特征值大小来表示文档,则文档的特征向量太过稀疏,且维度太高
    • +
    • LSI的解决办法是,将文档-词的矩阵进行奇异值分解,降维,但是这样得到的降维空间,即词到文档之间的隐变量无法解释,纯数学的方法,太暴力
    • +
    • PLSA提出了隐变量应该是主题,可以把文档表示为主题向量,而主题定义为在词典上的某一种多项式分布,这样PLSA中包含了两层多项式分布:文档到主题的多项式分布(文档中各个主题的混合比例,即文档的特征向量),主题到词的多项式分布(在整个词典上的概率分布,表示不同主题下各个词出现的概率)
    • +
    • LDA则对这两个多项式分布的参数制定了迪利克雷先验,为PLSA引入贝叶斯框架
    -

    Barack’s -Wife Hillary: Using Knowledge Graphs for Fact-Aware Language -Modeling

    -
      -
    • 作者希望在语言模型当中维持一个local knowledge -graph来管理已经探测到的事实,并利用该图谱来查询未知的事实用于文本生成,称之为KGLM(Knowledge -Graph Language Model)

    • -
    • 假设实体集合为\(\xi\),则KGLM要预测的是 \[ -p(x_t,\xi _t|x_{1,t-1},\xi_ {1,t-1}) -\]

    • -
    • 生成下一个词的流程可以拆分如下:

      +

      贝叶斯模型

        -
      • 下一个词不是实体:那就正常词典范围上计算概率

      • -
      • 下一个词是全新实体:在正常词典以及所有实体范围上计算概率

      • -
      • 下一个词是与已经看见的实体相关的实体:先挑出一个已经看见的实体作为父节点,再挑出一个子节点,之后在正常词典以及该子节点的所有别名上计算概率

      • -
    • -
    • 作者使用LSTM作为LM的基础模型,所有的挑选:挑新实体、挑父节点、挑子节点,均利用LSTM的隐状态(切分为三部分),并加上实体和关系的预训练embedding作为输入依赖,之后通过softmax计算概率

    • -
    • 为了实现这样的模型数据集应该提供实体信息,作者提出了Linked -WikiText2数据集,该数据集的构建流程如下:

      +
    • LDA是一种贝叶斯模型
    • +
    • 给定训练数据,贝叶斯模型怎么学习参数(参数的分布):贝叶斯估计
        -
      • 根据维基百科上的链接创造实体之间的链接,借助neural-el来识别wikidata数据库中额外的链接,使用stanford -corenlp来做共指消解。

      • -
      • 构造local knowledge graph:接下来需要建立实体之间的parents -relation,每遇到一个实体a,将其在wikidata中相关联的所有实体{b}加入matching的候选,加入相关联的某一实体b在之后的文段中出现了,则将实体a作为实体b的父节点

      • -
      • 以上的做法只是构建了初始集合,需要不断扩展,作者还对日期、量词等做了alias -table

      • -
      • 以下是一句话在Linked WikiText2中的表示,相比WikiText使用api -query构造的方法,Linked -WikiText2直接对原始html操作,保留了更多链接信息:

      • +
      • 先给参数一个先验分布\(p(\theta)\)
      • +
      • 给定数据,计算似然\(p(X|\theta)\)和evidence\(P(X)\),根据贝叶斯公式计算参数的后验分布
      • +
      • 后验分布就是学习到的参数分布 \[ +p(\vartheta | X)=\frac{p(X | \vartheta) \cdot +p(\vartheta)}{p(\mathcal{X})} +\]
    • -
    • Train and -Inference:首先对实体和关系使用TransE算法做一个Pretraining,给定三元组(p,r,e),目标是最小化距离: -\[ -\delta\left(\mathbf{v}_{p}, \mathbf{v}_{r}, -\mathbf{v}_{e}\right)=\left\|\mathbf{v}_{p}+\mathbf{v}_{r}-\mathbf{v}_{e}\right\|^{2} -\] 采用Hinge Loss,使得正负样本得分之差不超过\(\gamma\): \[ -\mathcal{L}=\max \left(0, \gamma+\delta\left(\mathbf{v}_{p}, -\mathbf{v}_{r}, -\mathbf{v}_{e}\right)-\delta\left(\mathbf{v}_{p}^{\prime}, -\mathbf{v}_{r}, \mathbf{v}_{e}^{\prime}\right)\right) -\]

    • -
    • 虽然整个过程是生成式的,但是所有变量均可见,因此可以端到端的直接训练,对于有多个父节点的实体节点,需要对概率做归一化

    • -
    • 在推理过程中,我们没有标注信息,我们希望计算的也是单词\(x\)在实体\(\xi\)求和得到的边缘概率,而不是联合概率(我们只希望得到词,词的实体信息被marginalize了),然而实体太多,不可能对所有实体计算联合概率再求和,因此作者采用了重要性采样: -\[ -\begin{aligned} p(\mathbf{x}) &=\sum_{\mathcal{E}} p(\mathbf{x}, -\mathcal{E})=\sum_{\mathcal{E}} \frac{p(\mathbf{x}, -\mathcal{E})}{q(\mathcal{E} | \mathbf{x})} q(\mathcal{E} | \mathbf{x}) -\\ & \approx \frac{1}{N} \sum_{\mathcal{E} \sim q} -\frac{p(\mathbf{x}, \mathcal{E})}{q(\mathcal{E} | \mathbf{x})} +

    • 可能数据太多,那就分批更新,上一次更新后得到的后验作为下一次更新的先验,类似于随机梯度下降中的思想
    • +
    • 对于新数据的似然,不像最大似然估计或者最大后验估计,两者是点估计,直接算\(p(x_{new}|\theta _{ML})\),\(p(x_{new}|\theta +_{MAP})\),贝叶斯估计需要对参数分布求积分: \[ +\begin{aligned} +p(\tilde{x} | X) &=\int_{\vartheta \in \Theta} p(\tilde{x} | +\vartheta) p(\vartheta | X) \mathrm{d} \vartheta \\ +&=\int_{\vartheta \in \Theta} p(\tilde{x} | \vartheta) \frac{p(X | +\vartheta) p(\vartheta)}{p(X)} \mathrm{d} \vartheta \end{aligned} -\] 其中proposed -distribution使用判别式的KGLM得到,即另外训练一个KGLM判断当前token的annotation

    • -
    • 结果非常漂亮,KGLM仅仅用了LSTM,参数量也不大,和超大规模的GPT-2模型相比,在实体词的预测上有着明显优势。

    • -
    -

    DyKgChat: -Benchmarking Dialogue Generation Grounding on Dynamic Knowledge -Graphs

    -
      -
    • 本文作者提出了一个新的任务,动态知识图谱对话生成,也就是希望抓住图谱中的关系,来将基于知识图谱的对话生成推广到zero-shot

    • -
    • 任务的详细描述分为两步:

      -
        -
      • 每轮对话t,给定输入x和图谱K,希望生成正确的回答y,而且包含正确的知识图谱实体

      • -
      • 当知识图谱更新之后(这里只可能更新关系和受体),回答y能够相应更改回答。

      • -
    • -
    • 为了有效衡量动态知识图谱对话的质量,作者提出了两类指标:

      -
        -
      • 知识实体建模:包括已知要预测实体,实体词命中的准确率;判别要预测实体还是通用词的TP;整个知识图谱所有实体的TP

      • -
      • 图自适应:作者提出了三种改变图的方法,包括shuffle和随即替换实体,观察生成的序列是否替换且替换正确

      • -
    • -
    • 作者提出了一个平行语料库,包含中英两个电视剧的语料,并做了详细的处理

    • -
    • 作者提出的模型Qadpt在seq2seq的基础上修改,首先将decoder的当前状态\(d_t\)生成一个controller\(c_t\)来决定是从KG里挑实体还是从generic -vocab里生成一般词汇。和copy -mechanism一样这个选择不是hard,而是分别计算概率,最后将两部分词表拼到一起,最后依概率选择: -\[ -\begin{aligned} P\left(\{K B, \mathcal{W}\} | y_{1} y_{2} \ldots -y_{t-1}, \mathbf{e}(x)\right) -\\=\operatorname{softmax}\left(\phi\left(\mathbf{d}_{t}\right)\right) \\ -\mathbf{w}_{t}=P\left(\mathcal{W} | y_{1} y_{2} \ldots y_{t-1}, -\mathbf{e}(x)\right) \\ c_{t}=P\left(K B | y_{1} y_{2} \ldots y_{t-1}, -\mathbf{e}(x)\right) \\ \mathbf{o}_{t}=\left\{c_{t} \mathbf{k}_{t} ; -\mathbf{w}_{t}\right\} \end{aligned} -\]

    • -
    • 至于如何产生实体候选列表,就是在知识图谱上做reasoning,不同于一般的attention -based graph embedding的做法,作者采用了multi-hop reasoning

      -
        -
      • 首先将path matrix和adjacency matrix合成transition matrix,其中的path -matrix是指用\(d_t\)学习到的每个实体选择每一种关系的概率,之后依概率选择受体节点:
      • -
      -

      \[ -\begin{aligned} \mathbf{R}_{t} -&=\operatorname{softmax}\left(\theta\left(\mathbf{d}_{t}\right)\right) -\\ \mathbf{A}_{i, j, \gamma} &=\left\{\begin{array}{ll}{1,} & -{\left(h_{i}, r_{j}, t_{\gamma}\right) \in \mathcal{K}} \\ {0,} & -{\left(h_{i}, r_{j}, t_{\gamma}\right) \notin -\mathcal{K}}\end{array}\right.\\ \mathbf{T}_{t}=\mathbf{R}_{t} -\mathbf{A} \end{aligned} -\]

      +\]
    • +
    • 贝叶斯估计里常常出现两个问题
        -
      • 之后取一个初始向量\(s\)(均匀分布?),用transition -matrix做n次transform,得到每个实体出现的概率并提供给controller计算,这里会使用one -hot ground truth计算一个交叉熵作为辅助损失
      • +
      • 有了先验,有了似然,计算出的后验很复杂
      • +
      • evidence很难算
    • -
    -

    Graph2Seq: -Graph to Sequence Learning with Attention-based Neural Networks

    -
      -
    • 顾名思义,输入为图结构组织的数据,生成的是序列

    • -
    • 以往的做法,将图编码成固定长度的序列,再用Seq2Seq,作者认为这样存在信息丢失,本身Enc -Seq 2 Dec Seq就存在信息丢失,现在Graph 2 Enc -Seq会再丢失一层信息

    • -
    • 因此比较自然的做法应该是,解码器在编码的图节点上做attention,直接利用图的信息

    • -
    • 首先是图编码器,参考了GraphSage的做法,值得注意的是作者处理的是有向图,因此将邻居节点按两个方向做了区分,分别做Aggregate和Update的操作,做了k跳之后再拼接回来

    • -
    • 作者试了Mean、LSTM、Pooling三种,由于邻居是无序的,因此LSTM没有时序上的效果,作者直接随机排列邻居用LSTM -Aggregate

    • -
    • 作者认为传给解码器的不只node embedding还需要graph -embedding。作者采用了两种方法获取graph embedding

      +
    • 因此共轭和gibbs sampling分别解决这两个问题
        -
      • Pooling-based:先将所有的node -embedding经过一个全连接层,然后逐元素做max、min、average -pooling,作者发现三种方法的实际效果相差不大,就使用max -pooling作为默认的池化方法

      • -
      • Node-based:在图中加入一个超级节点,该节点与图中其他所有节点相连,用该节点经过图编码之后的embedding作为Graph -embedding

      • +
      • 共轭:给定似然,找一个先验,使得后验的形式和先验一致
      • +
      • gibbs +sampling:利用MCMC的思路去近似后验,而不用显式的计算evidence
    • -
    • 基于注意力的解码器:graph -embedding作为解码器的初始状态输入,之后decoder每一步生成在所有node -embedding上的attention并加权作为该时间步decoder的隐状态

    • -
    • 重点关注NLG task,作者测试了SQL2Text任务,首先将SQL -Query建图,然后使用Graph2Seq。效果显著好于SQL -Query到Text的Seq2seq

    • -
    • 另外在Aggregate的比对实验中发现,Mean -Pooling的效果最好,对于Graph Embedding,Pooling based的效果显著好于Node -based

    • +
    • 假如是带隐变量的贝叶斯模型,那么有 \[ +p(\vartheta|x) = \int_{z} p(\vartheta|z)p(z|x) +\]
    • +
    • 在LDA当中,隐变量z就是词所属的主题(词的主题分配),那么\(p(\vartheta|z)\)自然是很好求的,那么剩下的\(p(z|x)\),就再套上面贝叶斯推断的公式: \[ +p(z | X)=\frac{p(X | z) \cdot p(z)}{p(\mathcal{X})} +\]
    • +
    • 在介绍LDA之前,介绍了其他两个模型,带贝叶斯的unigram以及plsa,前者可以看成是没有主题层的LDA,后者可以看成是没有贝叶斯的LDA
    • +
    • 接下来就分别介绍共轭、gibbs +sampling、带贝叶斯的unigram/plsa,最后介绍LDA
    -

    Graph -Matching Networks for Learning the Similarity of Graph Structured -Objects

    +

    共轭

    +

    Gamma函数

      -
    • google出品,实验和可视化结果一如既往的丰富
    • -
    • 两点贡献: +
    • 定义 \[ +\Gamma (x) = \int _0 ^{\infty} t^{x-1} e^{-t} dt +\]
    • +
    • 因为其递归性质\(\Gamma(x+1)=x\Gamma(x)\),可以将阶乘的定义扩展到实数域,进而将函数导数的定义扩展到实数集,例如计算1/2阶导数
    • +
    • Bohr-Mullerup定理:如果\(f:(0,\infty) +\rightarrow (0,\infty)\),且满足
        -
      • 证明了GNN可以产生用于相似度计算的graph embedding
      • -
      • 提出了attention based的Graph Matching -Networks,并超越了baseline
      • +
      • \(f(1)=1\)
      • +
      • \(f(x+1)=xf(x)\)
      • +
      • \(log f(x)\)是凸函数 那么\(f(x)=\Gamma(x)\)
    • +
    • Digamma函数 \[ +\psi (x)=\frac{d log \Gamma(x)}{dx} +\] 其具有以下性质 \[ +\psi (x+1)=\psi (x)+\frac 1x +\]
    • +
    • 在用变分推断对LDA进行推断时结果就是digamma函数的形式
    -

    Graph Embedding Model

    +

    Gamma分布

      -
    • baseline:Graph Embedding -Model,一个简单的encode-propagation-aggregate模型
    • -
    • encode:将点和边的特征通过MLP编码得到embedding
    • -
    • proprgation:将中心点,邻接点,邻接边的embedding传递到下一层的中心点embedding +
    • 将上式变换 \[ +\int _0 ^{\infty} \frac{x^{\alpha -1}e^{-x}}{\Gamma(\alpha)}dx = 1 +\] +因此可取积分中的函数作为概率密度,得到形式最简单的Gamma分布的密度函数: \[ -\begin{aligned} \mathbf{m}_{j \rightarrow i} &=f_{\text {message -}}\left(\mathbf{h}_{i}^{(t)}, \mathbf{h}_{j}^{(t)}, \mathbf{e}_{i -j}\right) \\ \mathbf{h}_{i}^{(t+1)} &=f_{\text {node -}}\left(\mathbf{h}_{i}^{(t)}, \sum_{j:(j, i) \in E} \mathbf{m}_{j -\rightarrow i}\right) \end{aligned} +Gamma_{\alpha}(x)=\frac{x^{\alpha -1}e^{-x}}{\Gamma(\alpha)} \]
    • -
    • aggregate:作者用门控的方式将各个节点的embedding加权求和得到最后的graph -embedding \[ -\mathbf{h}_{G}=\operatorname{MLP}_{G}\left(\sum_{i \in V} -\sigma\left(\operatorname{MLP}_{\operatorname{gate}}\left(\mathbf{h}_{i}^{(T)}\right)\right) -\odot \operatorname{MLP}\left(\mathbf{h}_{i}^{(T)}\right)\right) +
    • 指数分布和\(\chi +^2\)分布都是特殊的Gamma分布,且作为先验分布非常有用,广泛应用于贝叶斯分析当中。
    • +
    • Gamma分布与泊松分布具有形式上的一致性,实际上在两者的通常表示中,仅仅只有参数差1的区别,且之前说到阶乘可以用Gamma函数表示,因此可以直观的认为Gamma分布是Poisson分布在正实数集上的连续化版本。 +\[ +Poisson(X=k|\lambda)=\frac{\lambda ^k e^{-\lambda}}{k!} \]
    • +
    • 令二项分布中\(np=\lambda\),当n趋向于无穷且p趋向于0时,泊松分布就是二项分布的极限分布。经常用于解释泊松分布的一个例子是交换机接收呼叫,假设将整个时间分成若干个时间段,每个时间段内至多达到一次呼叫,概率为p,则总体呼叫数符合一个二项分布,当np为定值\(\lambda\)时,将时间分为无穷个段,几乎是连续的,取\(p=\frac{\lambda}{n}\)带入二项分布,取极限后即得到泊松分布。在此基础上分布的取值连续化(即将泊松分布中k的阶乘用Gamma函数替代)就得到Gamma分布。
    -

    Graph Matching Networks

    +

    Beta分布

      -
    • GMN并不像Baseline一样分别对两个图先生成embedding再match,而是接受两个图作为输入直接输出similarity -score。 \[ -\begin{aligned} \mathbf{m}_{j \rightarrow i} &=f_{\text {message -}}\left(\mathbf{h}_{i}^{(t)}, \mathbf{h}_{j}^{(t)}, \mathbf{e}_{i -j}\right), \forall(i, j) \in E_{1} \cup E_{2} \\ \boldsymbol{\mu}_{j -\rightarrow i} &=f_{\text {match }}\left(\mathbf{h}_{i}^{(t)}, -\mathbf{h}_{j}^{(t)}\right) \\ \forall i \in V_{1}, j & \in V_{2}, -\text { or } i \in V_{2}, j \in V_{1} \\ \mathbf{h}_{i}^{(t+1)} -&=f_{\text {node }}\left(\mathbf{h}_{i}^{(t)}, \sum_{j} -\mathbf{m}_{j \rightarrow i}, \sum_{j^{\prime}} \mu_{j^{\prime} -\rightarrow i}\right) \\ \mathbf{h}_{G_{1}} -&=f_{G}\left(\left\{\mathbf{h}_{i}^{(T)}\right\}_{i \in -V_{1}}\right) \\ \mathbf{h}_{G_{2}} -&=f_{G}\left(\left\{\mathbf{h}_{i}^{(T)}\right\}_{i \in -V_{2}}\right) \\ s &=f_{s}\left(\mathbf{h}_{G_{1}}, -\mathbf{h}_{G_{2}}\right) \end{aligned} -\]
    • -
    • 从上面的公式可以看到,在propagation阶段,GMN做出了两点改动 +
    • 背景:
        -
      • 因为一次性输入一对图,因此第一步的邻域节点是从两张图的范围内找。但是一般而言两张图之间是没有节点连接的,除非两张图里的相同节点共享邻域?
      • -
      • 除了邻域信息的传递之外,作者还计算了两张图之间的match,这里用了一个最简单的attention机制,用待匹配两个节点embedding的距离加权两个节点embedding之间的差: -\[ -\begin{aligned} a_{j \rightarrow i} &=\frac{\exp -\left(s_{h}\left(\mathbf{h}_{i}^{(t)}, -\mathbf{h}_{j}^{(t)}\right)\right)}{\sum_{j^{\prime}} \exp -\left(s_{h}\left(\mathbf{h}_{i}^{(t)}, -\mathbf{h}_{j^{\prime}}^{(t)}\right)\right)} \\ \boldsymbol{\mu}_{j -\rightarrow i} &=a_{j \rightarrow -i}\left(\mathbf{h}_{i}^{(t)}-\mathbf{h}_{j}^{(t)}\right) \end{aligned} -\]
      • -
      • 这样在update到下一层节点embedding时,match的那部分实际上计算了a图某一结点与b图所有节点的加权距离: +
      • 现在有n个在[0,1]区间上均匀分布的随机变量,将这n个随机变量按大小排序后,如何求得第k个顺序统计量\(p=x_k\)的分布?
      • +
      • 为了求分布,利用极限的思想,我们求这个变量落在一小段区间上的概率\(x \leq X_{k} \leq x+\Delta x\)
      • +
      • 将整个区间分为三部分:小区间以前,小区间,小区间以后,若小区间内只有第k大的数,则小区间以前应该有k-1个数,小区间以后应该有n-k个数,这种情况的概率为 \[ -\sum_{j} \boldsymbol{\mu}_{j \rightarrow i}=\sum_{j} a_{j \rightarrow -i}\left(\mathbf{h}_{i}^{(t)}-\mathbf{h}_{j}^{(t)}\right)=\mathbf{h}_{i}^{(t)}-\sum_{j} -a_{j \rightarrow i} \mathbf{h}_{j}^{(t)} -\]
      • -
      • 这样计算的复杂度就升到了\(O(V(G_1)V(G_2))\),但正是这逐点的比较能够区分那些细微的变化,而且可视化更加具有可解释性。所以该算法的使用场景应该是小图且对区分精度要求高
      • -
    • -
    • 对于这样的匹配问题可以用pair 或者triplet -loss,前者比较相似不相似,后者比较和两个候选相比跟哪个更相似,作者分别给出了两种形式下的margin -loss: \[ -L_{\text {pair }}=\mathbb{E}_{\left(G_{1}, G_{2}, t\right)}\left[\max -\left\{0, \gamma-t\left(1-d\left(G_{1}, -G_{2}\right)\right)\right\}\right] \\ -L_{\text {triplet }}=\mathbb{E}_{\left(G_{1}, G_{2}, -G_{3}\right)}\left[\max \left\{0, d\left(G_{1}, -G_{2}\right)-d\left(G_{1}, G_{3}\right)+\gamma\right\}\right] \\ +\begin{aligned} +P(E)&=x^{k-1}(1-x-\Delta x)^{n-k}\Delta x \\ +&=x^{k-1}(1-x)^{n-k}\Delta x+\omicron (\Delta x) \\ +\end{aligned} \]
    • -
    • 作者还特意提到,为了加速运算,可以对Graph -Embedding做二值化处理,这样在衡量距离的时候就是用汉明距离,牺牲掉了一些欧式空间的部分,具体做法是将整个向量过tanh并作平均内积用作训练时的图相似度,并设计损失将正样本对的汉明距离推向1,负样本对的汉明距离推向-1,假如在推断检索下使用汉明距离进行检索,这样的损失设计比margin -loss更加稳定: \[ -s\left(G_{1}, G_{2}\right)=\frac{1}{H} \sum_{i=1}^{H} \tanh -\left(h_{G_{1} i}\right) \cdot \tanh \left(h_{G_{2} i}\right) \\ -L_{\text {pair }}=\mathbb{E}_{\left(G_{1}, G_{2}, -t\right)}\left[\left(t-s\left(G_{1}, G_{2}\right)\right)^{2}\right] / 4 +
    • 若小区间内有两个及两个以上的数,计算可得这种情况的概率是\(\omicron (\Delta +x)\),因此只考虑小区间内只有第k大的数,此时令\(\Delta +x\)趋向于0,则得到第k大数的概率密度函数(注意事件E的系数应该是\(nC_n^k\)): \[ +f(x)=\frac{n!}{(k-1)!(n-k)!}x^{k-1}(1-x)^{n-k} \quad x \in [0,1] +\] 用Gamma函数表示(令\(\alpha =k,\beta += n-k+1\))得到: \[ +\begin{aligned} +f(x)&=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}x^{\alpha-1}(1-x)^{\beta-1} \\ -\begin{aligned} L_{\text {triplet }}=\mathbb{E}_{\left(G_{1}, G_{2}, -G_{3}\right)}\left[\left(s\left(G_{1}, -G_{2}\right)-1\right)^{2}+\right.\\\left.\left(s\left(G_{1}, -G_{3}\right)+1\right)^{2}\right] / 8 \end{aligned} \\ -\] 其中除以4或者除以8是为了约束损失的范围在[0,1]区间内。
    • +&=Beta(p|k,n-k+1) \\ +&=Beta(\alpha,\beta) \\ +\end{aligned} +\] +这就是Beta分布,我们可以取概率分布最大的点作为第k大数的预测值。 +
    +
  • Beta分布实际上是对分布的预测,即分布的分布。在背景里,我们要找第k大顺序统计量的概率分布,我们把这个第k大顺序统计量记作p,现在知道有n个在[0,1]区间上均匀分布的值,n和k建立了一个在[0,1]区间内的相对位置,这也就是\(\alpha\)\(\beta\)的作用(因为\(\alpha\)\(\beta\)就是n和k计算出来的),代表我倾向于认为p在[0,1]中的哪里。因为n个统计量是均匀分布的,而p是其中第k大的,那么p就倾向于在\(\frac kn\)这个位置。
  • +
  • 因此Beta分布的参数(\(\alpha\)\(\beta\))意义很明显了,就是我在什么都不知道的情况下,先入为主的认为p可能所在的位置,即先验,而Beta分布的结果就是在这种先验影响下,计算出来的p的分布,这个p的实际含义,是二项式分布的参数。因此,Beta分布可以作为二项式分布的参数先验。
  • -

    Learning to -Update Knowledge Graphs by Reading News

    +

    Beta-Binomial共轭

      -
    • EMNLP2019的一项工作,作者肯定是个篮球迷,举了一个很恰当的NBA转会的例子来说明本文要解决的问题:知识图谱更新
    • -
    • 比如发生了球员转俱乐部,则相关的两个俱乐部的球员图谱就会发生变化,作者提出了两个重点,如文中图1所示: +
    • 这样我们可以对第k大数的分布建立一个Beta分布的先验,如果现在我们知道有m个在[0,1]之间均匀分布的数,且其中有几个比第k大数大,有几个比第k大数小,则可以将其作为一种数据知识补充进去,形成后验分布。
    • +
    • 假设要猜的数\(p=X_k\),现在我们知道了有\(m_1\)个数比\(p\)小,\(m_2\)个数比\(p\)大,显然此时\(p\)的概率密度函数就变成了\(Beta(p|k+m_1,n-k+1+m_2)\)
    • +
    • 补充进m个数的数据知识相对于做了m次贝努利实验,因为我们讨论的范围在[0,1]上,m个数只关心比\(p\)大还是小,\(p=X_k\)的数值便可以代表这一概率,因此\(m_1\)服从二项分布\(B(m,p)\)
    • +
    + + + + + + + + + + + + + + + +
    先验数据知识后验
    Beta分布二项分布Beta分布
      -
    • 知识图谱的更新只发生在text subgraph而不是1-hop subgraph
    • -
    • 传统方法不能从文本中获取隐藏的图谱更新信息,例如球员转会之后,这个球员的队友就会发生变化,这是文中没提但是可以推断出来的
    • +
    • 因此我们可以得到Beta-Binomial共轭 \[ +Beta(p|\alpha,\beta)+BinomCount(m_1,m_2)=Beta(p|\alpha+m_1,\beta+m_2) +\] +即数据符合二项分布时,参数的先验分布和后验分布都能保持Beta分布的形式,我们能够在先验分布中赋予参数明确的物理意义,并将其延续到后验分布中进行解释,因此一般将Beta分布中的参数\(\alpha,\beta\)称为伪计数,表示物理计数。
    • +
    • 可以验证的是当Beta分布的两个参数均为1时,就是均匀分布,这时对共轭关系可以看成:开始对硬币不均匀性不知道,假设硬币正面向上的概率为均匀分布,在投掷了m次硬币后,获得了\(m_1\)次向上其他次向下的数据知识,通过贝叶斯公式计算后验概率,可以算出正面向上的概率正好是\(Beta(p|m_1+1,m_2+1)\)
    • +
    • 通过这个共轭,我们可以推出关于二项分布的一个重要公式: \[ +P(C \leq k) = \frac{n!}{k!(n-k-1)!}\int _p ^1 t^k(1-t)^{n-k-1}dt \quad C +\sim B(n,p) +\] 现在可以证明如下: +
        +
      • 式子左边是二项分布的概率累积,式子右边时是\(Beta(t|k+1,n-k)\)分布的概率积分
      • +
      • 取n个随机变量,均匀分布于[0,1],对于二项分布\(B(n,p)\),若数小于\(p\)则是成功,否则失败,则n个随机变量小于\(p\)的个数C符合二项分布\(B(n,p)\)
      • +
      • 此时可以得到\(P(C \leq +k)=P(X_{k+1}>p)\),即n个随机变量按顺序排好后,小于\(p\)的有\(k\)
      • +
      • 这时利用我们对第k大数的概率密度计算出为Beta分布,带入有 \[ +\begin{aligned} +P(C \leq k) &=P(X_{k+1} > p) \\ + &=\int _p ^1 Beta(t|k+1,n-k)dt \\ + &=\frac{n!}{k!(n-k-1)!}\int _p ^1 t^k(1-t)^{n-k-1}dt \\ +\end{aligned} +\] 即证
    • -
    • 整体的结构是一个基于R-GCN和GAT的encoder和一个基于DistMult的decoder,基本上就是把RGCN改成了attention -based,decoder依然不变,做链接预测任务
    • +
    • 通过这个式子,将n取极限到无穷大,转换为泊松分布,可以推导出Gamma分布。
    • +
    • 在本节中,我们为先验引入了其他信息,就是有几个数比第k大数大和小,这些信息相当于是告诉我:我可以修改p的先验,我之前倾向于认为的p的位置改动了。假如我知道了几个数比p大,那么p的先验位置应该往后移,如果我知道了几个数比p小,那么p的先验位置应该往前移,如果我同时知道了100个数比p大,100个数比p小呢?p的位置不变,但是我更加确信了p真实的位置就是现在这个先验位置,因此Beta分布在这个先验位置上更集中,从后文分析Dirichlet参数的意义中我们会再次看到这一点。先验加上数据知识修改之后,就形成了后验,这就是贝叶斯公式的基本内容。
    -

    encoder

    +

    Dirichlet-Multinomial共轭

      -
    • encoder:RGCN+GAT=RGAT,在RGCN中前向过程为: 假设我们不仅要猜一个数,还要猜两个数\(x_{k_1},x_{k_1+k_2}\)的联合分布,该如何计算?
    • +
    • 同理,我们设置两个极小区间\(\Delta +x\),将整个区间分为五块,极小区间之间分别为\(x_1,x_2,x_3\)计算之后可以得到 \[ -\mathbf{H}^{l+1}=\sigma\left(\sum_{r \in \mathbf{R}} -\hat{\mathbf{A}}_{r}^{l} \mathbf{H}^{l} \mathbf{W}_{r}^{l}\right) +f(x_1,x_2,x_3)=\frac{\Gamma(n+1)}{\Gamma(k_1)\Gamma(k_2)\Gamma(n-k_1-k_2+1)}x_1^{k_1-1}x_2^{k_2-1}x_3^{n-k_1-k_2} \]
    • -
    • 即对异构的边分给予一个参数矩阵,独立的计算之后求和再激活。 -将邻接矩阵改为注意力矩阵,注意力计算为: \[ -a_{i j}^{l r}=\left\{\begin{array}{ll}{\frac{\exp \left(a t t^{l -r}\left(\mathbf{h}_{i}^{l}, \mathbf{h}_{j}^{l}\right)\right)}{\sum_{k -\in \mathcal{N}_{i}^{r}} \exp \left(a t t^{l} r\left(\mathbf{h}_{i}^{l}, -\mathbf{h}_{k}^{l}\right)\right)}} & {, j \in \mathcal{N}_{i}^{r}} -\\ {0} & {, \text { otherwise }}\end{array}\right. +
    • 整理一下可以写成 \[ +f(x_1,x_2,x_3)=\frac{\Gamma(\alpha _1+\alpha _2+\alpha +_3)}{\Gamma(\alpha _1)\Gamma(\alpha _2)\Gamma(\alpha _3)}x_1^{\alpha +_1-1}x_2^{\alpha _2-1}x_3^{\alpha _3-1} +\] 这就是3维形式的Dirichlet分布。其中\(x_1,x_2,x_3\)(实际上只有两个变量)确定了两个顺序数联合分布,\(f\)代表概率密度。
    • +
    • 注意到在\(\alpha\)确定的情况下,前面的一堆gamma函数其实是概率归一化的分母,后文我们将Dirichlet分布更一般的写成: +\[ +Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})=\frac{1}{\int +\prod_{k=1}^V p_k^{\alpha _k -1}d\mathop{p}^{\rightarrow}} \prod_{k=1}^V +p_k^{\alpha _k -1} \]
    • -
    • 其中注意力函数\(attn\)基于文本计算 -
        -
      • 首先用双向GRU对序列编码\(u\)
      • -
      • 再利用序列注意力得到上下文表示 \[ -b_{t}^{l r}=\frac{\exp \left(\mathbf{u}_{t}^{T} \mathbf{g}_{t e x t}^{l -r}\right)}{\sum_{k=1}^{|S|} \exp \left(\mathbf{u}_{k}^{T} \mathbf{g}_{t -e x t}^{l r}\right)} \\ -\mathbf{c}^{l r}=\sum_{t=1}^{|S|} b_{t}^{l r} \mathbf{u}_{t} \\ +
      • 其中归一化分母,也即那一堆gamma,令其为: \[ +\Delta(\mathop{\alpha}^{\rightarrow})=\int \prod _{k=1}^V p_k^{\alpha _k +-1}d\mathop{p}^{\rightarrow} \]
      • -
      • 之后利用注意力的时候,trainable guidance vector\(g\)就利用了这个上下文表示,利用一个简单的线性插值引入 +
      • 同样,我们也可以对Dirichlet分布的先验加入数据知识,其后验依然是Dirichlet分布 \[ -\mathbf{g}_{f i n}^{l r}=\alpha^{l r} \mathbf{g}_{g r a p h}^{l -r}+\left(1-\alpha^{l r}\right) \mathbf{U}^{l r} \mathbf{c}^{l r} \\ -a t t^{l r}(\mathbf{h}_{i}^{l}, \mathbf{h}_{j}^{l}) =\mathbf{g}_{f i -n}^{l r}[\mathbf{h}_{i}^{l} | \mathbf{h}_{j}^{l}] \\ -\]
      • -
    • -
    • 在实际应用到作者想要完成的kg update任务中,作者还引入了几个小技巧 +Dir(p|\alpha)+MultCount(m)=Dir(p|\alpha+m) +\] 上式中的参数均是向量,对应多维情况。
    • +
    • 无论是Beta分布还是Dirichlet分布,都有一个很重要的性质,即他们的均值可以用参数的比例表示,例如对于Beta分布,\(E(p)=\frac{\alpha}{\alpha+\beta}\),对于Dirichlet分布,均值是一个向量,对应于各个参数比例组成的向量。
    • +
    +

    Dirichlet分析

      -
    • RGCN/RGAT中的参数量随着边(关系)的类别数量成线性增长,为了减少参数量,作者利用了basis-decomposition,也就是k类关系,存在k套参数,这k套参数用b套参数线性组合而成,而b小于k,这样来减少参数
    • -
    • 实际数据集里实体之间的关系很稀疏,一两层的RGAT聚合不到消息,因此在构造数据集时首先对图中所有实体之间人为添加一个叫SHORTCUT的关系,并使用现成的信息抽取工具将SHORTCUT细化为add,delete和other,用来初步的判定人员的转会(从一个俱乐部delete,add到另一个俱乐部)关系
    • -
    +
  • 根据Dirichlet的性质,其参数比例代表了[0,1]上的一个划分,决定了dirichlet分布高概率的位置,其参数大小决定了高概率的比例(陡峭),例如下图,多项式分布有三项,参数分别为\(p_1,p_2,p_3\),他们的和为一且各项大于零,在三维空间内便是一个三角面,面上每一点代表一种多项式分布,红色区域概率高,蓝色区域概率低:
  • -

    decoder

    +
    +i0orkR.png + +
      -
    • 在EMBEDDING ENTITIES AND RELATIONS FOR LEARNING AND INFERENCE IN -KNOWLEDGE -BASES一文中总结了知识图谱中的关系embedding学习问题,可以归结为不同的线性/双线性参数矩阵搭配不同的打分函数,计算margin -triplet loss:
    • -
    • DistMult即最简单的,将双线性参数矩阵换成对角阵,即最后的分数是两个实体embedding逐元素相乘并加权求和得到,权重与关系相关,在本文中的具体实现为: -\[ -P(y)=\operatorname{sigmoid}\left(\mathbf{h}_{i}^{T}\left(\mathbf{r}_{k} -\circ \mathbf{h}_{j}\right)\right) -\]
    • +
    • \(\alpha\)控制了多项式分布参数的mean +shape和sparsity。
    • +
    • 最左边,Dirichlet的三个参数\(\alpha +_1,\alpha _2,\alpha _3\)相等,代表其红色区域位置居中,且三个\(\alpha\)的值均较大,红色区域较小,把热力图看成等高线图的话就代表红色区域较陡峭,说明Dirichlet非常确认多项式分布的参数会在居中的位置。对于三个多项式分布的参数\(p_1,p_2,p_3\)来说,较大可能取到三个p等值的情况。
    • +
    • 中间的图,三个\(\alpha\)不相等,某一个\(\alpha\)偏大,导致红色区域偏向三角面某一角,导致某一个p取值较大,其余两个p取值较小的可能性比较大,这时体现参数先验的参数作为concentration的作用,将概率注意力集中于某些项。
    • +
    • 最右边,同最左边,三个\(\alpha\)相等,红色区域居中,但是\(\alpha\)的值均偏小,导致红色区域发散,也就是Dirichlet认为三个p的值应该在最中间,但是不那么确定。结果就是三个p之间有差别,但差别不会太大(依然在最中间附近),不会出现非常陡峭的情况(最陡峭也就是最中间无限高,概率为1,三个p值一定相同)
    • +
    • 因此可以看出,\(\alpha\)的比例决定了多项式分布高概率的位置,也就是主要确定了各个\(p\)的比例,定好concentration,而\(\alpha\)的大小决定了这个位置的集中情况,\(\alpha\)越小,位置越集中,p的分布越确定,反之p的分布由红色区域位置大致确定,但是变化范围较大。
    • +
    • \(\alpha\)远小于1时,Dirichelt分布会走向另一个极端,在上面这个三角面的例子里,红色区域依然会陡峭,但是陡峭在三角面的三个角上,可以想成\(alpha\)从大变到1,再变小,大概率密度区域从最中间慢慢分散到整个面,然后又聚集在三个角。
    • +
    • 再来看看维基百科中关于Dirichlet参数\(\alpha\)的描述:

      The concentration parameter Dirichlet distributions are very often +used as prior distributions in Bayesian inference. The simplest and +perhaps most common type of Dirichlet prior is the symmetric Dirichlet +distribution, where all parameters are equal. This corresponds to the +case where you have no prior information to favor one component over any +other. As described above, the single value α to which all parameters +are set is called the concentration parameter. If the sample space of +the Dirichlet distribution is interpreted as a discrete probability +distribution, then intuitively the concentration parameter can be +thought of as determining how "concentrated" the probability mass of a +sample from a Dirichlet distribution is likely to be. With a value much +less than 1, the mass will be highly concentrated in a few components, +and all the rest will have almost no mass. With a value much greater +than 1, the mass will be dispersed almost equally among all the +components. See the article on the concentration parameter for further +discussion.

      +
    • +
    • \(\alpha\)远小于1时,概率密度会主要堆积在一个或少数几个项上,也就是红色区域聚集在三个角的情况,这时Dirichlet分布抽样得到的多项式分布大概率在角上,也就是概率密度堆积在一个项上,其余两个项概率近似为0。\(\alpha\)远大于1时,概率密度会分散到各个部分,就是对应三图中最左边的图,三个项概率相差不大的可能性比较大。
    -

    result

    +

    Role in LDA

      -
    • 对比几个Baseline:RGCN,PCNN,感觉作者使用了GRU这样data-hungry的网络提取语义计算相似度,数据集偏小,当然最后结果还是很好看,可以看到数据集明显不平衡,但是在add和delete这些小样本类上RGAT比RGCN提升了一倍的准确率。
    • -
    • 值得称赞的是论文将链接预测问题包装的很好,一个update突出了持续学习持续更新的想法,最后简化问题为链接预测,模型没有太多改进,但是效果达到了。
    • +
    • 总结一下共轭:设有分布A,A的参数分布(或者叫分布的分布)为B,若B的先验在获得A的数据知识之后得到的后验与先验属于同一类分布,则A与B共轭,B称为A的参数共轭分布(或者叫先验共轭) +,在上文提到的例子里,Beta分布是二项分布的参数共轭分布,Dirichlet分布是多项式分布的参数共轭分布。
    • +
    • LDA实际上是将文本生成建模为一个概率生成模型,具体而言是一个三层贝叶斯模型,并且针对文档-主题和主题-词语两个multinomial分布都假设其参数先验为Dirichlet分布,用Dirichlet-Multinomial共轭来利用数据知识更新其后验。
    • +
    • 为了介绍Dirichlet-Multinomial共轭,先介绍Gamma函数及其分布,Gamma函数将阶乘扩展到实数域,之后介绍了能估计分布的Beta函数,在引入了Gamma函数之后Beta分布的参数能扩展到实数域。之后介绍了Beta-Binomial共轭,这种共轭带来的好处是在用数据训练修正时,我们已经知道了后验分布的形式,之后将这种共轭关系扩展到高维(估计多个分布),就得到了Dirichlet-Multinomial共轭。
    • +
    • 为文档到主题和主题到词的两个多项式分布加入Dirichlet分布作为参数先验的好处是:将多项式参数作为变量,先验信息指导了参数在哪个范围内变动,而不是具体的值,使得模型在小训练样本内的泛化能力更强。
    • +
    • 在Dirichlet Process中\(\alpha\)的大小体现了Dirichlet分布拟合Base +Measure时的离散程度,\(\alpha\)越大,越不离散,各个项均能得到差不多的概率。
    • +
    • 对应到LDA模型中,这种离散程度就代表了文档是集中在某几个主题上还是在所有主题上较均匀的分布,或者主题是集中在少数词上还是在整体的词上较均匀的分布。
    -

    Learning -Attention-based Embeddings for Relation Prediction in Knowledge -Graphs

    +

    吉步斯采样

    +

    随机模拟

      -
    • 依然是做链接预测,依然是基于GAT
    • -
    • 作者认为在KG当中关系非常重要,但是又不好给边加特征,因此就曲线救国,将边的特征融入到节点的特征当中
    • -
    • 一图胜千言
    • -
    • 从左到右 +
    • 即蒙特卡洛的含义,用于已知分布,需要生成一系列满足此分布的随机样本,并用这些样本的统计量来估计原分布一些不好直接解析计算的参数。
    • +
    • 马尔可夫是指产生随机样本的方法依赖于马氏链的性质,通过构造马氏链当中的转移矩阵,使得马氏链收敛时能够产生满足给定分布的样本序列。
    • +
    • MCMC的一种方法是随机采样,利用已知分布计算出接受率,只接收部分采样,而吉布斯采样是接受率为1的一种MCMC方法。它提升了接受率,但是加长了采样过程。
    • +
    +

    马氏链

      -
    • 输入,依然是节点特征输入GAT,只不过每个节点特征是与其相关的三元组特征做self -attention得到,而三元组特征由节点和关系特征拼接得到,绿色为输入关系特征,黄色为输入节点特征: -\[ -c_{i j k}=\mathbf{W}_{1}\left[\vec{h}_{i}\left\|\vec{h}_{j}\right\| -\vec{g}_{k}\right] \\ -\begin{aligned} \alpha_{i j k} &=\operatorname{softmax}_{j -k}\left(b_{i j k}\right) \\ &=\frac{\exp \left(b_{i j -k}\right)}{\sum_{n \in \mathcal{N}_{i}} \sum_{r \in \mathcal{R}_{i n}} -\exp \left(b_{i n r}\right)} \end{aligned} \\ -\overrightarrow{h_{i}^{\prime}}=\|_{m=1}^{M} \sigma\left(\sum_{j \in -\mathcal{N}_{i}} \alpha_{i j k}^{m} c_{i j k}^{m}\right) \\ -\]
    • -
    • 之后经过GAT,得到灰色的中间层节点特征,两个3维灰色拼接是指GAT里multi-head -attention的拼接,之后两个6维灰色与绿色做变换之后拼接是指依然用三元组表示每个节点
    • -
    • 最后一层,不做拼接了,做average -pooling,并且加入了输入节点特征,再拼接上关系特征,计算损失
    • -
    • 损失依然用三元组距离,即subject+predicate-object,margin triplet -loss,负采样时随机替换subject或者object
    • +
    • 马氏链即状态转移的概率只依赖于前一个状态
    • +
    • 因为转移概率只依赖于前一个状态,因此可以将状态转移概率写成转移概率矩阵,经过n次转移之后的各状态概率分布即初始状态概率分布向量乘以矩阵的n次幂得到的结果
    • +
    • 矩阵的幂从某一次数之后不变,即每一行收敛成相同的概率分布,同时初始概率转移足够多次之后也收敛成相同的分布
    • +
    • 关于马氏链收敛的定义 +
        +
      • 如果一个非周期马氏链具有转移概率矩阵P(可以有无穷多状态),且它的两个任何状态是联通(任何两个状态可以通过有限步转移到达)的,则\(lim_{n \rightarrow +\infty}P_{ij}^n\)存在且与\(i\)无关,记这个收敛的矩阵为\(\pi(j)\)
      • +
      • \(\pi (j)=\sum _{i=0}^{\infty} \pi (i) +P_{ij}\)
      • +
      • \(\pi\)是方程$P = +$的唯一非负解
      • +
      • \(\pi\)称为马氏链的平稳分布
    • -
    • 以上是encoder部分,decoder用ConvKB \[ -f\left(t_{i j}^{k}\right)=\left(\prod_{m=1}^{\Omega} -\operatorname{ReLU}\left(\left[\vec{h}_{i}, \vec{g}_{k}, -\vec{h}_{j}\right] * \omega^{m}\right)\right) \mathbf{. W} \\ -\]
    • -
    • 损失为soft-margin loss(好像1和-1写反了?) +

      Markov Chain Monte Carlo

      +
        +
      • 回到随机生成,对于给定的概率分布,我们希望能生成它对应的样本,一个想法就是构造一个马氏链,其平稳分布刚好就是这个概率分布:因为当马氏链收敛以后,其平稳分布就是各个状态的概率分布,收敛后无论经过状态转移生成多长的状态序列,这个序列里状态的分布一直保持着平稳分布。若平稳分布是要生成的概率分布,则状态序列就是给定概率分布下的一个随机样本序列。
      • +
      • 因此,问题在于,如何已知平稳分布构造马氏链的状态转移矩阵。主要利用了非周期马氏链的细致平稳条件:若\(\pi(i)P_{ij}=\pi(j)P_{ij} \quad for \quad all +\quad i,j\),则\(\pi(x)\)是马氏链的平稳分布。这个定理一个物理解释是:若状态i的概率质量是稳定的,则从状态i转移到状态j变化的概率质量恰好和从状态j转移到状态i变化的概率质量互补。
      • +
      • 设从状态i转移到状态j的概率为\(q(i,j)\),若\(p(i)q(i,j)=p(j)q(j,i)\),那么此时\(p(x)\)就是这个马氏链的平稳分布,转移矩阵也不用改了,但一般情况下你的运气没有那么好,在已知\(p(x)\)的情况下,我们需要对\(q\)进行改造,为此我们乘上一个接受率\(\alpha\),使得: \[ -\begin{array}{l}{\mathcal{L}=\sum_{t_{i j}^{k} \in\left\{S \cup -S^{\prime}\right\}} \log \left(1+\exp \left(l_{t_{i j}^{k}} * -f\left(t_{i -j}^{k}\right)\right)\right)+\frac{\lambda}{2}\|\mathbf{W}\|_{2}^{2}} \\ -{\text { where } l_{t_{i j}^{k}}=\left\{\begin{array}{ll}{1} & -{\text { for } t_{i j}^{k} \in S} \\ {-1} & {\text { for } t_{i -j}^{k} \in S^{\prime}}\end{array}\right.}\end{array} +p(i)q(i,j)\alpha (i,j)=p(j)q(j,i)\alpha (j,i) +\] 为什么叫接受率?因为可以理解为这个\(\alpha\)是在原来的状态转移之后再乘一个概率,代表是否接受这次转移。
      • +
      • 如何确定接受率?其实显而易见\(\alpha +(i,j)=p(j)q(j,i)\),对称构造即可。
      • +
      • 因此在每次转移之后,我们从均匀分布采样一个变量,若变量小于接受率则按原始状态转移矩阵进行转移,否则不转移。
      • +
      • 这样的MCMC采样算法存在一个问题,我们其实没有改动原始状态转移矩阵q,而是根据q计算了接受率来保证收敛到p,但是接受率可能计算出来很小,导致状态长期原地踏步,收敛缓慢。事实上,将式\(p(i)q(i,j)\alpha +(i,j)=p(j)q(j,i)\alpha(j,i)\)两边同时乘以一个倍数,细致平稳条件没有被打破,但是接受率获得了提高,因此只要将两边接受率乘以一个倍数并保证两个接受率翻倍之后不大于1即可,一般做法是将较大的接受率乘到1。这时就得到了最常见的一种MCMC方法:Metropolis-Hastings算法。
      • +
      +

      Gibbs Sampling

      +
        +
      • 之前说到了MCMC实际上没有对状态转移矩阵改动,因此需要一个接受率补充,即便放缩之后总有一个接受率小于1,降低了收敛效率。吉步斯采样希望找到一个转移矩阵Q使得接受率等于1。
      • +
      • 对二维概率分布\(p(x,y)\),易得到 +\[ +\begin{aligned} +p(x_1,y_1)p(y_2|x_1) & =p(x_1)p(y_1|x_1)p(y_2|x_1) \\ +& =p(x_1)p(y_2|x_1)p(y_1|x_1) \\ +& =p(x_1,y_2)p(y_1|x_1) \\ +\end{aligned} \]
      • -
      • 另外作者还为2跳距离的节点之间加入了边
      • -
      • 结果非常好,在FB15K-237和WN18RR上取得了SOTA。作者并没有试图将边的特征直接整合进GAT的message -passing,而是就把特征当成待训练的输入,用encoder专注于训练特征,并且在模型的每一层都直接输入的初始特征来保证梯度能够传递到原始输入。
      • +
      • 从左式到最终式,这种形式非常像细致平稳条件!实际上假如固定\(x=x_1\),则\(p(y|x_1)\)可以作为直线\(x=x_1\)上任意两个不同y值的点之间的转移概率,且这种转移满足细致平稳条件。固定y我们能得到相同的结论,因此在这个二位平面上任意两点之间我们可以构造转移概率矩阵: +
          +
        • 若两点在垂直线\(x=x_1\)上,则\(Q=p(y|x_1)\)
        • +
        • 若两点在水平线\(y=y_1\)上,则\(Q=p(x|y_1)\)
        • +
        • 若两点连线既不垂直也水平,则\(Q=0\) +这样对平面上任意两点应用转移矩阵Q,均满足细致平稳条件,这个二维平面上的马氏链将收敛到\(p(x,y)\)
        • +
      • +
      • gibbs采样得到新的x维度之后,在计算新的y维度时是依赖了新的x维度,因为是在之前选定坐标轴转换的基础上再进行转移,不然无法跳转到新状态\((x_2,y_2)\),你得到的实际上是\((x_1,y_2)\)\((x_2,y_1)\)
      • +
      • 因此,给定二维概率分布,可以计算出这个平面上沿水平或者垂直方向的满足细致平稳条件的转移概率,从平面上任何一点状态出发,它一次转移只改变横坐标或者纵坐标,也就是水平或者垂直移动,从细致平稳条件的公式可以看到这个平稳是可以传递的,如果从某一个维度的转移满足平稳条件,之后接着另一个维度,那么两次转移所等效的一次转移也是平稳的。
      • +
      • 等到所有维度都转移了一次,就得到了一个新的样本。等到马氏链收敛之后形成的样本序列就是我们所需要的随机生成样本序列。状态的转移可以是坐标轴轮流变换的,即这次水平转换,下次垂直转换,也可以每次随机选择坐标轴。虽然每次随机选择坐标轴会导致中途计算出来的新的维度值不一样,但是平稳条件没有打破,最终能够收敛到一样的给定分布。
      • +
      • 同样,上述算法也可以推广到多维。扩展到多维时,在\(x\)轴上构建的的转移概率就是\(Q=p(x|¬ +x)\)。值得注意的是,上述得到的采样样本并不是相互独立的,只是符合给定的概率分布。
      -]]> - - 自然语言处理 - - - deep learning - natural language processing - machine learning - knowledge graph - - - - Logistic Regression and Maximum Entropy - /2018/10/14/lr-and-me/ - 翻译John Mount的The equivalence of logistic regression and -maximum entropy models -一文,并说明了这种证明是在统计学习方法中介绍最大熵模型的通用导出证明的一个特例

      -

      结论 - 最大熵模型就是softmax分类 - -在满足广义线性模型的平衡条件下,满足最大熵条件的模型映射函数就是softmax函数 -- -在统计机器学习方法一书中,给出了在特征函数定义下的最大熵模型,其与softmax回归都属于对数线性模型 -- -当特征函数从二值函数扩展为特征值本身时,最大熵模型就化为softmax回归模型 -- 最大熵最大化的是条件熵,不是条件概率的熵,也不是联合概率的熵。

      - -

      明确符号

      +

      Role in LDA

        -
      • n维特征,m个样本,\(x(i)_j\)表示第i个样本第j维特征,讨论多分类情况,输出分类\(y(i)\)有k类,映射概率函数\(\pi\)\(R^n\)映射到\(R^k\),我们希望\(\pi(x(i))_{y(i)}\)尽可能大。
      • -
      • 指示函数\(A(u,v)\),当\(u==v\)时为1,否则为0
      • +
      • 首先明确,MCMC方法是产生已知分布的样本,但是gibbs采样只需要使用完全条件概率,产生了满足联合分布的样本,而不像一般采样方法直接从联合分布中采样
      • +
      • gibbs采样这种特性就使其可以在不知道联合概率的情况下去推断参数,进一步推出联合概率分布
      • +
      • 但是在LDA中,并没有用gibbs +sampling去直接推断参数,而是用其去近似后验,完成用数据知识更新先验这一步。而且由于LDA存在着主题这一隐变量,gibbs采样的联合分布并不是文档的主题分布或者主题的词分布,和LDA模型的参数没有直接挂钩。Gibbs +sampling在LDA中采样的是token的主题分配,即隐变量的分布。
      • +
      • 但是所有token主题分配确定之后,LDA模型的参数就确定了,通过古典概型(最大似然估计)就可以得到两个multinomial分布(参数),对应的dirichelt分布(参数后验分布)也得到更新。且由于引入了主题分解了文档-单词矩阵,实际上我们不需要维护\(Document \* word\)矩阵,而是维护\(Document \* topic + topic \* +word\)即可。
      • +
      • gibbs采样词的主题分配,实际上是在计算隐变量分布的后验,进而得到参数分布的后验。
      • +
      • gibbs采样中在不断更新参数,例如本次迭代更新\(p(x_1^{t+1})=p(x_1|x_2^t,x_3^t)\),则下一次迭代为\(p(x_2^{t+1})=p(x_2|x_1^{t+1},x_3^t)\),即使用更新之后的\(x_1^{t+1}\)来计算。在LDA中,这一过程通过更新被采样单词的主题实现。贝叶斯推断中将数据分批,用后验更新先验的迭代,在这里被进一步细化到了gibbs +sampling的每一次坐标更新。
      • +
      • 下文可以看到gibbs采样公式,可以解释为根据其他词的主题分配情况决定自己的主题分配,迭代更新所有词的主题分配;具体如何决定,包含了两个部分,这两个部分类似于tf和idf提供的信息。
      • +
      • 当根据采样公式计算出主题分配的后验时,我们并没有直接得到参数的后验分布,但是当根据主题分配后验采样出新主题,更新了统计量之后,由于gibbs +sampling公式里本身包含了统计量,这里相当于计算后验和用后验更新先验一步完成。或者也可以理解成,LDA里一直做的是主题分配分布(隐变量)的贝叶斯推断,即\(p(topic|word,doc)\),做完之后根据主题分配,做一次最大似然估计(古典概型)就能得到模型的参数。
      -

      Logistic回归

      -

      \[ -\pi(x)_1 = \frac{e^{\lambda x}}{1+e^{\lambda x}} \\ -\pi(x)_2 = 1 - \pi(x)_1\\ -\] - 其中要学习到的参数\(\lambda\)\(R^n\)

      -

      Softmax回归

      -

      \[ -\pi(x)_v = \frac{e^{\lambda _v x}} {\sum _{u=1}^k e^{\lambda _u x}} -\] - \(\lambda\)\(R^{k * n}\)

      -

      求解softmax

      +

      文本建模

        -
      • 当使用softmax或者logistic作为非线性函数时,它们存在一个很好的求导的性质,即导函数可以用原函数表示 +
      • 接下来讨论如何对文本进行概率建模,基本思想是我们假设一个文档中所有的词是按照一种预先设置的概率分布生成的,我们希望找到这个概率分布。具体而言分为以下两个任务: +
          +
        • 模型是怎样的?
        • +
        • 各个词的生成概率或者说模型参数是多少?
        • +
      • +
      +

      Unigram模型

      +
        +
      • 模型是怎样的?传统的unigram模型即一元语法模型,认为各个词之间的生成是独立的,文档之间、词之间都是独立可交换的,无所谓顺序,就像所有的词放在一个袋子里,每次按概率分布取出一个词,因此也叫词袋模型(BoW)。词袋模型的参数就是各个词的生成概率,频率派认为可以通过词频统计确定生成概率。
      • +
      • 这里为unigram引入一层贝叶斯框架,为后文LDA两层贝叶斯框架的推导铺垫。贝叶斯学派认为词的生成不止一层:词的概率分布有很多种,即概率分布本身也服从一种概率分布,就像是上帝有许多骰子,他挑选了一个骰子再扔,生成了词。
      • +
      • 也就是说,Unigram模型下一篇文档只是一袋子词,这些词的生成遵循一个分布,设为\(\mathop{p}^{\rightarrow}\),同时这个词生成分布也遵循一个分布,设为\(p(\mathop{p}^{\rightarrow})\)。用数学公式把上面说的两层分布翻译下,就是一篇文档的生成概率: \[ -\frac {\partial \pi (x)_v}{\partial \lambda _{v,j}} = x_j \pi (x)_v -(1-\pi (x)_v) \\ -\frac {\partial \pi (x)_v}{\partial \lambda _{u,j}} = -x_j \pi (x)_v \pi -(x)_u \ where \ u \neq v \\ +p(W)=\int +p(W|\mathop{p}^{\rightarrow})p(\mathop{p}^{\rightarrow})d\mathop{p}^{\rightarrow} \]
      • -
      • 现在我们可以定义目标函数,即希望\(\pi\)函数输出的正确类别概率最大(最大似然),并定义最优化得到的\(\lambda\)\[ -\lambda = argmax \sum _{i=1}^m log (\pi (x(i))_{y(i)}) \\ -= argmax f(\lambda) \\ +
      • 按照贝叶斯学派的观点,我们应该先假设一个先验分布,再用训练数据修正它,此处我们需要假设\(p(\mathop{p}^{\rightarrow})\),也就是分布的分布的先验,训练数据是什么?是我们从语料中提取的词频分布,假设\(\mathop{n}^{\rightarrow}\)是所有词的词频序列,则这个序列满足多项分布: +\[ +\begin{aligned} +p(\mathop{n}^{\rightarrow}) &= +Mult(\mathop{n}^{\rightarrow}|\mathop{p}^{\rightarrow},N) \\ +&= C_N ^{\mathop{n}^{\rightarrow}} \prod_{k=1}^V p_k^{n_k} \\ +\end{aligned} \]
      • -
      -

      平衡等式

      -
        -
      • 对上面的目标函数求导并令导函数为0: \[ -\frac {\partial f(\lambda)}{\partial \lambda _{u,j}} = \sum -_{i=1,y(i)=u}^m x(i)_j - \sum _{i=1}^m x(i)_j \pi (x(i))_u =0 \\ +
      • 既然训练数据满足多项分布,我们自然而然想利用Dirichlet-Multinomial共轭,因此假设\(p(\mathop{p}^{\rightarrow})\)的先验分布为Dirichlet分布: +\[ +Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})=\frac{1}{\int +\prod_{k=1}^V p_k^{\alpha _k -1}d\mathop{p}^{\rightarrow}} \prod_{k=1}^V +p_k^{\alpha _k -1} +\] 其中\(V\)是语料词典大小,Dirichlet分布的参数\(\alpha\)需要自己设置。之后根据共轭得到数据修正之后\(p(\mathop{p}^{\rightarrow})\)的后验分布: +\[ +\begin{aligned} +p(\mathop{p}^{\rightarrow}|W,\mathop{\alpha}^{\rightarrow}) &= +Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})+MultCount(\mathop{n}^{\rightarrow}) +\\ +&= +Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow}+\mathop{n}^{\rightarrow}) +\\ +\end{aligned} \]
      • -
      • 这样我们就得到一个重要的平衡等式(Balance Equation): \[ -\ \ for \ all \ u,j \\ -\sum _{i=1,y(i)=u}^m x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ +
      • 得到后验之后,可以使用极大似然估计或者均值估计来计算\(\mathop{p}^{\rightarrow}\),这里我们使用后验里Dirichlet分布的均值来估计,结合之前提到了Dirichlet的性质,有: +\[ +\mathop{p_i}^{~}=\frac{n_i+\alpha _i}{\sum _{i=1}^{V} (n_i+\alpha _i)} +\] +这个式子的物理解释:不同于一般的使用词频作为估计,我们首先假设了词频(即先验的伪计数\(\alpha _i\)),然后加上数据给出的词频\(n_i\),再归一化作为概率。
      • +
      • 现在得到了词语的生成概率分布\(\mathop{p}^{\rightarrow}\),那么在此分布下的文档的生成概率显然为: +\[ +p(W|\mathop{p}^{\rightarrow})=\prod _{k=1}^V p_k^{n_k} +\] +将词生成概率分布的分布,文档在词生成分布下的条件生成概率带入之前提到的文档概率积分式,就得到所有分布情况下,文档的生成概率。代入化简之后可以得到一个很漂亮的式子。 +\[ +p(W|\mathop{\alpha}^{\rightarrow})=\frac{\Delta(\mathop{\alpha}^{\rightarrow}+\mathop{n}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} +\] 其中\(\Delta\)是归一化因子: +\[ +\Delta(\mathop{\alpha}^{\rightarrow})=\int \prod _{k=1}^V p_k^{\alpha _k +-1}d\mathop{p}^{\rightarrow} \]
      • -
      • 分析这个等式: +
      +

      PLSA模型

        -
      • 大白话:我们希望得到这么一个映射函数\(\pi\),对某一维(j)特征,用所有样本被映射函数归为第u类的概率加权所有样本的特征值之和,等于第u类内所有样本的特征值之和。显然,最好的情况就是左右两个累加式内的元素完全一样,只有第u类的样本被累加,且第u类样本被映射函数归为第u类的概率为1,其他类样本被归为第u类样本的概率为0.
      • -
      • 但是,这个等式非常的宽松,它只要求两个和式相同,并不要求每一个元素相同,而且这个式子没有显示的写出映射函数的表达式,任何满足该式的非线性映射都有可能称为映射函数。
      • -
      • 用公式表达,就是 \[ - \sum _{i=1}^m A(u,y(i)) x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ - \pi (x(i))_u \approx A(u,y(i)) \\ - \]
      • -
    • +
    • PLSA即概率隐含语义分析模型,这个模型认为文档到词之间存在一个隐含的主题层次,文档包含多个主题,每个主题对应一种词的分布,生成词时,先选主题,再从主题中选词生成(实际计算时是各个主题的概率叠加)。
    • +
    • 与没有贝叶斯的unigram模型相比,plsa在文档和词之间加了一层,主题。
    • +
    • PLSA没有引入贝叶斯,只是一个包含隐变量的模型,做最大似然估计,那么可以用EM算法迭代学习到参数,具体的计算在这里就略过了。
    -

    由最大熵推出softmax

    +

    Role in LDA

      -
    • 上面说到了平衡等式并没有要求映射函数的格式,那么为什么我们选择了softmax?换句话,什么条件下能从平衡等式的约束推出非线性映射为softmax?
    • -
    • 答案是最大熵。我们现在回顾一下\(\pi\)需要满足的条件: +
    • 现在整理一下,Unigram模型中主要包含两部分
        -
      • 平衡等式(即这个\(\pi\)能拟合数据): \[ - \ \ for \ all \ u,j \\ - \sum _{i=1,y(i)=u}^m x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ - \]
      • -
      • \(\pi\)的输出得是一个概率: \[ - \pi (x)_v \geq 0 \\ - \sum _{v=1}^k \pi (x)_v = 1 \\ - \]
      • +
      • 词生成概率分布
      • +
      • 词生成概率分布的参数分布
    • -
    • 根据最大熵原理,我们希望满足上述约束条件的\(\pi\)能够具有最大的熵: \[ -\pi = argmax \ Ent(\pi) \\ -Ent(\pi) = - \sum_{v=1}^k \sum _{i=1}^m \pi (x(i))_v log (\pi (x(i))_v) -\\ -\]
    • -
    • 最大熵可以从两个角度理解: +
    • PLSA模型主要包含两部分
        -
      • 最大熵也就是最大困惑度,即模型过拟合的风险低,模型复杂程度低,根据奥卡姆剃刀原则,在多个具有相同效果的模型中复杂程度小的模型具有更好的泛化能力,在满足了约束条件的情况下,当然我们希望要一个复杂程度小的模型,相当于正则化。
      • -
      • 约束条件是我们的模型已知的需要满足、需要拟合的部分,剩下的部分是未知的部分,没有规则或者数据指导我们分配概率,那该怎么办?在未知的情况下就应该均匀分配概率给所有可能,这正是对应了最大熵的情况。
      • +
      • 词生成概率分布
      • +
      • 主题生成概率分布
    • -
    • 现在问题已经形式化带约束条件的最优化问题,利用拉格朗日乘子法求解即可。这里有一个trick,原文中说如果直接考虑概率的不等条件就有点复杂,需要使用KTT条件,这里先不考虑,之后如果求出的\(\pi\)满足不等式条件的话就可以跳过了(事实也正是如此)。
    • +
    • Unigram模型展示了分布的分布,即为词分布引入参数先验的意义:使得词的分布是一个变量,从掷色子选出一个词变成了先选一个色子,再掷色子选词。至于引入先验究竟有没有用是贝叶斯学派和频率学派之间争吵的话题了。
    • +
    • PLSA模型为人类语言生成提供了一个很直观的建模,引入了主题作为隐含语义,并定义了主题代表词的分布,将文章看成是主题的混合。
    -

    \[ -L = \sum _{j=1}^n \sum _{v=1}^k \lambda _{v,j} (\sum _{i=1}^m \pi -(x(i))_v x(i)_j - A(v,y(i)) x(i)_j) \\ -+ \sum _{v=1}^k \sum _{i=1}^m \beta _i (\pi (x(i))_v -1) \\ -- \sum _{v=1}^k \sum _{i=1}^m \pi(x(i))_v log(\pi (x(i))_v) \\ -\] - 这里又有一个trick,本来应该对所有参数求导,这里我们先对\(\pi (x(i))_u\)求导令其为0可得: \[ -\pi (x(i))_u = e^{\lambda _u x(i) + \beta _i -1} -\] - 再考虑等式约束条件(概率之和为1),这样就不用再对\(\beta\)求导: \[ -\sum _{v=1}^k e^{\lambda _v x(i) + \beta _i -1} = 1 \\ -e^{\beta} = \frac {1}{\sum _{v=1}^k e^{\lambda _v x(i) - 1}} \\ -\] - 回代可得: \[ -\pi (x)_u = \frac {e^{\lambda _u}x}{\sum _{v=1}^k e^{\lambda _v}x} -\]

    -

    求解参数

    +

    LDA文本建模

    +

    模型概述

      -
    • 从推出平衡等式的时候可以看到,我们需要解\(n \* k\)个方程来得到\(n \* k\)个参数\(\lambda\),或者在最大熵的拉格朗日方程里对\(n \* k\)\(\lambda\)求偏导,因为\(\pi\)\(\lambda\)的非线性函数,这两种求解方法比较困难,但是我们可以求导计算这些等式的雅各比方程(或者说是目标函数的Hessian矩阵),之后我们就可以用某种牛顿法、Fisher -Scoring或者迭代的方法求解\(\lambda\)
    • +
    • LDA整合了Unigram和PLSA的优点,对于词和主题这两个骰子分别加上了Dirichlet先验假设 +
        +
      • 词生成概率分布(暂记A)
      • +
      • 词生成概率分布的参数分布(暂记B)
      • +
      • 主题生成概率分布(暂记C)
      • +
      • 主题生成概率分布的参数分布(暂记D)
      • +
    • +
    • 这里初学容易混淆的是,主题生成概率分布并不是词生成概率分布的参数分布,要区分LDA模型中的层次关系和各个层次里共轭关系。另外主题和词并不是一对多的层次关系,两者是多对多的关系,事实上,在LDA模型中一篇文档是这么生成的(假设有K个主题): +
        +
      • 先在B分布条件下抽样得到K个A分布
      • +
      • 对每一篇文档,在符合D分布条件下抽取得到一个C分布,重复如下过程生成词: +
          +
        • 从C分布中抽样得到一个主题z
        • +
        • 从第z个A分布中抽样得到一个单词
        • +
      • +
    • +
    • 假设有\(m\)篇文档,\(n\)个词,\(k\)个主题,则\(D+C\)\(m\)个独立的Dirichlet-Multinomial共轭,\(B+A\)\(k\)个独立的Dirichlet-Multinomial共轭。两个dirichlet参数分别为1个k维向量(\(\alpha\))和1个n维向量(\(\beta\))。现在我们可以理解本文最开始的配图,我们将符号用其实际意义表述,与标题配图对应,这幅图实际上描述了LDA中这\(m+k\)个独立的Dirichlet-Multinomial共轭:
    -

    与特征函数定义的最大熵模型的联系

    +

    +

    建立分布

      -
    • 在本文中,约束为(省略了\(\pi\)必须为概率的约束): \[ -\sum _{i=1,y(i)=u}^m x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ -\]
    • -
    • 最大化的熵为: \[ -Ent(\pi) = - \sum_{v=1}^k \sum _{i=1}^m \pi (x(i))_v log (\pi (x(i))_v) +
    • 现在我们可以用\(m+k\)个Dirichlet-Multinomial共轭对LDA主题模型建模了,借鉴之前推导Unigram模型时得到最终的文档生成分布,我们可以分别计算: +\[ +\begin{aligned} +p(\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow}) = \prod +_{m=1}^M +\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} +\\ +p(\mathop{w}^{\rightarrow}|\mathop{z}^{\rightarrow},\mathop{\beta}^{\rightarrow}) += \prod _{k=1}^K +\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} \\ +\end{aligned} \]
    • -
    • 得到的结果为: \[ -\pi (x)_u = \frac {e^{\lambda _u}x}{\sum _{v=1}^k e^{\lambda _v}x} +
    • 最终得到词与主题的联合分布: \[ +p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow},\mathop{\beta}^{\rightarrow}) += \prod _{m=1}^M +\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} +\prod _{k=1}^K +\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} \]
    • -
    • 而在统计学习方法中,约束为(同样省略了概率约束),其中\(P^{*}\)代表经验分布: \[ -\sum _{x,y} P^{*} (x,y)f(x,y) = \sum _{x,y} P^{*} (x)P(y|x)f(x,y) +
    +

    采样

    +
      +
    • 在前面说了,我们按照贝叶斯推断的框架估计模型参数,需要直到主题分配的后验概率,这里就需要gibbs +sampling来帮忙对后验做一个近似
    • +
    • 按照gibbs sampling的定义,我们需要主题分配的完全条件概率\(p(z_i=k|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w}^{\rightarrow})\)去采样,进而近似\(p(z_i=k|\mathop{w}^{\rightarrow})\)\(z_i\)代表第i个词的主题(这里下标i代表第m篇文档第n个词),而向量w代表我们现在观察到的所有词。
    • +
    • 在建立了整个概率模型之后,我们通过以下方法训练:设定好超参,随机初始化各个词频统计(包括文章m下主题k的词数,词汇t属于主题k的词数,文章m的总词数,主题k的总词数),然后对语料中所有词,依次进行吉布斯采样,采样其主题,并分配给该词这个主题,并更新四个词频(即利用共轭更新后验),循环采样直到收敛,即采样之后的主题分布基本符合后验概率下的模型产生的主题分布,数据已经不能提供给模型更多的知识(不再进行更新)。 +
        +
      • 其中吉布斯采样是需要限定某一维,按照其他维度的条件概率进行采样,在文本主题建模中维度就是词语,按其他维度的条件概率计算就是在四个词频中除去当前词语及其主题的计数。
      • +
      • 采样后主题后将这个主题分配给词语,四个词频计数增加,如果已经收敛,则采样前后主题相同,词频没有改变,则相当于后验没有从数据知识中获得更新。
      • +
    • +
    • 公式推导:下面分别介绍两种推导方法,第一种是LDA数学八卦一文中基于共轭关系做出的推导,另一种是Parameter +estimation for text analysis 一文中基于联合分布做出的推导
    • +
    • 基于共轭关系推导如下:
    • +
    • 采样的对象是词所对应的主题,概率为: \[ +p(z_i=k|\mathop{w}^{\rightarrow}) \]
    • -
    • 最大化的熵为: \[ -Ent(P) = - \sum _{x,y} P^{*}(x) P(y|x) log P(y|x) +
    • 使用吉布斯采样来采样某一个词的主题,则需要用其他词的主题作为条件计算条件概率: +\[ +p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow}) \]
    • -
    • 得到的结果为: \[ -P(y|x) = \frac{e^{\sum _i w_i f_i(x,y)}}{\sum _y e^{\sum _i w_i -f_i(x,y)}} +
    • 由贝叶斯公式,这个条件概率正比于(采样我们可以按正比扩大各个概率采样): +\[ +p(z_i=k,w_i=t|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ +i}}^{\rightarrow}) \]
    • -
    • 可以看到两者的表示有区别,前者直接得到了softmax函数的形式,但是最大化的不是条件熵,后者则相反
    • -
    • 实际上两者是统一的。首先,模型的参数都是拉格朗日乘子,前者是\(\lambda\),后者是\(w\),两者的关系: 把这个公式按主题分布和词分布展开: \[ +\int p(z_i=k,w_i=t,\mathop{\vartheta _m}^{\rightarrow},\mathop{\varphi +_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ +i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} d\mathop{\varphi +_k}^{\rightarrow} +\]
    • +
    • 由于所有的共轭都是独立的,上式可以写成: \[ -\lambda = \{w_0,...,w_i,...\} +\int p(z_i=k,\mathop{\vartheta _m}^{\rightarrow}|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})p(w_i=t,\mathop{\varphi +_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ +i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} d\mathop{\varphi +_k}^{\rightarrow} \]
    • -
    • 当特征函数扩展到特征值时,两者得到的模型就是一样的(softmax函数): +
    • 把概率链式分解下,又因为两个式子分别和主题分布和词分布相关,因此可以写成两个积分相乘: \[ -f_i(x_j,y) = x(j)_i +\int p(z_i=k|\mathop{\vartheta _m}^{\rightarrow})p(\mathop{\vartheta +_m}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ +i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} \cdot \int +p(w_i=t|\mathop{\varphi _k}^{\rightarrow})p(\mathop{\varphi +_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ +i}}^{\rightarrow})d\mathop{\varphi _k}^{\rightarrow} \]
    • -
    • 两者的平衡条件也是一致的,注意到\(P^{*}\)是经验分布,是在训练集上通过古典概型统计出来的,一般情况下不考虑重复数据(样本总数为N,类别数为K),则有: +
    • 已知第m篇文档的主题分布和第k个主题词分布,求第i个词为t的概率和第i个词对应主题为k的概率,那么显然: \[ -P^{*} (x) = \frac 1N \\ -\sum _{x,y} P^{*} (x,y) = 1 \\ -P^{*} (x,y) \in \{0,\frac 1N \} \\ +p(z_i=k|\mathop{\vartheta _m}^{\rightarrow})=\mathop{\vartheta _{mk}} \\ +p(w_i=t|\mathop{\varphi _k}^{\rightarrow})=\mathop{\varphi _{kt}} \\ \]
    • -
    • 代入之后会发现两者的平衡条件一致,而论文中计算的貌似是熵,实际上是条件熵,只不过把$P^{*} -(x) = 1N $这一常量条件从argmax表达式中忽略了,写成了熵的形式。
    • -
    -]]>
    - - 机器学习 - - - machine learning - math - logistic regression - -
    - - Numpy Cookbook - /2017/01/23/numpycookbook/ - Cookbook网址:Numpy -Cookbook Numpy的一些语法查询和总结 持续更新

    - -
      -
    • shape() shape是numpy函数库中的方法,用于查看矩阵或者数组的维素 -shape(array) 若矩阵有m行n列,则返回(m,n) array.shape[0] -返回矩阵的行数m,参数为1的话返回列数n

    • -
    • tile() tile是numpy函数库中的方法,用法如下: tile(A,(m,n)) -将数组A作为元素构造出m行n列的数组

    • -
    • sum() sum()是numpy函数库中的方法 -array.sum(axis=1)按行累加,axis=0为按列累加

    • -
    • argsort() argsort()是numpy中的方法,得到矩阵中每个元素的排序序号 -A=array.argsort() A[0]表示排序后 -排在第一个的那个数在原来数组中的下标

    • -
    • dict.get(key,x) -Python中字典的方法,get(key,x)从字典中获取key对应的value,字典中没有key的话返回0

    • -
    • sorted()

    • -
    • numpy中有min()、max()方法,用法如下 array.min(0) -返回一个数组,数组中每个数都是它所在列的所有数的最小值 array.min(1) -返回一个数组,数组中每个数都是它所在行的所有数的最小值

    • -
    • listdir('str') strlist=listdir('str') -读取目录str下的所有文件名,返回一个字符串列表

    • -
    • split() python中的方法,切片函数 -string.split('str')以字符str为分隔符切片,返回list

    • -
    • zeros a=np.zeros((m,n), dtype=np.int) -#创建数据类型为int型的大小为m*n的零矩阵

    • -
    -]]>
    - - Python - - - machine learning - math - code - python - -
    - - Note for Latent Dirichlet Allocation - /2018/07/23/lda/ - -

    Latent Dirichlet Allocation 文档主题生成模型学习笔记 -本文主要归纳自《LDA数学八卦》,原文写的非常精彩(建议先阅读原文),有许多抛砖引玉之处,本文梳理了其一步一步推出LDA的脉络,删除了不相关的一些扩展,比较大白话的总结一下LDA。

    - -
    -i0oNlT.jpg - -
    -

    LDA用来做什么

    -
      -
    • LDA是一种主题模型,问题实际上是主题模型是用来做什么?用来表示文档 -。在这里将文档看成一个词袋。
    • -
    • 如果将词典里每一个词看成一个特征,tfidf值作为特征值大小来表示文档,则文档的特征向量太过稀疏,且维度太高
    • -
    • LSI的解决办法是,将文档-词的矩阵进行奇异值分解,降维,但是这样得到的降维空间,即词到文档之间的隐变量无法解释,纯数学的方法,太暴力
    • -
    • PLSA提出了隐变量应该是主题,可以把文档表示为主题向量,而主题定义为在词典上的某一种多项式分布,这样PLSA中包含了两层多项式分布:文档到主题的多项式分布(文档中各个主题的混合比例,即文档的特征向量),主题到词的多项式分布(在整个词典上的概率分布,表示不同主题下各个词出现的概率)
    • -
    • LDA则对这两个多项式分布的参数制定了迪利克雷先验,为PLSA引入贝叶斯框架
    • -
    -

    贝叶斯模型

    -
      -
    • LDA是一种贝叶斯模型
    • -
    • 给定训练数据,贝叶斯模型怎么学习参数(参数的分布):贝叶斯估计 -
        -
      • 先给参数一个先验分布\(p(\theta)\)
      • -
      • 给定数据,计算似然\(p(X|\theta)\)和evidence\(P(X)\),根据贝叶斯公式计算参数的后验分布
      • -
      • 后验分布就是学习到的参数分布 \[ -p(\vartheta | X)=\frac{p(X | \vartheta) \cdot -p(\vartheta)}{p(\mathcal{X})} +
      • 而根据共轭关系,有 \[ +p(\mathop{\vartheta _m}^{\rightarrow}|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})=Dir(\mathop{\vartheta +_m}^{\rightarrow}|\mathop{n_{m,¬ +i}}^{\rightarrow}+\mathop{\alpha}^{\rightarrow}) \\ +p(\mathop{\varphi _k}^{\rightarrow}|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})=Dir(\mathop{\varphi +_k}^{\rightarrow}|\mathop{n_{k,¬ +i}}^{\rightarrow}+\mathop{\beta}^{\rightarrow}) \\ \]
      • -
    • -
    • 可能数据太多,那就分批更新,上一次更新后得到的后验作为下一次更新的先验,类似于随机梯度下降中的思想
    • -
    • 对于新数据的似然,不像最大似然估计或者最大后验估计,两者是点估计,直接算\(p(x_{new}|\theta _{ML})\),\(p(x_{new}|\theta -_{MAP})\),贝叶斯估计需要对参数分布求积分: 因此整个式子可以看作是两个Dirichlet分布的期望向量的第k项和第t项相乘。而根据之前Dirichlet的性质,易得这两个期望是按Dirichlet参数比例得到的分式,因此最后的概率计算出来就是(注意是正比于): +\[ +p(z_i=k|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝\frac{n_{m,¬ i}^{(k)}+\alpha +_k}{\sum _{k=1}^K (n_{m,¬ i}^{(k)}+\alpha _k)} \cdot \frac{n_{k,¬ +i}^{(t)}+\beta _t}{\sum _{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} +\]
    • +
    • 这个概率可以理解为(排除当前这第i个token以外): \[ -\begin{aligned} -p(\tilde{x} | X) &=\int_{\vartheta \in \Theta} p(\tilde{x} | -\vartheta) p(\vartheta | X) \mathrm{d} \vartheta \\ -&=\int_{\vartheta \in \Theta} p(\tilde{x} | \vartheta) \frac{p(X | -\vartheta) p(\vartheta)}{p(X)} \mathrm{d} \vartheta -\end{aligned} +(文档m中主题k所占的比例) * (主题k中词t所占的比例) +\]
    • +
    • 注意到第一项的分母是对主题求和,实际上和k无关,因此可以写成: \[ +p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝ +(n_{m,¬ i}^{(k)}+\alpha _k) \cdot \frac{n_{k,¬ i}^{(t)}+\beta _t}{\sum +_{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} +\]
    • +
    • 我们再看看基于联合分布如何推导
    • +
    • 之前我们已经得到词和主题的联合分布: \[ +p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow},\mathop{\beta}^{\rightarrow}) += \prod _{m=1}^M +\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} +\prod _{k=1}^K +\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} +\]
    • +
    • 根据贝叶斯公式有 \[ +p(z_i=k|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w}^{\rightarrow})=\frac{p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow})}{p(\mathop{w}^{\rightarrow},\mathop{z_{¬ +i}}^{\rightarrow})} \\ +=\frac{p(\mathop{w}^{\rightarrow}|\mathop{z}^{\rightarrow})} +{p(\mathop{w_{¬ i}}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow})p(w_i)} +\cdot \frac{p(\mathop{z}^{\rightarrow})} {\mathop{p(z_{¬ +i})}^{\rightarrow}} \\ +\]
    • +
    • 因为\(p(w_i)\)是可观测变量,我们省略它,得到一个正比于的式子,将这个式子用之前的\(\Delta\)形式表示(分式除以分式,分母相同抵消了): +\[ +∝ +\frac{\Delta(\mathop{n_{z}}^{\rightarrow})+\mathop{\beta}^{\rightarrow}}{\Delta(\mathop{n_{z,¬ +i}}^{\rightarrow})+\mathop{\beta}^{\rightarrow}} \cdot +\frac{\Delta(\mathop{n_{m}}^{\rightarrow})+\mathop{\alpha}^{\rightarrow}}{\Delta(\mathop{n_{m,¬ +i}}^{\rightarrow})+\mathop{\alpha}^{\rightarrow}} \]
    • -
    • 贝叶斯估计里常常出现两个问题 -
        -
      • 有了先验,有了似然,计算出的后验很复杂
      • -
      • evidence很难算
      • -
    • -
    • 因此共轭和gibbs sampling分别解决这两个问题 -
        -
      • 共轭:给定似然,找一个先验,使得后验的形式和先验一致
      • -
      • gibbs -sampling:利用MCMC的思路去近似后验,而不用显式的计算evidence
      • -
    • -
    • 假如是带隐变量的贝叶斯模型,那么有 \[ -p(\vartheta|x) = \int_{z} p(\vartheta|z)p(z|x) +
    • \(\Delta\)的表达式带入计算,也可以得到: +\[ +p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝ +(n_{m,¬ i}^{(k)}+\alpha _k) \cdot \frac{n_{k,¬ i}^{(t)}+\beta _t}{\sum +_{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} \]
    • -
    • 在LDA当中,隐变量z就是词所属的主题(词的主题分配),那么\(p(\vartheta|z)\)自然是很好求的,那么剩下的\(p(z|x)\),就再套上面贝叶斯推断的公式: 最后附上Parameter estimation for text +analysis一文中吉布斯采样的伪算法图:
    • +
    +
    +i0oU6U.png + +
    +
      +
    • 可以看到主要通过记录四个n值(两个矩阵两个向量)来计算条件概率,更新主题时也是更新四个n值进行增量更新。算法先通过随机均匀采样赋初值,然后按采样公式更新主题(先减去旧的主题分配,再加上新的主题分配),其中公式78即之前我们计算得到的\(p(z_i=k|\mathop{z_{¬ +i}}^{\rightarrow},\mathop{w}^{\rightarrow})\),公式81和82分别为\(\mathop{\vartheta _{mk}},\mathop{\varphi +_{kt}}\),我们可以直接通过四个n值得到,不用考虑采样时的\(¬ i\)条件了,具体是: \[ -p(z | X)=\frac{p(X | z) \cdot p(z)}{p(\mathcal{X})} +\mathop{\vartheta _{mk}} = \frac{n_{m}^{(k)}+\alpha _k}{\sum _{k=1}^K +(n_{m}^{(t)}+\alpha _k)} \\ +\mathop{\varphi _{kt}} = \frac{n_{k}^{(t)}+\beta _t}{\sum _{t=1}^V +(n_{k}^{(t)}+\beta _t)} \]
    • -
    • 在介绍LDA之前,介绍了其他两个模型,带贝叶斯的unigram以及plsa,前者可以看成是没有主题层的LDA,后者可以看成是没有贝叶斯的LDA
    • -
    • 接下来就分别介绍共轭、gibbs -sampling、带贝叶斯的unigram/plsa,最后介绍LDA
    -

    共轭

    -

    Gamma函数

    +

    训练与测试

      -
    • 定义 \[ -\Gamma (x) = \int _0 ^{\infty} t^{x-1} e^{-t} dt -\]
    • -
    • 因为其递归性质\(\Gamma(x+1)=x\Gamma(x)\),可以将阶乘的定义扩展到实数域,进而将函数导数的定义扩展到实数集,例如计算1/2阶导数
    • -
    • Bohr-Mullerup定理:如果\(f:(0,\infty) -\rightarrow (0,\infty)\),且满足 +
    • 接下来我们来训练LDA模型,首先对LDA的Dir参数随机初始化(先验),然后使用文本进行数据知识补充,得到最终正确的后验,训练是一个迭代过程:
        -
      • \(f(1)=1\)
      • -
      • \(f(x+1)=xf(x)\)
      • -
      • \(log f(x)\)是凸函数 那么\(f(x)=\Gamma(x)\)
      • +
      • 迭代什么?采样并更新词对应的主题
      • +
      • 根据什么迭代?gibbs采样的完全条件概率
      • +
      • 迭代之后的效果?主题分配改变、统计量改变、下一次gibbs采样的完全条件概率改变
      • +
      • 迭代到什么时候为止?Gibbs采样收敛,即采样一段时间区间内主题分布稳定不变,或者根据困惑度等指标来衡量模型收敛的程度。
    • -
    • Digamma函数 \[ -\psi (x)=\frac{d log \Gamma(x)}{dx} -\] 其具有以下性质 \[ -\psi (x+1)=\psi (x)+\frac 1x -\]
    • -
    • 在用变分推断对LDA进行推断时结果就是digamma函数的形式
    • +
    • 训练和测试的区别在于,训练是针对全文档集进行采样更新,文档到主题和主题到词的分布都在更新,而测试则保留主题到词的分布不变,只针对当前测试的文档采样到收敛,得到该文档的主题分布。
    • +
    • 事实上两个超参\(\alpha\)\(\beta\)在训练完之后是经过了很多次后验替换先验的迭代,参数值很大了,\(\alpha\)就抛弃了这最后的后验结果,在对新文档产生主题分布时重新用最开始的先验值,这样的话中途得到的训练集上的文档到主题的分布在测试新文档时实际上是用不上的,我们利用的是主题到词的分布:因为只有主题集合是针对整个文档空间的(训练集和测试集),主题到词的分布也是建立在整个文档空间的词典上的,这一部分的k个\(\beta\)向量我们保留最后的后验结果,因为这个后验吸收了数据的似然知识后参数值很大,不确定度很小了,基本上每个\(\beta\)向量就等同于确定了一个主题到词的多项式分布,也就是确定了一个主题。我们利用这确定的主题,来测试一篇新文档在各个主题上的分布。因此在测试新文档时参数\(\alpha\)一般设置为对称的,即各个分量相同(没有先验偏好那个主题),且值很小(即不确定度大,否则生成的主题分布是均匀分布),这里类似于最大熵的思想。测试是利用已知的固定的主题去得到文档到主题的分布。
    • +
    • LDA的训练实际上是一种无参贝叶斯推断,可以采用MCMC方法和非MCMC方法,MCMC方法中经常采用的就是Gibbs采样,而非MCMC方法还可以用变分推断等方法来迭代得到参数。
    -

    Gamma分布

    +

    LDA in Gensim

      -
    • 将上式变换 \[ -\int _0 ^{\infty} \frac{x^{\alpha -1}e^{-x}}{\Gamma(\alpha)}dx = 1 -\] -因此可取积分中的函数作为概率密度,得到形式最简单的Gamma分布的密度函数: -\[ -Gamma_{\alpha}(x)=\frac{x^{\alpha -1}e^{-x}}{\Gamma(\alpha)} -\]
    • -
    • 指数分布和\(\chi -^2\)分布都是特殊的Gamma分布,且作为先验分布非常有用,广泛应用于贝叶斯分析当中。
    • -
    • Gamma分布与泊松分布具有形式上的一致性,实际上在两者的通常表示中,仅仅只有参数差1的区别,且之前说到阶乘可以用Gamma函数表示,因此可以直观的认为Gamma分布是Poisson分布在正实数集上的连续化版本。 -\[ -Poisson(X=k|\lambda)=\frac{\lambda ^k e^{-\lambda}}{k!} -\]
    • -
    • 令二项分布中\(np=\lambda\),当n趋向于无穷且p趋向于0时,泊松分布就是二项分布的极限分布。经常用于解释泊松分布的一个例子是交换机接收呼叫,假设将整个时间分成若干个时间段,每个时间段内至多达到一次呼叫,概率为p,则总体呼叫数符合一个二项分布,当np为定值\(\lambda\)时,将时间分为无穷个段,几乎是连续的,取\(p=\frac{\lambda}{n}\)带入二项分布,取极限后即得到泊松分布。在此基础上分布的取值连续化(即将泊松分布中k的阶乘用Gamma函数替代)就得到Gamma分布。
    • +
    • Gensim中的LDA提供了几个参数,其中\(\alpha\)的默认值如下:

      alpha ({numpy.ndarray, str}, optional) – Can be set to an 1D array of +length equal to the number of expected topics that expresses our +a-priori belief for the each topics’ probability. Alternatively default +prior selecting strategies can be employed by supplying a string: +’asymmetric’: Uses a fixed normalized asymmetric prior of 1.0 / topicno. +’default’: Learns an asymmetric prior from the corpus.

      +
    • +
    • gensim中没有暴露\(\beta\)给用户,用户只能设置\(\alpha\),可以自定义,也可以设置对称或者不对称。其中对称设置即全为1,不对称设置则拟合了zipf +law(?),可能\(\beta\)的默认设置就是不对称。
    -

    Beta分布

    +

    More

      -
    • 背景: +
    • Parameter estimation for text analysis +一文指出了隐主题实际上来自词与词之间的高阶共现关系
    • +
    • LDA用于document +query,其中LDA在candidates上训练,新来一个query就进行一次测试
        -
      • 现在有n个在[0,1]区间上均匀分布的随机变量,将这n个随机变量按大小排序后,如何求得第k个顺序统计量\(p=x_k\)的分布?
      • -
      • 为了求分布,利用极限的思想,我们求这个变量落在一小段区间上的概率\(x \leq X_{k} \leq x+\Delta x\)
      • -
      • 将整个区间分为三部分:小区间以前,小区间,小区间以后,若小区间内只有第k大的数,则小区间以前应该有k-1个数,小区间以后应该有n-k个数,这种情况的概率为 +
      • 基于similarity +ranking的方法,使用JS距离或者KL散度计算candidate与query之间topic +distribution的相似度,并排序
      • +
      • 基于Predictive likelihood +ranking的方法,计算给定query,每个candidate出现的概率,基于主题z分解: \[ \begin{aligned} -P(E)&=x^{k-1}(1-x-\Delta x)^{n-k}\Delta x \\ -&=x^{k-1}(1-x)^{n-k}\Delta x+\omicron (\Delta x) \\ +p\left(\vec{w}_{m} | \tilde{\vec{w}}_{\tilde{m}}\right) +&=\sum_{k=1}^{K} p\left(\vec{w}_{m} | z=k\right) p\left(z=k | +\tilde{\vec{w}}_{\tilde{m}}\right) \\ +&=\sum_{k=1}^{K} \frac{p\left(z=k | \vec{w}_{m}\right) +p\left(\vec{w}_{m}\right)}{p(z=k)} p\left(z=k | +\tilde{\vec{w}}_{\tilde{m}}\right) \\ +&=\sum_{k=1}^{K} \vartheta_{m, k} \frac{n_{m}}{n_{k}} +\vartheta_{\tilde{m}, k} \end{aligned} \]
      • -
      • 若小区间内有两个及两个以上的数,计算可得这种情况的概率是\(\omicron (\Delta -x)\),因此只考虑小区间内只有第k大的数,此时令\(\Delta -x\)趋向于0,则得到第k大数的概率密度函数(注意事件E的系数应该是\(nC_n^k\)): \[ -f(x)=\frac{n!}{(k-1)!(n-k)!}x^{k-1}(1-x)^{n-k} \quad x \in [0,1] -\] 用Gamma函数表示(令\(\alpha =k,\beta -= n-k+1\))得到: \[ -\begin{aligned} -f(x)&=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}x^{\alpha-1}(1-x)^{\beta-1} -\\ -&=Beta(p|k,n-k+1) \\ -&=Beta(\alpha,\beta) \\ -\end{aligned} -\] -这就是Beta分布,我们可以取概率分布最大的点作为第k大数的预测值。
    • -
    • Beta分布实际上是对分布的预测,即分布的分布。在背景里,我们要找第k大顺序统计量的概率分布,我们把这个第k大顺序统计量记作p,现在知道有n个在[0,1]区间上均匀分布的值,n和k建立了一个在[0,1]区间内的相对位置,这也就是\(\alpha\)\(\beta\)的作用(因为\(\alpha\)\(\beta\)就是n和k计算出来的),代表我倾向于认为p在[0,1]中的哪里。因为n个统计量是均匀分布的,而p是其中第k大的,那么p就倾向于在\(\frac kn\)这个位置。
    • -
    • 因此Beta分布的参数(\(\alpha\)\(\beta\))意义很明显了,就是我在什么都不知道的情况下,先入为主的认为p可能所在的位置,即先验,而Beta分布的结果就是在这种先验影响下,计算出来的p的分布,这个p的实际含义,是二项式分布的参数。因此,Beta分布可以作为二项式分布的参数先验。
    • +
    • LDA用于聚类 +
        +
      • 事实上主题分布就是对文档的一种软聚类划分,假如把每篇文档划分到拥有最大概率的主题上的话,那就是一种硬划分。
      • +
      • 或者利用topic +distribution作为文档的特征向量,再进一步使用各种聚类算法聚类
      • +
      • 聚类结果的评估,可以利用一个已知聚类划分的结果作为参考,利用Variation +of Information distance进行评估
      • +
    • +
    • LDA的评价指标,困惑度,其定义为模型在验证集上测出的似然的reciprocal +geometric mean: \[ +\mathrm{P}(\tilde{\boldsymbol{W}} | \boldsymbol{M})=\prod_{m=1}^{M} +p\left(\tilde{\vec{w}}_{\tilde{m}} | +\mathcal{M}\right)^{-\frac{1}{N}}=\exp -\frac{\sum_{m=1}^{M} \log +p\left(\tilde{\bar{w}}_{\tilde{m}} | \mathcal{M}\right)}{\sum_{m=1}^{M} +N_{m}} +\]
    • +
    • 假定验证集和训练集分布一致,那么LDA在验证集上的困惑度高,代表熵越大,不确定性大,模型还没有学到一个稳定的参数。
    -

    Beta-Binomial共轭

    +]]>
    + + 机器学习 + + + math + topic model + lda + mcmc + +
    + + Logistic Regression and Maximum Entropy + /2018/10/14/lr-and-me/ + 翻译John Mount的The equivalence of logistic regression and +maximum entropy models +一文,并说明了这种证明是在统计学习方法中介绍最大熵模型的通用导出证明的一个特例

    +

    结论 - 最大熵模型就是softmax分类 - +在满足广义线性模型的平衡条件下,满足最大熵条件的模型映射函数就是softmax函数 +- +在统计机器学习方法一书中,给出了在特征函数定义下的最大熵模型,其与softmax回归都属于对数线性模型 +- +当特征函数从二值函数扩展为特征值本身时,最大熵模型就化为softmax回归模型 +- 最大熵最大化的是条件熵,不是条件概率的熵,也不是联合概率的熵。

    + +

    明确符号

      -
    • 这样我们可以对第k大数的分布建立一个Beta分布的先验,如果现在我们知道有m个在[0,1]之间均匀分布的数,且其中有几个比第k大数大,有几个比第k大数小,则可以将其作为一种数据知识补充进去,形成后验分布。
    • -
    • 假设要猜的数\(p=X_k\),现在我们知道了有\(m_1\)个数比\(p\)小,\(m_2\)个数比\(p\)大,显然此时\(p\)的概率密度函数就变成了\(Beta(p|k+m_1,n-k+1+m_2)\)
    • -
    • 补充进m个数的数据知识相对于做了m次贝努利实验,因为我们讨论的范围在[0,1]上,m个数只关心比\(p\)大还是小,\(p=X_k\)的数值便可以代表这一概率,因此\(m_1\)服从二项分布\(B(m,p)\)
    • +
    • n维特征,m个样本,\(x(i)_j\)表示第i个样本第j维特征,讨论多分类情况,输出分类\(y(i)\)有k类,映射概率函数\(\pi\)\(R^n\)映射到\(R^k\),我们希望\(\pi(x(i))_{y(i)}\)尽可能大。
    • +
    • 指示函数\(A(u,v)\),当\(u==v\)时为1,否则为0
    • +
    +

    Logistic回归

    +

    \[ +\pi(x)_1 = \frac{e^{\lambda x}}{1+e^{\lambda x}} \\ +\pi(x)_2 = 1 - \pi(x)_1\\ +\] - 其中要学习到的参数\(\lambda\)\(R^n\)

    +

    Softmax回归

    +

    \[ +\pi(x)_v = \frac{e^{\lambda _v x}} {\sum _{u=1}^k e^{\lambda _u x}} +\] - \(\lambda\)\(R^{k * n}\)

    +

    求解softmax

    +
      +
    • 当使用softmax或者logistic作为非线性函数时,它们存在一个很好的求导的性质,即导函数可以用原函数表示 +\[ +\frac {\partial \pi (x)_v}{\partial \lambda _{v,j}} = x_j \pi (x)_v +(1-\pi (x)_v) \\ +\frac {\partial \pi (x)_v}{\partial \lambda _{u,j}} = -x_j \pi (x)_v \pi +(x)_u \ where \ u \neq v \\ +\]
    • +
    • 现在我们可以定义目标函数,即希望\(\pi\)函数输出的正确类别概率最大(最大似然),并定义最优化得到的\(\lambda\)\[ +\lambda = argmax \sum _{i=1}^m log (\pi (x(i))_{y(i)}) \\ += argmax f(\lambda) \\ +\]
    - - - - - - - - - - - - - - - -
    先验数据知识后验
    Beta分布二项分布Beta分布
    +

    平衡等式

      -
    • 因此我们可以得到Beta-Binomial共轭 \[ -Beta(p|\alpha,\beta)+BinomCount(m_1,m_2)=Beta(p|\alpha+m_1,\beta+m_2) -\] -即数据符合二项分布时,参数的先验分布和后验分布都能保持Beta分布的形式,我们能够在先验分布中赋予参数明确的物理意义,并将其延续到后验分布中进行解释,因此一般将Beta分布中的参数\(\alpha,\beta\)称为伪计数,表示物理计数。
    • -
    • 可以验证的是当Beta分布的两个参数均为1时,就是均匀分布,这时对共轭关系可以看成:开始对硬币不均匀性不知道,假设硬币正面向上的概率为均匀分布,在投掷了m次硬币后,获得了\(m_1\)次向上其他次向下的数据知识,通过贝叶斯公式计算后验概率,可以算出正面向上的概率正好是\(Beta(p|m_1+1,m_2+1)\)
    • -
    • 通过这个共轭,我们可以推出关于二项分布的一个重要公式: 对上面的目标函数求导并令导函数为0: \[ +\frac {\partial f(\lambda)}{\partial \lambda _{u,j}} = \sum +_{i=1,y(i)=u}^m x(i)_j - \sum _{i=1}^m x(i)_j \pi (x(i))_u =0 \\ +\]
    • +
    • 这样我们就得到一个重要的平衡等式(Balance Equation): \[ -P(C \leq k) = \frac{n!}{k!(n-k-1)!}\int _p ^1 t^k(1-t)^{n-k-1}dt \quad C -\sim B(n,p) -\] 现在可以证明如下: +\ \ for \ all \ u,j \\ +\sum _{i=1,y(i)=u}^m x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ +\]
    • +
    • 分析这个等式:
        -
      • 式子左边是二项分布的概率累积,式子右边时是\(Beta(t|k+1,n-k)\)分布的概率积分
      • -
      • 取n个随机变量,均匀分布于[0,1],对于二项分布\(B(n,p)\),若数小于\(p\)则是成功,否则失败,则n个随机变量小于\(p\)的个数C符合二项分布\(B(n,p)\)
      • -
      • 此时可以得到\(P(C \leq -k)=P(X_{k+1}>p)\),即n个随机变量按顺序排好后,小于\(p\)的有\(k\)
      • -
      • 这时利用我们对第k大数的概率密度计算出为Beta分布,带入有 \[ -\begin{aligned} -P(C \leq k) &=P(X_{k+1} > p) \\ - &=\int _p ^1 Beta(t|k+1,n-k)dt \\ - &=\frac{n!}{k!(n-k-1)!}\int _p ^1 t^k(1-t)^{n-k-1}dt \\ -\end{aligned} -\] 即证
      • +
      • 大白话:我们希望得到这么一个映射函数\(\pi\),对某一维(j)特征,用所有样本被映射函数归为第u类的概率加权所有样本的特征值之和,等于第u类内所有样本的特征值之和。显然,最好的情况就是左右两个累加式内的元素完全一样,只有第u类的样本被累加,且第u类样本被映射函数归为第u类的概率为1,其他类样本被归为第u类样本的概率为0.
      • +
      • 但是,这个等式非常的宽松,它只要求两个和式相同,并不要求每一个元素相同,而且这个式子没有显示的写出映射函数的表达式,任何满足该式的非线性映射都有可能称为映射函数。
      • +
      • 用公式表达,就是 \[ + \sum _{i=1}^m A(u,y(i)) x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ + \pi (x(i))_u \approx A(u,y(i)) \\ + \]
    • -
    • 通过这个式子,将n取极限到无穷大,转换为泊松分布,可以推导出Gamma分布。
    • -
    • 在本节中,我们为先验引入了其他信息,就是有几个数比第k大数大和小,这些信息相当于是告诉我:我可以修改p的先验,我之前倾向于认为的p的位置改动了。假如我知道了几个数比p大,那么p的先验位置应该往后移,如果我知道了几个数比p小,那么p的先验位置应该往前移,如果我同时知道了100个数比p大,100个数比p小呢?p的位置不变,但是我更加确信了p真实的位置就是现在这个先验位置,因此Beta分布在这个先验位置上更集中,从后文分析Dirichlet参数的意义中我们会再次看到这一点。先验加上数据知识修改之后,就形成了后验,这就是贝叶斯公式的基本内容。
    -

    Dirichlet-Multinomial共轭

    +

    由最大熵推出softmax

      -
    • 假设我们不仅要猜一个数,还要猜两个数\(x_{k_1},x_{k_1+k_2}\)的联合分布,该如何计算?
    • -
    • 同理,我们设置两个极小区间\(\Delta -x\),将整个区间分为五块,极小区间之间分别为\(x_1,x_2,x_3\)计算之后可以得到 上面说到了平衡等式并没有要求映射函数的格式,那么为什么我们选择了softmax?换句话,什么条件下能从平衡等式的约束推出非线性映射为softmax?
    • +
    • 答案是最大熵。我们现在回顾一下\(\pi\)需要满足的条件: +
        +
      • 平衡等式(即这个\(\pi\)能拟合数据): \[ -f(x_1,x_2,x_3)=\frac{\Gamma(n+1)}{\Gamma(k_1)\Gamma(k_2)\Gamma(n-k_1-k_2+1)}x_1^{k_1-1}x_2^{k_2-1}x_3^{n-k_1-k_2} -\]
      • -
      • 整理一下可以写成 \[ -f(x_1,x_2,x_3)=\frac{\Gamma(\alpha _1+\alpha _2+\alpha -_3)}{\Gamma(\alpha _1)\Gamma(\alpha _2)\Gamma(\alpha _3)}x_1^{\alpha -_1-1}x_2^{\alpha _2-1}x_3^{\alpha _3-1} -\] 这就是3维形式的Dirichlet分布。其中\(x_1,x_2,x_3\)(实际上只有两个变量)确定了两个顺序数联合分布,\(f\)代表概率密度。
      • -
      • 注意到在\(\alpha\)确定的情况下,前面的一堆gamma函数其实是概率归一化的分母,后文我们将Dirichlet分布更一般的写成: -\[ -Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})=\frac{1}{\int -\prod_{k=1}^V p_k^{\alpha _k -1}d\mathop{p}^{\rightarrow}} \prod_{k=1}^V -p_k^{\alpha _k -1} -\]
      • -
      • 其中归一化分母,也即那一堆gamma,令其为:
      • +
      • \(\pi\)的输出得是一个概率: \[ -\Delta(\mathop{\alpha}^{\rightarrow})=\int \prod _{k=1}^V p_k^{\alpha _k --1}d\mathop{p}^{\rightarrow} + \pi (x)_v \geq 0 \\ + \sum _{v=1}^k \pi (x)_v = 1 \\ + \]
      • +
    • +
    • 根据最大熵原理,我们希望满足上述约束条件的\(\pi\)能够具有最大的熵: \[ +\pi = argmax \ Ent(\pi) \\ +Ent(\pi) = - \sum_{v=1}^k \sum _{i=1}^m \pi (x(i))_v log (\pi (x(i))_v) +\\ \]
    • -
    • 同样,我们也可以对Dirichlet分布的先验加入数据知识,其后验依然是Dirichlet分布 -\[ -Dir(p|\alpha)+MultCount(m)=Dir(p|\alpha+m) -\] 上式中的参数均是向量,对应多维情况。
    • -
    • 无论是Beta分布还是Dirichlet分布,都有一个很重要的性质,即他们的均值可以用参数的比例表示,例如对于Beta分布,\(E(p)=\frac{\alpha}{\alpha+\beta}\),对于Dirichlet分布,均值是一个向量,对应于各个参数比例组成的向量。
    • -
    -

    Dirichlet分析

    -
      -
    • 根据Dirichlet的性质,其参数比例代表了[0,1]上的一个划分,决定了dirichlet分布高概率的位置,其参数大小决定了高概率的比例(陡峭),例如下图,多项式分布有三项,参数分别为\(p_1,p_2,p_3\),他们的和为一且各项大于零,在三维空间内便是一个三角面,面上每一点代表一种多项式分布,红色区域概率高,蓝色区域概率低:
    • -
    -
    -i0orkR.png - -
    +
  • 最大熵可以从两个角度理解:
      -
    • \(\alpha\)控制了多项式分布参数的mean -shape和sparsity。
    • -
    • 最左边,Dirichlet的三个参数\(\alpha -_1,\alpha _2,\alpha _3\)相等,代表其红色区域位置居中,且三个\(\alpha\)的值均较大,红色区域较小,把热力图看成等高线图的话就代表红色区域较陡峭,说明Dirichlet非常确认多项式分布的参数会在居中的位置。对于三个多项式分布的参数\(p_1,p_2,p_3\)来说,较大可能取到三个p等值的情况。
    • -
    • 中间的图,三个\(\alpha\)不相等,某一个\(\alpha\)偏大,导致红色区域偏向三角面某一角,导致某一个p取值较大,其余两个p取值较小的可能性比较大,这时体现参数先验的参数作为concentration的作用,将概率注意力集中于某些项。
    • -
    • 最右边,同最左边,三个\(\alpha\)相等,红色区域居中,但是\(\alpha\)的值均偏小,导致红色区域发散,也就是Dirichlet认为三个p的值应该在最中间,但是不那么确定。结果就是三个p之间有差别,但差别不会太大(依然在最中间附近),不会出现非常陡峭的情况(最陡峭也就是最中间无限高,概率为1,三个p值一定相同)
    • -
    • 因此可以看出,\(\alpha\)的比例决定了多项式分布高概率的位置,也就是主要确定了各个\(p\)的比例,定好concentration,而\(\alpha\)的大小决定了这个位置的集中情况,\(\alpha\)越小,位置越集中,p的分布越确定,反之p的分布由红色区域位置大致确定,但是变化范围较大。
    • -
    • \(\alpha\)远小于1时,Dirichelt分布会走向另一个极端,在上面这个三角面的例子里,红色区域依然会陡峭,但是陡峭在三角面的三个角上,可以想成\(alpha\)从大变到1,再变小,大概率密度区域从最中间慢慢分散到整个面,然后又聚集在三个角。
    • -
    • 再来看看维基百科中关于Dirichlet参数\(\alpha\)的描述:

      The concentration parameter Dirichlet distributions are very often -used as prior distributions in Bayesian inference. The simplest and -perhaps most common type of Dirichlet prior is the symmetric Dirichlet -distribution, where all parameters are equal. This corresponds to the -case where you have no prior information to favor one component over any -other. As described above, the single value α to which all parameters -are set is called the concentration parameter. If the sample space of -the Dirichlet distribution is interpreted as a discrete probability -distribution, then intuitively the concentration parameter can be -thought of as determining how "concentrated" the probability mass of a -sample from a Dirichlet distribution is likely to be. With a value much -less than 1, the mass will be highly concentrated in a few components, -and all the rest will have almost no mass. With a value much greater -than 1, the mass will be dispersed almost equally among all the -components. See the article on the concentration parameter for further -discussion.

      -
    • -
    • \(\alpha\)远小于1时,概率密度会主要堆积在一个或少数几个项上,也就是红色区域聚集在三个角的情况,这时Dirichlet分布抽样得到的多项式分布大概率在角上,也就是概率密度堆积在一个项上,其余两个项概率近似为0。\(\alpha\)远大于1时,概率密度会分散到各个部分,就是对应三图中最左边的图,三个项概率相差不大的可能性比较大。
    • +
    • 最大熵也就是最大困惑度,即模型过拟合的风险低,模型复杂程度低,根据奥卡姆剃刀原则,在多个具有相同效果的模型中复杂程度小的模型具有更好的泛化能力,在满足了约束条件的情况下,当然我们希望要一个复杂程度小的模型,相当于正则化。
    • +
    • 约束条件是我们的模型已知的需要满足、需要拟合的部分,剩下的部分是未知的部分,没有规则或者数据指导我们分配概率,那该怎么办?在未知的情况下就应该均匀分配概率给所有可能,这正是对应了最大熵的情况。
    • +
  • +
  • 现在问题已经形式化带约束条件的最优化问题,利用拉格朗日乘子法求解即可。这里有一个trick,原文中说如果直接考虑概率的不等条件就有点复杂,需要使用KTT条件,这里先不考虑,之后如果求出的\(\pi\)满足不等式条件的话就可以跳过了(事实也正是如此)。
  • -

    Role in LDA

    +

    \[ +L = \sum _{j=1}^n \sum _{v=1}^k \lambda _{v,j} (\sum _{i=1}^m \pi +(x(i))_v x(i)_j - A(v,y(i)) x(i)_j) \\ ++ \sum _{v=1}^k \sum _{i=1}^m \beta _i (\pi (x(i))_v -1) \\ +- \sum _{v=1}^k \sum _{i=1}^m \pi(x(i))_v log(\pi (x(i))_v) \\ +\] - 这里又有一个trick,本来应该对所有参数求导,这里我们先对\(\pi (x(i))_u\)求导令其为0可得: \[ +\pi (x(i))_u = e^{\lambda _u x(i) + \beta _i -1} +\] - 再考虑等式约束条件(概率之和为1),这样就不用再对\(\beta\)求导: \[ +\sum _{v=1}^k e^{\lambda _v x(i) + \beta _i -1} = 1 \\ +e^{\beta} = \frac {1}{\sum _{v=1}^k e^{\lambda _v x(i) - 1}} \\ +\] - 回代可得: \[ +\pi (x)_u = \frac {e^{\lambda _u}x}{\sum _{v=1}^k e^{\lambda _v}x} +\]

    +

    求解参数

      -
    • 总结一下共轭:设有分布A,A的参数分布(或者叫分布的分布)为B,若B的先验在获得A的数据知识之后得到的后验与先验属于同一类分布,则A与B共轭,B称为A的参数共轭分布(或者叫先验共轭) -,在上文提到的例子里,Beta分布是二项分布的参数共轭分布,Dirichlet分布是多项式分布的参数共轭分布。
    • -
    • LDA实际上是将文本生成建模为一个概率生成模型,具体而言是一个三层贝叶斯模型,并且针对文档-主题和主题-词语两个multinomial分布都假设其参数先验为Dirichlet分布,用Dirichlet-Multinomial共轭来利用数据知识更新其后验。
    • -
    • 为了介绍Dirichlet-Multinomial共轭,先介绍Gamma函数及其分布,Gamma函数将阶乘扩展到实数域,之后介绍了能估计分布的Beta函数,在引入了Gamma函数之后Beta分布的参数能扩展到实数域。之后介绍了Beta-Binomial共轭,这种共轭带来的好处是在用数据训练修正时,我们已经知道了后验分布的形式,之后将这种共轭关系扩展到高维(估计多个分布),就得到了Dirichlet-Multinomial共轭。
    • -
    • 为文档到主题和主题到词的两个多项式分布加入Dirichlet分布作为参数先验的好处是:将多项式参数作为变量,先验信息指导了参数在哪个范围内变动,而不是具体的值,使得模型在小训练样本内的泛化能力更强。
    • -
    • 在Dirichlet Process中\(\alpha\)的大小体现了Dirichlet分布拟合Base -Measure时的离散程度,\(\alpha\)越大,越不离散,各个项均能得到差不多的概率。
    • -
    • 对应到LDA模型中,这种离散程度就代表了文档是集中在某几个主题上还是在所有主题上较均匀的分布,或者主题是集中在少数词上还是在整体的词上较均匀的分布。
    • +
    • 从推出平衡等式的时候可以看到,我们需要解\(n \* k\)个方程来得到\(n \* k\)个参数\(\lambda\),或者在最大熵的拉格朗日方程里对\(n \* k\)\(\lambda\)求偏导,因为\(\pi\)\(\lambda\)的非线性函数,这两种求解方法比较困难,但是我们可以求导计算这些等式的雅各比方程(或者说是目标函数的Hessian矩阵),之后我们就可以用某种牛顿法、Fisher +Scoring或者迭代的方法求解\(\lambda\)
    -

    吉步斯采样

    -

    随机模拟

    +

    与特征函数定义的最大熵模型的联系

      -
    • 即蒙特卡洛的含义,用于已知分布,需要生成一系列满足此分布的随机样本,并用这些样本的统计量来估计原分布一些不好直接解析计算的参数。
    • -
    • 马尔可夫是指产生随机样本的方法依赖于马氏链的性质,通过构造马氏链当中的转移矩阵,使得马氏链收敛时能够产生满足给定分布的样本序列。
    • -
    • MCMC的一种方法是随机采样,利用已知分布计算出接受率,只接收部分采样,而吉布斯采样是接受率为1的一种MCMC方法。它提升了接受率,但是加长了采样过程。
    • +
    • 在本文中,约束为(省略了\(\pi\)必须为概率的约束): \[ +\sum _{i=1,y(i)=u}^m x(i)_j = \sum _{i=1}^m x(i)_j \pi (x(i))_u \\ +\]
    • +
    • 最大化的熵为: \[ +Ent(\pi) = - \sum_{v=1}^k \sum _{i=1}^m \pi (x(i))_v log (\pi (x(i))_v) +\\ +\]
    • +
    • 得到的结果为: \[ +\pi (x)_u = \frac {e^{\lambda _u}x}{\sum _{v=1}^k e^{\lambda _v}x} +\]
    • +
    • 而在统计学习方法中,约束为(同样省略了概率约束),其中\(P^{*}\)代表经验分布: \[ +\sum _{x,y} P^{*} (x,y)f(x,y) = \sum _{x,y} P^{*} (x)P(y|x)f(x,y) +\]
    • +
    • 最大化的熵为: \[ +Ent(P) = - \sum _{x,y} P^{*}(x) P(y|x) log P(y|x) +\]
    • +
    • 得到的结果为: \[ +P(y|x) = \frac{e^{\sum _i w_i f_i(x,y)}}{\sum _y e^{\sum _i w_i +f_i(x,y)}} +\]
    • +
    • 可以看到两者的表示有区别,前者直接得到了softmax函数的形式,但是最大化的不是条件熵,后者则相反
    • +
    • 实际上两者是统一的。首先,模型的参数都是拉格朗日乘子,前者是\(\lambda\),后者是\(w\),两者的关系: \[ +\lambda = \{w_0,...,w_i,...\} +\]
    • +
    • 当特征函数扩展到特征值时,两者得到的模型就是一样的(softmax函数): +\[ +f_i(x_j,y) = x(j)_i +\]
    • +
    • 两者的平衡条件也是一致的,注意到\(P^{*}\)是经验分布,是在训练集上通过古典概型统计出来的,一般情况下不考虑重复数据(样本总数为N,类别数为K),则有: +\[ +P^{*} (x) = \frac 1N \\ +\sum _{x,y} P^{*} (x,y) = 1 \\ +P^{*} (x,y) \in \{0,\frac 1N \} \\ +\]
    • +
    • 代入之后会发现两者的平衡条件一致,而论文中计算的貌似是熵,实际上是条件熵,只不过把$P^{*} +(x) = 1N $这一常量条件从argmax表达式中忽略了,写成了熵的形式。
    -

    马氏链

    +]]>
    + + 机器学习 + + + math + machine learning + logistic regression + +
    + + Multi-agent Reinforcement Learning Notes + /2023/07/20/marl/ + A simple note on the RL used in single-agent and multi-agent.

    + +

    序列决策

      -
    • 马氏链即状态转移的概率只依赖于前一个状态
    • -
    • 因为转移概率只依赖于前一个状态,因此可以将状态转移概率写成转移概率矩阵,经过n次转移之后的各状态概率分布即初始状态概率分布向量乘以矩阵的n次幂得到的结果
    • -
    • 矩阵的幂从某一次数之后不变,即每一行收敛成相同的概率分布,同时初始概率转移足够多次之后也收敛成相同的分布
    • -
    • 关于马氏链收敛的定义 +
    • 建模序列决策下的智能体,而不仅仅是单一回合或者一次性决策问题
    • +
    • 讨论一个
        -
      • 如果一个非周期马氏链具有转移概率矩阵P(可以有无穷多状态),且它的两个任何状态是联通(任何两个状态可以通过有限步转移到达)的,则\(lim_{n \rightarrow -\infty}P_{ij}^n\)存在且与\(i\)无关,记这个收敛的矩阵为\(\pi(j)\)
      • -
      • \(\pi (j)=\sum _{i=0}^{\infty} \pi (i) -P_{ij}\)
      • -
      • \(\pi\)是方程$P = -$的唯一非负解
      • -
      • \(\pi\)称为马氏链的平稳分布
      • +
      • 完全可观测的随机环境
      • +
      • 具有马尔科夫转移模型
      • +
      • 加性奖励 +的序列决策问题,通常包含状态集合、动作集合、转移模型、奖励函数。问题的解即策略。
    • +
    • 假如序列没有时间限制,最优策略只与状态有关,与时间无关,则称最优策略是平稳的。
    -

    Markov Chain Monte Carlo

    +

    bellman方程,U和Q函数

      -
    • 回到随机生成,对于给定的概率分布,我们希望能生成它对应的样本,一个想法就是构造一个马氏链,其平稳分布刚好就是这个概率分布:因为当马氏链收敛以后,其平稳分布就是各个状态的概率分布,收敛后无论经过状态转移生成多长的状态序列,这个序列里状态的分布一直保持着平稳分布。若平稳分布是要生成的概率分布,则状态序列就是给定概率分布下的一个随机样本序列。
    • -
    • 因此,问题在于,如何已知平稳分布构造马氏链的状态转移矩阵。主要利用了非周期马氏链的细致平稳条件:若\(\pi(i)P_{ij}=\pi(j)P_{ij} \quad for \quad all -\quad i,j\),则\(\pi(x)\)是马氏链的平稳分布。这个定理一个物理解释是:若状态i的概率质量是稳定的,则从状态i转移到状态j变化的概率质量恰好和从状态j转移到状态i变化的概率质量互补。
    • -
    • 设从状态i转移到状态j的概率为\(q(i,j)\),若\(p(i)q(i,j)=p(j)q(j,i)\),那么此时\(p(x)\)就是这个马氏链的平稳分布,转移矩阵也不用改了,但一般情况下你的运气没有那么好,在已知\(p(x)\)的情况下,我们需要对\(q\)进行改造,为此我们乘上一个接受率\(\alpha\),使得: 价值函数(价值函数),代表某一状态/行为序列的奖励综合,U(s0,a0,s1,a0....),从当前状态和动作s0,a0开始
    • +
    • 用加性折扣定义价值,未来的奖励乘gamma递减: \[ -p(i)q(i,j)\alpha (i,j)=p(j)q(j,i)\alpha (j,i) -\] 为什么叫接受率?因为可以理解为这个\(\alpha\)是在原来的状态转移之后再乘一个概率,代表是否接受这次转移。
    • -
    • 如何确定接受率?其实显而易见\(\alpha -(i,j)=p(j)q(j,i)\),对称构造即可。
    • -
    • 因此在每次转移之后,我们从均匀分布采样一个变量,若变量小于接受率则按原始状态转移矩阵进行转移,否则不转移。
    • -
    • 这样的MCMC采样算法存在一个问题,我们其实没有改动原始状态转移矩阵q,而是根据q计算了接受率来保证收敛到p,但是接受率可能计算出来很小,导致状态长期原地踏步,收敛缓慢。事实上,将式\(p(i)q(i,j)\alpha -(i,j)=p(j)q(j,i)\alpha(j,i)\)两边同时乘以一个倍数,细致平稳条件没有被打破,但是接受率获得了提高,因此只要将两边接受率乘以一个倍数并保证两个接受率翻倍之后不大于1即可,一般做法是将较大的接受率乘到1。这时就得到了最常见的一种MCMC方法:Metropolis-Hastings算法。
    • -
    -

    Gibbs Sampling

    +U\left(\,\left[s_{0},\,s_{1},\,s_{2},\,\cdots\,\right]\,\right)=R(s_{0})+\gamma +R(s_{1})+\gamma ^2 R(s_{2})+\,\cdots +\]
      -
    • 之前说到了MCMC实际上没有对状态转移矩阵改动,因此需要一个接受率补充,即便放缩之后总有一个接受率小于1,降低了收敛效率。吉步斯采样希望找到一个转移矩阵Q使得接受率等于1。
    • -
    • 对二维概率分布\(p(x,y)\),易得到 -\[ -\begin{aligned} -p(x_1,y_1)p(y_2|x_1) & =p(x_1)p(y_1|x_1)p(y_2|x_1) \\ -& =p(x_1)p(y_2|x_1)p(y_1|x_1) \\ -& =p(x_1,y_2)p(y_1|x_1) \\ -\end{aligned} -\]
    • -
    • 从左式到最终式,这种形式非常像细致平稳条件!实际上假如固定\(x=x_1\),则\(p(y|x_1)\)可以作为直线\(x=x_1\)上任意两个不同y值的点之间的转移概率,且这种转移满足细致平稳条件。固定y我们能得到相同的结论,因此在这个二位平面上任意两点之间我们可以构造转移概率矩阵: +
    • 因为看重近期奖励
    • +
    • 如果奖励可以投资,则越早的奖励价值越大
    • +
    • 等价于每次转移有\(1-\gamma\)的意外终止
    • +
    • 满足平稳性,t+1的最佳选择未来也是t的最佳选择未来
    • +
    • 避免无穷的序列转移
    • +
    +
  • 基于价值函数,可以选出当前最佳动作,即在当前状态下,使得当前价值最大的动作(转移的即时奖励+后续的期望折扣价值)
      -
    • 若两点在垂直线\(x=x_1\)上,则\(Q=p(y|x_1)\)
    • -
    • 若两点在水平线\(y=y_1\)上,则\(Q=p(x|y_1)\)
    • -
    • 若两点连线既不垂直也水平,则\(Q=0\) -这样对平面上任意两点应用转移矩阵Q,均满足细致平稳条件,这个二维平面上的马氏链将收敛到\(p(x,y)\)
    • +
    • 这里存在一个期望,因为每个动作都可能到每个状态(概率),因此一个动作的价值是在所有可能的未来状态下累加。
    • +
    • 价值函数只是状态的函数,已经对所有动作累加求期望 \[ +\pi^*(s) = \underset{a \in A(s)}{\text{argmax}} \sum_{s^{'}} +P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U(s^{'})] +\]
  • -
  • gibbs采样得到新的x维度之后,在计算新的y维度时是依赖了新的x维度,因为是在之前选定坐标轴转换的基础上再进行转移,不然无法跳转到新状态\((x_2,y_2)\),你得到的实际上是\((x_1,y_2)\)\((x_2,y_1)\)
  • -
  • 因此,给定二维概率分布,可以计算出这个平面上沿水平或者垂直方向的满足细致平稳条件的转移概率,从平面上任何一点状态出发,它一次转移只改变横坐标或者纵坐标,也就是水平或者垂直移动,从细致平稳条件的公式可以看到这个平稳是可以传递的,如果从某一个维度的转移满足平稳条件,之后接着另一个维度,那么两次转移所等效的一次转移也是平稳的。
  • -
  • 等到所有维度都转移了一次,就得到了一个新的样本。等到马氏链收敛之后形成的样本序列就是我们所需要的随机生成样本序列。状态的转移可以是坐标轴轮流变换的,即这次水平转换,下次垂直转换,也可以每次随机选择坐标轴。虽然每次随机选择坐标轴会导致中途计算出来的新的维度值不一样,但是平稳条件没有打破,最终能够收敛到一样的给定分布。
  • -
  • 同样,上述算法也可以推广到多维。扩展到多维时,在\(x\)轴上构建的的转移概率就是\(Q=p(x|¬ -x)\)。值得注意的是,上述得到的采样样本并不是相互独立的,只是符合给定的概率分布。
  • - -

    Role in LDA

    +
  • 同理,价值函数只是状态的函数,已经对所有动作累加求期望,其实就是上式,只不过不是argmax选动作,而是max,这里的解释是:假设agent选择了最佳动作,状态价值是下一次转移的期望奖励加上下一个状态的折扣价值 +\[ +U(s) = \underset{a \in A(s)}{\text{max}} \sum_{s^{'}} +P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U(s^{'})] +\]
      -
    • 首先明确,MCMC方法是产生已知分布的样本,但是gibbs采样只需要使用完全条件概率,产生了满足联合分布的样本,而不像一般采样方法直接从联合分布中采样
    • -
    • gibbs采样这种特性就使其可以在不知道联合概率的情况下去推断参数,进一步推出联合概率分布
    • -
    • 但是在LDA中,并没有用gibbs -sampling去直接推断参数,而是用其去近似后验,完成用数据知识更新先验这一步。而且由于LDA存在着主题这一隐变量,gibbs采样的联合分布并不是文档的主题分布或者主题的词分布,和LDA模型的参数没有直接挂钩。Gibbs -sampling在LDA中采样的是token的主题分配,即隐变量的分布。
    • -
    • 但是所有token主题分配确定之后,LDA模型的参数就确定了,通过古典概型(最大似然估计)就可以得到两个multinomial分布(参数),对应的dirichelt分布(参数后验分布)也得到更新。且由于引入了主题分解了文档-单词矩阵,实际上我们不需要维护\(Document \* word\)矩阵,而是维护\(Document \* topic + topic \* -word\)即可。
    • -
    • gibbs采样词的主题分配,实际上是在计算隐变量分布的后验,进而得到参数分布的后验。
    • -
    • gibbs采样中在不断更新参数,例如本次迭代更新\(p(x_1^{t+1})=p(x_1|x_2^t,x_3^t)\),则下一次迭代为\(p(x_2^{t+1})=p(x_2|x_1^{t+1},x_3^t)\),即使用更新之后的\(x_1^{t+1}\)来计算。在LDA中,这一过程通过更新被采样单词的主题实现。贝叶斯推断中将数据分批,用后验更新先验的迭代,在这里被进一步细化到了gibbs -sampling的每一次坐标更新。
    • -
    • 下文可以看到gibbs采样公式,可以解释为根据其他词的主题分配情况决定自己的主题分配,迭代更新所有词的主题分配;具体如何决定,包含了两个部分,这两个部分类似于tf和idf提供的信息。
    • -
    • 当根据采样公式计算出主题分配的后验时,我们并没有直接得到参数的后验分布,但是当根据主题分配后验采样出新主题,更新了统计量之后,由于gibbs -sampling公式里本身包含了统计量,这里相当于计算后验和用后验更新先验一步完成。或者也可以理解成,LDA里一直做的是主题分配分布(隐变量)的贝叶斯推断,即\(p(topic|word,doc)\),做完之后根据主题分配,做一次最大似然估计(古典概型)就能得到模型的参数。
    • +
    • 注意两个式子本质是一样的,都是挑动作,都是在所有可能的状态下累加,但这是基于对未来期望的估计,实际执行就是选择一个动作,转移到一个状态。
    • +
    • 该式即bellman方程
    • +
  • +
  • 引入Q函数,Q是动作和状态的函数,U仅仅是状态的函数,两者的转换关系如下 +\[ +U(s) = \underset{a \in A(s)}{\text{max}} Q(s,a) +\]
  • +
  • 同理也可以写成bellman方程的形式 \[ +Q(s,a) = \sum_{s^{'}} P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma +Q(s^{'},a^{'})] +\]
  • +
  • 注意以上讨论的都是最优价值函数和最优q函数,都是取max,即计算最优策略下的return,区别于on-policy价值函数和q函数,计算的是期望
  • -

    文本建模

    +

    reward shaping

      -
    • 接下来讨论如何对文本进行概率建模,基本思想是我们假设一个文档中所有的词是按照一种预先设置的概率分布生成的,我们希望找到这个概率分布。具体而言分为以下两个任务: +
    • 可以通过修改奖励函数R(而不改变最优策略)来使强化学习过程更加稳定
        -
      • 模型是怎样的?
      • -
      • 各个词的生成概率或者说模型参数是多少?
      • +
      • 约束:避免一些agent套路reward的情况
      • +
      • 探索:鼓励explore
      • +
      • 加速:改善奖励稀疏的情况,将任务分解成更小的子任务,从而使得智能体更容易学习
    • +
    • 一种常见的修改方式是引入势函数
    • +
    • 势函数是一个仅与状态相关的函数\(\Phi(s)\)(不同于价值函数,与动作状态序列无关,不是消掉动作得到的)
    • +
    • 势函数编码了环境本身客观存在的因素,影响了奖励
    • +
    • 可以证明,势函数可以为状态s的任意函数,且加入及时奖励时,bellman方程得到的最优策略不变,即当奖励函数改成 +\[ +R^{'}(s,a,s^{'}) = R(s,a,s^{'}) + \gamma \Phi(s^{'}) - +\Phi(s) +\] 时,最优策略不变,\(Q(s,a)=Q^{'}(s,a)\)
    -

    Unigram模型

    +

    求解MDP

    +

    价值迭代

      -
    • 模型是怎样的?传统的unigram模型即一元语法模型,认为各个词之间的生成是独立的,文档之间、词之间都是独立可交换的,无所谓顺序,就像所有的词放在一个袋子里,每次按概率分布取出一个词,因此也叫词袋模型(BoW)。词袋模型的参数就是各个词的生成概率,频率派认为可以通过词频统计确定生成概率。
    • -
    • 这里为unigram引入一层贝叶斯框架,为后文LDA两层贝叶斯框架的推导铺垫。贝叶斯学派认为词的生成不止一层:词的概率分布有很多种,即概率分布本身也服从一种概率分布,就像是上帝有许多骰子,他挑选了一个骰子再扔,生成了词。
    • -
    • 也就是说,Unigram模型下一篇文档只是一袋子词,这些词的生成遵循一个分布,设为\(\mathop{p}^{\rightarrow}\),同时这个词生成分布也遵循一个分布,设为\(p(\mathop{p}^{\rightarrow})\)。用数学公式把上面说的两层分布翻译下,就是一篇文档的生成概率: -\[ -p(W)=\int -p(W|\mathop{p}^{\rightarrow})p(\mathop{p}^{\rightarrow})d\mathop{p}^{\rightarrow} -\]
    • -
    • 按照贝叶斯学派的观点,我们应该先假设一个先验分布,再用训练数据修正它,此处我们需要假设\(p(\mathop{p}^{\rightarrow})\),也就是分布的分布的先验,训练数据是什么?是我们从语料中提取的词频分布,假设\(\mathop{n}^{\rightarrow}\)是所有词的词频序列,则这个序列满足多项分布: -\[ -\begin{aligned} -p(\mathop{n}^{\rightarrow}) &= -Mult(\mathop{n}^{\rightarrow}|\mathop{p}^{\rightarrow},N) \\ -&= C_N ^{\mathop{n}^{\rightarrow}} \prod_{k=1}^V p_k^{n_k} \\ -\end{aligned} -\]
    • -
    • 既然训练数据满足多项分布,我们自然而然想利用Dirichlet-Multinomial共轭,因此假设\(p(\mathop{p}^{\rightarrow})\)的先验分布为Dirichlet分布: -\[ -Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})=\frac{1}{\int -\prod_{k=1}^V p_k^{\alpha _k -1}d\mathop{p}^{\rightarrow}} \prod_{k=1}^V -p_k^{\alpha _k -1} -\] 其中\(V\)是语料词典大小,Dirichlet分布的参数\(\alpha\)需要自己设置。之后根据共轭得到数据修正之后\(p(\mathop{p}^{\rightarrow})\)的后验分布: -\[ -\begin{aligned} -p(\mathop{p}^{\rightarrow}|W,\mathop{\alpha}^{\rightarrow}) &= -Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow})+MultCount(\mathop{n}^{\rightarrow}) -\\ -&= -Dir(\mathop{p}^{\rightarrow}|\mathop{\alpha}^{\rightarrow}+\mathop{n}^{\rightarrow}) -\\ -\end{aligned} -\]
    • -
    • 得到后验之后,可以使用极大似然估计或者均值估计来计算\(\mathop{p}^{\rightarrow}\),这里我们使用后验里Dirichlet分布的均值来估计,结合之前提到了Dirichlet的性质,有: -\[ -\mathop{p_i}^{~}=\frac{n_i+\alpha _i}{\sum _{i=1}^{V} (n_i+\alpha _i)} -\] -这个式子的物理解释:不同于一般的使用词频作为估计,我们首先假设了词频(即先验的伪计数\(\alpha _i\)),然后加上数据给出的词频\(n_i\),再归一化作为概率。
    • -
    • 现在得到了词语的生成概率分布\(\mathop{p}^{\rightarrow}\),那么在此分布下的文档的生成概率显然为: -\[ -p(W|\mathop{p}^{\rightarrow})=\prod _{k=1}^V p_k^{n_k} -\] -将词生成概率分布的分布,文档在词生成分布下的条件生成概率带入之前提到的文档概率积分式,就得到所有分布情况下,文档的生成概率。代入化简之后可以得到一个很漂亮的式子。 -\[ -p(W|\mathop{\alpha}^{\rightarrow})=\frac{\Delta(\mathop{\alpha}^{\rightarrow}+\mathop{n}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} -\] 其中\(\Delta\)是归一化因子: -\[ -\Delta(\mathop{\alpha}^{\rightarrow})=\int \prod _{k=1}^V p_k^{\alpha _k --1}d\mathop{p}^{\rightarrow} +
    • n个状态,bellman方程就有n个方程n个未知数,非线性方程的解析解很难得到,可以通过迭代的方法,随机初始值,再根据邻居的价值更新每个状态的价值,重复直至平衡
    • +
    • 引入迭代的timestep i,bellman更新(Bellman +Update)如下 \[ +U_{i+1}(s) \leftarrow \underset{a \in A(s)}{\text{max}} \sum_{s^{'}} +P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U_i(s^{'})] \]
    • +
    • 可以证明:无限次迭代可以保证达到平衡,得到最优策略(前提是即时奖励是正确的)。
    • +
    +

    策略迭代

    +
      +
    • 有些时候我们并不需要得到精确的价值函数,只要知道哪个动作带来的价值最大即可,这就引出了直接对策略进行迭代优化的思想 +.
    • +
    • 从某个初始策略开始,交替进行以下两个步骤 +
        +
      • 策略评估:给定策略,计算执行策略后某一时间步每个状态的价值
      • +
      • 策略改进:基于所有状态价值的一步前瞻(即价值函数bellman方程)来计算新的策略
      • +
    • +
    • 直到策略改进不对价值产生(足够大)改变
    • +
    • 策略评估也是基于bellman方程,只不过不用遍历动作,因为动作已经由策略决定,然后固定当前时间步i策略\(\pi_i\),我们可以得到n个方程,求解即可
    -

    PLSA模型

    +

    \[ +U_{i}(s) = \sum_{s^{'}} +P(s^{'}|s,\pi_i(s))[R(s,\pi_i(s),s^{'}) + \gamma U_i(s^{'})] +\]

      -
    • PLSA即概率隐含语义分析模型,这个模型认为文档到词之间存在一个隐含的主题层次,文档包含多个主题,每个主题对应一种词的分布,生成词时,先选主题,再从主题中选词生成(实际计算时是各个主题的概率叠加)。
    • -
    • 与没有贝叶斯的unigram模型相比,plsa在文档和词之间加了一层,主题。
    • -
    • PLSA没有引入贝叶斯,只是一个包含隐变量的模型,做最大似然估计,那么可以用EM算法迭代学习到参数,具体的计算在这里就略过了。
    • +
    • 在状态空间比较大的时候,精确求解比较困难,这时候可以使用修正策略迭代来进行策略评估,即下一时间步的价值函数直接由当前策略计算出,然后反复迭代
    -

    Role in LDA

    +

    \[ +U_{i+1}(s) \leftarrow \sum_{s^{'}} +P(s^{'}|s,\pi_i(s))[R(s,\pi_i(s),s^{'}) + \gamma U_i(s^{'})] +\]

      -
    • 现在整理一下,Unigram模型中主要包含两部分 +
    • 以上都是同步的形式,即每次迭代更新所有状态。事实上可以只更新部分状态,即异步策略迭代
        -
      • 词生成概率分布
      • -
      • 词生成概率分布的参数分布
      • +
      • 好处是可以只专注为某些有效的状态更新策略,有些状态可能无论什么动作都达不到最优解
    • -
    • PLSA模型主要包含两部分 +
    +

    线性规划

      -
    • 词生成概率分布
    • -
    • 主题生成概率分布
    • +
    • TBD
    • +
    +

    在线算法

    +
      +
    • 价值迭代和策略迭代都是离线的:给定了所有条件/奖励,先生成最优解,然后agent执行
    • +
    • 在线算法:agent不是拿到离线解之后再执行,而是在每个决策点即时计算决策。
    • +
    +

    老虎机问题

    +
      +
    • TBD
    • +
    +

    POMDP

    +
      +
    • 部分可观测环境的马尔科夫决策过程
    • +
    • 因为agent对自己所处的状态不确定(这是部分可观测的定义),所以需要引入一个信念状态,然后agent的决策周期增加了一个环节 +
        +
      • 根据信念状态,执行动作
      • +
      • 观测感知(证据)
      • +
      • 基于感知、动作、之前的信念状态,通过某种更新机制得到新的信念
    • -
    • Unigram模型展示了分布的分布,即为词分布引入参数先验的意义:使得词的分布是一个变量,从掷色子选出一个词变成了先选一个色子,再掷色子选词。至于引入先验究竟有没有用是贝叶斯学派和频率学派之间争吵的话题了。
    • -
    • PLSA模型为人类语言生成提供了一个很直观的建模,引入了主题作为隐含语义,并定义了主题代表词的分布,将文章看成是主题的混合。
    • +
    • 在物理空间状态上求解POMDP可以简化为在信念状态空间上求解MDP
    • +
    • POMDP的价值迭代
    -

    LDA文本建模

    -

    模型概述

    +

    Single Agent RL

      -
    • LDA整合了Unigram和PLSA的优点,对于词和主题这两个骰子分别加上了Dirichlet先验假设 +
    • Agent处在MDP当中,不知道转移模型和奖励函数,需要通过采取行动了解更多信息
    • +
    • 上文的序列决策是在已知环境下,如何得到一个最优策略,其实不需要agent的互动。一般而言的强化学习是指环境未知,需要agent在与环境的交互中来得到数据,从而确定最优策略。
    • +
    • 基于模型的方法
        -
      • 词生成概率分布(暂记A)
      • -
      • 词生成概率分布的参数分布(暂记B)
      • -
      • 主题生成概率分布(暂记C)
      • -
      • 主题生成概率分布的参数分布(暂记D)
      • +
      • 环境提供了转移模型,或者一开始未知环境模型,但是需要去学习
      • +
      • 通常会学习一个价值函数,定义为状态s之后的奖励总和
      • +
      • 上文的序列决策都是在基于模型的前提下阐述的
    • -
    • 这里初学容易混淆的是,主题生成概率分布并不是词生成概率分布的参数分布,要区分LDA模型中的层次关系和各个层次里共轭关系。另外主题和词并不是一对多的层次关系,两者是多对多的关系,事实上,在LDA模型中一篇文档是这么生成的(假设有K个主题): +
    • 无模型的方法
        -
      • 先在B分布条件下抽样得到K个A分布
      • -
      • 对每一篇文档,在符合D分布条件下抽取得到一个C分布,重复如下过程生成词: +
      • 不知道环境的转移模型,而且也不会学习它
      • +
      • agent直接学习策略,一般通过两种方式来在无模型的前提下学习策略
          -
        • 从C分布中抽样得到一个主题z
        • -
        • 从第z个A分布中抽样得到一个单词
        • +
        • 学习Q函数,即学习处于状态s下采取动作a得到的奖励
        • +
        • 直接学习策略\(\pi\),即学习状态到动作的映射
    • -
    • 假设有\(m\)篇文档,\(n\)个词,\(k\)个主题,则\(D+C\)\(m\)个独立的Dirichlet-Multinomial共轭,\(B+A\)\(k\)个独立的Dirichlet-Multinomial共轭。两个dirichlet参数分别为1个k维向量(\(\alpha\))和1个n维向量(\(\beta\))。现在我们可以理解本文最开始的配图,我们将符号用其实际意义表述,与标题配图对应,这幅图实际上描述了LDA中这\(m+k\)个独立的Dirichlet-Multinomial共轭:
    -

    -

    建立分布

    +

    被动强化学习

      -
    • 现在我们可以用\(m+k\)个Dirichlet-Multinomial共轭对LDA主题模型建模了,借鉴之前推导Unigram模型时得到最终的文档生成分布,我们可以分别计算: -\[ -\begin{aligned} -p(\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow}) = \prod -_{m=1}^M -\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} -\\ -p(\mathop{w}^{\rightarrow}|\mathop{z}^{\rightarrow},\mathop{\beta}^{\rightarrow}) -= \prod _{k=1}^K -\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} -\\ -\end{aligned} -\]
    • -
    • 最终得到词与主题的联合分布: \[ -p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow},\mathop{\beta}^{\rightarrow}) -= \prod _{m=1}^M -\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} -\prod _{k=1}^K -\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} -\]
    • +
    • 策略固定,学习价值函数
    • +
    • 策略固定,比如说贪心的取价值最大的动作,这时候只需要将Q函数学好,策略固定的情况下具体的最优动作也就出来了。
    • +
    • 类似于策略评估(给定策略,计算执行策略后某一时间步每个状态的价值),但agent不知道采取动作后到各个状态的转移概率,也不知道即时奖励
    -

    采样

    +

    直接价值估计

      -
    • 在前面说了,我们按照贝叶斯推断的框架估计模型参数,需要直到主题分配的后验概率,这里就需要gibbs -sampling来帮忙对后验做一个近似
    • -
    • 按照gibbs sampling的定义,我们需要主题分配的完全条件概率\(p(z_i=k|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w}^{\rightarrow})\)去采样,进而近似\(p(z_i=k|\mathop{w}^{\rightarrow})\)\(z_i\)代表第i个词的主题(这里下标i代表第m篇文档第n个词),而向量w代表我们现在观察到的所有词。
    • -
    • 在建立了整个概率模型之后,我们通过以下方法训练:设定好超参,随机初始化各个词频统计(包括文章m下主题k的词数,词汇t属于主题k的词数,文章m的总词数,主题k的总词数),然后对语料中所有词,依次进行吉布斯采样,采样其主题,并分配给该词这个主题,并更新四个词频(即利用共轭更新后验),循环采样直到收敛,即采样之后的主题分布基本符合后验概率下的模型产生的主题分布,数据已经不能提供给模型更多的知识(不再进行更新)。 +
    • 一个状态的价值定义为从该状态出发的期望总奖励(reward-to-go)
    • +
    • 每次trial都会在其经过的状态上留下一个价值的数值样本(多次经过一个状态就提供多个样本)
    • +
    • 这样就收集了样本,可以使用监督学习学到状态到价值的映射
    • +
    • 但是该方法忽略了一个重要约束:状态价值应满足固定策略的bellman方程,即状态的价值和后继状态的奖励和期望价值相关,而不是只取决于自己
    • +
    • 这种忽略将导致搜索空间变大,收敛缓慢
    • +
    +

    自适应动态规划(ADP)

      -
    • 其中吉布斯采样是需要限定某一维,按照其他维度的条件概率进行采样,在文本主题建模中维度就是词语,按其他维度的条件概率计算就是在四个词频中除去当前词语及其主题的计数。
    • -
    • 采样后主题后将这个主题分配给词语,四个词频计数增加,如果已经收敛,则采样前后主题相同,词频没有改变,则相当于后验没有从数据知识中获得更新。
    • -
    -
  • 公式推导:下面分别介绍两种推导方法,第一种是LDA数学八卦一文中基于共轭关系做出的推导,另一种是Parameter -estimation for text analysis 一文中基于联合分布做出的推导
  • -
  • 基于共轭关系推导如下:
  • -
  • 采样的对象是词所对应的主题,概率为: \[ -p(z_i=k|\mathop{w}^{\rightarrow}) -\]
  • -
  • 使用吉布斯采样来采样某一个词的主题,则需要用其他词的主题作为条件计算条件概率: -\[ -p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow}) -\]
  • -
  • 由贝叶斯公式,这个条件概率正比于(采样我们可以按正比扩大各个概率采样): -\[ -p(z_i=k,w_i=t|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ -i}}^{\rightarrow}) -\]
  • -
  • 把这个公式按主题分布和词分布展开: \[ -\int p(z_i=k,w_i=t,\mathop{\vartheta _m}^{\rightarrow},\mathop{\varphi -_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ -i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} d\mathop{\varphi -_k}^{\rightarrow} -\]
  • -
  • 由于所有的共轭都是独立的,上式可以写成: \[ -\int p(z_i=k,\mathop{\vartheta _m}^{\rightarrow}|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})p(w_i=t,\mathop{\varphi -_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ -i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} d\mathop{\varphi -_k}^{\rightarrow} -\]
  • -
  • 把概率链式分解下,又因为两个式子分别和主题分布和词分布相关,因此可以写成两个积分相乘: -\[ -\int p(z_i=k|\mathop{\vartheta _m}^{\rightarrow})p(\mathop{\vartheta -_m}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ -i}}^{\rightarrow})d\mathop{\vartheta _m}^{\rightarrow} \cdot \int -p(w_i=t|\mathop{\varphi _k}^{\rightarrow})p(\mathop{\varphi -_k}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w_{¬ -i}}^{\rightarrow})d\mathop{\varphi _k}^{\rightarrow} -\]
  • -
  • 已知第m篇文档的主题分布和第k个主题词分布,求第i个词为t的概率和第i个词对应主题为k的概率,那么显然: -\[ -p(z_i=k|\mathop{\vartheta _m}^{\rightarrow})=\mathop{\vartheta _{mk}} \\ -p(w_i=t|\mathop{\varphi _k}^{\rightarrow})=\mathop{\varphi _{kt}} \\ -\]
  • -
  • 而根据共轭关系,有 \[ -p(\mathop{\vartheta _m}^{\rightarrow}|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})=Dir(\mathop{\vartheta -_m}^{\rightarrow}|\mathop{n_{m,¬ -i}}^{\rightarrow}+\mathop{\alpha}^{\rightarrow}) \\ -p(\mathop{\varphi _k}^{\rightarrow}|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w_{¬ i}}^{\rightarrow})=Dir(\mathop{\varphi -_k}^{\rightarrow}|\mathop{n_{k,¬ -i}}^{\rightarrow}+\mathop{\beta}^{\rightarrow}) \\ -\]
  • -
  • 因此整个式子可以看作是两个Dirichlet分布的期望向量的第k项和第t项相乘。而根据之前Dirichlet的性质,易得这两个期望是按Dirichlet参数比例得到的分式,因此最后的概率计算出来就是(注意是正比于): -\[ -p(z_i=k|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝\frac{n_{m,¬ i}^{(k)}+\alpha -_k}{\sum _{k=1}^K (n_{m,¬ i}^{(k)}+\alpha _k)} \cdot \frac{n_{k,¬ -i}^{(t)}+\beta _t}{\sum _{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} -\]
  • -
  • 这个概率可以理解为(排除当前这第i个token以外): \[ -(文档m中主题k所占的比例) * (主题k中词t所占的比例) -\]
  • -
  • 注意到第一项的分母是对主题求和,实际上和k无关,因此可以写成: \[ -p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝ -(n_{m,¬ i}^{(k)}+\alpha _k) \cdot \frac{n_{k,¬ i}^{(t)}+\beta _t}{\sum -_{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} -\]
  • -
  • 我们再看看基于联合分布如何推导
  • -
  • 之前我们已经得到词和主题的联合分布: \[ -p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow}|\mathop{\alpha}^{\rightarrow},\mathop{\beta}^{\rightarrow}) -= \prod _{m=1}^M -\frac{\Delta(\mathop{n_m}^{\rightarrow}+\mathop{\alpha}^{\rightarrow})}{\Delta(\mathop{\alpha}^{\rightarrow})} -\prod _{k=1}^K -\frac{\Delta(\mathop{n_k}^{\rightarrow}+\mathop{\beta}^{\rightarrow})}{\Delta(\mathop{\beta}^{\rightarrow})} -\]
  • -
  • 根据贝叶斯公式有 \[ -p(z_i=k|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w}^{\rightarrow})=\frac{p(\mathop{w}^{\rightarrow},\mathop{z}^{\rightarrow})}{p(\mathop{w}^{\rightarrow},\mathop{z_{¬ -i}}^{\rightarrow})} \\ -=\frac{p(\mathop{w}^{\rightarrow}|\mathop{z}^{\rightarrow})} -{p(\mathop{w_{¬ i}}^{\rightarrow}|\mathop{z_{¬ i}}^{\rightarrow})p(w_i)} -\cdot \frac{p(\mathop{z}^{\rightarrow})} {\mathop{p(z_{¬ -i})}^{\rightarrow}} \\ -\]
  • -
  • 因为\(p(w_i)\)是可观测变量,我们省略它,得到一个正比于的式子,将这个式子用之前的\(\Delta\)形式表示(分式除以分式,分母相同抵消了): -\[ -∝ -\frac{\Delta(\mathop{n_{z}}^{\rightarrow})+\mathop{\beta}^{\rightarrow}}{\Delta(\mathop{n_{z,¬ -i}}^{\rightarrow})+\mathop{\beta}^{\rightarrow}} \cdot -\frac{\Delta(\mathop{n_{m}}^{\rightarrow})+\mathop{\alpha}^{\rightarrow}}{\Delta(\mathop{n_{m,¬ -i}}^{\rightarrow})+\mathop{\alpha}^{\rightarrow}} -\]
  • -
  • \(\Delta\)的表达式带入计算,也可以得到: -\[ -p(z_i=k|\mathop{z_{¬ i}}^{\rightarrow},\mathop{w}^{\rightarrow})∝ -(n_{m,¬ i}^{(k)}+\alpha _k) \cdot \frac{n_{k,¬ i}^{(t)}+\beta _t}{\sum -_{t=1}^V (n_{k,¬ i}^{(t)}+\beta _t)} +
  • agent学习状态之间转移模型,并用dp解决MDP
  • +
  • 在环境确定/可观测的情况下,不断的trial,得到数据,训练一个监督模型,输入当前状态和动作,输出后续状态概率,即转移模型
  • +
  • 得到转移模型后,之后按照序列决策的方法,通过修正策略迭代求解MDP
  • +
  • 可以看到ADP是需要agent先不断的trial,在环境中得到一系列包含奖励信号的历史数据,然后用这些数据学习到环境的转移模型,将其转化为环境已知的序列决策问题。
  • +
  • 自适应动态规划可以看成是策略迭代在被动强化学习设置下的扩展
  • + +

    时序差分学习

    +
      +
    • 在被动强化学习的setting下,即给定策略\(\pi\),假如在状态s下采取动作\(\pi(s)\)转移到了状态\(s^{'}\),则通过时序差分方程更新价值函数: +\[ +U^{\pi}(s) \leftarrow U^{\pi}(s) + \alpha (R(s,\pi(s),s^{'}) + +\gamma U^{\pi}(s^{'}) - U^{\pi}(s)) \]
    • -
    • 最后附上Parameter estimation for text -analysis一文中吉布斯采样的伪算法图:
    • -
    -
    -i0oU6U.png - -
    +
  • 其中\(\alpha\)是学习率。对比bellman,时序差分是在观测到在状态s下采取动作a到达了状态s',就根据这个相继状态之间价值的差分更新价值:
      -
    • 可以看到主要通过记录四个n值(两个矩阵两个向量)来计算条件概率,更新主题时也是更新四个n值进行增量更新。算法先通过随机均匀采样赋初值,然后按采样公式更新主题(先减去旧的主题分配,再加上新的主题分配),其中公式78即之前我们计算得到的\(p(z_i=k|\mathop{z_{¬ -i}}^{\rightarrow},\mathop{w}^{\rightarrow})\),公式81和82分别为\(\mathop{\vartheta _{mk}},\mathop{\varphi -_{kt}}\),我们可以直接通过四个n值得到,不用考虑采样时的\(¬ i\)条件了,具体是: 差分项是关于误差的信息,更新是为了减少这个误差
    • +
    • 公式变化后可以看出来是当前价值和奖励+未来折扣价值之间做插值: \[ -\mathop{\vartheta _{mk}} = \frac{n_{m}^{(k)}+\alpha _k}{\sum _{k=1}^K -(n_{m}^{(t)}+\alpha _k)} \\ -\mathop{\varphi _{kt}} = \frac{n_{k}^{(t)}+\beta _t}{\sum _{t=1}^V -(n_{k}^{(t)}+\beta _t)} +U^{\pi}(s) \leftarrow (1-\alpha)U^{\pi}(s) + \alpha +(R(s,\pi(s),s^{'}) + \gamma U^{\pi}(s^{'})) \]
    • -
    -

    训练与测试

    +
  • +
  • 与自适应动态规划的联系与区别:
      -
    • 接下来我们来训练LDA模型,首先对LDA的Dir参数随机初始化(先验),然后使用文本进行数据知识补充,得到最终正确的后验,训练是一个迭代过程: +
    • 都是根据未来调整当前价值,自适应的未来是在所有可能后继状态上加权求和,而时间差分的未来是观测到的后继
    • +
    • 自适应尽可能进行多的调整,以保证价值估计和转移模型的一致性;差分对观测到的转移只做单次调整
    • +
    • TD可以看成一种近似ADP
        -
      • 迭代什么?采样并更新词对应的主题
      • -
      • 根据什么迭代?gibbs采样的完全条件概率
      • -
      • 迭代之后的效果?主题分配改变、统计量改变、下一次gibbs采样的完全条件概率改变
      • -
      • 迭代到什么时候为止?Gibbs采样收敛,即采样一段时间区间内主题分布稳定不变,或者根据困惑度等指标来衡量模型收敛的程度。
      • +
      • 可以用转移模型生成多个pseudo +experience,而不是仅仅只看真实发生的一次转移,这样TD的价值估计会接近ADP
      • +
      • prioritized sweeping,对哪些高概率 +后继状态刚刚经过大调整的状态进行更新
      • +
      • TD作为近似ADP的一个优点是,训练刚开始时,转移模型往往学不正确,因此像ADP一样学习一个精确的价值函数来匹配这个转移模型意义不大。
      • +
  • -
  • 训练和测试的区别在于,训练是针对全文档集进行采样更新,文档到主题和主题到词的分布都在更新,而测试则保留主题到词的分布不变,只针对当前测试的文档采样到收敛,得到该文档的主题分布。
  • -
  • 事实上两个超参\(\alpha\)\(\beta\)在训练完之后是经过了很多次后验替换先验的迭代,参数值很大了,\(\alpha\)就抛弃了这最后的后验结果,在对新文档产生主题分布时重新用最开始的先验值,这样的话中途得到的训练集上的文档到主题的分布在测试新文档时实际上是用不上的,我们利用的是主题到词的分布:因为只有主题集合是针对整个文档空间的(训练集和测试集),主题到词的分布也是建立在整个文档空间的词典上的,这一部分的k个\(\beta\)向量我们保留最后的后验结果,因为这个后验吸收了数据的似然知识后参数值很大,不确定度很小了,基本上每个\(\beta\)向量就等同于确定了一个主题到词的多项式分布,也就是确定了一个主题。我们利用这确定的主题,来测试一篇新文档在各个主题上的分布。因此在测试新文档时参数\(\alpha\)一般设置为对称的,即各个分量相同(没有先验偏好那个主题),且值很小(即不确定度大,否则生成的主题分布是均匀分布),这里类似于最大熵的思想。测试是利用已知的固定的主题去得到文档到主题的分布。
  • -
  • LDA的训练实际上是一种无参贝叶斯推断,可以采用MCMC方法和非MCMC方法,MCMC方法中经常采用的就是Gibbs采样,而非MCMC方法还可以用变分推断等方法来迭代得到参数。
  • -

    LDA in Gensim

    +

    主动强化学习

      -
    • Gensim中的LDA提供了几个参数,其中\(\alpha\)的默认值如下:

      alpha ({numpy.ndarray, str}, optional) – Can be set to an 1D array of -length equal to the number of expected topics that expresses our -a-priori belief for the each topics’ probability. Alternatively default -prior selecting strategies can be employed by supplying a string: -’asymmetric’: Uses a fixed normalized asymmetric prior of 1.0 / topicno. -’default’: Learns an asymmetric prior from the corpus.

      -
    • -
    • gensim中没有暴露\(\beta\)给用户,用户只能设置\(\alpha\),可以自定义,也可以设置对称或者不对称。其中对称设置即全为1,不对称设置则拟合了zipf -law(?),可能\(\beta\)的默认设置就是不对称。
    • +
    • 需要学习策略
    • +
    • 需要学习一个完整的转移模型,需要考虑所有的动作,因为策略不固定(未知)
    • +
    • 需要考虑,得到最优策略后,简单的执行这个策略就是正确的吗?
    -

    More

    +

    引入explore

      -
    • Parameter estimation for text analysis -一文指出了隐主题实际上来自词与词之间的高阶共现关系
    • -
    • LDA用于document -query,其中LDA在candidates上训练,新来一个query就进行一次测试 +
    • 自适应动态规划是greedy的,需要引入exploration
    • +
    • 一个宏观的设计,是引入探索函数f(u,n),选择价值u较高的即贪心,选择尝试次数n少的即探索
    • +
    +

    TD Q-learning

      -
    • 基于similarity -ranking的方法,使用JS距离或者KL散度计算candidate与query之间topic -distribution的相似度,并排序
    • -
    • 基于Predictive likelihood -ranking的方法,计算给定query,每个candidate出现的概率,基于主题z分解: -\[ -\begin{aligned} -p\left(\vec{w}_{m} | \tilde{\vec{w}}_{\tilde{m}}\right) -&=\sum_{k=1}^{K} p\left(\vec{w}_{m} | z=k\right) p\left(z=k | -\tilde{\vec{w}}_{\tilde{m}}\right) \\ -&=\sum_{k=1}^{K} \frac{p\left(z=k | \vec{w}_{m}\right) -p\left(\vec{w}_{m}\right)}{p(z=k)} p\left(z=k | -\tilde{\vec{w}}_{\tilde{m}}\right) \\ -&=\sum_{k=1}^{K} \vartheta_{m, k} \frac{n_{m}}{n_{k}} -\vartheta_{\tilde{m}, k} -\end{aligned} +
    • 一种主动强化学习下的时序差分方法
    • +
    • 无需一个学习转移概率的模型,无模型的方法
    • +
    • 通过学习动作-价值函数来避免对转移模型本身的需求 \[ +Q(s,a) \leftarrow Q(s,a) + \alpha (R(s,a,s^{'}) + \gamma +max_{a^{'}}Q(s^{'},a^{'}) - Q(s,a)) \]
    • +
    • 不需要转移模型P(s'|s,a)
    • +
    • 注意因为没有给定策略,这里需要对所有可能动作取max
    • +
    • 奖励稀疏时难以学习
    • +
    +

    Sarsa

    +
      +
    • 即state,action,reward,state,action,sarsa的缩写代表了更新的五元组 +\[ +Q(s,a) \leftarrow Q(s,a) + \alpha (R(s,a,s^{'}) + \gamma +Q(s^{'},a^{'}) - Q(s,a)) +\]

    • +
    • 相比TD +Q-learning,不是对所有可能动作取max,而是先执行动作,再根据这个动作更新

    • +
    • 如果agent是贪心的,总是执行q-value最大的动作,则sarse和q-learning等价;如果不是贪心,sarsa会惩罚探索时遇到的负面奖励动作

    • +
    • on/off policy

      +
        +
      • sarsa是on-policy:“假设我坚持我自己的策略,那么这个动作在该状态下的价值是多少?”
      • +
      • q-learning是off-policy:“假设我停止使用我正在使用的任何策略,并依据估计选择最佳动作的策略开始行动,那么这个动作在改状态下的价值是多少?”
    • -
    • LDA用于聚类 +
    +

    强化学习中的泛化

      -
    • 事实上主题分布就是对文档的一种软聚类划分,假如把每篇文档划分到拥有最大概率的主题上的话,那就是一种硬划分。
    • -
    • 或者利用topic -distribution作为文档的特征向量,再进一步使用各种聚类算法聚类
    • -
    • 聚类结果的评估,可以利用一个已知聚类划分的结果作为参考,利用Variation -of Information distance进行评估
    • +
    • 价值函数和Q函数都用表格的形式记录,状态空间巨大
    • +
    • 要是能参数化,需要学习的参数值可以减少很多
    • +
    • 对于被动强化学习,需要根据trials使用监督学习价值函数,这里可以用函数或者NN来参数化。
    • +
    • 对于时序差分学习,可以将差分项参数化,通过梯度下降学习
    • +
    • 参数化来近似学习价值或者q函数存在几个问题 +
        +
      • 难以收敛
      • +
      • 灾难性遗忘:可以通过experience +replay,保存轨迹进行回放,确保agent不再访问的那部分状态空间上的价值函数仍然准确
    • -
    • LDA的评价指标,困惑度,其定义为模型在验证集上测出的似然的reciprocal -geometric mean: \[ -\mathrm{P}(\tilde{\boldsymbol{W}} | \boldsymbol{M})=\prod_{m=1}^{M} -p\left(\tilde{\vec{w}}_{\tilde{m}} | -\mathcal{M}\right)^{-\frac{1}{N}}=\exp -\frac{\sum_{m=1}^{M} \log -p\left(\tilde{\bar{w}}_{\tilde{m}} | \mathcal{M}\right)}{\sum_{m=1}^{M} -N_{m}} +
    • 奖励函数设计,如何解决稀疏奖励? +
        +
      • 问题:credit +assignment,最后的正面或者负面奖励应该归因到哪次动作上
      • +
      • 可以通过修改奖励函数(reward +shaping)来提供一些中间奖励,势函数就是一个例子,势反映了我们所希望的部分状态(某个子目标的实现、离最终希望的终止状态的某种可度量的距离)
      • +
    • +
    • 另一种方案是分层强化学习,TBD
    • +
    +

    策略搜索

    +
      +
    • 只要策略的表现有所改进,就继续调整策略
    • +
    • 策略是一个状态到动作的映射函数
    • +
    • 将策略参数化表达,尽管可以通过优化q函数得到,但并不一定得到最优的q函数或者价值估计,因为策略搜索只在乎策略是否最优
    • +
    • 直接学习Q值,然后argmax +Q值得到策略会存在离散不可导问题,这时将Q值作为logits,用softmax表示动作概率,用类似gumbel-softmax使得策略连续可导
    • +
    • 假如执行策略所得到的期望奖励可以写成关于参数的表达式,则可以使用策略梯度直接优化;否则可以通过执行策略观测累计的奖励来计算表达式,通过经验梯度优化
    • +
    • 考虑最简单的只有一次动作的情况,策略梯度可以写成下式,即对各个动作的奖励按其策略概率加权求和,并对策略参数求导。 +\[ +\triangledown_{\theta}\sum_aR(s_0,a,s_0)\pi_{\theta}(s_0,a) \]
    • -
    • 假定验证集和训练集分布一致,那么LDA在验证集上的困惑度高,代表熵越大,不确定性大,模型还没有学到一个稳定的参数。
    • +
    • 将这个求和用策略所定义的概率分布生成的样本来近似,并且扩展到时序状态,就得到了REINFORCE算法,这里用N次trial近似策略概率加权求和,并且将单步奖励扩展到价值函数,状态也扩展到整个环境的状态集合: +\[ +\frac1N +\sum_{j=1}^N\frac{u_j(s)\triangledown_{\theta}\pi_{\theta}(s,a_j)}{\pi_{\theta}(s,a_j)} +\]
    • +
    +

    MARL (Multi-Agent Rl)

    +
      +
    • 先挖坑
    • +
    • +
    • +
    • +
    ]]>
    - 机器学习 + 强化学习 - math - topic model - lda - mcmc + reinforcement learning + multi-agent
    - Multi-agent Reinforcement Learning Notes - /2023/07/20/marl/ - A simple note on the RL used in single-agent and multi-agent.

    + Numpy Cookbook + /2017/01/23/numpycookbook/ + Cookbook网址:Numpy +Cookbook Numpy的一些语法查询和总结 持续更新

    -

    序列决策

      -
    • 建模序列决策下的智能体,而不仅仅是单一回合或者一次性决策问题
    • -
    • 讨论一个 -
        -
      • 完全可观测的随机环境
      • -
      • 具有马尔科夫转移模型
      • -
      • 加性奖励 -的序列决策问题,通常包含状态集合、动作集合、转移模型、奖励函数。问题的解即策略。
      • -
    • -
    • 假如序列没有时间限制,最优策略只与状态有关,与时间无关,则称最优策略是平稳的。
    • +
    • shape() shape是numpy函数库中的方法,用于查看矩阵或者数组的维素 +shape(array) 若矩阵有m行n列,则返回(m,n) array.shape[0] +返回矩阵的行数m,参数为1的话返回列数n

    • +
    • tile() tile是numpy函数库中的方法,用法如下: tile(A,(m,n)) +将数组A作为元素构造出m行n列的数组

    • +
    • sum() sum()是numpy函数库中的方法 +array.sum(axis=1)按行累加,axis=0为按列累加

    • +
    • argsort() argsort()是numpy中的方法,得到矩阵中每个元素的排序序号 +A=array.argsort() A[0]表示排序后 +排在第一个的那个数在原来数组中的下标

    • +
    • dict.get(key,x) +Python中字典的方法,get(key,x)从字典中获取key对应的value,字典中没有key的话返回0

    • +
    • sorted()

    • +
    • numpy中有min()、max()方法,用法如下 array.min(0) +返回一个数组,数组中每个数都是它所在列的所有数的最小值 array.min(1) +返回一个数组,数组中每个数都是它所在行的所有数的最小值

    • +
    • listdir('str') strlist=listdir('str') +读取目录str下的所有文件名,返回一个字符串列表

    • +
    • split() python中的方法,切片函数 +string.split('str')以字符str为分隔符切片,返回list

    • +
    • zeros a=np.zeros((m,n), dtype=np.int) +#创建数据类型为int型的大小为m*n的零矩阵

    -

    bellman方程,U和Q函数

    -
      -
    • 价值函数(价值函数),代表某一状态/行为序列的奖励综合,U(s0,a0,s1,a0....),从当前状态和动作s0,a0开始
    • -
    • 用加性折扣定义价值,未来的奖励乘gamma递减: \[ -U\left(\,\left[s_{0},\,s_{1},\,s_{2},\,\cdots\,\right]\,\right)=R(s_{0})+\gamma -R(s_{1})+\gamma ^2 R(s_{2})+\,\cdots -\] -
        -
      • 因为看重近期奖励
      • -
      • 如果奖励可以投资,则越早的奖励价值越大
      • -
      • 等价于每次转移有\(1-\gamma\)的意外终止
      • -
      • 满足平稳性,t+1的最佳选择未来也是t的最佳选择未来
      • -
      • 避免无穷的序列转移
      • -
    • -
    • 基于价值函数,可以选出当前最佳动作,即在当前状态下,使得当前价值最大的动作(转移的即时奖励+后续的期望折扣价值) +]]> + + Python + + + math + machine learning + code + python + + + + OJ + /2017/03/27/oj/ + +

      算法刷题目录,方便自己查找回忆复习 +之后(2018.9.27)只更新leetcode上的题了,也懒得整理源码了,leetcode上都存了,只记录思路吧

      + +

      mark

      +

      Leetcode

        -
      • 这里存在一个期望,因为每个动作都可能到每个状态(概率),因此一个动作的价值是在所有可能的未来状态下累加。
      • -
      • 价值函数只是状态的函数,已经对所有动作累加求期望 \[ -\pi^*(s) = \underset{a \in A(s)}{\text{argmax}} \sum_{s^{'}} -P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U(s^{'})] -\]
      • -
    • -
    • 同理,价值函数只是状态的函数,已经对所有动作累加求期望,其实就是上式,只不过不是argmax选动作,而是max,这里的解释是:假设agent选择了最佳动作,状态价值是下一次转移的期望奖励加上下一个状态的折扣价值 -\[ -U(s) = \underset{a \in A(s)}{\text{max}} \sum_{s^{'}} -P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U(s^{'})] -\] +
    • Leetcode算法列表
    • +
    • 直接搜每道题的序号即可
    • +
    +

    排序

      -
    • 注意两个式子本质是一样的,都是挑动作,都是在所有可能的状态下累加,但这是基于对未来期望的估计,实际执行就是选择一个动作,转移到一个状态。
    • -
    • 该式即bellman方程
    • -
    -
  • 引入Q函数,Q是动作和状态的函数,U仅仅是状态的函数,两者的转换关系如下 -\[ -U(s) = \underset{a \in A(s)}{\text{max}} Q(s,a) -\]
  • -
  • 同理也可以写成bellman方程的形式 \[ -Q(s,a) = \sum_{s^{'}} P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma -Q(s^{'},a^{'})] -\]
  • -
  • 注意以上讨论的都是最优价值函数和最优q函数,都是取max,即计算最优策略下的return,区别于on-policy价值函数和q函数,计算的是期望
  • +
  • 75:给出一个只包含0,1,2的数列,排序形成[0,0,...,0,1,...,1,2,...,2]的形式,在原数列上修改。借鉴Lomuto +partition +algorithm,维护三个区间[0,i],[i,j],[j,k]为0,1,2的范围,按优先级,若当前数为2或1或0,先将nums[k]=2,k++,若当前数为1或0,则nums[j]=1,j++,若当前数为0,则nums[i]=0,i++,越往后能覆盖前面的,优先级越高。
  • +
  • 164:给出一个无序数列,请在O(n)时间复杂度内找到数列有序化后相隔元素差最大值。桶排序,设数列中最大值最小值分别为max,min,易得这个相邻元素差最大值肯定大于(max-min)/(n-1)并设这个值为gap,n是数列长度。将数列的取值区间[min,max]以(max-min)/(n-1)为间隔分成nums个桶,nums是int((max +- min) / gap + +1),把数列各个元素分到桶中,每个桶只存对应区间内的最大元素和最小元素,把那么最大间隔肯定在相邻两个桶的边界处(前一个桶的最大值和后一个桶的最小值),因为桶内的最大间隔小于gap。最后遍历一遍桶就可以了。
  • +
  • 179:水题,给出一个数列,要求把各个数连起来组合成一个最大的数。字符串排序
  • -

    reward shaping

    +

    堆、栈、队列

      -
    • 可以通过修改奖励函数R(而不改变最优策略)来使强化学习过程更加稳定 +
    • 23:合并K个有序链表为1个有序链表,用最小堆存所有链表头节点,依次取出插入到新链表中
    • +
    • 150:算术表达式,栈,python的switch写法
    • +
    • 224:带括号的算术表达式,栈,巧妙地方法处理括号,如果括号外是负号则符号乘-1否则乘1
    • +
    • 373:在2对有序数组中找出有最小和的k组数对,优先队列
    • +
    +

    组合数学

      -
    • 约束:避免一些agent套路reward的情况
    • -
    • 探索:鼓励explore
    • -
    • 加速:改善奖励稀疏的情况,将任务分解成更小的子任务,从而使得智能体更容易学习
    • -
    -
  • 一种常见的修改方式是引入势函数
  • -
  • 势函数是一个仅与状态相关的函数\(\Phi(s)\)(不同于价值函数,与动作状态序列无关,不是消掉动作得到的)
  • -
  • 势函数编码了环境本身客观存在的因素,影响了奖励
  • -
  • 可以证明,势函数可以为状态s的任意函数,且加入及时奖励时,bellman方程得到的最优策略不变,即当奖励函数改成 -\[ -R^{'}(s,a,s^{'}) = R(s,a,s^{'}) + \gamma \Phi(s^{'}) - -\Phi(s) -\] 时,最优策略不变,\(Q(s,a)=Q^{'}(s,a)\)
  • +
  • 47:生成n个数字的所有组合,数字有重复,依次插入数字到已生成k个数字组合的k+1个空中,排重直接用集合,Top +Solution中用插入处后一个数字是否重复来排重
  • -

    求解MDP

    -

    价值迭代

    +

    搜索与查找

      -
    • n个状态,bellman方程就有n个方程n个未知数,非线性方程的解析解很难得到,可以通过迭代的方法,随机初始值,再根据邻居的价值更新每个状态的价值,重复直至平衡
    • -
    • 引入迭代的timestep i,bellman更新(Bellman -Update)如下 \[ -U_{i+1}(s) \leftarrow \underset{a \in A(s)}{\text{max}} \sum_{s^{'}} -P(s^{'}|s,a)[R(s,a,s^{'}) + \gamma U_i(s^{'})] -\]
    • -
    • 可以证明:无限次迭代可以保证达到平衡,得到最优策略(前提是即时奖励是正确的)。
    • +
    • 74:在一个有有特定顺序的矩阵中查找,两次二分查找
    • +
    • 78:生成子集,递归或者迭代,每个数字分加入子集或者不加入子集进行递归
    • +
    • 79:在一个字母矩阵中查找单词,深搜
    • +
    • 89:生成格雷码,迭代,每次在最前面加1或0,格雷码上下对称
    • +
    • 140:将一个字符串按给定词典加空格成句子,记忆化搜索
    • +
    • 153:一个有序数组拆成两部分再倒接一起,查找,特殊的二分查找
    • +
    • 154:153如果加入重复数字的变形,加入一个条件,二分的start和end是相邻不重复的第一个
    • +
    • 240:74的改版,每一行每一列有序,查数,对行和列分别做二分,数肯定在满足条件的行与列的交集处,还有其他解法
    -

    策略迭代

    +

      -
    • 有些时候我们并不需要得到精确的价值函数,只要知道哪个动作带来的价值最大即可,这就引出了直接对策略进行迭代优化的思想 -.
    • -
    • 从某个初始策略开始,交替进行以下两个步骤 +
    • 98:判断一颗二叉树是不是查找树,即左子树都小于节点,右子树都大于节点,中序遍历看看是不是递增数列即可,递归或者栈
    • +
    • 101:判断一棵二叉树是不是对称的,递归,注意递归的是(left.left,right.right)和(left.right,right.left)即内外两队子节点,另外可以用栈实现迭代版本
    • +
    • 106:给出中序遍历后序遍历,求前序遍历。后序遍历的最后一个是根节点,在中序遍历中找到这个根节点并在后序遍历中删除,根节点以左是左子树,以右是右子树,这时后序遍历的最后一个节点就是左子树的根节点,递归即可
    • +
    • 107:从下往上从左往右输出树每一层的节点,用二维数组记录答案,如果二维数组的一维长度即层数比当前遍历的节点层数少就新建一层存答案。可以直接dfs,或者用栈和队列替代递归,如果用栈就是dfs,如果用队列就是bfs
    • +
    • 108:构造一棵二叉查找树,递归
    • +
    • 114:给一棵树,按前序遍历将其压扁,变成一棵只有右节点的树。将一个节点压扁操作定义为,把左子树置空,右子树变成原左子树,原右子树接在原左子树的尾节点上,原左子树的尾节点就是按前序遍历这个子树遍历到的最后一个点。递归,先压扁左节点,再压扁右节点,再回溯压父节点
    • +
    • 144:求一棵树的前序遍历,利用栈,弹出一个节点记录值,并先压入右节点,再压入左节点
    • +
    • 515:求二叉树每一层的最大值,BFS
    • +
    +

    图论

      -
    • 策略评估:给定策略,计算执行策略后某一时间步每个状态的价值
    • -
    • 策略改进:基于所有状态价值的一步前瞻(即价值函数bellman方程)来计算新的策略
    • -
    -
  • 直到策略改进不对价值产生(足够大)改变
  • -
  • 策略评估也是基于bellman方程,只不过不用遍历动作,因为动作已经由策略决定,然后固定当前时间步i策略\(\pi_i\),我们可以得到n个方程,求解即可
  • +
  • 130:水题,把一个图中被黑子包围的白子全部替换成黑子,直接从边上找出所有白子并存起来,再将整个棋盘涂黑,把白子复原。存的是top +solution,写法很pythonic
  • -

    \[ -U_{i}(s) = \sum_{s^{'}} -P(s^{'}|s,\pi_i(s))[R(s,\pi_i(s),s^{'}) + \gamma U_i(s^{'})] -\]

    +

    数学题

      -
    • 在状态空间比较大的时候,精确求解比较困难,这时候可以使用修正策略迭代来进行策略评估,即下一时间步的价值函数直接由当前策略计算出,然后反复迭代
    • +
    • 4:给出两个有序数列,求出两个数列合并后的中位数,要求时间复杂度O(log(m+n)),所以不能直接一个一个比较。中位数的意义是把序列拆成长度相等两部分,大部分中最小数比小部分中最大数大,根据这个原理将两个序列拆成两部分,设两个数列长度分别为m,n,设数列1在i位置拆开,数列2在j位置拆开,则需要保证:1:两个长度一样,则\(i+j=m-i+n-j\);2:两个数列的小部分的并集的任意数比两个数列大部分的并集的任意数要小,因为拆开后的部分依然有序,因此这个条件就是\(B[j-1] <= A[i] and A[i-1] <= +B[j]\),i的位置确定,j的位置就确定,因此只需二分查找i的位置即可。注意奇偶性和边界判断。
    • +
    • 57:给出一组区间,插入一个新区间并合并。模拟
    • +
    • 122:水,一行代码,找一个序列中的最大相邻元素差
    • +
    • 142:给出一个链表,找出链表中环的起点。依然是快慢钟算法,设一快一慢两个指针一起从链表开始走,第一次相遇时说明存在环且他们步数之差是环的长度,而且可以推算出链表起点到环起点的距离等于相遇点到环起点的距离,就可以找到环的起点
    • +
    • 166:给出除数被除数写出结果,包括循环小数显示,数学分析题,小数不断乘10除除数,更新余数,余数出现重复即小数出现重复
    • +
    • 172:求n!中0的个数,数学分析题,0来自5*2,就看n中有多少5及其倍数
    • +
    • 202:快慢指针,求循环的一种方法
    • +
    • 263:数学题
    • +
    • 264:数学题
    • +
    • 313:数学题
    -

    \[ -U_{i+1}(s) \leftarrow \sum_{s^{'}} -P(s^{'}|s,\pi_i(s))[R(s,\pi_i(s),s^{'}) + \gamma U_i(s^{'})] -\]

    +

    字符串

      -
    • 以上都是同步的形式,即每次迭代更新所有状态。事实上可以只更新部分状态,即异步策略迭代 +
    • 131:将一个字符串分成回文子串,用python的[i::-1]很好找,也是一行代码
    • +
    • 242:水题,python字典的使用
    • +
    • 301:给定字符串,删除最小数目的括号使得字符串中所有括号匹配,输出所有情况。注意两点:正序逆序各做一遍,因为有删左括号和右括号两种方案;所有情况都要输出,用集合存取所有情况
    • +
    • 451:按频率统计字母,哈希,python字典
    • +
    • 541:部分字符串翻转,模拟,注意python切片的使用
    • +
    +

    贪心

      -
    • 好处是可以只专注为某些有效的状态更新策略,有些状态可能无论什么动作都达不到最优解
    • -
    +
  • 134:加油站排成一圈,给定各个加油站可以加的油和站与站之间路程所耗的油,问可以走完一圈需要从哪个加油站出发,数据保证答案唯一,贪心,如果前i个加油站走不完了,那么出发点就设成i+1
  • +
  • 402:从一个大数中移除k个数字,使得新的数最小,栈,贪心
  • +
  • 452:重叠区间问题,贪心
  • -

    线性规划

    +

    动态规划

      -
    • TBD
    • +
    • 70:经典问题爬梯子,斐波那契数列,dp
    • +
    • 96:给一个1到n的数列,问可以构造出多少不同的bst。设ans(i)为长度为i的数列能构造不同的bst的个数,我们需要找到ans(i)与ans(i-1)的关系,引入中间变量f(i,n),指以第i个数字为根构造bst,长度为n的数列能构造不同的bst的个数,这里可以找到递归关系,根左边的子数列构造出根的左子树,设有left种不同的左子树,右数列right同理,则f(i,n)应该是left*right,即f(i,n)=ans(i-1)*ans(n-i),同时以不同的i为根会有完全不同的划分,则\(ans(n)=\sum _{i=1}^n +f(i,n)\),合并可以得到ans(i)=ans(0) * ans(n-1) + ans(1) * +ans(n-2) + … + ans(n-1) * ans(0),边界ans(0)=ans(1)=1。
    • +
    • 139:给出词典,给出一个字符串,判断字符串是否可以完全由词典内的单词构成。设f[i]==true即前字符串前i位都可以完全由单词构成,则遍历每个单词,单词长度为k,若f[i-k]为真则f[i]为真,也可以转换为图用dfs做,i与j之间有一条边说明s[i:j]是一个单词,我们要找到一条路径从0到len(s)
    • +
    • 174:矩阵中有正数负数,在中途不为0的情况下求最小路径。动态规划,从后往前
    • +
    • 312:给出一个数列,问怎样依次消去数能得到最多硬币,得硬币的规则:消掉一个数得到这个数和相邻两个数累乘的数量的硬币。区间dp(分治),一段区间内能得到的最多硬币f[x,y]是看其最后一次消去位置在i,得到的硬币就是f[x,i-1]+num[i-1]*num[i]*num[i+1]+f[i+1,y],在这个区间内枚举位置i,其中需要左右两个小区间的位置已知,因此将区间从小到大枚举。总共三层循环:外循环区间长度,中循环区间在整个序列中的开始位置,内循环枚举区间内位置i。
    • +
    • 338:求出[1,num]内每个数字二进制中有多少个1,列举几个数分析发现对偶数n,它的二进制就是n/2的二进制左移一位,1的个数不变,对奇数n,它的二进制就是n/2的二进制左移一位并末尾加1,即1的个数多一个,显然状态转移方程 +\[ +f(x)= +\begin{cases} +f(n) & x=2n \\ +f(n)+1 & x=2n+1 \\ +\end{cases} +\]
    • +
    • 397:一个数是偶数就除2,是奇数就变到相邻数,问最少几次变成1,根据题意可以写出状态转移方程: +\[ +f(x)= +\begin{cases} +f(n)+1 & x=2n \\ +min(f(2n+2)+1,f(2n)+1) & x=2n+1 \\ +\end{cases} +\] 奇数情况可以化简为\(min(f(2n)+1,f(n+1)+2)\),这样就可以从1到n动规了,但是会超时 +可以将方程进一步化简 If n % 4 = 3 and n != 3, then f(n) = f(n + 1) + 1. +If n % 4 = 1 or n = 3, then f(n) = f(n - 1) + 1. 证明在这里
      +
    • +
    • 472:是139的变式,依然是判断字符串是否可以由单词构成,但单词和要判断的字符串都在一个词典里,每个单词都需要判断是否完全能被其他单词组成。因为词典中无重复单词,所以先按单词长度排序,每个单词只能由它前面的单词构成,然后问题就转变成了139,第i个单词为要查询的字符串,前i-1个单词构成了查询所需的词典,一样的进行动态规划。top +solution中利用了trie字典树加速,见Python中实现字典树
    -

    在线算法

    +

    分治

      -
    • 价值迭代和策略迭代都是离线的:给定了所有条件/奖励,先生成最优解,然后agent执行
    • -
    • 在线算法:agent不是拿到离线解之后再执行,而是在每个决策点即时计算决策。
    • +
    • 247:给出一个算式,无括号,问加括号的情况下有多少种可能的解(不要求去重),分治,取第i个运算符号,对符号左边和右边分别递归求解部分解,python中map的用法
    -

    老虎机问题

    +

    Poj

      -
    • TBD
    • +
    • C++源码
    • +
    • 1062:Dijkstra
    • +
    • 1068:模拟
    • +
    • 1094:拓扑排序
    • +
    • 1328:贪心,换求解变量
    • +
    • 1753:枚举,位运算
    • +
    • 1789:Prim,优先队列
    • +
    • 1860:bellman-ford
    • +
    • 2109:贪心,高精度乘法
    • +
    • 2965:枚举,位运算
    • +
    • 3259:建模,bellman-ford
    • +
    • 3295:模拟,栈
    -

    POMDP

    +

    校内赛

      -
    • 部分可观测环境的马尔科夫决策过程
    • -
    • 因为agent对自己所处的状态不确定(这是部分可观测的定义),所以需要引入一个信念状态,然后agent的决策周期增加了一个环节 +
    • 2017pre
    • +
    • A,集合中找有序三个数,满足和为0,求这些数平方和,Leetcode原题
    • +
    • D,求一个数的连续质数和分解,poj原题,数据大,因此没必要打表,直接对每一个输入判断
    • +
    • F,题目骗人,不需要回溯,递推公式可以写出特征方程求解
    • +
    • G,找一个集合中的最大子集,有绑定规则,选一个数必须选其他几个数,bfs
    • +
    • H,给出字符变换规则和代价,求把两个字符串变成一样的最小代价,flyod,注意两个字母可以变成第三个字母,不一定是互相变,两个字符串可能不等长,不等长直接输出-1
    • +
    • I,高中物理,求重力加速度,方程不好解,二分法逼近答案
    • +
    +

    hiho

      -
    • 根据信念状态,执行动作
    • -
    • 观测感知(证据)
    • -
    • 基于感知、动作、之前的信念状态,通过某种更新机制得到新的信念
    • -
    -
  • 在物理空间状态上求解POMDP可以简化为在信念状态空间上求解MDP
  • -
  • POMDP的价值迭代
  • +
  • hiho
  • +
  • 1505:给定一个组,问有多少种下标四元组(i, j, p, q)满足i, j, p, +q两两不同,并且i < j, p < q, Ai + Aj = Ap + +Aq。2sum问题,数据范围不大,直接开哈希数组,sum[i]记录两个数之和为i有多少组,利用容斥定理解。
  • +
  • 1506:投掷硬币,投n次m次朝上的概率是多少,每次投正面朝上概率不同。动态规划,记dp[i][j]为投前i次j次朝上的概率,状态转移方程为:dp[i][j]=dp[i-1][j-1]a[i]+dp[i-1][j](1.0-a[i]);a[i]为第i次正面朝上的概率,注意对j=0进行特判。
  • +
  • 1507:错误的记录,给出一棵树,给出根节点编号,在中间加一条错误边,找出所有可能的错误边。注意因为只加了一条错误边,因此情况可以分为两种:1.这条错误边连向根节点,直接输出。2.根节点正常,则这条错误边一定连在入度为2的节点上,且这样的节点只有一个,找到这个节点,将连接它的两条边分别去掉并从根节点开始dfs,如果dfs遍历完次数为n,说明这条边去掉后树依然成立,这是错误边,如果次数小于n,说明去掉这条边树就断了,形成森林,这条边不是错误边。注意边重复的情况,这时候只去掉其中一条,但是两条边是分别当错误边输出。因为错误边数小于等于2,所以dfs的次数小于等于2,加上构造去掉边的图,时间复杂度是O(n)。
  • +
  • 1515:给定一些同学之间的分数关系(A比B高或低多少分),最后对q个查询给出答案。带权并查集,每个集维护同学到这个集某一个根同学的分数差。每次输入一条关系便合并两个同学所在的并查集,并对每个并查集做一次更新,加入y被x合并,x,y之间关系值是s,更新公式是d[root +of +y]=d[x]-d[y]-s,并在下一次循环中更新整个并查集的值。最后直接查询。
  • -

    Single Agent RL

    +]]>
    + + 算法 + + + code + python + c++ + algorithm + +
    + + Prompt - Task Reformulation in NLP + /2021/05/13/pet/ +
      -
    • Agent处在MDP当中,不知道转移模型和奖励函数,需要通过采取行动了解更多信息
    • -
    • 上文的序列决策是在已知环境下,如何得到一个最优策略,其实不需要agent的互动。一般而言的强化学习是指环境未知,需要agent在与环境的交互中来得到数据,从而确定最优策略。
    • -
    • 基于模型的方法 +
    • 记录近年基于模板来完成任务重构的方法,这是一个比较有意思的方向,尤其是GPT3出现之后。 +这类方法一般针对任务设计prompt,将样本和任务一起转换为自然语言形式的template,直接输入预训练语言模型预测出文本,间接的完成任务。prompt的构建一方面统一了下游任务和预训练任务的形式(语言模型)在few +shot learning上能取得较好结果。主要阅读以下9篇论文:
        -
      • 环境提供了转移模型,或者一开始未知环境模型,但是需要去学习
      • -
      • 通常会学习一个价值函数,定义为状态s之后的奖励总和
      • -
      • 上文的序列决策都是在基于模型的前提下阐述的
      • +
      • 早期的将问题转为自然语言并使用预训练语言模型解答的: +
          +
        • (Harvard)Commonsense Knowledge Mining from Pretrained Models
        • +
        • (Heidelberg)Argumentative Relation Classification as Plausibility +Ranking
        • +
        • (NVIDIA)Zero-shot Text Classification With Generative Language +Models
      • -
      • 无模型的方法 +
      • PET方向,Pattern Exploiting Training
          -
        • 不知道环境的转移模型,而且也不会学习它
        • -
        • agent直接学习策略,一般通过两种方式来在无模型的前提下学习策略 +
        • (LMU)Exploiting Cloze Questions for Few Shot Text Classification and +Natural Language Inference
        • +
        • (LMU)It’s Not Just Size That Matters: Small Language Models Are Also +Few-Shot Learners
        • +
        • (UNC)Improving and Simplifying Pattern Exploiting Training
        • +
      • +
      • 自动构建prompt,Automatically Searching Prompts
          -
        • 学习Q函数,即学习处于状态s下采取动作a得到的奖励
        • -
        • 直接学习策略\(\pi\),即学习状态到动作的映射
        • +
        • (UCI,UCB)AUTOPROMPT: Eliciting Knowledge from Language Models with +Automatically Generated Prompts
        • +
        • (Princeton, MIT)Making Pre-trained Language Models Better Few-shot +Learners
        • +
        • (THU)GPT Understands, Too
    -

    被动强化学习

    + +

    Commonsense +Knowledge Mining from Pretrained Models

      -
    • 策略固定,学习价值函数
    • -
    • 策略固定,比如说贪心的取价值最大的动作,这时候只需要将Q函数学好,策略固定的情况下具体的最优动作也就出来了。
    • -
    • 类似于策略评估(给定策略,计算执行策略后某一时间步每个状态的价值),但agent不知道采取动作后到各个状态的转移概率,也不知道即时奖励
    • -
    -

    直接价值估计

    +
  • 作者想要做到挖掘未知分布数据中的常识,而传统的监督学习方法容易受到训练集中的数据分布影响,导致结果有偏差
  • +
  • 将关系三元组转换为masked +sentence送给BERT,通过BERT的预测结果计算互信息来对三元组的可信度排序
  • +
  • 任务,给定一个三元组为其打分,确定这个三元组代表了真实世界知识的可能性,作者将其分为两步:
      -
    • 一个状态的价值定义为从该状态出发的期望总奖励(reward-to-go)
    • -
    • 每次trial都会在其经过的状态上留下一个价值的数值样本(多次经过一个状态就提供多个样本)
    • -
    • 这样就收集了样本,可以使用监督学习学到状态到价值的映射
    • -
    • 但是该方法忽略了一个重要约束:状态价值应满足固定策略的bellman方程,即状态的价值和后继状态的奖励和期望价值相关,而不是只取决于自己
    • -
    • 这种忽略将导致搜索空间变大,收敛缓慢
    • +
    • 将三元组转化为mask过后的句子:对每个关系手工设计了多个模板,同时还设计了一系列规则来确保语法正确性(单复数、插入冠词、改动名词等等),这样所有模板和规则的组合得到了一系列候选句子,然后通过预训练单向语言模型来计算每个句子是正常句子的得分log-likelihood
    • +
    • 将生成的句子输入BERT打分:这里作者用条件点互信息计算,即在关系r的条件下,头尾实体之间的互信息大小作为分数: +\[ +PMI(tail,head|relation) = \log p(tail|head, relation) - \log +p(tail|realtion) \\ +\] 放在语言模型中,实际上就是将tail +mask掉然后预测,只不过上式右边第一项是只mask +tail,第二项则还mask掉了head(只mask,不预测)。另外可能出现实体由多个词组成的情况,这里作者采用了一种贪心近似的方法,先把词全部mask掉然后预测,拿到概率最高的词unmask,再反复迭代预测剩下的词,每次还原概率最高的词,之后累乘这一系列概率就可以得到整个词的条件概率。上式并不是对称的,因此作者还反过来计算了基于关系和尾实体的头实体概率,最后平均两个PMI值作为结果。
    • +
  • +
  • 最终结果虽然比不上监督学习,但是在无监督学习中取得了最佳效果
  • +
  • 这是较早尝试利用预训练模型的Mask +Predict,将任务设计为完形填空来完成,可以看到这里的Pattern还是手工设计(针对每个关系设计一系列规则)。
  • -

    自适应动态规划(ADP)

    +

    Argumentative +Relation Classification as Plausibility Ranking

      -
    • agent学习状态之间转移模型,并用dp解决MDP
    • -
    • 在环境确定/可观测的情况下,不断的trial,得到数据,训练一个监督模型,输入当前状态和动作,输出后续状态概率,即转移模型
    • -
    • 得到转移模型后,之后按照序列决策的方法,通过修正策略迭代求解MDP
    • -
    • 可以看到ADP是需要agent先不断的trial,在环境中得到一系列包含奖励信号的历史数据,然后用这些数据学习到环境的转移模型,将其转化为环境已知的序列决策问题。
    • -
    • 自适应动态规划可以看成是策略迭代在被动强化学习设置下的扩展
    • +
    • 这篇论文做的任务为Argumentative relation +classification,即文本对分类,给定(或者不显式给出)结论,区分一对文本是支持还是反对。正例文本对里,两个文本都支持结论;负例文本对里,一个支持结论而另一个不支持,互相反驳。
    • +
    • 对于这个很有意思的任务,作者采用了一个同样很有意思的做法:使用孪生网络做ranking,rank的是一个构造文本的plausibility,即可信度。而这个构造文本是什么?很简单,将要判别的两个句子用一个连接词连接起来,得到构造文本的正负例: +
        +
      • 正例:文本A,而且,文本B
      • +
      • 负例:文本A,然而,文本B
      • +
    • +
    • 假如文本A和文本B是反对的关系,那么显然负例这么一段文本的可信度高;为文本A和文本B互相支持,那么正例构造文本的可信度高。
    • +
    • 接下来就用预训练语言模型作为孪生网络的编码器,然后做ranking。
    • +
    • 本质思想是构造了文本和任务,将任务用正常的自然语言表示,这样就可以利用学习到正常文本知识的语言模型来做学习和预测。
    • +
    • 和上一篇论文一样,核心都是将任务转为自然语言(模板),巧用预训练语言模型间接的完成任务(完成构造任务)
    -

    时序差分学习

    +

    Zero-shot +Text Classification With Generative Language Models

      -
    • 在被动强化学习的setting下,即给定策略\(\pi\),假如在状态s下采取动作\(\pi(s)\)转移到了状态\(s^{'}\),则通过时序差分方程更新价值函数: -\[ -U^{\pi}(s) \leftarrow U^{\pi}(s) + \alpha (R(s,\pi(s),s^{'}) + -\gamma U^{\pi}(s^{'}) - U^{\pi}(s)) -\]
    • -
    • 其中\(\alpha\)是学习率。对比bellman,时序差分是在观测到在状态s下采取动作a到达了状态s',就根据这个相继状态之间价值的差分更新价值: +
    • 作者使用GPT,将文本分类问题转化为给定包含原文本和类别的自然语言,通过文本生成间接判断类别
    • +
    • 这样做的一个好处即标题提到的zero-shot,可以泛化到训练集中不存在的类别
    • +
    • 具体而言,将文本分类问题转为一个选择QA任务,即所有的选项拼成了问题:该文本属于下面哪一类?A;B;C;D.....,之后再拼接上待分类文本,目标是训练语言模型,直接生成正确的类别的文本。
    • +
    • 另外为了减少预训练和finetune之间的gap,作者还加入了一个前置的预训练任务,叫title +prediction +pretraining,即将所有候选标题和正文拼接起来,然后生成正确的标题。
    • +
    • 这是一篇非常直观、间接且大胆的利用语言模型分类任务的工作,直接让语言模型生成类别文字。 +
    • +
    • 最终的zero-shot结果,虽然依然比不上finetune和sota,但是相比random和majority两个baseline可以比较出模型还是学到了相当强的泛化能力。最主要的还是把语言模型玩出了花,提供了这么一种直接设计多项选择疑问句来完成分类任务的思路。
    • +
    +

    Exploiting +Cloze Questions for Few Shot Text Classification and NaturalLanguage +Inference

      -
    • 差分项是关于误差的信息,更新是为了减少这个误差
    • -
    • 公式变化后可以看出来是当前价值和奖励+未来折扣价值之间做插值: \[ -U^{\pi}(s) \leftarrow (1-\alpha)U^{\pi}(s) + \alpha -(R(s,\pi(s),s^{'}) + \gamma U^{\pi}(s^{'})) -\]
    • -
    -
  • 与自适应动态规划的联系与区别: +
  • 该论文正式引入了PET的概念:Pattern-Exploiting Training。
  • +
  • 在上面三篇论文中我们可以看到,很多NLP任务可以通过提供自然语言任务描述的方式,通过语言模型来无监督的或者间接的完成。但是这类方法终究还是比不过监督学习方法。
  • +
  • PET提供了一种半监督学习方式,在低资源场景下成功超过了监督学习模型的结果。
  • +
  • 一张图就能说明PET的原理: gWivmd.png
      -
    • 都是根据未来调整当前价值,自适应的未来是在所有可能后继状态上加权求和,而时间差分的未来是观测到的后继
    • -
    • 自适应尽可能进行多的调整,以保证价值估计和转移模型的一致性;差分对观测到的转移只做单次调整
    • -
    • TD可以看成一种近似ADP +
    • 作者引入了两个名词,pattern负责把输入文本根据任务改造成一个带mask的完形填空文本,verbalizer负责把语言模型预测的mask词映射到label上。这样一个pattern对应一个verbalizer,称为PvP。。。(pattern +verbalizer pair)
    • +
    • 整个PET过程分三步:
        -
      • 可以用转移模型生成多个pseudo -experience,而不是仅仅只看真实发生的一次转移,这样TD的价值估计会接近ADP
      • -
      • prioritized sweeping,对哪些高概率 -后继状态刚刚经过大调整的状态进行更新
      • -
      • TD作为近似ADP的一个优点是,训练刚开始时,转移模型往往学不正确,因此像ADP一样学习一个精确的价值函数来匹配这个转移模型意义不大。
      • +
      • 第一步用PvP,在小训练集上微调预训练语言模型
      • +
      • 第二步,每一个任务可以设计多个PvP,这样得到多个第一步训练出的语言模型,集成,在大量未标注数据上打标软标签
      • +
      • 第三步,用一个分类器在打标后的数据上完成监督学习
  • +
  • 第二步中有两个小细节:多分类器集成,即多个预测标签分布相加,这里可以等权重相加,也可以根据PvP直接在训练集上zero-shot的表现作为先验权重(实验结果这样做好些);打标时打的是软标签即概率分布,softmax时取T=2做了温度处理。这两个处理都是为了能够更好的学习到语言模型的知识,一个在于集成更加鲁棒,另一个则相当于知识蒸馏。
  • +
  • 另外作者还提出了iPET,其实就是传统的半监督学习,训练打标之间迭代,用越来越多的数据训练出不同代模型然后集成。
  • +
  • 这样的半监督框架好处在于,最终实际操作依然是监督学习,准确率较高,而语言模型带来的不确定性在知识蒸馏(软化标签)的时候降低了。
  • -

    主动强化学习

    -
      -
    • 需要学习策略
    • -
    • 需要学习一个完整的转移模型,需要考虑所有的动作,因为策略不固定(未知)
    • -
    • 需要考虑,得到最优策略后,简单的执行这个策略就是正确的吗?
    • -
    -

    引入explore

    +

    It's +Not Just Size That Matters: Small Language Models Are Also Few-Shot +Learners

      -
    • 自适应动态规划是greedy的,需要引入exploration
    • -
    • 一个宏观的设计,是引入探索函数f(u,n),选择价值u较高的即贪心,选择尝试次数n少的即探索
    • +
    • 还是PET原版人马,又水了一篇,换了个动机,说用PET的话,小模型也能在few-shot上取得与GPT-3这样的大模型接近的结果,环保
    • +
    • 将PvP中要预测的词从单个mask扩展为多个mask,训练的时候插入固定最大数量的mask,预测时再做后处理
    • +
    • 给了更丰富的实验结果(不过好像还是arxiv挂着,没中会议。。。)(更新:惊了,拿到了NAACL +2021 杰出论文)
    -

    TD Q-learning

    +

    Improving +and Simplifying Pattern Exploiting Training

      -
    • 一种主动强化学习下的时序差分方法
    • -
    • 无需一个学习转移概率的模型,无模型的方法
    • -
    • 通过学习动作-价值函数来避免对转移模型本身的需求 \[ -Q(s,a) \leftarrow Q(s,a) + \alpha (R(s,a,s^{'}) + \gamma -max_{a^{'}}Q(s^{'},a^{'}) - Q(s,a)) -\]
    • -
    • 不需要转移模型P(s'|s,a)
    • -
    • 注意因为没有给定策略,这里需要对所有可能动作取max
    • -
    • 奖励稀疏时难以学习
    • -
    -

    Sarsa

    +
  • +
  • PET依然需要大量领域未标注数据来做半监督学习,本文提出了ADAPET,不用未标注数据也能取得更好效果
  • +
  • 作者通过修改任务目标来达成这一目的。当我们使用PET时,浪费了两类信息:
      -
    • 即state,action,reward,state,action,sarsa的缩写代表了更新的五元组 -\[ -Q(s,a) \leftarrow Q(s,a) + \alpha (R(s,a,s^{'}) + \gamma -Q(s^{'},a^{'}) - Q(s,a)) -\]

    • -
    • 相比TD -Q-learning,不是对所有可能动作取max,而是先执行动作,再根据这个动作更新

    • -
    • 如果agent是贪心的,总是执行q-value最大的动作,则sarse和q-learning等价;如果不是贪心,sarsa会惩罚探索时遇到的负面奖励动作

    • -
    • on/off policy

      +
    • mask位置上预测的词,仅仅在与类别label有映射关系的target word +vocab上做softmax计算交叉熵,其余词没有计算损失
    • +
    • 仅仅预测了mask位置,其他所有位置的embedding没有计算损失
    • +
  • +
  • 因此作者就想充分利用这两个信息,修改任务目标
      -
    • sarsa是on-policy:“假设我坚持我自己的策略,那么这个动作在该状态下的价值是多少?”
    • -
    • q-learning是off-policy:“假设我停止使用我正在使用的任何策略,并依据估计选择最佳动作的策略开始行动,那么这个动作在改状态下的价值是多少?”
    • +
    • 将损失从交叉熵改为两个二元交叉熵,一个依然是在label相关target词上算损失,另一部分损失则负责优化降低其他所有不相关词的概率
    • +
    • 将mask替换为正确或者错误的target +word,然后对输入剩下部分做MLM,要是target +word对的话MLM就应该预测对,反之就应该预测错
    • +
    • 分别对应图中左右两类损失
  • +
  • ADAPET增加了目标函数,对参数做了更充分的训练,对比PET结果也确实不错,不使用未标注数据还在很多任务上超过了PET
  • -

    强化学习中的泛化

    +

    AUTOPROMPT: +Eliciting Knowledge from Language Models with Automatically Generated +Prompts

      -
    • 价值函数和Q函数都用表格的形式记录,状态空间巨大
    • -
    • 要是能参数化,需要学习的参数值可以减少很多
    • -
    • 对于被动强化学习,需要根据trials使用监督学习价值函数,这里可以用函数或者NN来参数化。
    • -
    • 对于时序差分学习,可以将差分项参数化,通过梯度下降学习
    • -
    • 参数化来近似学习价值或者q函数存在几个问题 +
    • 由上面介绍的工作可以发现,构建有效的文本来触发语言模型得到结果至关重要,即构建prompt。目前看到的都是手工构建的,后来也出现了一批工作尝试自动构建prompts
    • +
    • 这个工作其实不能算是prompts,更准确的说法是trigger words +sequence,因为它其实是把文本对抗样本生成的一套方法拿到了prompt构建当中。
    • +
    • 具体而言,其借鉴了HotFlip: White-box adversarial examples for text +classification 和 Universal Adversarial Triggers for Attacking and +Analyzing +NLP两篇论文,即在样本中拼接一系列触发词,即可使得模型的预测结果错误,而模型的触发词搜索主要使用的是hotflip方法:
        -
      • 难以收敛
      • -
      • 灾难性遗忘:可以通过experience -replay,保存轨迹进行回放,确保agent不再访问的那部分状态空间上的价值函数仍然准确
      • +
      • 初始化触发词 \[\mathbf{e}_{a d +v}\](比如the,a,an等),前向过一遍模型得到损失关于触发词embedding的梯度 +\[\nabla_{\mathbf{e}_{a d v}} +\mathcal{L}\] +,注意这里用于计算损失所用的label应该是想要攻击得到的错误label,即fool +model之后的label
      • +
      • 我们希望替换第i个触发词为词 \[\mathbf{e}_{i}\],使得替换之后损失下降的最多,模型最容易预测出错误的标签,所以我们要找的词是 +\[ \underset{\mathbf{e}_{i}^{\prime} \in +\mathcal{V}}{\arg \min } \mathcal{L}(\mathbf{e}_{i}^{\prime}) +\]。这里通过泰勒一阶展开来近似,需要求到损失关于token的导数,由于token +embedding lookup不可导,所以才需要求到某个token的embedding的导数
      • +
      +\[ +\mathcal{L}(\mathbf{e}_{i}^{\prime}) = \mathcal{L}(\mathbf{e}_{a d +v_{i}}) + \left[\mathbf{e}_{i}^{\prime}-\mathbf{e}_{a d +v_{i}}\right]^{\top} \nabla_{\mathbf{e}_{a d v_{i}}} \mathcal{L} +\] \[ +\propto \left[\mathbf{e}_{i}^{\prime}-\mathbf{e}_{a d +v_{i}}\right]^{\top} \nabla_{\mathbf{e}_{a d v_{i}}} \mathcal{L} +\] +
        +
      • 这样就得到了第一轮迭代中的第一个触发词,之后通过beam +search得到剩下的触发词,并迭代多次,最终得到可以用于攻击模型的触发词序列。
    • -
    • 奖励函数设计,如何解决稀疏奖励? +
    • 以上是文本对抗攻击中的hotflip方法,其本质就是生成一些触发词,拼接到样本上,使得模型预测出错的label。autoprompt的思想就是生成触发词,使得模型预测出指定label。 +
    • +
    • 接下来就简单了。作者首先在训练集上用hotflip方法为每个任务生成了触发词,然后用模板将样本变为一个句子,如图所示,句子拼接上触发词序列([T])和PLM要预测的mask位置([P]),让模型预测出词之后再后处理得到label。具体的后处理操作是,将每个label对应的预测词集合得到的概率累加,最后归一化,作为标签的概率。
    • +
    • 上面只说了PvP中的prompt自动构建方法,而verbalizer,即预测词到标签的映射作者也给出了一个自动搜索的方法:
        -
      • 问题:credit -assignment,最后的正面或者负面奖励应该归因到哪次动作上
      • -
      • 可以通过修改奖励函数(reward -shaping)来提供一些中间奖励,势函数就是一个例子,势反映了我们所希望的部分状态(某个子目标的实现、离最终希望的终止状态的某种可度量的距离)
      • +
      • 将PLM编码之后包含上下文信息的mask +token的embedding作为特征输入,标签作为输出来训练一个logistic分类器,之后将所有词的PLM编码之后的embedding依次输入这个分类器,得到每个词在每个标签上的评分,根据评分top +k来为每个标签类别选择词作为映射集合。这么做实际上是将预测标签所需的mask +token编码embedding和每个词的编码embedding比较,取最相近的top +k,只不过利用logistic分类器做了一个类别相关的特征加权,不仅仅是取PLM编码之后的语义相似度,非常巧妙。
    • -
    • 另一种方案是分层强化学习,TBD
    -

    策略搜索

    +

    Making +Pre-trained Language Models Better Few-shot Learners

      -
    • 只要策略的表现有所改进,就继续调整策略
    • -
    • 策略是一个状态到动作的映射函数
    • -
    • 将策略参数化表达,尽管可以通过优化q函数得到,但并不一定得到最优的q函数或者价值估计,因为策略搜索只在乎策略是否最优
    • -
    • 直接学习Q值,然后argmax -Q值得到策略会存在离散不可导问题,这时将Q值作为logits,用softmax表示动作概率,用类似gumbel-softmax使得策略连续可导
    • -
    • 假如执行策略所得到的期望奖励可以写成关于参数的表达式,则可以使用策略梯度直接优化;否则可以通过执行策略观测累计的奖励来计算表达式,通过经验梯度优化
    • -
    • 考虑最简单的只有一次动作的情况,策略梯度可以写成下式,即对各个动作的奖励按其策略概率加权求和,并对策略参数求导。 -\[ -\triangledown_{\theta}\sum_aR(s_0,a,s_0)\pi_{\theta}(s_0,a) -\]
    • -
    • 将这个求和用策略所定义的概率分布生成的样本来近似,并且扩展到时序状态,就得到了REINFORCE算法,这里用N次trial近似策略概率加权求和,并且将单步奖励扩展到价值函数,状态也扩展到整个环境的状态集合: -\[ -\frac1N -\sum_{j=1}^N\frac{u_j(s)\triangledown_{\theta}\pi_{\theta}(s,a_j)}{\pi_{\theta}(s,a_j)} -\]
    • +
    • 这篇论文标题就是GPT3的标题加了个better,强调如何更好的利用prompt做few +shot learning。
    • +
    • 提出了一个训练体系:基于prompt的微调+prompt自动生成+动态选择性融入任务说明到prompt中,且这一切都是strong +task-agnostic。接下来分别说这三点改进。
    • +
    • +
    • 上图清晰的展示了第一点改进:基于prompt的微调。可以看到,和以往prompt方法相比,除了输入、prompt之外,输入还拼接上了每个label的说明
    • +
    • 至于prompt自动生成,分为两部分: +
        +
      • 如何在给定模板的情况下,自动生成目标词到标签的映射。这里作者也是用PLM的结果不断迭代。首先对每个类,找出这个类的所有训练样本,通过PLM推断得到mask词的概率分布,累加所有样本的概率分布取topk就得到了词到该类别标签的映射。由于接下来训练微调时模型参数变化,结果可能有改变,所以需要每轮训练后重新rerank调整一下映射关系。
      • +
      • 给定类别和这个类别的目标词,如何生成模板。作者采用了T5模型,因为其mask +span seq2seq预训练的目标和模板生成任务很符合。一张图就可以解释清楚: g5YjfI.png +这样生成的prompt考虑了训练样本上下文和标签词的语境。作者使用wide beam +width来beam +search出一堆prompt候选(100+),然后在一个小训练集上微调每个样本,取验证集最高的(或者topk集成)作为最终prompt
      • +
      • 动态选择性融入任务,这里做的比较麻烦,即得到prompt后如何构造输入样本,也是如第一张图所示,对每个类别,采样一个样本转化为prompt当做这个类别的说明,将所有类别说明和输入样本(待训练样本)拼接。采样时,使用sentence-BERT得到每个样本的语义embedding,然后只取和输入样本语义相似度前50%的样本进行采样。
      • +
    • +
    • 这种prompt的设计有点像是在做语义相似度任务,输入x,已知y为正例,z为负例,构造了输入为“x是mask例?y为正例;z为负例”,相当于比较x与yz的语义相似度,做一个标签的传播
    -

    MARL (Multi-Agent Rl)

    +

    GPT Understands, Too

      -
    • 先挖坑
    • -
    • -
    • -
    • -
    • +
    • +
    • 本文提出了P-tuning,即不是找离散的prompt(具体文本),而是找连续的(embedding)
    • +
    • 回顾一下整个prompt based +methods,都是把数据和任务转化为语言模型任务的形式,使其更加贴近预训练目标,能够更好的利用预训练模型的知识。实际操作时,就是把输入添加一些prompt +generated templates,输出变成与类别label相关的target +words,作者反思,这些prompt generated templates +本质上就是一些词,一定要是人类能够理解的文本吗?这些文本输入到模型的实际上是embedding,那么搜索prompt的时候为什么不直接优化embedding呢?所以作者提出就用几个词表中没用的符号(例如BERT中的unused)来作为pseudo +template +token,固定这些token,不去搜索新的token,而是直接优化token对应的embedding。
    • +
    • 为了让这些pseudo +token更像是自然语言,而不是独立的几个符号,作者还用了双向LSTM来做编码,即prompt +encoder,这里感觉动机阐释的不是很清楚,为什么不能放在PLM里直接建模之间关系?
    • +
    • 这么看来整体就相当于输入拼接上几个embedding然后去优化,只不过输出和后处理采用了PET的形式,很像自己加了某个层去微调(所以叫Prompt +finetuning?)。我感觉加层微调和P-tuning都是引入少量参数把PLM用到自己的下游任务上,只不过P-tuning转换了下游任务形式,使其跟贴近预训练目标,算是微调结构先验更合理吧,同时也算是从另一个高度总结了prompt一类的工作。
    ]]>
    - 强化学习 + 自然语言处理 - reinforcement learning - multi-agent + machine learning + nlp + pretrained language model + pet + few shot
    - OJ - /2017/03/27/oj/ + Pandas Basics + /2017/02/04/pandas-skill/ -

    算法刷题目录,方便自己查找回忆复习 -之后(2018.9.27)只更新leetcode上的题了,也懒得整理源码了,leetcode上都存了,只记录思路吧

    +

    以泰坦尼克号的数据为例介绍一下前期对数据的基础操作。

    -

    mark

    -

    Leetcode

    - -

    排序

    -
      -
    • 75:给出一个只包含0,1,2的数列,排序形成[0,0,...,0,1,...,1,2,...,2]的形式,在原数列上修改。借鉴Lomuto -partition -algorithm,维护三个区间[0,i],[i,j],[j,k]为0,1,2的范围,按优先级,若当前数为2或1或0,先将nums[k]=2,k++,若当前数为1或0,则nums[j]=1,j++,若当前数为0,则nums[i]=0,i++,越往后能覆盖前面的,优先级越高。
    • -
    • 164:给出一个无序数列,请在O(n)时间复杂度内找到数列有序化后相隔元素差最大值。桶排序,设数列中最大值最小值分别为max,min,易得这个相邻元素差最大值肯定大于(max-min)/(n-1)并设这个值为gap,n是数列长度。将数列的取值区间[min,max]以(max-min)/(n-1)为间隔分成nums个桶,nums是int((max -- min) / gap + -1),把数列各个元素分到桶中,每个桶只存对应区间内的最大元素和最小元素,把那么最大间隔肯定在相邻两个桶的边界处(前一个桶的最大值和后一个桶的最小值),因为桶内的最大间隔小于gap。最后遍历一遍桶就可以了。
    • -
    • 179:水题,给出一个数列,要求把各个数连起来组合成一个最大的数。字符串排序
    • -
    -

    堆、栈、队列

    +

    引入库

    +
    import csv as csv 
    import pandas as pd
    import numpy as np
    +

    读取文件

    +
    train = pd.read_csv(r"文件目录") 
    +

    此时数据的样式是: i0Tn41.jpg

    +

    数据概览

      -
    • 23:合并K个有序链表为1个有序链表,用最小堆存所有链表头节点,依次取出插入到新链表中
    • -
    • 150:算术表达式,栈,python的switch写法
    • -
    • 224:带括号的算术表达式,栈,巧妙地方法处理括号,如果括号外是负号则符号乘-1否则乘1
    • -
    • 373:在2对有序数组中找出有最小和的k组数对,优先队列
    • +
    • describe 显示整体数据常见属性
      print(train.describe())
      i0TP3V.jpg
    • +
    • head tail 显示首尾一些数据
      print(train.head(5))
      print(train.tail(3))
      i0TFjU.jpg
    • +
    • index:索引,默认自建整型索引;columns:列;values:数据数值 +
      print(train.index)
      print(train.columns)
      print(train.values)
      # 数据操作
    • +
    • T:数据的转置
      print(train.T)
      i0TAuF.jpg
    • +
    • sort:可以按索引或者值进行排序,axis选择维度(行还是列),ascending选择升序或者降序,Nan永远排在最后,无论升序降序 +
      print(train.sort_index(axis=0,ascending=True))
      print(train.sort_values(by="Age",ascending=False))
    -

    组合数学

    +

    数据选择

      -
    • 47:生成n个数字的所有组合,数字有重复,依次插入数字到已生成k个数字组合的k+1个空中,排重直接用集合,Top -Solution中用插入处后一个数字是否重复来排重
    • +
    • 按照标签选择,选择列,行切片
      print(train['Age'])
      print(train[0:9])
      i0TVHJ.jpg i0TeE9.jpg
    • +
    • 利用loc自由选择某些行某些列,可以用at替代
      print(train.loc[train.index[4:6]])
      print(train.loc[:,['Age','Fare']])
      print(train.loc[3:5,['Age','Fare']])
      print(train.loc[4,'Age'])
      print(train.at[4,'Age'])
    • +
    • 利用iloc按照位置进行选择
      print(train.iloc[5])
      print(train.iloc[3:5,2:4])
      print(train.iloc[[1,2,4],[2,5]])
      print(train.iloc[3,3])
    • +
    • 布尔选择
      print( train[ (train['Age']>40) & (train['Age']<50) ] )
      print(train[train['Parch'].isin([1,2])])
      print(train[pd.isnull(train['Age'])==True])
      i0TK9x.jpg i0TM36.jpg i0TljO.jpg
    -

    搜索与查找

    +

    缺失值处理

      -
    • 74:在一个有有特定顺序的矩阵中查找,两次二分查找
    • -
    • 78:生成子集,递归或者迭代,每个数字分加入子集或者不加入子集进行递归
    • -
    • 79:在一个字母矩阵中查找单词,深搜
    • -
    • 89:生成格雷码,迭代,每次在最前面加1或0,格雷码上下对称
    • -
    • 140:将一个字符串按给定词典加空格成句子,记忆化搜索
    • -
    • 153:一个有序数组拆成两部分再倒接一起,查找,特殊的二分查找
    • -
    • 154:153如果加入重复数字的变形,加入一个条件,二分的start和end是相邻不重复的第一个
    • -
    • 240:74的改版,每一行每一列有序,查数,对行和列分别做二分,数肯定在满足条件的行与列的交集处,还有其他解法
    • +
    • 利用reindex选择部分数据进行拷贝,并进行缺失值处理。一些函数会自动过滤掉缺失值,比如mean() +
      train1=train.reindex(index=train.index[0:5],columns=['PassengerId']+['Age']+['Sex'])#选择前5行,只取选定的三列
      print(train1)
      print(train1.dropna(axis=0)) #删除存在nan值的行
      print(train1.dropna(subset=['Age','Sex'])) #删除年龄性别列中存在nan值的行
      print(pd.isnull(train1)) #nan值改为true,其余值改为false
      print(train1.fillna(value=2333)) #缺失值替换为2333
      # 应用函数
    • +
    • 可以自己写函数并应用到数据的行或者列,通过axis参数选择行列 +
      #写函数统计包含nan值的行数
      def null_count(column):
      column_null=pd.isnull(column)
      null=column[column_null == True]
      return len(null)
      print(train.apply(null_count))
      #写函数对年龄列进行分类
      def judge(row):
      if pd.isnull(row['Age']) ==True:
      return 'unknown'
      return 'youngth' if row['Age']<18 else 'adult'
      print(train.apply(judge,axis=1))
      i07jFs.jpg # +数据透视表
    • +
    • 自选分类和值进行数据透视,比如按照pclass和sex分类,统计age和fare的平均值 +
      print(train.pivot_table(index=["Pclass","Sex"], values=["Age", "Fare"], aggfunc=np.mean))
    -

    +

    数据合并

      -
    • 98:判断一颗二叉树是不是查找树,即左子树都小于节点,右子树都大于节点,中序遍历看看是不是递增数列即可,递归或者栈
    • -
    • 101:判断一棵二叉树是不是对称的,递归,注意递归的是(left.left,right.right)和(left.right,right.left)即内外两队子节点,另外可以用栈实现迭代版本
    • -
    • 106:给出中序遍历后序遍历,求前序遍历。后序遍历的最后一个是根节点,在中序遍历中找到这个根节点并在后序遍历中删除,根节点以左是左子树,以右是右子树,这时后序遍历的最后一个节点就是左子树的根节点,递归即可
    • -
    • 107:从下往上从左往右输出树每一层的节点,用二维数组记录答案,如果二维数组的一维长度即层数比当前遍历的节点层数少就新建一层存答案。可以直接dfs,或者用栈和队列替代递归,如果用栈就是dfs,如果用队列就是bfs
    • -
    • 108:构造一棵二叉查找树,递归
    • -
    • 114:给一棵树,按前序遍历将其压扁,变成一棵只有右节点的树。将一个节点压扁操作定义为,把左子树置空,右子树变成原左子树,原右子树接在原左子树的尾节点上,原左子树的尾节点就是按前序遍历这个子树遍历到的最后一个点。递归,先压扁左节点,再压扁右节点,再回溯压父节点
    • -
    • 144:求一棵树的前序遍历,利用栈,弹出一个节点记录值,并先压入右节点,再压入左节点
    • -
    • 515:求二叉树每一层的最大值,BFS
    • +
    • 数据合并的一些操作,待补全

      +
      import pandas as pd
      data1 = pd.DataFrame({'level':['a','b','c','d'],
      'numeber':[1,3,5,7]})

      data2=pd.DataFrame({'level':['a','b','c','e'],
      'numeber':[2,3,6,10]})

      print("merge:\n",pd.merge(data1,data2),"\n")

      data3 = pd.DataFrame({'level1':['a','b','c','d'],
      'numeber1':[1,3,5,7]})
      data4 = pd.DataFrame({'level2':['a','b','c','e'],
      'numeber2':[2,3,6,10]})
      print("merge with left_on,right_on: \n",pd.merge(data3,data4,left_on='level1',right_on='level2'),"\n")

      print("concat: \n",pd.concat([data1,data2]),"\n")

      data3 = pd.DataFrame({'level':['a','b','c','d'],
      'numeber1':[1,3,5,np.nan]})
      data4=pd.DataFrame({'level':['a','b','c','e'],
      'numeber2':[2,np.nan,6,10]})
      print("combine: \n",data3.combine_first(data4),"\n")
      +
      +i0T8De.jpg + +
    -

    图论

    +]]>
    + + Python + + + math + machine learning + code + python + +
    + + Reformer - Paper Reading + /2020/02/07/reformer/ + Reformer论文解读

    + +

    多快好省

      -
    • 130:水题,把一个图中被黑子包围的白子全部替换成黑子,直接从边上找出所有白子并存起来,再将整个棋盘涂黑,把白子复原。存的是top -solution,写法很pythonic
    • +
    • 作者主要提出了两点操作来降低Transformer,尤其是在处理超长序列时的内存占用,减少了大量运算,提升了速度。
    -

    数学题

    +

    LSH Attention

    +

    39Y8pt.png +- 这一部分最原始的想法就是,Transformer当中的self +attention,每一个token作为query时,要把序列中所有token当成key去计算注意力,再在所有token上加权得到当前token的一个表示,但我们知道注意力一般是非常稀疏的,权重就集中于少数几个token上,那不如只在这几个token上计算权重并加权,这样就大大减少了self +attention里\(O(N^2)\)的计算量和内存占用量。 - +那么怎么才知道那少数几个token是哪几个?假如要完全靠注意力计算出来才能得到的话,怎么可能在计算注意力之前就知道哪几个token权重大?是不可能,但是在self +attention里,query和key计算权重,就是简单的内积,和query相似的key权重大。模型学习到注意力,是指学习到生成正确的query以及key的表示,在计算注意力时只需要比对query和key就可以了。 +- +所以问题转换成,对每一个query,我先找到相近的几个key计算注意力就好了。怎么找?当然不是全部算一遍取top +k,那就与我们减少计算量的初衷相悖,在这里作者用到了Local Sensitive +Hashing(LSH),局部敏感哈希,大意就是相近的向量,映射到同一哈希值的概率较大,多个相近的、映射到同一哈希值的向量相当于装进了同一个桶里(bucket),那么我们只需要对每个桶里的向量计算self +attention。详细一点的描述是,两个向量\(q_1,q_2\),满足LSH的哈希函数\(h\)能做到 \[ + for \ dis(q_1,q_2) <= d_1 , \ p(h(q_1)==h(q_2)) >= p_1 \\ + for \ dis(q_1,q_2) >= d_2 , \ p(h(q_1)==h(q_2)) <= p_2 \\ + \] - 相关领域已经有很多研究,对于不同的距离度量\(dis\),有不同的\(h\)满足LSH。显然在这里我们的距离度量是cosine距离,对应的LSH哈希是球形投影,即将向量投影到一个b维超球面上,该球面被分成了\(n_{buckets}\)个象限,投影到同一象限的向量即在同一个桶中,该投影哈希具体写出来是: +\[ + h(x) = argmax[xR;-xR] \\ + \] \(R\)是一个\([d_k,b/2]\)的随机投影矩阵 - +接下来的一个问题是,一个桶里面,query和key的数量不一定相等,而且有可能一个桶里许多query,没有key。于是作者干脆share +QK,即令query和key相同,都是embedding从同一个线性变换出来的,只不过key做了归一化操作\(k_{j}=\frac{q_{j}}{\left\|q_{j}\right\|}\) +- chunk操作:接下来作者并不是让每个桶里分别做self +attention,而是做了分段,即把同一个桶里的放在一起,重新排成一个序列,然后等长切成若干个段,段内做self +attention,相邻的段也做一次attention。这里其实有点疑问,论文的图画的非常理想,每个桶的大小差不多,可能差了一两个可以通过相邻段做attention来弥补,但是实际情况并不知道每个桶的大小。也许是因为attention本身也是学习出来的,作者这么人为设置,是不是相当于给了一个每个桶大小都趋于相同且等于段长的先验限制了attention的学习。 +- Multi-round +lsh:lsh是讲概率的,有概率就有误差,作者构造了一个巧妙的实验来验证lsh对原始attention的还原度,发现单轮的效果并不好。因此就多次hash来保证概率,取多轮hash的并集来保证相似的向量能落到同一个桶里。这里取并集而不是交集,个人理解是桶一多,hash其实很稀疏,不相似的向量落在同一个桶的概率远小于相似的向量落在不同桶的概率。这里还有一些细节待补充 +- casual +masking:正常的transformer在decoder端是要做时序掩码的,这里lsh把序列顺序打乱了,因此也要做对应的处理,保证时序掩码的正确性。 +- 值得一提的是大部分self +attention的实现,value包括了自身,但是在lsh里不能包含自身,因为key和value共享值,自身永远是最相似的。

    +

    Reversible Transformer

      -
    • 4:给出两个有序数列,求出两个数列合并后的中位数,要求时间复杂度O(log(m+n)),所以不能直接一个一个比较。中位数的意义是把序列拆成长度相等两部分,大部分中最小数比小部分中最大数大,根据这个原理将两个序列拆成两部分,设两个数列长度分别为m,n,设数列1在i位置拆开,数列2在j位置拆开,则需要保证:1:两个长度一样,则\(i+j=m-i+n-j\);2:两个数列的小部分的并集的任意数比两个数列大部分的并集的任意数要小,因为拆开后的部分依然有序,因此这个条件就是\(B[j-1] <= A[i] and A[i-1] <= -B[j]\),i的位置确定,j的位置就确定,因此只需二分查找i的位置即可。注意奇偶性和边界判断。
    • -
    • 57:给出一组区间,插入一个新区间并合并。模拟
    • -
    • 122:水,一行代码,找一个序列中的最大相邻元素差
    • -
    • 142:给出一个链表,找出链表中环的起点。依然是快慢钟算法,设一快一慢两个指针一起从链表开始走,第一次相遇时说明存在环且他们步数之差是环的长度,而且可以推算出链表起点到环起点的距离等于相遇点到环起点的距离,就可以找到环的起点
    • -
    • 166:给出除数被除数写出结果,包括循环小数显示,数学分析题,小数不断乘10除除数,更新余数,余数出现重复即小数出现重复
    • -
    • 172:求n!中0的个数,数学分析题,0来自5*2,就看n中有多少5及其倍数
    • -
    • 202:快慢指针,求循环的一种方法
    • -
    • 263:数学题
    • -
    • 264:数学题
    • -
    • 313:数学题
    • +
    • 这一部分的想法参照了论文:The Reversible Residual Network: +Backpropagation Without Storing Activations。
    • +
    • 基本思想就是,将残差结构改为可逆残差结构,从而节省了显存。网络在做方向传播的时候,需要存储每一层的激活值,带入自动微分计算每一层的导数,再链式求导,其中存储每一层的激活值占了很大的显存。可逆残差的思想就是,通过将channel一分为二,做成两路,互相残差,更改计算图的拓扑结构,使得两路的激活值能够通过上一层的激活值计算出来,如图:
      +
    • +
    • 前向传播过程为: \[ +\begin{array}{l}{y_{1}=x_{1}+\mathcal{F}\left(x_{2}\right)} \\ +{y_{2}=x_{2}+\mathcal{G}\left(y_{1}\right)}\end{array} +\]
    • +
    • 反向传播为: \[ +\begin{array}{l}{x_{2}=y_{2}-\mathcal{G}\left(y_{1}\right)} \\ +{x_{1}=y_{1}-\mathcal{F}\left(x_{2}\right)}\end{array} +\]
    • +
    • 可以看到计算\(x_2\)时只用了上一层的激活值\(y_1,y_2\),计算\(x_1\)时用了上一步计算出来的\(x_1\),因此不需要存储这两个激活值。虽然节省了空间,但是激活函数需要重新算一遍,相当于用时间换空间。
    • +
    • 原始论文用在resnet里,节约显存可以换得更大的batch_size,在transformer中就可以用来训练更长的sequence
    • +
    • reformer中把两个函数\(\mathcal{F}\)\(\mathcal{G}\)分别改成了自注意力层和全连接层,这样就对应了transformer的可逆结构
    • +
    • 可逆结构虽然消除了层数对于空间复杂度的影响,但是transformer里占显存最大的FFN,其依然受序列长度影响,为了减少这一部分显存占用,作者有一次采用了chunking,因为FFN这里是不存在序列依赖的,完全可以拆成几段计算,相应的,可逆结构的输入输出也拆成几段计算,又一次用时间换空间。此外,对于词典较大的应用场景,作者在计算损失log-probabilities时也是分段的。
    • +
    • 作者还额外提到,这样节省的是反向传播计算梯度时用到的中间临时变量,并不会节省参数量,节省参数量在GPU的消耗可以通过将其转到CPU内存来解决,通常这样的操作得不偿失,因为在CPU和GPU之间传输数据非常耗时,但是由于reformer在每次转换时可以处理更多的数据,就“得能尝失”了。
    -

    字符串

    +]]>
    + + 自然语言处理 + + + deep learning + natural language processing + local sensitive hashing + transformer + +
    + + Seq2seq based Summarization + /2018/07/04/seq2seq-summarization/ + 本科毕业设计是做一个基于seq2seq的短句文摘模型,并设计了一种情感融合机制 +现在对整个模型做一个简单的总结

    + +
    +i0TGHH.png + +
    +

    任务

      -
    • 131:将一个字符串分成回文子串,用python的[i::-1]很好找,也是一行代码
    • -
    • 242:水题,python字典的使用
    • -
    • 301:给定字符串,删除最小数目的括号使得字符串中所有括号匹配,输出所有情况。注意两点:正序逆序各做一遍,因为有删左括号和右括号两种方案;所有情况都要输出,用集合存取所有情况
    • -
    • 451:按频率统计字母,哈希,python字典
    • -
    • 541:部分字符串翻转,模拟,注意python切片的使用
    • +
    • 自动文摘是一类自然语言处理(Natural Language +Processin,NLP)任务。对于一段较长的文本,产生一段能够覆盖原文核心意义的短文本,这段短文本就是原文本的摘要。自动文摘技术是指在计算机上构建数学模型,将长文本输入模型,通过计算之后模型能自动生成短摘要。根据需要产生摘要的语料规模和摘要的规模,可以将摘要分为多文本摘要、长文摘要、短文摘要。本文主要研究的是短文摘要:对于一句或者几句文本,生成一句短摘要,概括原文关键信息,且流畅可读,尽量达到人类作者撰写摘要的水平。
    • +
    • 自动文摘分抽取式和生成式,前者是抽取原文句子构成文摘,后者是通过深度学习模型逐字生成文摘。本文主要研究生成文摘,并将问题抽象成对一个平均长度为28词的长句生成一个平均长度为8词的短句。
    -

    贪心

    +
    +i0TYEd.jpg + +
    +

    预备知识

    +

    循环神经网络

      -
    • 134:加油站排成一圈,给定各个加油站可以加的油和站与站之间路程所耗的油,问可以走完一圈需要从哪个加油站出发,数据保证答案唯一,贪心,如果前i个加油站走不完了,那么出发点就设成i+1
    • -
    • 402:从一个大数中移除k个数字,使得新的数最小,栈,贪心
    • -
    • 452:重叠区间问题,贪心
    • +
    • 循环神经网络(Recurrent Neural +Network,RNN),是神经网络的一种变形,能够有效处理序列型数据,其所有的隐藏层共享参数,每一隐藏层不仅依赖当前时刻的输入还依赖上一时刻的隐藏层状态,数据流并不是如传统神经网络那样在网络层之间传播,而是作为状态在自身网络中循环传递。
    • +
    • 不展开时形式如下: i0TtUA.jpg
    • +
    • 按时间步展开之后: i0TN4I.jpg
    -

    动态规划

    +

    LSTM和GRU

      -
    • 70:经典问题爬梯子,斐波那契数列,dp
    • -
    • 96:给一个1到n的数列,问可以构造出多少不同的bst。设ans(i)为长度为i的数列能构造不同的bst的个数,我们需要找到ans(i)与ans(i-1)的关系,引入中间变量f(i,n),指以第i个数字为根构造bst,长度为n的数列能构造不同的bst的个数,这里可以找到递归关系,根左边的子数列构造出根的左子树,设有left种不同的左子树,右数列right同理,则f(i,n)应该是left*right,即f(i,n)=ans(i-1)*ans(n-i),同时以不同的i为根会有完全不同的划分,则\(ans(n)=\sum _{i=1}^n -f(i,n)\),合并可以得到ans(i)=ans(0) * ans(n-1) + ans(1) * -ans(n-2) + … + ans(n-1) * ans(0),边界ans(0)=ans(1)=1。
    • -
    • 139:给出词典,给出一个字符串,判断字符串是否可以完全由词典内的单词构成。设f[i]==true即前字符串前i位都可以完全由单词构成,则遍历每个单词,单词长度为k,若f[i-k]为真则f[i]为真,也可以转换为图用dfs做,i与j之间有一条边说明s[i:j]是一个单词,我们要找到一条路径从0到len(s)
    • -
    • 174:矩阵中有正数负数,在中途不为0的情况下求最小路径。动态规划,从后往前
    • -
    • 312:给出一个数列,问怎样依次消去数能得到最多硬币,得硬币的规则:消掉一个数得到这个数和相邻两个数累乘的数量的硬币。区间dp(分治),一段区间内能得到的最多硬币f[x,y]是看其最后一次消去位置在i,得到的硬币就是f[x,i-1]+num[i-1]*num[i]*num[i+1]+f[i+1,y],在这个区间内枚举位置i,其中需要左右两个小区间的位置已知,因此将区间从小到大枚举。总共三层循环:外循环区间长度,中循环区间在整个序列中的开始位置,内循环枚举区间内位置i。
    • -
    • 338:求出[1,num]内每个数字二进制中有多少个1,列举几个数分析发现对偶数n,它的二进制就是n/2的二进制左移一位,1的个数不变,对奇数n,它的二进制就是n/2的二进制左移一位并末尾加1,即1的个数多一个,显然状态转移方程 -\[ -f(x)= -\begin{cases} -f(n) & x=2n \\ -f(n)+1 & x=2n+1 \\ -\end{cases} -\]
    • -
    • 397:一个数是偶数就除2,是奇数就变到相邻数,问最少几次变成1,根据题意可以写出状态转移方程: -\[ -f(x)= -\begin{cases} -f(n)+1 & x=2n \\ -min(f(2n+2)+1,f(2n)+1) & x=2n+1 \\ -\end{cases} -\] 奇数情况可以化简为\(min(f(2n)+1,f(n+1)+2)\),这样就可以从1到n动规了,但是会超时 -可以将方程进一步化简 If n % 4 = 3 and n != 3, then f(n) = f(n + 1) + 1. -If n % 4 = 1 or n = 3, then f(n) = f(n - 1) + 1. 证明在这里
      -
    • -
    • 472:是139的变式,依然是判断字符串是否可以由单词构成,但单词和要判断的字符串都在一个词典里,每个单词都需要判断是否完全能被其他单词组成。因为词典中无重复单词,所以先按单词长度排序,每个单词只能由它前面的单词构成,然后问题就转变成了139,第i个单词为要查询的字符串,前i-1个单词构成了查询所需的词典,一样的进行动态规划。top -solution中利用了trie字典树加速,见Python中实现字典树
    • +
    • 循环神经网络能够有效捕捉序列数据的顺序信息且能够构造很深的神经网络而不产生大量需要学习的参数;但也因为参数共享,梯度通过时间步进行链式求导时相当于进行矩阵幂运算,若参数矩阵的特征值过小会造成梯度弥散,特征值过大会造成梯度爆炸,影响反向传播过程,即RNN的长期依赖问题。在处理长序列数据时长期依赖问题会导致序列的长期记忆信息丢失,虽然人们通过引入梯度截断和跳跃链接技术试图缓解此问题,但效果并不显著,直到长短期记忆神经网络和门控循环神经网络作为 +RNN 的扩展形式的出现,有效地解决了这个问题。
    • +
    • LSTM即长短期记忆神经网络。为了捕捉长期记忆信息,LSTM在其节点中引入了门控单元,作为网络参数的一部分参与训练。门控单元控制了当前隐藏层节点记忆(遗忘)过去信息,接受当前输入新记忆的程度。 +
    • +
    • GRU即门控神经网络,与LSTM不同的是,GRU +将遗忘门和输入门整合为重置门,遗忘门的门控值和输入门的门控值和为 1,因此 +GRU 在 LSTM 的基础上简化了参数,从而使得模型能够更快得收敛。 i0Td8P.jpg ## +词嵌入
    • +
    • 深度学习的一大好处就是能自动学习特征,在自然语言处理中,我们专门用word2vec之类的技术学习词语的特征表示,即词嵌入。
    • +
    • 词向量(Word Vector)表示,又称词嵌入(Word +Embedding),指以连续值向量形式表示(Distributed +Representation)词语,而不是用离散的方式表示(One-hot +Representation)。在传统的离散表示中,一个词用一个长度为 V +的向量表示,其中 V 是词典大小。向量中只有一个元素为 1,其余元素为 +0,元素 +1的位置代表这个词在词典中的下标。用离散的方式存储单词效率低下,且向量无法反映单词的语义语法特征,而词向量可以解决以上问题。词向量将向量的维 +度从 V 降低到 \(\sqrt[k] V\)(一般 k 取 +4),每个元素的值不再是 1 和 0,而是连续值。词向量是建立神经网络语言模型 +(Neural Network Language +Model,NNLM)对语料进行监督学习得到的副产物,此模型的提出基于一个语言学上的假设:具有相近语义的词有相似的上下文,即 +NNLM 模型能够在给定上下文环境的条件下求出相应中心词。
    • +
    • 下图展示了word2vec中的skipgram模型: i0Twgf.jpg
    • +
    • 得到的词嵌入矩阵如下: i0T0v8.jpg
    • +
    • Mikolov等人在NNLM基础上提出了 Word2Vec +模型,此模型进行监督学习的输入输出分别为中心词与上下文(即 Skip Gram +模型) 或者上下文与中心词(即 CBOW +模型)。两种方式均能有效训练出高质量的词向量,但是 CBOW +模型是根据上下文求中心词,训练速度快,适合在大语料上训练;Skip Gram +模型能充分利用训练语料,其本身含义为“跳跃的语法模型”,不仅使用相邻词构成中心词的上下文环境,隔一个词的跳跃词也构成上下文环境,以图 +2-1 为例,语料中的一个中心词的上下文包括四个词,假如语料中有 Wtotal +个词语,则 Skip Gram 模型能计算 4 · Wtotal +次损失并进行反向传播学习,对于语料的学习次数是 CBOW +模型的四倍,因此该模型适合于充分利用小语料训练词向量。
    • +
    • Word2Vec +模型训练完成时,输入层与隐藏层之间的权重矩阵即词嵌入矩阵(Word Embedding +Matrix)。离散表示单词的向量与矩阵相乘即得到词向量,这项操作实际上等效于在词嵌入矩阵中查找对应词向量(Embedding +Look +Up)。词向量能够有效表示词的语义关系,其本质是为机器学习模型提供了一种提取文本信息特征的方法,方便将单词数值化输入模型进行处理。传统的语言模型训练词向量在输出 +Softmax 层开销太大,
    • +
    • 而 Word2Vec 模型采用了分层 Softmax(Hierarchical +Softmax)和噪声对比估计(Noise Contrastive +Estimation)两种技术,大大加速了训练,使得在自然语言处理中使用大规模语料训练出的优质词向量成为可能。
    -

    分治

    +

    注意力

      -
    • 247:给出一个算式,无括号,问加括号的情况下有多少种可能的解(不要求去重),分治,取第i个运算符号,对符号左边和右边分别递归求解部分解,python中map的用法
    • +
    • 在 NLP +任务中注意力机制最早应用于机器翻译,即引入一个权重矩阵代表编码器序列中各个元素对解码器生成的每一个词的贡献程度。在实际实现时注意力机制会生成一个注意力权重,对各个编码器元素的隐藏层状态进行注意力加权生成中间表示,而不是简单的采用最后一个元素的隐藏层状态。最简单的注意力即解码器对编码器的注意力,分为全局和局部注意力。全局注意力生成对整个编码器序列的注意力权重,而局部注意力先训练出一个注意力对齐位置,再对此位置附近取一个窗口,仅对窗口内的序列加权,使得注意力更加精确、集中。注意力机制带来的一个副产品即词与词之间的对齐Alignment)。在机器翻译中,对齐关系可以理解为词到翻译词的关联程度。在自动文摘中采用注意力机制,可以有效缓解长序列经过编码器编码成中间表示时的信息损失问题。 +
    -

    Poj

    +

    序列到序列

      -
    • C++源码
    • -
    • 1062:Dijkstra
    • -
    • 1068:模拟
    • -
    • 1094:拓扑排序
    • -
    • 1328:贪心,换求解变量
    • -
    • 1753:枚举,位运算
    • -
    • 1789:Prim,优先队列
    • -
    • 1860:bellman-ford
    • -
    • 2109:贪心,高精度乘法
    • -
    • 2965:枚举,位运算
    • -
    • 3259:建模,bellman-ford
    • -
    • 3295:模拟,栈
    • +
    • seq2seq模型,即使用一个RNN作为编码器,编码输入的序列数据得到中间语义表示,再利用另外一个RNN作为解码器,利用中间语义表示得到序列化的输出。广义的序列到序列以及端到端学习不一定使用RNN,也可以用CNN或者纯注意力机制。 +
    • +
    • 对于序列到序列模型的一些个人理解: +
        +
      • (信息论)如果不考虑编码器和解码器的具体实现形式,只认为编码器可以将序列数据转化为中间表示,解码器可以将中间表示转化为序列数据,则整个序列到序列模型相当于对文摘信息的一次编码解码,由于中间表示的维度远小于编码器的总维度,因此这种编码是有损编码。序列到序列模型要使得有损编码的结果是提取原文中的文摘信息,因此训练网络的目标是让损失的部分为文摘不需要的冗余信息。解码器相当于编码器的逆过程,从包含文摘信息的中间表示中还原出文摘的序列形式数据。
      • +
      • (学习与应用)将整个模型比作人类的大脑,则编码器的隐藏层状态相当于大脑内存储的知识,解码器则是利用这些知识解决问题,即编码器是一个学习过程而解码器是一个应用过程。这种比喻能够形象地解释后来对序列到序列模型的各种改进:时间步上的学习对应现实时间线上的学习,越早学习的知识在大脑中越容易忘记(靠前的时间步隐藏层信息传递到最终步时信息丢失严重),且大脑的容量一定(中间表示的信息存储容量一定),因此学习时我们选择性记忆和忘记信息(LSTM +和 GRU +的应用),并且在记忆的过程中划重点(注意力机制),甚至还可以借助向外界环境查询信息,不完全靠自己的记忆解决问题(记忆网络)。
      • +
      • (循环神经网络)完全从数据流和网络结构的角度看,整个序列到序列模型可以看作一个长的、限定了某些时间步输入输出的 +RNN,以图 3-1 为例,模型就是一个具有 8 个时间步的 RNN,前 5 +时间步没有输出,后 3 +个时间步将输出传递到下一时间步指导状态变化。编码器和解码器联合训练即相当于对这个大型RNN +进行训练。这种只在部分节点进行输入输出的 RNN +从结构上就适合处理序列到序列任务。
      • +
    -

    校内赛

    +

    序列损失

      -
    • 2017pre
    • -
    • A,集合中找有序三个数,满足和为0,求这些数平方和,Leetcode原题
    • -
    • D,求一个数的连续质数和分解,poj原题,数据大,因此没必要打表,直接对每一个输入判断
    • -
    • F,题目骗人,不需要回溯,递推公式可以写出特征方程求解
    • -
    • G,找一个集合中的最大子集,有绑定规则,选一个数必须选其他几个数,bfs
    • -
    • H,给出字符变换规则和代价,求把两个字符串变成一样的最小代价,flyod,注意两个字母可以变成第三个字母,不一定是互相变,两个字符串可能不等长,不等长直接输出-1
    • -
    • I,高中物理,求重力加速度,方程不好解,二分法逼近答案
    • +
    • 解码器每一步解码出来的实际上时词典的概率分布,取最大概率的词输出(或者做束搜索),损失是每一步的概率和这一步标准词语的01分布做交叉熵,求和再平均。实际上还要应用一个mask来解决句子长度不一定的问题。
    -

    hiho

    +

    基本模型

      -
    • hiho
    • -
    • 1505:给定一个组,问有多少种下标四元组(i, j, p, q)满足i, j, p, -q两两不同,并且i < j, p < q, Ai + Aj = Ap + -Aq。2sum问题,数据范围不大,直接开哈希数组,sum[i]记录两个数之和为i有多少组,利用容斥定理解。
    • -
    • 1506:投掷硬币,投n次m次朝上的概率是多少,每次投正面朝上概率不同。动态规划,记dp[i][j]为投前i次j次朝上的概率,状态转移方程为:dp[i][j]=dp[i-1][j-1]a[i]+dp[i-1][j](1.0-a[i]);a[i]为第i次正面朝上的概率,注意对j=0进行特判。
    • -
    • 1507:错误的记录,给出一棵树,给出根节点编号,在中间加一条错误边,找出所有可能的错误边。注意因为只加了一条错误边,因此情况可以分为两种:1.这条错误边连向根节点,直接输出。2.根节点正常,则这条错误边一定连在入度为2的节点上,且这样的节点只有一个,找到这个节点,将连接它的两条边分别去掉并从根节点开始dfs,如果dfs遍历完次数为n,说明这条边去掉后树依然成立,这是错误边,如果次数小于n,说明去掉这条边树就断了,形成森林,这条边不是错误边。注意边重复的情况,这时候只去掉其中一条,但是两条边是分别当错误边输出。因为错误边数小于等于2,所以dfs的次数小于等于2,加上构造去掉边的图,时间复杂度是O(n)。
    • -
    • 1515:给定一些同学之间的分数关系(A比B高或低多少分),最后对q个查询给出答案。带权并查集,每个集维护同学到这个集某一个根同学的分数差。每次输入一条关系便合并两个同学所在的并查集,并对每个并查集做一次更新,加入y被x合并,x,y之间关系值是s,更新公式是d[root -of -y]=d[x]-d[y]-s,并在下一次循环中更新整个并查集的值。最后直接查询。
    • +
    • 预处理:应用序列到序列模型需要对数据进行一定的预处理,除了常用的去停用词加UNK,以及padding之外,还需要设计解码的开始与结束符号,如下: +
    • +
    • 训练好词嵌入之后,对输入做一个embedding lookup的操作得到特征 i0T6Ej.jpg
    • +
    • 特征输入编码器得到中间表示 i0Tg5n.png
    • +
    • 拿到中间表示和输出文摘(相当于label),输入解码器进行解码 i0TIrF.png
    • +
    • 加入注意力机制后完整的序列到序列模型结构如下: i0TRCq.jpg
    -]]>
    - - 算法 - - - code - python - c++ - algorithm - -
    - - Pandas Basics - /2017/02/04/pandas-skill/ - -

    以泰坦尼克号的数据为例介绍一下前期对数据的基础操作。

    - -

    引入库

    -
    import csv as csv 
    import pandas as pd
    import numpy as np
    -

    读取文件

    -
    train = pd.read_csv(r"文件目录") 
    -

    此时数据的样式是: i0Tn41.jpg

    -

    数据概览

    +

    情感融合机制

      -
    • describe 显示整体数据常见属性
      print(train.describe())
      i0TP3V.jpg
    • -
    • head tail 显示首尾一些数据
      print(train.head(5))
      print(train.tail(3))
      i0TFjU.jpg
    • -
    • index:索引,默认自建整型索引;columns:列;values:数据数值 -
      print(train.index)
      print(train.columns)
      print(train.values)
      # 数据操作
    • -
    • T:数据的转置
      print(train.T)
      i0TAuF.jpg
    • -
    • sort:可以按索引或者值进行排序,axis选择维度(行还是列),ascending选择升序或者降序,Nan永远排在最后,无论升序降序 -
      print(train.sort_index(axis=0,ascending=True))
      print(train.sort_values(by="Age",ascending=False))
    • +
    • 情感机制主要是为文本补充了情感特征,通过查找情感词典的方式手动构造了一个六维的特征,未来希望能够用自动构造特征的方式来进行这方面工作。
    • +
    • 先训练情感分类器,对原语料进行了筛选形成情感语料,在情感语料和普通语料上都测试了模型 +
    • +
    • 查找词典得到情感向量(即情感特征) i0Tf2V.jpg
    • +
    • 将情感特征直接拼接在中间表示之后,输入解码器 i0ThvT.jpg
    -

    数据选择

    +

    结果

      -
    • 按照标签选择,选择列,行切片
      print(train['Age'])
      print(train[0:9])
      i0TVHJ.jpg i0TeE9.jpg
    • -
    • 利用loc自由选择某些行某些列,可以用at替代
      print(train.loc[train.index[4:6]])
      print(train.loc[:,['Age','Fare']])
      print(train.loc[3:5,['Age','Fare']])
      print(train.loc[4,'Age'])
      print(train.at[4,'Age'])
    • -
    • 利用iloc按照位置进行选择
      print(train.iloc[5])
      print(train.iloc[3:5,2:4])
      print(train.iloc[[1,2,4],[2,5]])
      print(train.iloc[3,3])
    • -
    • 布尔选择
      print( train[ (train['Age']>40) & (train['Age']<50) ] )
      print(train[train['Parch'].isin([1,2])])
      print(train[pd.isnull(train['Age'])==True])
      i0TK9x.jpg i0TM36.jpg i0TljO.jpg
    • +
    • 结果由ROUGE-F1值形式记录,情感语料下各种方法对比 i0T5KU.png
    • +
    • 普通语料下情感融合方案对比 i0Tb5R.png
    • +
    • 情感分类准确率,作为参考,之前训练的情感分类器准确率为74% i0Tob4.png
    • +
    • 因为是大语料小batch训练,只训练了十次迭代,各个迭代的测试集效果 i0T7VJ.png
    -

    缺失值处理

    +

    问题

      -
    • 利用reindex选择部分数据进行拷贝,并进行缺失值处理。一些函数会自动过滤掉缺失值,比如mean() -
      train1=train.reindex(index=train.index[0:5],columns=['PassengerId']+['Age']+['Sex'])#选择前5行,只取选定的三列
      print(train1)
      print(train1.dropna(axis=0)) #删除存在nan值的行
      print(train1.dropna(subset=['Age','Sex'])) #删除年龄性别列中存在nan值的行
      print(pd.isnull(train1)) #nan值改为true,其余值改为false
      print(train1.fillna(value=2333)) #缺失值替换为2333
      # 应用函数
    • -
    • 可以自己写函数并应用到数据的行或者列,通过axis参数选择行列 -
      #写函数统计包含nan值的行数
      def null_count(column):
      column_null=pd.isnull(column)
      null=column[column_null == True]
      return len(null)
      print(train.apply(null_count))
      #写函数对年龄列进行分类
      def judge(row):
      if pd.isnull(row['Age']) ==True:
      return 'unknown'
      return 'youngth' if row['Age']<18 else 'adult'
      print(train.apply(judge,axis=1))
      i07jFs.jpg # -数据透视表
    • -
    • 自选分类和值进行数据透视,比如按照pclass和sex分类,统计age和fare的平均值 -
      print(train.pivot_table(index=["Pclass","Sex"], values=["Age", "Fare"], aggfunc=np.mean))
    • +
    • unk替换问题:在很多文献中都提到了使用指针开关技术解决生成文摘中的罕见词(unk),即从原文中挑选词语替换掉文摘中的unk,但是由于ROUGE评测的是词的共现程度,因此只要替换了原文的词,哪怕位置、词语不对,都有可能是ROUGE值上升,造成评测结果偏高,本文设计了对比试验,发现即便是没有采用任何机制的随机替换都能提高ROUGE值 +
    • +
    • 语料重复问题:在检查语料时我们发现了大量短文本不同但短文摘相同的语料,重复的语料来自于对于相同事件的不同描述,或者一些功能性的文字,翻译过来例如“...... +周三...... +黄金价格上涨”和“......周四......黄金价格上涨”均生成相同的文摘“黄金价格上涨”。短文摘重复的语料会导致模型在解码端学到一些不应该固化的短语,而如果训练集和测试集中有重复的相同的文摘,则固化的文摘反而会导致生成文摘正确率虚高。对于这类文本,本文进行了四组实验: +
        +
      • 不去重:保留原文本,不去重,进行训练和测试
      • +
      • 去重:删除语料中所有重复文摘对应的的短文本-短文摘对。
      • +
      • 训练去重:部分去重,只将训练语料中的重复数据删除,即学习好的模型已经没有受到重复文本的影响。
      • +
      • 测试去重:部分去重,只将测试集中与训练集重复的部分删除,学习好的模型受到了重复文本的影响,但测试集中没有与重复文本中相对应的数据。 +重复的语料训练下 ROUGE-1 和 ROUGE-L 都突破了 +30,远超正常训练的模型,去重之后便恢复到正常水平。两种部分去重的结果则分别表明:训练去重时,没有受重复语料影响的模型对于测试集中的重复数据没有明显的反应,与完全去重的普通模型近似;测试去重时,虽然模型受到了重复语料影响,但是测试集中没有重复的数据让其利用学习到的固化的文摘,因此结果也不会虚高,且由于学习到了不同短文对应相同文摘的模式,编码端实际上结构更加灵活,导致 +ROUGE 指标高于训练去重的结果。 i0TLP1.png
      • +
    -

    数据合并

    +

    实现环境

      -
    • 数据合并的一些操作,待补全

      -
      import pandas as pd
      data1 = pd.DataFrame({'level':['a','b','c','d'],
      'numeber':[1,3,5,7]})

      data2=pd.DataFrame({'level':['a','b','c','e'],
      'numeber':[2,3,6,10]})

      print("merge:\n",pd.merge(data1,data2),"\n")

      data3 = pd.DataFrame({'level1':['a','b','c','d'],
      'numeber1':[1,3,5,7]})
      data4 = pd.DataFrame({'level2':['a','b','c','e'],
      'numeber2':[2,3,6,10]})
      print("merge with left_on,right_on: \n",pd.merge(data3,data4,left_on='level1',right_on='level2'),"\n")

      print("concat: \n",pd.concat([data1,data2]),"\n")

      data3 = pd.DataFrame({'level':['a','b','c','d'],
      'numeber1':[1,3,5,np.nan]})
      data4=pd.DataFrame({'level':['a','b','c','e'],
      'numeber2':[2,np.nan,6,10]})
      print("combine: \n",data3.combine_first(data4),"\n")
      -
      -i0T8De.jpg - -
    • +
    • 这里是github地址:- Abstract_Summarization_Tensorflow
    • +
    • Ubuntu 16.04
    • +
    • Tensorflow 1.6
    • +
    • CUDA 9.0
    • +
    • Cudnn 7.1.2
    • +
    • Gigawords数据集,训练了部分数据,约30万
    • +
    • GTX1066,训练时间3到4个小时
    +

    参考文献

    +

    ]]>
    - Python + 自然语言处理 + abstractive summarization machine learning - math - code - python + nlp + seq2seq + rnn + lstm + gru
    - Reformer - Paper Reading - /2020/02/07/reformer/ - Reformer论文解读

    + Statistical Learning - A hand-write note + /2018/08/09/statistical-handwriting/ + +

    把统计学习方法十大算法精简了一些手写了出来(虽然我觉得书本身已经很精简了) +现在只有算法本身的流程,以后如果有什么新的理解再补充 +字太丑,自己都看不下去,发上来纯粹做个备份

    -

    多快好省

    +

    概论

    +
    +i0HLjK.jpg + +
    +
    +i0Hb1x.jpg + +
    +
    +i0HoN9.jpg + +
    +

    感知机

    +
    +i0HH91.jpg + +
    +
    +i0HThR.jpg + +
    +

    k近邻

    +
    +i0Hqc6.jpg + +
    +
    +i0HXnO.jpg + +
    +

    朴素贝叶斯

    +
    +i0HjBD.jpg + +
    +

    决策树

      -
    • 作者主要提出了两点操作来降低Transformer,尤其是在处理超长序列时的内存占用,减少了大量运算,提升了速度。
    • +
    • GBDT写在了提升方法里,另外可以扩展看看随机森林,是一个自举的方法,利用了决策树。 +
    -

    LSH Attention

    -

    39Y8pt.png -- 这一部分最原始的想法就是,Transformer当中的self -attention,每一个token作为query时,要把序列中所有token当成key去计算注意力,再在所有token上加权得到当前token的一个表示,但我们知道注意力一般是非常稀疏的,权重就集中于少数几个token上,那不如只在这几个token上计算权重并加权,这样就大大减少了self -attention里\(O(N^2)\)的计算量和内存占用量。 - -那么怎么才知道那少数几个token是哪几个?假如要完全靠注意力计算出来才能得到的话,怎么可能在计算注意力之前就知道哪几个token权重大?是不可能,但是在self -attention里,query和key计算权重,就是简单的内积,和query相似的key权重大。模型学习到注意力,是指学习到生成正确的query以及key的表示,在计算注意力时只需要比对query和key就可以了。 -- -所以问题转换成,对每一个query,我先找到相近的几个key计算注意力就好了。怎么找?当然不是全部算一遍取top -k,那就与我们减少计算量的初衷相悖,在这里作者用到了Local Sensitive -Hashing(LSH),局部敏感哈希,大意就是相近的向量,映射到同一哈希值的概率较大,多个相近的、映射到同一哈希值的向量相当于装进了同一个桶里(bucket),那么我们只需要对每个桶里的向量计算self -attention。详细一点的描述是,两个向量\(q_1,q_2\),满足LSH的哈希函数\(h\)能做到 \[ - for \ dis(q_1,q_2) <= d_1 , \ p(h(q_1)==h(q_2)) >= p_1 \\ - for \ dis(q_1,q_2) >= d_2 , \ p(h(q_1)==h(q_2)) <= p_2 \\ - \] - 相关领域已经有很多研究,对于不同的距离度量\(dis\),有不同的\(h\)满足LSH。显然在这里我们的距离度量是cosine距离,对应的LSH哈希是球形投影,即将向量投影到一个b维超球面上,该球面被分成了\(n_{buckets}\)个象限,投影到同一象限的向量即在同一个桶中,该投影哈希具体写出来是: -\[ - h(x) = argmax[xR;-xR] \\ - \] \(R\)是一个\([d_k,b/2]\)的随机投影矩阵 - -接下来的一个问题是,一个桶里面,query和key的数量不一定相等,而且有可能一个桶里许多query,没有key。于是作者干脆share -QK,即令query和key相同,都是embedding从同一个线性变换出来的,只不过key做了归一化操作\(k_{j}=\frac{q_{j}}{\left\|q_{j}\right\|}\) -- chunk操作:接下来作者并不是让每个桶里分别做self -attention,而是做了分段,即把同一个桶里的放在一起,重新排成一个序列,然后等长切成若干个段,段内做self -attention,相邻的段也做一次attention。这里其实有点疑问,论文的图画的非常理想,每个桶的大小差不多,可能差了一两个可以通过相邻段做attention来弥补,但是实际情况并不知道每个桶的大小。也许是因为attention本身也是学习出来的,作者这么人为设置,是不是相当于给了一个每个桶大小都趋于相同且等于段长的先验限制了attention的学习。 -- Multi-round -lsh:lsh是讲概率的,有概率就有误差,作者构造了一个巧妙的实验来验证lsh对原始attention的还原度,发现单轮的效果并不好。因此就多次hash来保证概率,取多轮hash的并集来保证相似的向量能落到同一个桶里。这里取并集而不是交集,个人理解是桶一多,hash其实很稀疏,不相似的向量落在同一个桶的概率远小于相似的向量落在不同桶的概率。这里还有一些细节待补充 -- casual -masking:正常的transformer在decoder端是要做时序掩码的,这里lsh把序列顺序打乱了,因此也要做对应的处理,保证时序掩码的正确性。 -- 值得一提的是大部分self -attention的实现,value包括了自身,但是在lsh里不能包含自身,因为key和value共享值,自身永远是最相似的。

    -

    Reversible Transformer

    +
    +i0HvHe.jpg + +
    +
    +i0bP3t.jpg + +
    +
    +i0bSNd.jpg + +
    +

    逻辑斯蒂回归、最大熵

      -
    • 这一部分的想法参照了论文:The Reversible Residual Network: -Backpropagation Without Storing Activations。
    • -
    • 基本思想就是,将残差结构改为可逆残差结构,从而节省了显存。网络在做方向传播的时候,需要存储每一层的激活值,带入自动微分计算每一层的导数,再链式求导,其中存储每一层的激活值占了很大的显存。可逆残差的思想就是,通过将channel一分为二,做成两路,互相残差,更改计算图的拓扑结构,使得两路的激活值能够通过上一层的激活值计算出来,如图:
      -
    • -
    • 前向传播过程为: \[ -\begin{array}{l}{y_{1}=x_{1}+\mathcal{F}\left(x_{2}\right)} \\ -{y_{2}=x_{2}+\mathcal{G}\left(y_{1}\right)}\end{array} -\]
    • -
    • 反向传播为: \[ -\begin{array}{l}{x_{2}=y_{2}-\mathcal{G}\left(y_{1}\right)} \\ -{x_{1}=y_{1}-\mathcal{F}\left(x_{2}\right)}\end{array} -\]
    • -
    • 可以看到计算\(x_2\)时只用了上一层的激活值\(y_1,y_2\),计算\(x_1\)时用了上一步计算出来的\(x_1\),因此不需要存储这两个激活值。虽然节省了空间,但是激活函数需要重新算一遍,相当于用时间换空间。
    • -
    • 原始论文用在resnet里,节约显存可以换得更大的batch_size,在transformer中就可以用来训练更长的sequence
    • -
    • reformer中把两个函数\(\mathcal{F}\)\(\mathcal{G}\)分别改成了自注意力层和全连接层,这样就对应了transformer的可逆结构
    • -
    • 可逆结构虽然消除了层数对于空间复杂度的影响,但是transformer里占显存最大的FFN,其依然受序列长度影响,为了减少这一部分显存占用,作者有一次采用了chunking,因为FFN这里是不存在序列依赖的,完全可以拆成几段计算,相应的,可逆结构的输入输出也拆成几段计算,又一次用时间换空间。此外,对于词典较大的应用场景,作者在计算损失log-probabilities时也是分段的。
    • -
    • 作者还额外提到,这样节省的是反向传播计算梯度时用到的中间临时变量,并不会节省参数量,节省参数量在GPU的消耗可以通过将其转到CPU内存来解决,通常这样的操作得不偿失,因为在CPU和GPU之间传输数据非常耗时,但是由于reformer在每次转换时可以处理更多的数据,就“得能尝失”了。
    • +
    • 待补充最大熵和逻辑斯蒂回归之间的相互推导 i0bigP.jpg
    • +
    +
    +i0bp4A.jpg + +
    +

    支持向量机

    +
    +i0bFjf.jpg + +
    +
    +i0bAu8.jpg + +
    +
    +i0bEDS.jpg + +
    +
    +i0beEQ.jpg + +
    +
    +i0bVHg.jpg + +
    +
    +i0bmNj.jpg + +
    +

    提升方法

    +
      +
    • 待补充XGBoost
    • +
    +
    +i0bKCn.jpg + +
    +

    EM算法

    +
    +i0bM3q.jpg + +
    +
    +i0bQg0.jpg + +
    +
      +
    • 用EM算法做高斯混合模型的推断时,需要推断的参数包括k个高斯模型的均值、方差、比例系数,隐变量代表第j个观测样本来自第k个高斯模型的可能,叫做responsibility,而\(n_k\)则是对第k个高斯模型在所有样本上的responsibility的总和,除以\(N\)即以其均值来更新GMM比例系数,用responsibility加权样本来更新均值,方差同理。
    • +
    • 在更新完参数之后,再用这些参数重新计算responsibility,重新计算E步骤,再继续做M步骤,从而完成迭代。
    • +
    +

    隐马尔可夫

    +
    +i0b3uT.jpg + +
    +
    +i0blvV.jpg + +
    +
    +i0b8DU.jpg + +
    +
    +i0bGbF.jpg + +
    +

    条件随机场

    +
      +
    • 待补充三种问题的解法,因为条件随机场是隐马尔可夫模型的条件化扩展,算法也类似 +
    ]]>
    - 自然语言处理 + 机器学习 - deep learning - natural language processing - local sensitive hashing - transformer + math + machine learning + code + statistical learning
    @@ -12137,160 +12739,6 @@ href="https://github.com/coneycode/hexo-git-backup">hexo-git-backup github - - Statistical Learning - A hand-write note - /2018/08/09/statistical-handwriting/ - -

    把统计学习方法十大算法精简了一些手写了出来(虽然我觉得书本身已经很精简了) -现在只有算法本身的流程,以后如果有什么新的理解再补充 -字太丑,自己都看不下去,发上来纯粹做个备份

    - -

    概论

    -
    -i0HLjK.jpg - -
    -
    -i0Hb1x.jpg - -
    -
    -i0HoN9.jpg - -
    -

    感知机

    -
    -i0HH91.jpg - -
    -
    -i0HThR.jpg - -
    -

    k近邻

    -
    -i0Hqc6.jpg - -
    -
    -i0HXnO.jpg - -
    -

    朴素贝叶斯

    -
    -i0HjBD.jpg - -
    -

    决策树

    -
      -
    • GBDT写在了提升方法里,另外可以扩展看看随机森林,是一个自举的方法,利用了决策树。 -
    • -
    -
    -i0HvHe.jpg - -
    -
    -i0bP3t.jpg - -
    -
    -i0bSNd.jpg - -
    -

    逻辑斯蒂回归、最大熵

    -
      -
    • 待补充最大熵和逻辑斯蒂回归之间的相互推导 i0bigP.jpg
    • -
    -
    -i0bp4A.jpg - -
    -

    支持向量机

    -
    -i0bFjf.jpg - -
    -
    -i0bAu8.jpg - -
    -
    -i0bEDS.jpg - -
    -
    -i0beEQ.jpg - -
    -
    -i0bVHg.jpg - -
    -
    -i0bmNj.jpg - -
    -

    提升方法

    -
      -
    • 待补充XGBoost
    • -
    -
    -i0bKCn.jpg - -
    -

    EM算法

    -
    -i0bM3q.jpg - -
    -
    -i0bQg0.jpg - -
    -
      -
    • 用EM算法做高斯混合模型的推断时,需要推断的参数包括k个高斯模型的均值、方差、比例系数,隐变量代表第j个观测样本来自第k个高斯模型的可能,叫做responsibility,而\(n_k\)则是对第k个高斯模型在所有样本上的responsibility的总和,除以\(N\)即以其均值来更新GMM比例系数,用responsibility加权样本来更新均值,方差同理。
    • -
    • 在更新完参数之后,再用这些参数重新计算responsibility,重新计算E步骤,再继续做M步骤,从而完成迭代。
    • -
    -

    隐马尔可夫

    -
    -i0b3uT.jpg - -
    -
    -i0blvV.jpg - -
    -
    -i0b8DU.jpg - -
    -
    -i0bGbF.jpg - -
    -

    条件随机场

    -
      -
    • 待补充三种问题的解法,因为条件随机场是隐马尔可夫模型的条件化扩展,算法也类似 -
    • -
    -]]>
    - - 机器学习 - - - machine learning - math - code - statistical learning - -
    Structured Neural Summarization, Paper Reading /2020/02/28/structured-summarization/ @@ -12604,80 +13052,36 @@ class="math inline">\(b\)代表偏置,由支持向量决定,因此那 class="math inline">\(\alpha _j\)不为0对应的 \[ \tilde{y}_{i}\left(\overrightarrow{\mathbf{w}}^{*} \cdot -\overrightarrow{\mathbf{x}}_{i}+b^{*}\right)-1 -\] 决定了\(b\)(因为\(\alpha\)不为0,由松弛互补条件,则后一项为0,就可以求得\(b\))。最后得到: \[ -b^{*}=\tilde{y}_{j}-\sum_{i=1}^{N} \alpha_{i}^{*} -\tilde{y}_{i}\left(\overrightarrow{\mathrm{x}}_{i} \cdot -\overrightarrow{\mathrm{x}}_{j}\right) -\] 可以看到,\(w,b\)都是求和的形式,但大部分为0,只有不为0的\(\alpha\)(在\(b\)的表达式里直接找出不为0的记为\(\alpha -_j\))项才起作用,即支持向量机只有少数的支持向量决定。 -
  • 因此,给定数据,先求得对偶问题极大值,得到\(\alpha\),再由\(\alpha\)中不为0的部分计算出\(w,b\),得到超平面。
  • -
  • 软间隔和非线性支持向量机的定义和求解过程类似,只不过约束条件和目标函数不同。
  • -
  • \(\alpha\)的求解涉及凸二次规划,有很多解法。支持向量机的一个优点就是学习到的参数只依赖支持向量,推理时避免了维度灾难,但是在学习的过程中,需要对所有样本计算最优化,因此对于大规模数据不友好,这里可以用SMO算法来优化
  • - -]]> - - 自然语言处理 - - - machine learning - math - svm - -
    - - Trie in Python - /2017/05/02/trie/ - -

    在Python中有字典这一数据结构,因此用Python实现字典树很方便

    - -
    -i07rz6.jpg - -
    -

    字典树(trie)

    -
      -
    • 字典树主要用于词频统计,前缀后缀相关的算法,树的根节点不存任何字符,每一条边代表一个字符,其他每一个节点代表从根节点到此节点的所有边上字符构成的单词,存的内容根据需求而定。
    • -
    • 字典树快的原因就是充分利用的单词的共同前缀,如果前缀都不一样,就不需要继续查找
    • -
    • 一个单词不一定在叶子节点,因为它可能构成其他更长单词的前缀,因此如果用于词频统计,则可以插入完一个单词后在此单词最后一个节点中count++。如果仅仅用于判断某个词是否在字典树构成的字典中,则可以在插入完一个单词后,在最后一个节点中添加一个None节点,内容为单词本身
    • -
    -

    例子

    -
      -
    • 以leetcode472为例,当中需要判断某个序列中某个单词是否能由它前面的单词构成
    • -
    • 初始化trie
      trie = {}
    • -
    • trie中插入单词
      def insert(trie, w):
      for c in w:
      trie = trie.setdefault(c, {}) # if c not in trie then set trie[c]={}
      trie[None] = w
      -对每一个字符串,依次按字母索引,当索引不到时就对当前字母建立新节点 -遍历完单词后建立None节点存放单词(因为题目需要返回所有单词,因此此处存放单词,也可以存放出现次数 -这样一棵树最终完成时就如标题图所示,其中前四行是加入["cat", -"cats","dog", "rat"]之后树的内容
    • -
    • trie中查找某一个单词
      def prefixs(trie, w, lo):
      for i in range(lo, len(w)):
      trie = trie.get(w[i])
      if trie is None:
      break
      prefix = trie.get(None)
      if prefix:
      yield i + 1, prefix
      -因为题目需要,利用了生成器,这段函数是查找单词w中i从lo位置开始,i到单词尾这一段构成的字符串,是否在trie的字典集合中,返回所有符合结果的i+1。查找的方式与插入相同 -特别说明的是,trie的一大优势便是支持插入与查找同时进行
    • -
    -

    后缀树

    -
      -
    • 如果将一个单词,长度为l,拆分成l个子单词插入到trie中,每个子单词都是这个单词的[i:l]构成的后缀,则这样的字典树称之为后缀树。
    • -
    • 简单按上述方法建立后缀树会存在许多冗余信息,在空间上还可以进行优化
    • -
    • 待续
    • +\overrightarrow{\mathbf{x}}_{i}+b^{*}\right)-1 +\] 决定了\(b\)(因为\(\alpha\)不为0,由松弛互补条件,则后一项为0,就可以求得\(b\))。最后得到: \[ +b^{*}=\tilde{y}_{j}-\sum_{i=1}^{N} \alpha_{i}^{*} +\tilde{y}_{i}\left(\overrightarrow{\mathrm{x}}_{i} \cdot +\overrightarrow{\mathrm{x}}_{j}\right) +\] 可以看到,\(w,b\)都是求和的形式,但大部分为0,只有不为0的\(\alpha\)(在\(b\)的表达式里直接找出不为0的记为\(\alpha +_j\))项才起作用,即支持向量机只有少数的支持向量决定。 +
    • 因此,给定数据,先求得对偶问题极大值,得到\(\alpha\),再由\(\alpha\)中不为0的部分计算出\(w,b\),得到超平面。
    • +
    • 软间隔和非线性支持向量机的定义和求解过程类似,只不过约束条件和目标函数不同。
    • +
    • \(\alpha\)的求解涉及凸二次规划,有很多解法。支持向量机的一个优点就是学习到的参数只依赖支持向量,推理时避免了维度灾难,但是在学习的过程中,需要对所有样本计算最优化,因此对于大规模数据不友好,这里可以用SMO算法来优化
    ]]>
    - Python + 自然语言处理 - code - python + math + machine learning + svm
    @@ -12840,698 +13244,487 @@ exit就能取得较好效果,相比取用第六层,BLEU降低0.4,换来加

    EditNTS

      -
    • 提出了一个句子简化模型,显式地执行三类操作:插入、删除、保留
    • -
    • 与LevT不同的是,EditNTS依然是自回归的,并没有同时对整句操作,并且在预测操作时引入了更多的信息
    • -
    • 模型包含两部分:基于LSTM的seq2seq作为programmer,预测每个token位置的操作,产生编辑操作序列;以及一个额外的interpreter来执行操作生成编辑后的句子,这个interpreter还包含一个简单的LSTM来汇总编辑后句子的上下文信息 -
    • -
    • 值得注意的有三点: -
        -
      • 预测出删除和保留后,programmer就移动到下一个单词,而预测出插入操作时,programmer不移动单词,接着在这个单词上预测下一个操作,来满足插入多个词的场景
      • -
      • interpreter除了根据programmer预测结果完成编辑外,还用了一个LSTM来汇总当前时间步的编辑后句子信息
      • -
      • programmer在预测编辑操作时,用到了四部分信息: -
          -
        • encoder的context,来自encoder lstm last layer attention-weighted -output
        • -
        • 当前操作的词,来自decoder lstm hidden state
        • -
        • 已经编辑好的句子的context,来自interpreter lstm attention-weighted -output
        • -
        • 已经产生的编辑操作序列,来自attention-weighted edit label -output,这里只用了简单的attention,没有用lstm
        • -
      • -
    • -
    • encoder输入还额外引入了pos embedding
    • -
    • 标签构造,类似LevT,需要在句子简化数据集上构建出ground -truth编辑操作,依然是基于编辑距离的动态规划得到操作序列,当多个操作序列存在时,优先选择插入序列多的,作者尝试过其他优先方式(优先删除、随机、引入替换操作),效果均不如直接优先插入。
    • -
    • 使用100维的glove向量来初始化词向量和编辑label -embedding,用30维向量初始化pos -embedding,使用编辑标签逆频次作为损失权重来平衡各个标签的损失占比。
    • -
    • 结果并不是很优秀,在指标上没有比非编辑方法好,在人类评估上好一些但存在主观性。消融也不是很显著。
    • -
    -

    LaserTagger

    -
      -
    • 依然是保留、删除、插入三种操作,不过用上了BERT,且google的工程能力使得加速比达到了100-200倍
    • -
    • 贡献点 -
        -
      • 提出了模型,并提出了从数据中生成标签词典的方法
      • -
      • 提出了基于BERT的和用BERT初始化seq2seq -encoder的两个版本,前者加速快,后者效果好
      • -
    • -
    -

    Text Editing as Tagging

    -
      -
    • LaserTagger将文本编辑问题转换为序列标注问题,主要包含三部分 -
        -
      • 标注操作:将编辑转化标注,其标签并不是保留删除插入三种,而是分为两部分:base -tag B,有保留和删除两种;added phrase -P,有V种,代表插入的片段(空白、词或者短语),从训练数据中构建一个P -vocabulary得到,P和B组合得到标签,因此标签总共有2V种。可以根据下游人物添加任务相关的标签。
      • -
      • added phrase -vocabulary构建:构建词典是一个组合优化问题,一方面我们希望这个词典尽可能小,另一方面我们希望这个词袋能够覆盖最多的编辑情况,完美的解决该问题是NP-hard的,作者采用了另外一种方式。对每个训练文本对,通过动态规划求出最长公共子序列,用目标序列减去最长公共子序列就得到了需要添加的phrase,之后对phrase按照出现频次排序,取top -k,在公开数据集上top 500就能覆盖85%的数据。
      • -
      • 构建标注序列:直接见伪算法,这里不需要动态规划,而是采取了一种贪心的方式,逐字匹配,找最短phrase插入 -gdxc0x.png -这样可能会出现不能编辑的情况,这种情况就从训练集中筛去,作者认为这样也可以看成是一种降噪。
      • -
      • 根据预测结果编辑句子:就是直接操作,可能根据下游任务预测出特别的标签进行任务相关的操作。作者认为将编辑操作模块化出来比直接端到端要更灵活。
      • -
    • -
    -

    实验

    -
      -
    • 模型有两种,直接用BERT做标注或者用一个seq2seq,encoder用BERT初始化,前者的话就是在BERT最后一层是再加一层transformer -block做标注。
    • -
    • 四项任务,句子融合,分句与转述,摘要,语法纠错。均超过baseline,其中句子融合取得新的SOTA。但是LaserTagger最亮眼的表现在于其效率,只用BERT -encoder能达到最高200倍的加速比(毕竟把文本生成变成了一个小词典的序列标注),同时对于小样本学习非常友好。
    • -
    • 作者还分析了seq2seq和基于编辑的模型常出现的问题及其原因、两者的优势等等 -
        -
      • 想象词:seq2seq会在subword粒度上组合生成不存在的词,LaserTagger不存在这种情况
      • -
      • 过早结束:seq2seq可能很早生成EOS导致句子不完整或者过短,而LaserTagger理论上存在这种可能,实际上作者没有见到过,因为这意味着模型要预测出一堆删除操作,而这在训练数据中是几乎没有的。
      • -
      • 重复短语:在分句任务中,seq2seq经常会重复生成短语,而LaserTagger会选择不分句,或者lazy -split
      • -
      • Hallucination:即生成的文本与源文本无关或者反常识反事实,两类模型都会出现这类问题,seq2seq可能隐藏的更深(看起来流畅,实际上不合理)
      • -
      • 共指消解:两类模型都存在这种问题,seq2seq容易将代词替换为错误名词,LaserTagger容易保留代词不管
      • -
      • 错误删除:LaserTagger看似文本生成较为可控,但任然存在一些情况,即模型删除了部分词,剩下句子语义流畅,但含义错误
      • -
      • lazy -split:在分句任务中,LasterTagger可能只分句,而不对分开的句子做任何后处理。
      • -
    • -
    -

    PIE

    -
      -
    • 也是BERT+序列标注,同时从数据中构造phrase词典
    • -
    • 编辑操作包括复制(保留)、插入、删除、词形变换(用于语法纠错)
    • -
    • 构造phrase词典、构造ground truth编辑操作和LaserTagger基本一致
    • -
    • 将BERT左右扩展了两部分来获得替换或者增加所需的信息: -
        -
      • 输入层,M为mask标识符的embedding,p为positional embedding,X为word -embedding
      • -
      • h即原始BERT信息,包含词和位置信息
      • -
      • r即替换信息,只不过把当前位置的词mask掉,用M替代,且计算注意力时不查询当前位置的h
      • -
      • a即插入信息,只不过把当前位置的词mask掉,用M替代,且p替换为相邻位置p的平均 -
      • -
      • 之后利用三类信息来分别计算不同操作的概率,并归一化,CARDT分别代表复制(保留)、插入、替换、删除、词形变换 -
      • -
      • 上式第一项是每一项编辑操作的得分;第二项是保留当前词的得分,删除和替换不得分,其余的则用当前词embedding -\(\phi(x_i)\)来参数化得分,这里\(\phi\)的意义不明,原文是Embedding of w, -represented by \(\phi(w)\) is obtained -by summing up in-dividual output embeddings of tokens in -w;第三项是新词带来的影响,只有替换和插入有。
      • -
    • -
    • 推断时也是多轮推断(输出变输入),直到出现重复句子
    • -
    • 这里编辑操作设计的动机和解释不是很清楚,最终结果也很一般,ensemble情况下才与Transformer -+ Pre-training + LM+ Spellcheck + Ensemble Decoding -的工作持平,而且从消融来看,预训练模型是带来性能提升的主要原因。
    • -
    -

    Felix

    -
      -
    • 将编辑操作分为两个非自回归的部分,首先用一个基于Transformer的指针网络做tagging和reordering,并插入placeholder;然后用一个MLM对placeholder做预测
    • -
    • Felix的设计考虑三点需求 -
        -
      • 灵活的编辑,适合多种文本生成任务
      • -
      • 充分利用BERT等预训练模型
      • -
      • 高效推断
      • -
    • -
    • 下图可以清晰的表示出Felix的标签设计,其中yt是tagging模型需要预测出的编辑操作序列,ym是根据编辑操作序列,添加相关special -token(REPL,MASK)之后的中间状态序列,中间状态序列直接喂给MLM来预测需要插入的词,最终得到Pred里的结果
    • -
    • -
    • 这里需要注意两点: -
        -
      • MLM虽然只完成插入词的预测,但也需要完整的编辑操作信息,而不是输入MLM时直接把预测删除操作位置的词删掉,这里作者的做法是用REPL括起来要删除的span,给MLM也提供了删除编辑的信息。
      • -
      • 图中给出了Mask和Infill两种形式,其实就是对中间状态序列的MASK设计不同,涉及到多token插入的任务交给谁:Mask方式里是把任务交给了tagging模型,直接预测出插入多个词的编辑操作,例如\(DEL^{INS\_2}\),即插入两个,对应的就在中间序列中生成两个MASK让模型预测;Infill方式里把这个任务交给了MLM,统一对每个插入位置准备四个MASK让模型预测,多了的部分就预测PAD
      • -
    • -
    • 为了更灵活的建模,tagging部分的模型还需要做reordering,不然交互两个词的位置就得先删再添加,增加了复杂度。这里是通过指针网络注意力来为每个词确定其指向的后一个词,第一个词由特殊标识CLS指示。在推断时,使用了受控的beam -search避免指向顺序产生循环。
    • -
    • 主要与LaserTagger对比,在性能,小样本上的表现要优于LaserTagger,且没有了phrase -vocabulary的限制。作者也就phrase -vocabulary和reordering做了实验,结果很多可见原论文。
    • -
    -

    总结

    -
      -
    • 总结各个模型

      - --------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      模型编辑操作加速插入多个词构建ground truth编辑序列编辑失败测试任务
      LevT插入删除多轮非自回归,5倍先预测placeholder数量,再替换基于编辑距离动态规划退化为文本生成翻译、摘要
      EditNTS插入删除保留自回归,未提及加速插入时原地停留,直到插入完毕基于编辑距离动态规划退化为文本生成文本简化
      LaserTagger插入删除保留一轮序列标注,100+倍直接插入phrase,根据训练数据构建phrase词典贪心匹配不编辑句子融合,分句与转述,摘要,语法纠错
      PIE插入删除替换复制词形变换序列标注,2倍直接插入phrase,根据训练数据构建phrase词典贪心匹配未说明语法纠错
      Felix删除插入保留重排序标注+MLM,快于LaserTagger设置多个Mask让MLM预测简单比较较差的MLM预测结果句子融合、机器翻译后处理、摘要、文本简化
    • -
    -]]> - - 自然语言处理 - - - machine learning - math - theory - nlp - seq2seq - -
    - - Note for Variational Auto-Encoder - /2019/03/20/vae/ - +
  • 提出了一个句子简化模型,显式地执行三类操作:插入、删除、保留
  • +
  • 与LevT不同的是,EditNTS依然是自回归的,并没有同时对整句操作,并且在预测操作时引入了更多的信息
  • +
  • 模型包含两部分:基于LSTM的seq2seq作为programmer,预测每个token位置的操作,产生编辑操作序列;以及一个额外的interpreter来执行操作生成编辑后的句子,这个interpreter还包含一个简单的LSTM来汇总编辑后句子的上下文信息 +
  • +
  • 值得注意的有三点:
      -
    • 变分自编码器学习笔记
    • -
    • 参考文章: +
    • 预测出删除和保留后,programmer就移动到下一个单词,而预测出插入操作时,programmer不移动单词,接着在这个单词上预测下一个操作,来满足插入多个词的场景
    • +
    • interpreter除了根据programmer预测结果完成编辑外,还用了一个LSTM来汇总当前时间步的编辑后句子信息
    • +
    • programmer在预测编辑操作时,用到了四部分信息:
    • -
    • 关于VAE,上面的原论文以及两篇博客已经讲的很清楚了,我写也就是复读转述,自己捋一遍,如果有人看到这篇博客,建议优先读这三个参考来源 -
    • +
  • +
  • encoder输入还额外引入了pos embedding
  • +
  • 标签构造,类似LevT,需要在句子简化数据集上构建出ground +truth编辑操作,依然是基于编辑距离的动态规划得到操作序列,当多个操作序列存在时,优先选择插入序列多的,作者尝试过其他优先方式(优先删除、随机、引入替换操作),效果均不如直接优先插入。
  • +
  • 使用100维的glove向量来初始化词向量和编辑label +embedding,用30维向量初始化pos +embedding,使用编辑标签逆频次作为损失权重来平衡各个标签的损失占比。
  • +
  • 结果并不是很优秀,在指标上没有比非编辑方法好,在人类评估上好一些但存在主观性。消融也不是很显著。
  • -

    直接看网络结构

    +

    LaserTagger

      -
    • 变分自编码器用了变分推断,但是因为其中的参数估计部分用的是神经网络的梯度下降方法,因此可以直接画出其网络结构——实际上我们称其为自编码器,也是因为其结构上和自编码器有许多相通之处,如果不从贝叶斯的角度出发,甚至可以将VAE直接看成一类特殊的自编码器。
    • -
    • 以原论文的mnist实验为例,我们直接看VAE的网络结构,之后再一般化模型并解释细节: +
    • 依然是保留、删除、插入三种操作,不过用上了BERT,且google的工程能力使得加速比达到了100-200倍
    • +
    • 贡献点
        -
      • 整体和自编码器一样,一个encoder和一个decoder,目标是重构误差,获取有用的编码
      • -
      • 然而变分自编码器不对输入直接编码,而是假定编码服从多维正态分布,encoder编码的是这个多维正态分布的均值和方差
      • -
      • 也就是VAE假定编码很简单,就是服从正态分布,而我要训练出来并利用的是解码,这个解码器能从正态分布的采样中解码还原出输入,或者说,生成输出
      • +
      • 提出了模型,并提出了从数据中生成标签词典的方法
      • +
      • 提出了基于BERT的和用BERT初始化seq2seq +encoder的两个版本,前者加速快,后者效果好
    • -
    • mnist的输入为28*28,batch_size为128,假定隐层dim为200,参数dim为10,则整个网络为:
    -
      -
    1. 输入\(x\)[128,28*28],过一个linear+ReLu,得到编码器隐层\(h\)[128,200]
    2. -
    3. \(h\)分别过两个linear,得到正态分布的参数\(\mu _e\)[128,10],\(\log \sigma _e\)[128,10]
    4. -
    5. 从一个标准多维正态分布中采样\(\epsilon -\sim N(0,I)\),得到\(\epsilon\)[128,10]
    6. -
    7. 组合通过网络得到的参数\(\mu -_e\)\(\log \sigma -_e\)到标准多维正态分布的采样值中,\(z = -\mu _e + \sigma _e \bigodot \epsilon\)[128,10],\(z\)即编码
    8. -
    9. encoder部分就此完成,接下来是decoder部分:编码\(z\)过linear+ReLu得到解码隐层状态h[128,200]
    10. -
    11. 解码隐层状态h经过linear+sigmoid得到\(\mu -_d\)[128,28*28],即解码后的输出
    12. -
    13. 解码后输出\(\mu _d\)与输入\(x\)计算伯努利交叉熵损失
    14. -
    15. 此外还要加上一个类似正则项的损失\(\frac 12 -\sum _{i=1}^{10} (\sigma _{ei}^2 + \mu _{ei}^2 -log(\sigma _{ei}^2) - -1)\)
    16. -
    -

    直接对网络分析

    +

    Text Editing as Tagging

      -
    • 从网络可以看到,VAE相比AE最大的区别就是不直接对输入编码,而是将概率的思想引入了网络结构,对每一个输入单独构建一个满足多维正态分布的编码
    • -
    • 这么做的一个好处是,编码可以做插值,实现生成图像连续的变化:原始的AE对于每一个确定输入有确定的编码,而VAE中的网络只负责生成确定的均值和方差,也就是确定的正态分布,实际的编码只是在这个确定的正态分布中采样得到,依然是不确定的。在训练过程中VAE是对一片区域进行训练,而不是点训练,因此得到的编码具有连续性,在区域中心点附近也能生成相似的图像,甚至可以在两类图像输入确定的两个编码区域之间插值,实现两种生成图像的平滑过渡。
    • -
    • 步骤1,2,3,4实现的是编码器从一个\(N(\mu -_e,\sigma _e -^2)\)的分布中采样得到编码,然而这里存在一个reparameterization的技巧,即: +
    • LaserTagger将文本编辑问题转换为序列标注问题,主要包含三部分
        -
      • 本来应该是让编码器神经网络拟合一个满足\(N(\mu _e,\sigma _e -^2)\)的分布,再从分布中采样
      • -
      • 但是采样得到的值无法进行反向传播
      • -
      • 因此改成神经网络只拟合分布的参数,然后从一个简单的标准多维正态分布中采样,采样值经过拟合参数处理,即\(z = \mu _e + \sigma _e \bigodot -\epsilon\),来达到\(z\)仿佛直接从\(N(\mu _e,\sigma _e -^2)\)采样得到的效果,而神经网络仅仅拟合参数,可以进行反向传播,采样在其中相当于做了一些指定权值的加权,参与进网络的训练
      • +
      • 标注操作:将编辑转化标注,其标签并不是保留删除插入三种,而是分为两部分:base +tag B,有保留和删除两种;added phrase +P,有V种,代表插入的片段(空白、词或者短语),从训练数据中构建一个P +vocabulary得到,P和B组合得到标签,因此标签总共有2V种。可以根据下游人物添加任务相关的标签。
      • +
      • added phrase +vocabulary构建:构建词典是一个组合优化问题,一方面我们希望这个词典尽可能小,另一方面我们希望这个词袋能够覆盖最多的编辑情况,完美的解决该问题是NP-hard的,作者采用了另外一种方式。对每个训练文本对,通过动态规划求出最长公共子序列,用目标序列减去最长公共子序列就得到了需要添加的phrase,之后对phrase按照出现频次排序,取top +k,在公开数据集上top 500就能覆盖85%的数据。
      • +
      • 构建标注序列:直接见伪算法,这里不需要动态规划,而是采取了一种贪心的方式,逐字匹配,找最短phrase插入 +gdxc0x.png +这样可能会出现不能编辑的情况,这种情况就从训练集中筛去,作者认为这样也可以看成是一种降噪。
      • +
      • 根据预测结果编辑句子:就是直接操作,可能根据下游任务预测出特别的标签进行任务相关的操作。作者认为将编辑操作模块化出来比直接端到端要更灵活。
    • -
    • 步骤5,6,7则是普通的解码,因为输出是28*28的黑白图像,因此直接解码成28*28的二值向量,与输入比对计算交叉熵
    • -
    • 关键是8,这个正则项如何得到?
    -

    正则项

    +

    实验

      -
    • 这个正则项实际上是编码得到的正态分布和标准正态分布之间的KL散度,即(其中K是多维正态分布的维度,在上例中是10): -\[ -KL(N(\mu _e,\sigma _e ^2)||N(0,I)) = \frac 12 \sum _{i=1}^{K} (\sigma -_{ei}^2 + \mu _{ei}^2 -log(\sigma _{ei}^2) - 1) -\]
    • -
    • 也就是说,我们希望编码的正态分布接近标准正态分布,为什么?
    • -
    • 这里就有很多种说法了: +
    • 模型有两种,直接用BERT做标注或者用一个seq2seq,encoder用BERT初始化,前者的话就是在BERT最后一层是再加一层transformer +block做标注。
    • +
    • 四项任务,句子融合,分句与转述,摘要,语法纠错。均超过baseline,其中句子融合取得新的SOTA。但是LaserTagger最亮眼的表现在于其效率,只用BERT +encoder能达到最高200倍的加速比(毕竟把文本生成变成了一个小词典的序列标注),同时对于小样本学习非常友好。
    • +
    • 作者还分析了seq2seq和基于编辑的模型常出现的问题及其原因、两者的优势等等
        -
      • 第一种:我们希望的是对于不同类的输入,编码能编码到同一个大区域,即不同区域内部紧凑的同时,区域之间的距离也不应该太远,最好能体现图像特征上的距离,比如以mnist为例,4和9的图像比较近似,和0的图像差异比较大,则他们的编码区域之间的距离能反映相似的关系;或者说从0变到8的过程中中间状态会像9,那么9的编码区域能在0和8的编码区域之间最好。然而实际上是,编码器网络可能会学到这样的编码方法:对于不同类的输入,\(\mu\)相差很大,它将不同类输入(准确的说是不近似的输入,这里是无监督学习,没有类别)的编码区域隔得很开。神经网络这么做是有道理的:让解码器方便区别不同的输入进行解码。这就与我们希望它编码成连续区域方便插值的初衷相悖,因此我们强制希望所学到的编码分布都近似标准正态分布,这样都在一个大区域中,当然也不能太近似,不然大家都一样,解码器负担太大,根本解码不出来区别,这就是前面的重构损失的作用。
      • -
      • 第二种:VAE的效果相当于在标准的自编码器中加入了高斯噪声,使得decoder对噪声具有鲁棒性。KL散度的大小代表了噪声的强弱:KL散度小,噪声越贴近标准高斯噪声,即强度大;KL散度大,噪声强度就小,这里理解为噪声被同化了,而不是说方差变小了,因为噪声应该与输入信号无关,一直保持高斯噪声或者其他指定的分布,如果噪声变得和指定分布越来越远,和输入越来越相关,那其作为噪声的作用也就越来越小了。
      • -
      • 第三种:也是最严谨的一种理解,这个KL散度是从变分推断的角度出发得到的,整个模型也是从贝叶斯框架推理得到的。其之所以有网络结构是因为作者用了神经网络来拟合参数,神经网络的超参、分布的指定也是该框架在mnist生成任务中的一种特例,毕竟原文叫自编码变分贝叶斯(一种方法),而不是变分自编码网络(一种结构)。接下来我们从原论文的角度来看看整个模型如何推导出来,并自然而然得到这个KL散度正则项。
      • +
      • 想象词:seq2seq会在subword粒度上组合生成不存在的词,LaserTagger不存在这种情况
      • +
      • 过早结束:seq2seq可能很早生成EOS导致句子不完整或者过短,而LaserTagger理论上存在这种可能,实际上作者没有见到过,因为这意味着模型要预测出一堆删除操作,而这在训练数据中是几乎没有的。
      • +
      • 重复短语:在分句任务中,seq2seq经常会重复生成短语,而LaserTagger会选择不分句,或者lazy +split
      • +
      • Hallucination:即生成的文本与源文本无关或者反常识反事实,两类模型都会出现这类问题,seq2seq可能隐藏的更深(看起来流畅,实际上不合理)
      • +
      • 共指消解:两类模型都存在这种问题,seq2seq容易将代词替换为错误名词,LaserTagger容易保留代词不管
      • +
      • 错误删除:LaserTagger看似文本生成较为可控,但任然存在一些情况,即模型删除了部分词,剩下句子语义流畅,但含义错误
      • +
      • lazy +split:在分句任务中,LasterTagger可能只分句,而不对分开的句子做任何后处理。
    -

    变分自编码贝叶斯

    +

    PIE

      -
    • 整个解码器部分我们可以看成一个生成模型,其概率图为: AKu5FA.png
    • -
    • \(z\)即编码,\(\theta\)是我们希望得到的解码器参数,控制解码器从编码中解码出(生成出)\(x\)
    • -
    • 现在问题回归到概率图模型的推断:已知观测变量x,怎么得到参数\(\theta\)
    • -
    • 作者采取的思路并不是完全照搬变分推断,在VAE中也采用了\(q\)分布来近似后验分布\(p(z|x)\),并将观测量的对数似然拆分成ELBO和KL(q||p(z|x)),不同的是变分推断中用EM的方式得到q,而在VAE中用神经网络的方式拟合q(神经网络输入为\(z\),因此\(q\)本身也是后验分布\(q(z|x)\)。完整写下来: \[ -\log p(x|\theta) = \log p(x,z|\theta) - \log p(z|x,\theta) \\ -\] \[ -= \log \frac{p(x,z|\theta)}{q(z|x,\phi)} - \log -\frac{p(z|x,\theta)}{q(z|x,\phi)} \\ -\] \[ -= \log p(x,z|\theta) - \log q(z|x,\phi) - \log -\frac{p(z|x,\theta)}{q(z|x,\phi)} \\ -\] \[ -= [ \int _z q(z|x,\phi) \log p(x,z|\theta)dz - \int _z q(z|x,\phi) \log -q(z|x,\phi)dz ] + [- \int _z \log \frac{p(z|x,\theta)}{q(z|x,\phi)} -q(z|x,\phi) dz ]\\ -\]
    • -
    • 注意,我们实际希望得到的是使得观测量对数似然最大的参数\(\theta\)\(\phi\),而隐变量\(z\)可以在输入确定的情况下随模型得到。
    • -
    • 可以看到,在观测量即对数似然确定的情况下,前一个中括号内即ELBO值越大,则后面的KL散度,即后验\(q(z|x,\phi)\)分布和后验真实分布\(p(z|x,\theta)\)越相近。这个后验分布,即已知\(x\)得到\(z\)实际上就是编码器,因此这个KL散度越小则编码器效果越好,既然如此我们就应该最大化ELBO,ELBO可以改写成: -\[ -ELBO = \int _z q(z|x,\phi) \log p(x,z|\theta)dz - \int _z q(z|x,\phi) -\log q(z|x,\phi)dz \\ -\] \[ -= E_{q(z|x,\phi)}[\log p(x,z|\theta)-\log q(z|x,\phi)] \\ -\] \[ -= E_{q(z|x,\phi)}[\log p(x|z,\theta)]-KL(q(z|x,\phi)||(p(z|\theta))) \\ -\]
    • -
    • 又出现了一个KL散度!这个KL散度是编码器编码出的隐变量后验分布和隐变量先验分布之间的KL散度。而前半部分,\(p(x|z,\theta)\),已知隐变量求出观测量的分布,实际上就是解码器。因此\(\phi\)\(\theta\)分别对应编码器和解码器的参数,实际上即神经网络的参数。前者称为variational -parameter,后者称为generative parameter
    • -
    • 我们要使得这个ELBO最大,VAE就直接将其作为网络结构的目标函数,做梯度下降,分别对\(\theta\)\(\phi\)求导。在这里前半部分\(E_{q(z|x,\phi)}[\log -p(x|z,\theta)]\)求期望,用的是蒙特卡罗方法,即从\(z \sim q(z|x,\phi)\)中采样多个\(z\),再求均值求期望,这里用到了上面说到的reparameterization技巧。
    • -
    • 此时整个概率图模型,加上推断部分,变成了
    • -
    • 流程:得到观测量x->通过reparameterization得到z的样本->将z的样本带入目标函数(ELBO)求导->梯度下降,更新参数\(\theta\)\(\phi\)
    • -
    -

    回到mnist

    +
  • 也是BERT+序列标注,同时从数据中构造phrase词典
  • +
  • 编辑操作包括复制(保留)、插入、删除、词形变换(用于语法纠错)
  • +
  • 构造phrase词典、构造ground truth编辑操作和LaserTagger基本一致
  • +
  • 将BERT左右扩展了两部分来获得替换或者增加所需的信息:
      -
    • 在mnist实验中,作者设置隐变量的先验、q分布、reparameterization中的基础分布\(\epsilon\)、观测量的后验分布分别为: \[ -p(z) = N(z|0,I) \\ -\] \[ -q(z|x,\phi) = N(z|\mu _e , diag(\sigma _e)) \\ -\] \[ -\epsilon \sim N(0,I) \\ -\] \[ -p(x|z,\theta) = \prod _{i=1}^D \mu _{d_i}^{x_i} (1-\mu _{d_i})^{1-x_i} -\\ -\]
    • -
    • 其中模型参数\(\phi = [\mu_e , \sigma -_e]\),\(\theta=\mu -_d\)通过神经网络学习得到
    • -
    • 而目标函数ELBO的前半部分,求期望部分已经通过reparameterization完成,内部的 -\[ -\log p(x|z,\theta) = \sum _{i=1}^D x_i \log \mu _{d_i} + (1-x_i) \log -(1- \mu _{d_i}) \\ -\]
    • -
    • 即伯努利交叉熵,在网络设计是最后一层增加sigmoid函数也就是为了输出的\(mu_d\)满足为概率。
    • -
    • 目标函数ELBO的后半部分,即隐变量的后验q分布和先验p分布之间的KL散度,就成为了上面所说的正则项,使得近似分布靠近先验分布
    • -
    • 整个模型既考虑了重构损失,也考虑了先验信息
    • -
    • 因此ELBO可以写成: -\[ -ELBO = -重构误差损失-正则惩罚 -\]
    • +
    • 输入层,M为mask标识符的embedding,p为positional embedding,X为word +embedding
    • +
    • h即原始BERT信息,包含词和位置信息
    • +
    • r即替换信息,只不过把当前位置的词mask掉,用M替代,且计算注意力时不查询当前位置的h
    • +
    • a即插入信息,只不过把当前位置的词mask掉,用M替代,且p替换为相邻位置p的平均 +
    • +
    • 之后利用三类信息来分别计算不同操作的概率,并归一化,CARDT分别代表复制(保留)、插入、替换、删除、词形变换 +
    • +
    • 上式第一项是每一项编辑操作的得分;第二项是保留当前词的得分,删除和替换不得分,其余的则用当前词embedding +\(\phi(x_i)\)来参数化得分,这里\(\phi\)的意义不明,原文是Embedding of w, +represented by \(\phi(w)\) is obtained +by summing up in-dividual output embeddings of tokens in +w;第三项是新词带来的影响,只有替换和插入有。
    • +
  • +
  • 推断时也是多轮推断(输出变输入),直到出现重复句子
  • +
  • 这里编辑操作设计的动机和解释不是很清楚,最终结果也很一般,ensemble情况下才与Transformer ++ Pre-training + LM+ Spellcheck + Ensemble Decoding +的工作持平,而且从消融来看,预训练模型是带来性能提升的主要原因。
  • + +

    Felix

    +
      +
    • 将编辑操作分为两个非自回归的部分,首先用一个基于Transformer的指针网络做tagging和reordering,并插入placeholder;然后用一个MLM对placeholder做预测
    • +
    • Felix的设计考虑三点需求 +
        +
      • 灵活的编辑,适合多种文本生成任务
      • +
      • 充分利用BERT等预训练模型
      • +
      • 高效推断
      • +
    • +
    • 下图可以清晰的表示出Felix的标签设计,其中yt是tagging模型需要预测出的编辑操作序列,ym是根据编辑操作序列,添加相关special +token(REPL,MASK)之后的中间状态序列,中间状态序列直接喂给MLM来预测需要插入的词,最终得到Pred里的结果
    • +
    • +
    • 这里需要注意两点: +
        +
      • MLM虽然只完成插入词的预测,但也需要完整的编辑操作信息,而不是输入MLM时直接把预测删除操作位置的词删掉,这里作者的做法是用REPL括起来要删除的span,给MLM也提供了删除编辑的信息。
      • +
      • 图中给出了Mask和Infill两种形式,其实就是对中间状态序列的MASK设计不同,涉及到多token插入的任务交给谁:Mask方式里是把任务交给了tagging模型,直接预测出插入多个词的编辑操作,例如\(DEL^{INS\_2}\),即插入两个,对应的就在中间序列中生成两个MASK让模型预测;Infill方式里把这个任务交给了MLM,统一对每个插入位置准备四个MASK让模型预测,多了的部分就预测PAD
      • +
    • +
    • 为了更灵活的建模,tagging部分的模型还需要做reordering,不然交互两个词的位置就得先删再添加,增加了复杂度。这里是通过指针网络注意力来为每个词确定其指向的后一个词,第一个词由特殊标识CLS指示。在推断时,使用了受控的beam +search避免指向顺序产生循环。
    • +
    • 主要与LaserTagger对比,在性能,小样本上的表现要优于LaserTagger,且没有了phrase +vocabulary的限制。作者也就phrase +vocabulary和reordering做了实验,结果很多可见原论文。
    -

    效果

    +

    总结

      -
    • 在mnist数据集上的重构效果
    • -
    • 对方差扰动得到的效果
    • -
    • 对均值扰动得到的效果
    • -
    • 对4和9进行插值的结果
    • +
    • 总结各个模型

      + +++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      模型编辑操作加速插入多个词构建ground truth编辑序列编辑失败测试任务
      LevT插入删除多轮非自回归,5倍先预测placeholder数量,再替换基于编辑距离动态规划退化为文本生成翻译、摘要
      EditNTS插入删除保留自回归,未提及加速插入时原地停留,直到插入完毕基于编辑距离动态规划退化为文本生成文本简化
      LaserTagger插入删除保留一轮序列标注,100+倍直接插入phrase,根据训练数据构建phrase词典贪心匹配不编辑句子融合,分句与转述,摘要,语法纠错
      PIE插入删除替换复制词形变换序列标注,2倍直接插入phrase,根据训练数据构建phrase词典贪心匹配未说明语法纠错
      Felix删除插入保留重排序标注+MLM,快于LaserTagger设置多个Mask让MLM预测简单比较较差的MLM预测结果句子融合、机器翻译后处理、摘要、文本简化
    ]]>
    - 机器学习 + 自然语言处理 math - mcmc - vae + machine learning + theory + nlp + seq2seq
    - Prompt - Task Reformulation in NLP - /2021/05/13/pet/ + Trie in Python + /2017/05/02/trie/ -
      -
    • 记录近年基于模板来完成任务重构的方法,这是一个比较有意思的方向,尤其是GPT3出现之后。 -这类方法一般针对任务设计prompt,将样本和任务一起转换为自然语言形式的template,直接输入预训练语言模型预测出文本,间接的完成任务。prompt的构建一方面统一了下游任务和预训练任务的形式(语言模型)在few -shot learning上能取得较好结果。主要阅读以下9篇论文: -
        -
      • 早期的将问题转为自然语言并使用预训练语言模型解答的: -
          -
        • (Harvard)Commonsense Knowledge Mining from Pretrained Models
        • -
        • (Heidelberg)Argumentative Relation Classification as Plausibility -Ranking
        • -
        • (NVIDIA)Zero-shot Text Classification With Generative Language -Models
        • -
      • -
      • PET方向,Pattern Exploiting Training -
          -
        • (LMU)Exploiting Cloze Questions for Few Shot Text Classification and -Natural Language Inference
        • -
        • (LMU)It’s Not Just Size That Matters: Small Language Models Are Also -Few-Shot Learners
        • -
        • (UNC)Improving and Simplifying Pattern Exploiting Training
        • -
      • -
      • 自动构建prompt,Automatically Searching Prompts -
          -
        • (UCI,UCB)AUTOPROMPT: Eliciting Knowledge from Language Models with -Automatically Generated Prompts
        • -
        • (Princeton, MIT)Making Pre-trained Language Models Better Few-shot -Learners
        • -
        • (THU)GPT Understands, Too
        • -
      • -
    • -
    +

    在Python中有字典这一数据结构,因此用Python实现字典树很方便

    -

    Commonsense -Knowledge Mining from Pretrained Models

    -
      -
    • 作者想要做到挖掘未知分布数据中的常识,而传统的监督学习方法容易受到训练集中的数据分布影响,导致结果有偏差
    • -
    • 将关系三元组转换为masked -sentence送给BERT,通过BERT的预测结果计算互信息来对三元组的可信度排序
    • -
    • 任务,给定一个三元组为其打分,确定这个三元组代表了真实世界知识的可能性,作者将其分为两步: -
        -
      • 将三元组转化为mask过后的句子:对每个关系手工设计了多个模板,同时还设计了一系列规则来确保语法正确性(单复数、插入冠词、改动名词等等),这样所有模板和规则的组合得到了一系列候选句子,然后通过预训练单向语言模型来计算每个句子是正常句子的得分log-likelihood
      • -
      • 将生成的句子输入BERT打分:这里作者用条件点互信息计算,即在关系r的条件下,头尾实体之间的互信息大小作为分数: -\[ -PMI(tail,head|relation) = \log p(tail|head, relation) - \log -p(tail|realtion) \\ -\] 放在语言模型中,实际上就是将tail -mask掉然后预测,只不过上式右边第一项是只mask -tail,第二项则还mask掉了head(只mask,不预测)。另外可能出现实体由多个词组成的情况,这里作者采用了一种贪心近似的方法,先把词全部mask掉然后预测,拿到概率最高的词unmask,再反复迭代预测剩下的词,每次还原概率最高的词,之后累乘这一系列概率就可以得到整个词的条件概率。上式并不是对称的,因此作者还反过来计算了基于关系和尾实体的头实体概率,最后平均两个PMI值作为结果。
      • -
    • -
    • 最终结果虽然比不上监督学习,但是在无监督学习中取得了最佳效果
    • -
    • 这是较早尝试利用预训练模型的Mask -Predict,将任务设计为完形填空来完成,可以看到这里的Pattern还是手工设计(针对每个关系设计一系列规则)。
    • -
    -

    Argumentative -Relation Classification as Plausibility Ranking

    -
      -
    • 这篇论文做的任务为Argumentative relation -classification,即文本对分类,给定(或者不显式给出)结论,区分一对文本是支持还是反对。正例文本对里,两个文本都支持结论;负例文本对里,一个支持结论而另一个不支持,互相反驳。
    • -
    • 对于这个很有意思的任务,作者采用了一个同样很有意思的做法:使用孪生网络做ranking,rank的是一个构造文本的plausibility,即可信度。而这个构造文本是什么?很简单,将要判别的两个句子用一个连接词连接起来,得到构造文本的正负例: -
        -
      • 正例:文本A,而且,文本B
      • -
      • 负例:文本A,然而,文本B
      • -
    • -
    • 假如文本A和文本B是反对的关系,那么显然负例这么一段文本的可信度高;为文本A和文本B互相支持,那么正例构造文本的可信度高。
    • -
    • 接下来就用预训练语言模型作为孪生网络的编码器,然后做ranking。
    • -
    • 本质思想是构造了文本和任务,将任务用正常的自然语言表示,这样就可以利用学习到正常文本知识的语言模型来做学习和预测。
    • -
    • 和上一篇论文一样,核心都是将任务转为自然语言(模板),巧用预训练语言模型间接的完成任务(完成构造任务)
    • -
    -

    Zero-shot -Text Classification With Generative Language Models

    +
    +i07rz6.jpg + +
    +

    字典树(trie)

      -
    • 作者使用GPT,将文本分类问题转化为给定包含原文本和类别的自然语言,通过文本生成间接判断类别
    • -
    • 这样做的一个好处即标题提到的zero-shot,可以泛化到训练集中不存在的类别
    • -
    • 具体而言,将文本分类问题转为一个选择QA任务,即所有的选项拼成了问题:该文本属于下面哪一类?A;B;C;D.....,之后再拼接上待分类文本,目标是训练语言模型,直接生成正确的类别的文本。
    • -
    • 另外为了减少预训练和finetune之间的gap,作者还加入了一个前置的预训练任务,叫title -prediction -pretraining,即将所有候选标题和正文拼接起来,然后生成正确的标题。
    • -
    • 这是一篇非常直观、间接且大胆的利用语言模型分类任务的工作,直接让语言模型生成类别文字。 -
    • -
    • 最终的zero-shot结果,虽然依然比不上finetune和sota,但是相比random和majority两个baseline可以比较出模型还是学到了相当强的泛化能力。最主要的还是把语言模型玩出了花,提供了这么一种直接设计多项选择疑问句来完成分类任务的思路。
    • +
    • 字典树主要用于词频统计,前缀后缀相关的算法,树的根节点不存任何字符,每一条边代表一个字符,其他每一个节点代表从根节点到此节点的所有边上字符构成的单词,存的内容根据需求而定。
    • +
    • 字典树快的原因就是充分利用的单词的共同前缀,如果前缀都不一样,就不需要继续查找
    • +
    • 一个单词不一定在叶子节点,因为它可能构成其他更长单词的前缀,因此如果用于词频统计,则可以插入完一个单词后在此单词最后一个节点中count++。如果仅仅用于判断某个词是否在字典树构成的字典中,则可以在插入完一个单词后,在最后一个节点中添加一个None节点,内容为单词本身
    -

    Exploiting -Cloze Questions for Few Shot Text Classification and NaturalLanguage -Inference

    -
      -
    • 该论文正式引入了PET的概念:Pattern-Exploiting Training。
    • -
    • 在上面三篇论文中我们可以看到,很多NLP任务可以通过提供自然语言任务描述的方式,通过语言模型来无监督的或者间接的完成。但是这类方法终究还是比不过监督学习方法。
    • -
    • PET提供了一种半监督学习方式,在低资源场景下成功超过了监督学习模型的结果。
    • -
    • 一张图就能说明PET的原理: gWivmd.png -
        -
      • 作者引入了两个名词,pattern负责把输入文本根据任务改造成一个带mask的完形填空文本,verbalizer负责把语言模型预测的mask词映射到label上。这样一个pattern对应一个verbalizer,称为PvP。。。(pattern -verbalizer pair)
      • -
      • 整个PET过程分三步: +

        例子

          -
        • 第一步用PvP,在小训练集上微调预训练语言模型
        • -
        • 第二步,每一个任务可以设计多个PvP,这样得到多个第一步训练出的语言模型,集成,在大量未标注数据上打标软标签
        • -
        • 第三步,用一个分类器在打标后的数据上完成监督学习
        • -
      • -
    • -
    • 第二步中有两个小细节:多分类器集成,即多个预测标签分布相加,这里可以等权重相加,也可以根据PvP直接在训练集上zero-shot的表现作为先验权重(实验结果这样做好些);打标时打的是软标签即概率分布,softmax时取T=2做了温度处理。这两个处理都是为了能够更好的学习到语言模型的知识,一个在于集成更加鲁棒,另一个则相当于知识蒸馏。
    • -
    • 另外作者还提出了iPET,其实就是传统的半监督学习,训练打标之间迭代,用越来越多的数据训练出不同代模型然后集成。
    • -
    • 这样的半监督框架好处在于,最终实际操作依然是监督学习,准确率较高,而语言模型带来的不确定性在知识蒸馏(软化标签)的时候降低了。
    • -
    -

    It's -Not Just Size That Matters: Small Language Models Are Also Few-Shot -Learners

    +
  • 以leetcode472为例,当中需要判断某个序列中某个单词是否能由它前面的单词构成
  • +
  • 初始化trie
    trie = {}
  • +
  • trie中插入单词
    def insert(trie, w):
    for c in w:
    trie = trie.setdefault(c, {}) # if c not in trie then set trie[c]={}
    trie[None] = w
    +对每一个字符串,依次按字母索引,当索引不到时就对当前字母建立新节点 +遍历完单词后建立None节点存放单词(因为题目需要返回所有单词,因此此处存放单词,也可以存放出现次数 +这样一棵树最终完成时就如标题图所示,其中前四行是加入["cat", +"cats","dog", "rat"]之后树的内容
  • +
  • trie中查找某一个单词
    def prefixs(trie, w, lo):
    for i in range(lo, len(w)):
    trie = trie.get(w[i])
    if trie is None:
    break
    prefix = trie.get(None)
    if prefix:
    yield i + 1, prefix
    +因为题目需要,利用了生成器,这段函数是查找单词w中i从lo位置开始,i到单词尾这一段构成的字符串,是否在trie的字典集合中,返回所有符合结果的i+1。查找的方式与插入相同 +特别说明的是,trie的一大优势便是支持插入与查找同时进行
  • + +

    后缀树

      -
    • 还是PET原版人马,又水了一篇,换了个动机,说用PET的话,小模型也能在few-shot上取得与GPT-3这样的大模型接近的结果,环保
    • -
    • 将PvP中要预测的词从单个mask扩展为多个mask,训练的时候插入固定最大数量的mask,预测时再做后处理
    • -
    • 给了更丰富的实验结果(不过好像还是arxiv挂着,没中会议。。。)(更新:惊了,拿到了NAACL -2021 杰出论文)
    • +
    • 如果将一个单词,长度为l,拆分成l个子单词插入到trie中,每个子单词都是这个单词的[i:l]构成的后缀,则这样的字典树称之为后缀树。
    • +
    • 简单按上述方法建立后缀树会存在许多冗余信息,在空间上还可以进行优化
    • +
    • 待续
    -

    Improving -and Simplifying Pattern Exploiting Training

    +]]>
    + + Python + + + code + python + +
    + + Note for Variational Auto-Encoder + /2019/03/20/vae/ +
      -
    • -
    • PET依然需要大量领域未标注数据来做半监督学习,本文提出了ADAPET,不用未标注数据也能取得更好效果
    • -
    • 作者通过修改任务目标来达成这一目的。当我们使用PET时,浪费了两类信息: +
    • 变分自编码器学习笔记
    • +
    • 参考文章:
    • -
    • 因此作者就想充分利用这两个信息,修改任务目标 +
    • 关于VAE,上面的原论文以及两篇博客已经讲的很清楚了,我写也就是复读转述,自己捋一遍,如果有人看到这篇博客,建议优先读这三个参考来源 +
    • +
    +

    直接看网络结构

      -
    • 将损失从交叉熵改为两个二元交叉熵,一个依然是在label相关target词上算损失,另一部分损失则负责优化降低其他所有不相关词的概率
    • -
    • 将mask替换为正确或者错误的target -word,然后对输入剩下部分做MLM,要是target -word对的话MLM就应该预测对,反之就应该预测错
    • -
    • 分别对应图中左右两类损失
    • +
    • 变分自编码器用了变分推断,但是因为其中的参数估计部分用的是神经网络的梯度下降方法,因此可以直接画出其网络结构——实际上我们称其为自编码器,也是因为其结构上和自编码器有许多相通之处,如果不从贝叶斯的角度出发,甚至可以将VAE直接看成一类特殊的自编码器。
    • +
    • 以原论文的mnist实验为例,我们直接看VAE的网络结构,之后再一般化模型并解释细节: +
        +
      • 整体和自编码器一样,一个encoder和一个decoder,目标是重构误差,获取有用的编码
      • +
      • 然而变分自编码器不对输入直接编码,而是假定编码服从多维正态分布,encoder编码的是这个多维正态分布的均值和方差
      • +
      • 也就是VAE假定编码很简单,就是服从正态分布,而我要训练出来并利用的是解码,这个解码器能从正态分布的采样中解码还原出输入,或者说,生成输出
    • -
    • ADAPET增加了目标函数,对参数做了更充分的训练,对比PET结果也确实不错,不使用未标注数据还在很多任务上超过了PET
    • +
    • mnist的输入为28*28,batch_size为128,假定隐层dim为200,参数dim为10,则整个网络为:
    -

    AUTOPROMPT: -Eliciting Knowledge from Language Models with Automatically Generated -Prompts

    +
      +
    1. 输入\(x\)[128,28*28],过一个linear+ReLu,得到编码器隐层\(h\)[128,200]
    2. +
    3. \(h\)分别过两个linear,得到正态分布的参数\(\mu _e\)[128,10],\(\log \sigma _e\)[128,10]
    4. +
    5. 从一个标准多维正态分布中采样\(\epsilon +\sim N(0,I)\),得到\(\epsilon\)[128,10]
    6. +
    7. 组合通过网络得到的参数\(\mu +_e\)\(\log \sigma +_e\)到标准多维正态分布的采样值中,\(z = +\mu _e + \sigma _e \bigodot \epsilon\)[128,10],\(z\)即编码
    8. +
    9. encoder部分就此完成,接下来是decoder部分:编码\(z\)过linear+ReLu得到解码隐层状态h[128,200]
    10. +
    11. 解码隐层状态h经过linear+sigmoid得到\(\mu +_d\)[128,28*28],即解码后的输出
    12. +
    13. 解码后输出\(\mu _d\)与输入\(x\)计算伯努利交叉熵损失
    14. +
    15. 此外还要加上一个类似正则项的损失\(\frac 12 +\sum _{i=1}^{10} (\sigma _{ei}^2 + \mu _{ei}^2 -log(\sigma _{ei}^2) - +1)\)
    16. +
    +

    直接对网络分析

      -
    • 由上面介绍的工作可以发现,构建有效的文本来触发语言模型得到结果至关重要,即构建prompt。目前看到的都是手工构建的,后来也出现了一批工作尝试自动构建prompts
    • -
    • 这个工作其实不能算是prompts,更准确的说法是trigger words -sequence,因为它其实是把文本对抗样本生成的一套方法拿到了prompt构建当中。
    • -
    • 具体而言,其借鉴了HotFlip: White-box adversarial examples for text -classification 和 Universal Adversarial Triggers for Attacking and -Analyzing -NLP两篇论文,即在样本中拼接一系列触发词,即可使得模型的预测结果错误,而模型的触发词搜索主要使用的是hotflip方法: +
    • 从网络可以看到,VAE相比AE最大的区别就是不直接对输入编码,而是将概率的思想引入了网络结构,对每一个输入单独构建一个满足多维正态分布的编码
    • +
    • 这么做的一个好处是,编码可以做插值,实现生成图像连续的变化:原始的AE对于每一个确定输入有确定的编码,而VAE中的网络只负责生成确定的均值和方差,也就是确定的正态分布,实际的编码只是在这个确定的正态分布中采样得到,依然是不确定的。在训练过程中VAE是对一片区域进行训练,而不是点训练,因此得到的编码具有连续性,在区域中心点附近也能生成相似的图像,甚至可以在两类图像输入确定的两个编码区域之间插值,实现两种生成图像的平滑过渡。
    • +
    • 步骤1,2,3,4实现的是编码器从一个\(N(\mu +_e,\sigma _e +^2)\)的分布中采样得到编码,然而这里存在一个reparameterization的技巧,即:
        -
      • 初始化触发词 \[\mathbf{e}_{a d -v}\](比如the,a,an等),前向过一遍模型得到损失关于触发词embedding的梯度 -\[\nabla_{\mathbf{e}_{a d v}} -\mathcal{L}\] -,注意这里用于计算损失所用的label应该是想要攻击得到的错误label,即fool -model之后的label
      • -
      • 我们希望替换第i个触发词为词 \[\mathbf{e}_{i}\],使得替换之后损失下降的最多,模型最容易预测出错误的标签,所以我们要找的词是 -\[ \underset{\mathbf{e}_{i}^{\prime} \in -\mathcal{V}}{\arg \min } \mathcal{L}(\mathbf{e}_{i}^{\prime}) -\]。这里通过泰勒一阶展开来近似,需要求到损失关于token的导数,由于token -embedding lookup不可导,所以才需要求到某个token的embedding的导数
      • +
      • 本来应该是让编码器神经网络拟合一个满足\(N(\mu _e,\sigma _e +^2)\)的分布,再从分布中采样
      • +
      • 但是采样得到的值无法进行反向传播
      • +
      • 因此改成神经网络只拟合分布的参数,然后从一个简单的标准多维正态分布中采样,采样值经过拟合参数处理,即\(z = \mu _e + \sigma _e \bigodot +\epsilon\),来达到\(z\)仿佛直接从\(N(\mu _e,\sigma _e +^2)\)采样得到的效果,而神经网络仅仅拟合参数,可以进行反向传播,采样在其中相当于做了一些指定权值的加权,参与进网络的训练
      • +
    • +
    • 步骤5,6,7则是普通的解码,因为输出是28*28的黑白图像,因此直接解码成28*28的二值向量,与输入比对计算交叉熵
    • +
    • 关键是8,这个正则项如何得到?
    -\[ -\mathcal{L}(\mathbf{e}_{i}^{\prime}) = \mathcal{L}(\mathbf{e}_{a d -v_{i}}) + \left[\mathbf{e}_{i}^{\prime}-\mathbf{e}_{a d -v_{i}}\right]^{\top} \nabla_{\mathbf{e}_{a d v_{i}}} \mathcal{L} -\] \[ -\propto \left[\mathbf{e}_{i}^{\prime}-\mathbf{e}_{a d -v_{i}}\right]^{\top} \nabla_{\mathbf{e}_{a d v_{i}}} \mathcal{L} -\] +

    正则项

      -
    • 这样就得到了第一轮迭代中的第一个触发词,之后通过beam -search得到剩下的触发词,并迭代多次,最终得到可以用于攻击模型的触发词序列。
    • -
    -
  • 以上是文本对抗攻击中的hotflip方法,其本质就是生成一些触发词,拼接到样本上,使得模型预测出错的label。autoprompt的思想就是生成触发词,使得模型预测出指定label。 -
  • -
  • 接下来就简单了。作者首先在训练集上用hotflip方法为每个任务生成了触发词,然后用模板将样本变为一个句子,如图所示,句子拼接上触发词序列([T])和PLM要预测的mask位置([P]),让模型预测出词之后再后处理得到label。具体的后处理操作是,将每个label对应的预测词集合得到的概率累加,最后归一化,作为标签的概率。
  • -
  • 上面只说了PvP中的prompt自动构建方法,而verbalizer,即预测词到标签的映射作者也给出了一个自动搜索的方法: +
  • 这个正则项实际上是编码得到的正态分布和标准正态分布之间的KL散度,即(其中K是多维正态分布的维度,在上例中是10): +\[ +KL(N(\mu _e,\sigma _e ^2)||N(0,I)) = \frac 12 \sum _{i=1}^{K} (\sigma +_{ei}^2 + \mu _{ei}^2 -log(\sigma _{ei}^2) - 1) +\]
  • +
  • 也就是说,我们希望编码的正态分布接近标准正态分布,为什么?
  • +
  • 这里就有很多种说法了:
      -
    • 将PLM编码之后包含上下文信息的mask -token的embedding作为特征输入,标签作为输出来训练一个logistic分类器,之后将所有词的PLM编码之后的embedding依次输入这个分类器,得到每个词在每个标签上的评分,根据评分top -k来为每个标签类别选择词作为映射集合。这么做实际上是将预测标签所需的mask -token编码embedding和每个词的编码embedding比较,取最相近的top -k,只不过利用logistic分类器做了一个类别相关的特征加权,不仅仅是取PLM编码之后的语义相似度,非常巧妙。
    • +
    • 第一种:我们希望的是对于不同类的输入,编码能编码到同一个大区域,即不同区域内部紧凑的同时,区域之间的距离也不应该太远,最好能体现图像特征上的距离,比如以mnist为例,4和9的图像比较近似,和0的图像差异比较大,则他们的编码区域之间的距离能反映相似的关系;或者说从0变到8的过程中中间状态会像9,那么9的编码区域能在0和8的编码区域之间最好。然而实际上是,编码器网络可能会学到这样的编码方法:对于不同类的输入,\(\mu\)相差很大,它将不同类输入(准确的说是不近似的输入,这里是无监督学习,没有类别)的编码区域隔得很开。神经网络这么做是有道理的:让解码器方便区别不同的输入进行解码。这就与我们希望它编码成连续区域方便插值的初衷相悖,因此我们强制希望所学到的编码分布都近似标准正态分布,这样都在一个大区域中,当然也不能太近似,不然大家都一样,解码器负担太大,根本解码不出来区别,这就是前面的重构损失的作用。
    • +
    • 第二种:VAE的效果相当于在标准的自编码器中加入了高斯噪声,使得decoder对噪声具有鲁棒性。KL散度的大小代表了噪声的强弱:KL散度小,噪声越贴近标准高斯噪声,即强度大;KL散度大,噪声强度就小,这里理解为噪声被同化了,而不是说方差变小了,因为噪声应该与输入信号无关,一直保持高斯噪声或者其他指定的分布,如果噪声变得和指定分布越来越远,和输入越来越相关,那其作为噪声的作用也就越来越小了。
    • +
    • 第三种:也是最严谨的一种理解,这个KL散度是从变分推断的角度出发得到的,整个模型也是从贝叶斯框架推理得到的。其之所以有网络结构是因为作者用了神经网络来拟合参数,神经网络的超参、分布的指定也是该框架在mnist生成任务中的一种特例,毕竟原文叫自编码变分贝叶斯(一种方法),而不是变分自编码网络(一种结构)。接下来我们从原论文的角度来看看整个模型如何推导出来,并自然而然得到这个KL散度正则项。
  • -

    Making -Pre-trained Language Models Better Few-shot Learners

    +

    变分自编码贝叶斯

      -
    • 这篇论文标题就是GPT3的标题加了个better,强调如何更好的利用prompt做few -shot learning。
    • -
    • 提出了一个训练体系:基于prompt的微调+prompt自动生成+动态选择性融入任务说明到prompt中,且这一切都是strong -task-agnostic。接下来分别说这三点改进。
    • -
    • -
    • 上图清晰的展示了第一点改进:基于prompt的微调。可以看到,和以往prompt方法相比,除了输入、prompt之外,输入还拼接上了每个label的说明
    • -
    • 至于prompt自动生成,分为两部分: +
    • 整个解码器部分我们可以看成一个生成模型,其概率图为: AKu5FA.png
    • +
    • \(z\)即编码,\(\theta\)是我们希望得到的解码器参数,控制解码器从编码中解码出(生成出)\(x\)
    • +
    • 现在问题回归到概率图模型的推断:已知观测变量x,怎么得到参数\(\theta\)
    • +
    • 作者采取的思路并不是完全照搬变分推断,在VAE中也采用了\(q\)分布来近似后验分布\(p(z|x)\),并将观测量的对数似然拆分成ELBO和KL(q||p(z|x)),不同的是变分推断中用EM的方式得到q,而在VAE中用神经网络的方式拟合q(神经网络输入为\(z\),因此\(q\)本身也是后验分布\(q(z|x)\)。完整写下来: \[ +\log p(x|\theta) = \log p(x,z|\theta) - \log p(z|x,\theta) \\ +\] \[ += \log \frac{p(x,z|\theta)}{q(z|x,\phi)} - \log +\frac{p(z|x,\theta)}{q(z|x,\phi)} \\ +\] \[ += \log p(x,z|\theta) - \log q(z|x,\phi) - \log +\frac{p(z|x,\theta)}{q(z|x,\phi)} \\ +\] \[ += [ \int _z q(z|x,\phi) \log p(x,z|\theta)dz - \int _z q(z|x,\phi) \log +q(z|x,\phi)dz ] + [- \int _z \log \frac{p(z|x,\theta)}{q(z|x,\phi)} +q(z|x,\phi) dz ]\\ +\]
    • +
    • 注意,我们实际希望得到的是使得观测量对数似然最大的参数\(\theta\)\(\phi\),而隐变量\(z\)可以在输入确定的情况下随模型得到。
    • +
    • 可以看到,在观测量即对数似然确定的情况下,前一个中括号内即ELBO值越大,则后面的KL散度,即后验\(q(z|x,\phi)\)分布和后验真实分布\(p(z|x,\theta)\)越相近。这个后验分布,即已知\(x\)得到\(z\)实际上就是编码器,因此这个KL散度越小则编码器效果越好,既然如此我们就应该最大化ELBO,ELBO可以改写成: +\[ +ELBO = \int _z q(z|x,\phi) \log p(x,z|\theta)dz - \int _z q(z|x,\phi) +\log q(z|x,\phi)dz \\ +\] \[ += E_{q(z|x,\phi)}[\log p(x,z|\theta)-\log q(z|x,\phi)] \\ +\] \[ += E_{q(z|x,\phi)}[\log p(x|z,\theta)]-KL(q(z|x,\phi)||(p(z|\theta))) \\ +\]
    • +
    • 又出现了一个KL散度!这个KL散度是编码器编码出的隐变量后验分布和隐变量先验分布之间的KL散度。而前半部分,\(p(x|z,\theta)\),已知隐变量求出观测量的分布,实际上就是解码器。因此\(\phi\)\(\theta\)分别对应编码器和解码器的参数,实际上即神经网络的参数。前者称为variational +parameter,后者称为generative parameter
    • +
    • 我们要使得这个ELBO最大,VAE就直接将其作为网络结构的目标函数,做梯度下降,分别对\(\theta\)\(\phi\)求导。在这里前半部分\(E_{q(z|x,\phi)}[\log +p(x|z,\theta)]\)求期望,用的是蒙特卡罗方法,即从\(z \sim q(z|x,\phi)\)中采样多个\(z\),再求均值求期望,这里用到了上面说到的reparameterization技巧。
    • +
    • 此时整个概率图模型,加上推断部分,变成了
    • +
    • 流程:得到观测量x->通过reparameterization得到z的样本->将z的样本带入目标函数(ELBO)求导->梯度下降,更新参数\(\theta\)\(\phi\)
    • +
    +

    回到mnist

      -
    • 如何在给定模板的情况下,自动生成目标词到标签的映射。这里作者也是用PLM的结果不断迭代。首先对每个类,找出这个类的所有训练样本,通过PLM推断得到mask词的概率分布,累加所有样本的概率分布取topk就得到了词到该类别标签的映射。由于接下来训练微调时模型参数变化,结果可能有改变,所以需要每轮训练后重新rerank调整一下映射关系。
    • -
    • 给定类别和这个类别的目标词,如何生成模板。作者采用了T5模型,因为其mask -span seq2seq预训练的目标和模板生成任务很符合。一张图就可以解释清楚: g5YjfI.png -这样生成的prompt考虑了训练样本上下文和标签词的语境。作者使用wide beam -width来beam -search出一堆prompt候选(100+),然后在一个小训练集上微调每个样本,取验证集最高的(或者topk集成)作为最终prompt
    • -
    • 动态选择性融入任务,这里做的比较麻烦,即得到prompt后如何构造输入样本,也是如第一张图所示,对每个类别,采样一个样本转化为prompt当做这个类别的说明,将所有类别说明和输入样本(待训练样本)拼接。采样时,使用sentence-BERT得到每个样本的语义embedding,然后只取和输入样本语义相似度前50%的样本进行采样。
    • -
    -
  • 这种prompt的设计有点像是在做语义相似度任务,输入x,已知y为正例,z为负例,构造了输入为“x是mask例?y为正例;z为负例”,相当于比较x与yz的语义相似度,做一个标签的传播
  • +
  • 在mnist实验中,作者设置隐变量的先验、q分布、reparameterization中的基础分布\(\epsilon\)、观测量的后验分布分别为: \[ +p(z) = N(z|0,I) \\ +\] \[ +q(z|x,\phi) = N(z|\mu _e , diag(\sigma _e)) \\ +\] \[ +\epsilon \sim N(0,I) \\ +\] \[ +p(x|z,\theta) = \prod _{i=1}^D \mu _{d_i}^{x_i} (1-\mu _{d_i})^{1-x_i} +\\ +\]
  • +
  • 其中模型参数\(\phi = [\mu_e , \sigma +_e]\),\(\theta=\mu +_d\)通过神经网络学习得到
  • +
  • 而目标函数ELBO的前半部分,求期望部分已经通过reparameterization完成,内部的 +\[ +\log p(x|z,\theta) = \sum _{i=1}^D x_i \log \mu _{d_i} + (1-x_i) \log +(1- \mu _{d_i}) \\ +\]
  • +
  • 即伯努利交叉熵,在网络设计是最后一层增加sigmoid函数也就是为了输出的\(mu_d\)满足为概率。
  • +
  • 目标函数ELBO的后半部分,即隐变量的后验q分布和先验p分布之间的KL散度,就成为了上面所说的正则项,使得近似分布靠近先验分布
  • +
  • 整个模型既考虑了重构损失,也考虑了先验信息
  • +
  • 因此ELBO可以写成: +\[ +ELBO = -重构误差损失-正则惩罚 +\]
  • -

    GPT Understands, Too

    +

    效果

      -
    • -
    • 本文提出了P-tuning,即不是找离散的prompt(具体文本),而是找连续的(embedding)
    • -
    • 回顾一下整个prompt based -methods,都是把数据和任务转化为语言模型任务的形式,使其更加贴近预训练目标,能够更好的利用预训练模型的知识。实际操作时,就是把输入添加一些prompt -generated templates,输出变成与类别label相关的target -words,作者反思,这些prompt generated templates -本质上就是一些词,一定要是人类能够理解的文本吗?这些文本输入到模型的实际上是embedding,那么搜索prompt的时候为什么不直接优化embedding呢?所以作者提出就用几个词表中没用的符号(例如BERT中的unused)来作为pseudo -template -token,固定这些token,不去搜索新的token,而是直接优化token对应的embedding。
    • -
    • 为了让这些pseudo -token更像是自然语言,而不是独立的几个符号,作者还用了双向LSTM来做编码,即prompt -encoder,这里感觉动机阐释的不是很清楚,为什么不能放在PLM里直接建模之间关系?
    • -
    • 这么看来整体就相当于输入拼接上几个embedding然后去优化,只不过输出和后处理采用了PET的形式,很像自己加了某个层去微调(所以叫Prompt -finetuning?)。我感觉加层微调和P-tuning都是引入少量参数把PLM用到自己的下游任务上,只不过P-tuning转换了下游任务形式,使其跟贴近预训练目标,算是微调结构先验更合理吧,同时也算是从另一个高度总结了prompt一类的工作。
    • +
    • 在mnist数据集上的重构效果
    • +
    • 对方差扰动得到的效果
    • +
    • 对均值扰动得到的效果
    • +
    • 对4和9进行插值的结果
    ]]>
    - 自然语言处理 + 机器学习 - machine learning - nlp - pretrained language model - pet - few shot + math + mcmc + vae
    @@ -13688,203 +13881,10 @@ C(\mathcal{H})}}{\delta}\right)}\) 机器学习 - machine learning math + machine learning statistical learning vc dimension - - Seq2seq based Summarization - /2018/07/04/seq2seq-summarization/ - 本科毕业设计是做一个基于seq2seq的短句文摘模型,并设计了一种情感融合机制 -现在对整个模型做一个简单的总结

    - -
    -i0TGHH.png - -
    -

    任务

    -
      -
    • 自动文摘是一类自然语言处理(Natural Language -Processin,NLP)任务。对于一段较长的文本,产生一段能够覆盖原文核心意义的短文本,这段短文本就是原文本的摘要。自动文摘技术是指在计算机上构建数学模型,将长文本输入模型,通过计算之后模型能自动生成短摘要。根据需要产生摘要的语料规模和摘要的规模,可以将摘要分为多文本摘要、长文摘要、短文摘要。本文主要研究的是短文摘要:对于一句或者几句文本,生成一句短摘要,概括原文关键信息,且流畅可读,尽量达到人类作者撰写摘要的水平。
    • -
    • 自动文摘分抽取式和生成式,前者是抽取原文句子构成文摘,后者是通过深度学习模型逐字生成文摘。本文主要研究生成文摘,并将问题抽象成对一个平均长度为28词的长句生成一个平均长度为8词的短句。
    • -
    -
    -i0TYEd.jpg - -
    -

    预备知识

    -

    循环神经网络

    -
      -
    • 循环神经网络(Recurrent Neural -Network,RNN),是神经网络的一种变形,能够有效处理序列型数据,其所有的隐藏层共享参数,每一隐藏层不仅依赖当前时刻的输入还依赖上一时刻的隐藏层状态,数据流并不是如传统神经网络那样在网络层之间传播,而是作为状态在自身网络中循环传递。
    • -
    • 不展开时形式如下: i0TtUA.jpg
    • -
    • 按时间步展开之后: i0TN4I.jpg
    • -
    -

    LSTM和GRU

    -
      -
    • 循环神经网络能够有效捕捉序列数据的顺序信息且能够构造很深的神经网络而不产生大量需要学习的参数;但也因为参数共享,梯度通过时间步进行链式求导时相当于进行矩阵幂运算,若参数矩阵的特征值过小会造成梯度弥散,特征值过大会造成梯度爆炸,影响反向传播过程,即RNN的长期依赖问题。在处理长序列数据时长期依赖问题会导致序列的长期记忆信息丢失,虽然人们通过引入梯度截断和跳跃链接技术试图缓解此问题,但效果并不显著,直到长短期记忆神经网络和门控循环神经网络作为 -RNN 的扩展形式的出现,有效地解决了这个问题。
    • -
    • LSTM即长短期记忆神经网络。为了捕捉长期记忆信息,LSTM在其节点中引入了门控单元,作为网络参数的一部分参与训练。门控单元控制了当前隐藏层节点记忆(遗忘)过去信息,接受当前输入新记忆的程度。 -
    • -
    • GRU即门控神经网络,与LSTM不同的是,GRU -将遗忘门和输入门整合为重置门,遗忘门的门控值和输入门的门控值和为 1,因此 -GRU 在 LSTM 的基础上简化了参数,从而使得模型能够更快得收敛。 i0Td8P.jpg ## -词嵌入
    • -
    • 深度学习的一大好处就是能自动学习特征,在自然语言处理中,我们专门用word2vec之类的技术学习词语的特征表示,即词嵌入。
    • -
    • 词向量(Word Vector)表示,又称词嵌入(Word -Embedding),指以连续值向量形式表示(Distributed -Representation)词语,而不是用离散的方式表示(One-hot -Representation)。在传统的离散表示中,一个词用一个长度为 V -的向量表示,其中 V 是词典大小。向量中只有一个元素为 1,其余元素为 -0,元素 -1的位置代表这个词在词典中的下标。用离散的方式存储单词效率低下,且向量无法反映单词的语义语法特征,而词向量可以解决以上问题。词向量将向量的维 -度从 V 降低到 \(\sqrt[k] V\)(一般 k 取 -4),每个元素的值不再是 1 和 0,而是连续值。词向量是建立神经网络语言模型 -(Neural Network Language -Model,NNLM)对语料进行监督学习得到的副产物,此模型的提出基于一个语言学上的假设:具有相近语义的词有相似的上下文,即 -NNLM 模型能够在给定上下文环境的条件下求出相应中心词。
    • -
    • 下图展示了word2vec中的skipgram模型: i0Twgf.jpg
    • -
    • 得到的词嵌入矩阵如下: i0T0v8.jpg
    • -
    • Mikolov等人在NNLM基础上提出了 Word2Vec -模型,此模型进行监督学习的输入输出分别为中心词与上下文(即 Skip Gram -模型) 或者上下文与中心词(即 CBOW -模型)。两种方式均能有效训练出高质量的词向量,但是 CBOW -模型是根据上下文求中心词,训练速度快,适合在大语料上训练;Skip Gram -模型能充分利用训练语料,其本身含义为“跳跃的语法模型”,不仅使用相邻词构成中心词的上下文环境,隔一个词的跳跃词也构成上下文环境,以图 -2-1 为例,语料中的一个中心词的上下文包括四个词,假如语料中有 Wtotal -个词语,则 Skip Gram 模型能计算 4 · Wtotal -次损失并进行反向传播学习,对于语料的学习次数是 CBOW -模型的四倍,因此该模型适合于充分利用小语料训练词向量。
    • -
    • Word2Vec -模型训练完成时,输入层与隐藏层之间的权重矩阵即词嵌入矩阵(Word Embedding -Matrix)。离散表示单词的向量与矩阵相乘即得到词向量,这项操作实际上等效于在词嵌入矩阵中查找对应词向量(Embedding -Look -Up)。词向量能够有效表示词的语义关系,其本质是为机器学习模型提供了一种提取文本信息特征的方法,方便将单词数值化输入模型进行处理。传统的语言模型训练词向量在输出 -Softmax 层开销太大,
    • -
    • 而 Word2Vec 模型采用了分层 Softmax(Hierarchical -Softmax)和噪声对比估计(Noise Contrastive -Estimation)两种技术,大大加速了训练,使得在自然语言处理中使用大规模语料训练出的优质词向量成为可能。
    • -
    -

    注意力

    -
      -
    • 在 NLP -任务中注意力机制最早应用于机器翻译,即引入一个权重矩阵代表编码器序列中各个元素对解码器生成的每一个词的贡献程度。在实际实现时注意力机制会生成一个注意力权重,对各个编码器元素的隐藏层状态进行注意力加权生成中间表示,而不是简单的采用最后一个元素的隐藏层状态。最简单的注意力即解码器对编码器的注意力,分为全局和局部注意力。全局注意力生成对整个编码器序列的注意力权重,而局部注意力先训练出一个注意力对齐位置,再对此位置附近取一个窗口,仅对窗口内的序列加权,使得注意力更加精确、集中。注意力机制带来的一个副产品即词与词之间的对齐Alignment)。在机器翻译中,对齐关系可以理解为词到翻译词的关联程度。在自动文摘中采用注意力机制,可以有效缓解长序列经过编码器编码成中间表示时的信息损失问题。 -
    • -
    -

    序列到序列

    -
      -
    • seq2seq模型,即使用一个RNN作为编码器,编码输入的序列数据得到中间语义表示,再利用另外一个RNN作为解码器,利用中间语义表示得到序列化的输出。广义的序列到序列以及端到端学习不一定使用RNN,也可以用CNN或者纯注意力机制。 -
    • -
    • 对于序列到序列模型的一些个人理解: -
        -
      • (信息论)如果不考虑编码器和解码器的具体实现形式,只认为编码器可以将序列数据转化为中间表示,解码器可以将中间表示转化为序列数据,则整个序列到序列模型相当于对文摘信息的一次编码解码,由于中间表示的维度远小于编码器的总维度,因此这种编码是有损编码。序列到序列模型要使得有损编码的结果是提取原文中的文摘信息,因此训练网络的目标是让损失的部分为文摘不需要的冗余信息。解码器相当于编码器的逆过程,从包含文摘信息的中间表示中还原出文摘的序列形式数据。
      • -
      • (学习与应用)将整个模型比作人类的大脑,则编码器的隐藏层状态相当于大脑内存储的知识,解码器则是利用这些知识解决问题,即编码器是一个学习过程而解码器是一个应用过程。这种比喻能够形象地解释后来对序列到序列模型的各种改进:时间步上的学习对应现实时间线上的学习,越早学习的知识在大脑中越容易忘记(靠前的时间步隐藏层信息传递到最终步时信息丢失严重),且大脑的容量一定(中间表示的信息存储容量一定),因此学习时我们选择性记忆和忘记信息(LSTM -和 GRU -的应用),并且在记忆的过程中划重点(注意力机制),甚至还可以借助向外界环境查询信息,不完全靠自己的记忆解决问题(记忆网络)。
      • -
      • (循环神经网络)完全从数据流和网络结构的角度看,整个序列到序列模型可以看作一个长的、限定了某些时间步输入输出的 -RNN,以图 3-1 为例,模型就是一个具有 8 个时间步的 RNN,前 5 -时间步没有输出,后 3 -个时间步将输出传递到下一时间步指导状态变化。编码器和解码器联合训练即相当于对这个大型RNN -进行训练。这种只在部分节点进行输入输出的 RNN -从结构上就适合处理序列到序列任务。
      • -
    • -
    -

    序列损失

    -
      -
    • 解码器每一步解码出来的实际上时词典的概率分布,取最大概率的词输出(或者做束搜索),损失是每一步的概率和这一步标准词语的01分布做交叉熵,求和再平均。实际上还要应用一个mask来解决句子长度不一定的问题。
    • -
    -

    基本模型

    -
      -
    • 预处理:应用序列到序列模型需要对数据进行一定的预处理,除了常用的去停用词加UNK,以及padding之外,还需要设计解码的开始与结束符号,如下: -
    • -
    • 训练好词嵌入之后,对输入做一个embedding lookup的操作得到特征 i0T6Ej.jpg
    • -
    • 特征输入编码器得到中间表示 i0Tg5n.png
    • -
    • 拿到中间表示和输出文摘(相当于label),输入解码器进行解码 i0TIrF.png
    • -
    • 加入注意力机制后完整的序列到序列模型结构如下: i0TRCq.jpg
    • -
    -

    情感融合机制

    -
      -
    • 情感机制主要是为文本补充了情感特征,通过查找情感词典的方式手动构造了一个六维的特征,未来希望能够用自动构造特征的方式来进行这方面工作。
    • -
    • 先训练情感分类器,对原语料进行了筛选形成情感语料,在情感语料和普通语料上都测试了模型 -
    • -
    • 查找词典得到情感向量(即情感特征) i0Tf2V.jpg
    • -
    • 将情感特征直接拼接在中间表示之后,输入解码器 i0ThvT.jpg
    • -
    -

    结果

    -
      -
    • 结果由ROUGE-F1值形式记录,情感语料下各种方法对比 i0T5KU.png
    • -
    • 普通语料下情感融合方案对比 i0Tb5R.png
    • -
    • 情感分类准确率,作为参考,之前训练的情感分类器准确率为74% i0Tob4.png
    • -
    • 因为是大语料小batch训练,只训练了十次迭代,各个迭代的测试集效果 i0T7VJ.png
    • -
    -

    问题

    -
      -
    • unk替换问题:在很多文献中都提到了使用指针开关技术解决生成文摘中的罕见词(unk),即从原文中挑选词语替换掉文摘中的unk,但是由于ROUGE评测的是词的共现程度,因此只要替换了原文的词,哪怕位置、词语不对,都有可能是ROUGE值上升,造成评测结果偏高,本文设计了对比试验,发现即便是没有采用任何机制的随机替换都能提高ROUGE值 -
    • -
    • 语料重复问题:在检查语料时我们发现了大量短文本不同但短文摘相同的语料,重复的语料来自于对于相同事件的不同描述,或者一些功能性的文字,翻译过来例如“...... -周三...... -黄金价格上涨”和“......周四......黄金价格上涨”均生成相同的文摘“黄金价格上涨”。短文摘重复的语料会导致模型在解码端学到一些不应该固化的短语,而如果训练集和测试集中有重复的相同的文摘,则固化的文摘反而会导致生成文摘正确率虚高。对于这类文本,本文进行了四组实验: -
        -
      • 不去重:保留原文本,不去重,进行训练和测试
      • -
      • 去重:删除语料中所有重复文摘对应的的短文本-短文摘对。
      • -
      • 训练去重:部分去重,只将训练语料中的重复数据删除,即学习好的模型已经没有受到重复文本的影响。
      • -
      • 测试去重:部分去重,只将测试集中与训练集重复的部分删除,学习好的模型受到了重复文本的影响,但测试集中没有与重复文本中相对应的数据。 -重复的语料训练下 ROUGE-1 和 ROUGE-L 都突破了 -30,远超正常训练的模型,去重之后便恢复到正常水平。两种部分去重的结果则分别表明:训练去重时,没有受重复语料影响的模型对于测试集中的重复数据没有明显的反应,与完全去重的普通模型近似;测试去重时,虽然模型受到了重复语料影响,但是测试集中没有重复的数据让其利用学习到的固化的文摘,因此结果也不会虚高,且由于学习到了不同短文对应相同文摘的模式,编码端实际上结构更加灵活,导致 -ROUGE 指标高于训练去重的结果。 i0TLP1.png
      • -
    • -
    -

    实现环境

    -
      -
    • 这里是github地址:- Abstract_Summarization_Tensorflow
    • -
    • Ubuntu 16.04
    • -
    • Tensorflow 1.6
    • -
    • CUDA 9.0
    • -
    • Cudnn 7.1.2
    • -
    • Gigawords数据集,训练了部分数据,约30万
    • -
    • GTX1066,训练时间3到4个小时
    • -
    -

    参考文献

    -

    -]]>
    - - 自然语言处理 - - - machine learning - abstractive summarization - nlp - seq2seq - rnn - lstm - gru - -
    diff --git a/sitemap.xml b/sitemap.xml index cf041c60..b63e7ada 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,108 +2,108 @@ - https://thinkwee.top/about/index.html + https://thinkwee.top/hiring/index.html - 2024-01-31 + 2024-03-11 monthly 0.6 - https://thinkwee.top/memory/index.html + https://thinkwee.top/tags/index.html - 2023-12-12 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2023/07/20/marl/ + https://thinkwee.top/memory/index.html - 2023-09-05 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2023/06/05/gpt-debate/ + https://thinkwee.top/google785ae9e190b58461.html - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/tags/index.html + https://thinkwee.top/game/data/Weapons.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/google785ae9e190b58461.html + https://thinkwee.top/game/data/Map003.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/System.json + https://thinkwee.top/game/data/MapInfos.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/States.json + https://thinkwee.top/game/data/Skills.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Tilesets.json + https://thinkwee.top/game/data/States.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Troops.json + https://thinkwee.top/game/data/System.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Weapons.json + https://thinkwee.top/game/data/Tilesets.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Skills.json + https://thinkwee.top/game/data/Troops.json - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -112,25 +112,25 @@ https://thinkwee.top/game/data/Armors.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/CommonEvents.json + https://thinkwee.top/game/data/Classes.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Classes.json + https://thinkwee.top/game/data/CommonEvents.json - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -139,7 +139,7 @@ https://thinkwee.top/game/data/Enemies.json - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -148,7 +148,7 @@ https://thinkwee.top/game/data/Items.json - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -157,142 +157,142 @@ https://thinkwee.top/game/data/Map001.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Map003.json + https://thinkwee.top/game/data/Map002.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Map002.json + https://thinkwee.top/game/data/Actors.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/MapInfos.json + https://thinkwee.top/game/data/Animations.json - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Animations.json + https://thinkwee.top/categories/index.html - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/game/data/Actors.json + https://thinkwee.top/2019/03/20/vae/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/categories/index.html + https://thinkwee.top/2020/05/15/vc-dimension/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/05/02/trie/ + https://thinkwee.top/about/index.html - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2021/05/11/text-edit-generation/ + https://thinkwee.top/2018/08/09/statistical-handwriting/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/03/20/vae/ + https://thinkwee.top/2017/01/16/setupmywebsite/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/05/15/vc-dimension/ + https://thinkwee.top/2020/02/28/structured-summarization/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/01/16/setupmywebsite/ + https://thinkwee.top/2020/02/13/svm/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/08/09/statistical-handwriting/ + https://thinkwee.top/2021/05/11/text-edit-generation/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/02/28/structured-summarization/ + https://thinkwee.top/2017/05/02/trie/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/02/13/svm/ + https://thinkwee.top/2017/03/27/oj/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/03/27/oj/ + https://thinkwee.top/2021/05/13/pet/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -301,7 +301,7 @@ https://thinkwee.top/2017/02/04/pandas-skill/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -310,43 +310,43 @@ https://thinkwee.top/2020/02/07/reformer/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2021/05/13/pet/ + https://thinkwee.top/2018/07/04/seq2seq-summarization/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/07/04/seq2seq-summarization/ + https://thinkwee.top/2018/07/23/lda/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/03/16/kmeans/ + https://thinkwee.top/2018/10/14/lr-and-me/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/10/14/lr-and-me/ + https://thinkwee.top/2023/07/20/marl/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -355,16 +355,16 @@ https://thinkwee.top/2017/01/23/numpycookbook/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/07/23/lda/ + https://thinkwee.top/2019/11/15/hlda/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -373,25 +373,25 @@ https://thinkwee.top/2020/03/17/incremental-decoding/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/08/09/interview201906/ + https://thinkwee.top/2018/08/28/inference-algorithm/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/08/28/inference-algorithm/ + https://thinkwee.top/2019/08/09/interview201906/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -400,88 +400,88 @@ https://thinkwee.top/2019/11/13/kg/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/10/30/heterogeneous/ + https://thinkwee.top/2017/03/16/kmeans/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/10/03/graph-summarization/ + https://thinkwee.top/2020/04/05/graph-doc-thesis/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/11/15/hlda/ + https://thinkwee.top/2019/10/03/graph-summarization/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/04/05/graph-doc-thesis/ + https://thinkwee.top/2019/10/30/heterogeneous/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/05/26/dachuangserver/ + https://thinkwee.top/2018/09/22/deepbayes2018/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/09/22/deepbayes2018/ + https://thinkwee.top/2019/09/23/easyrl/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/09/23/easyrl/ + https://thinkwee.top/2019/01/13/glove/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/03/09/dachuang/ + https://thinkwee.top/2023/06/05/gpt-debate/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/01/13/glove/ + https://thinkwee.top/2020/03/30/cs224w/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -490,34 +490,34 @@ https://thinkwee.top/2018/10/13/compute-future/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/03/30/cs224w/ + https://thinkwee.top/2017/03/09/dachuang/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/11/16/coling/ + https://thinkwee.top/2017/05/26/dachuangserver/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2020/03/02/bertology/ + https://thinkwee.top/2017/01/16/buptroomreview/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -526,97 +526,97 @@ https://thinkwee.top/2020/03/27/clscisumm/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/01/16/buptroomreview/ + https://thinkwee.top/2018/11/16/coling/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/01/03/PaperReading3/ + https://thinkwee.top/2019/08/15/acl2019-summarization/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/03/28/PythonNotes/ + https://thinkwee.top/2020/03/02/bertology/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/02/07/TitanicLinearRegression/ + https://thinkwee.top/2019/07/28/acl2019/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/07/28/acl2019/ + https://thinkwee.top/2019/01/03/PaperReading3/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/08/15/acl2019-summarization/ + https://thinkwee.top/2017/03/28/PythonNotes/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/03/07/NLPBasic/ + https://thinkwee.top/2017/02/07/TitanicLinearRegression/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/07/03/PaperReading2/ + https://thinkwee.top/2018/03/07/PaperReading/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2018/03/07/PaperReading/ + https://thinkwee.top/2018/03/07/NLPBasic/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/01/21/LinearAlgebra1/ + https://thinkwee.top/2018/07/03/PaperReading2/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -625,52 +625,61 @@ https://thinkwee.top/2017/01/22/LinearAlgebra3/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/01/21/LinearAlgebra2/ + https://thinkwee.top/2017/02/12/MachineLearningNote/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/02/12/MachineLearningNote/ + https://thinkwee.top/2017/03/18/Lagrange/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/08/13/CogGraph/ + https://thinkwee.top/2017/01/21/LinearAlgebra1/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2019/07/29/CorEx/ + https://thinkwee.top/2017/01/21/LinearAlgebra2/ - 2023-06-09 + 2024-03-11 monthly 0.6 - https://thinkwee.top/2017/03/18/Lagrange/ + https://thinkwee.top/2019/08/13/CogGraph/ - 2023-06-09 + 2024-03-11 + + monthly + 0.6 + + + + https://thinkwee.top/2019/07/29/CorEx/ + + 2024-03-11 monthly 0.6 @@ -679,7 +688,7 @@ https://thinkwee.top/2019/12/16/201912/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -688,7 +697,7 @@ https://thinkwee.top/2017/12/27/AM-Model-for-ASS/ - 2023-06-09 + 2024-03-11 monthly 0.6 @@ -697,7 +706,7 @@ https://thinkwee.top/ - 2024-01-31 + 2024-03-11 daily 1.0 @@ -705,406 +714,406 @@ https://thinkwee.top/tags/graph-neural-network/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/deep-learning/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/summarization/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/natural-language-processing/ - 2024-01-31 + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/machine-learning/ - 2024-01-31 + https://thinkwee.top/tags/abstractive-summarization/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/gnn/ - 2024-01-31 + https://thinkwee.top/tags/math/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/bert/ - 2024-01-31 + https://thinkwee.top/tags/machine-learning/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/corex/ - 2024-01-31 + https://thinkwee.top/tags/theory/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/math/ - 2024-01-31 + https://thinkwee.top/tags/nlp/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/topic-model/ - 2024-01-31 + https://thinkwee.top/tags/gnn/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/abstractive-summarization/ - 2024-01-31 + https://thinkwee.top/tags/bert/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/theory/ - 2024-01-31 + https://thinkwee.top/tags/corex/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/nlp/ - 2024-01-31 + https://thinkwee.top/tags/topic-model/ + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/code/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/linearalgebra/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/python/ - 2024-01-31 + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/workshop/ - 2024-01-31 + https://thinkwee.top/tags/android/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/comprehension/ - 2024-01-31 + https://thinkwee.top/tags/workshop/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/NLI/ - 2024-01-31 + https://thinkwee.top/tags/graph/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/android/ - 2024-01-31 + https://thinkwee.top/tags/comprehension/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/graph/ - 2024-01-31 + https://thinkwee.top/tags/NLI/ + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/server/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/linux/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/bayes/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/reinforcement-learning/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/glove/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/word-embedding/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/GPT/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/NLP/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/LLM/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/heterogeneous-information-network/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/lda/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/inference/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/seq2seq/ - 2024-01-31 + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/interview/ - 2024-01-31 + https://thinkwee.top/tags/mcmc/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/mcmc/ - 2024-01-31 + https://thinkwee.top/tags/variational-inference/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/variational-inference/ - 2024-01-31 + https://thinkwee.top/tags/em/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/em/ - 2024-01-31 + https://thinkwee.top/tags/interview/ + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/knowledge-graph/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/logistic-regression/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/multi-agent/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/c/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/tags/algorithm/ - 2024-01-31 + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/local-sensitive-hashing/ - 2024-01-31 + https://thinkwee.top/tags/pretrained-language-model/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/transformer/ - 2024-01-31 + https://thinkwee.top/tags/pet/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/web/ - 2024-01-31 + https://thinkwee.top/tags/few-shot/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/hexo/ - 2024-01-31 + https://thinkwee.top/tags/local-sensitive-hashing/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/github/ - 2024-01-31 + https://thinkwee.top/tags/transformer/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/statistical-learning/ - 2024-01-31 + https://thinkwee.top/tags/rnn/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/svm/ - 2024-01-31 + https://thinkwee.top/tags/lstm/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/vae/ - 2024-01-31 + https://thinkwee.top/tags/gru/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/pretrained-language-model/ - 2024-01-31 + https://thinkwee.top/tags/statistical-learning/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/pet/ - 2024-01-31 + https://thinkwee.top/tags/web/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/few-shot/ - 2024-01-31 + https://thinkwee.top/tags/hexo/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/vc-dimension/ - 2024-01-31 + https://thinkwee.top/tags/github/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/rnn/ - 2024-01-31 + https://thinkwee.top/tags/svm/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/lstm/ - 2024-01-31 + https://thinkwee.top/tags/vae/ + 2024-03-11 weekly 0.2 - https://thinkwee.top/tags/gru/ - 2024-01-31 + https://thinkwee.top/tags/vc-dimension/ + 2024-03-11 weekly 0.2 @@ -1113,63 +1122,63 @@ https://thinkwee.top/categories/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E6%95%B0%E5%AD%A6/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/Python/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/Android/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E9%9D%A2%E8%AF%95/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E7%AE%97%E6%B3%95/ - 2024-01-31 + 2024-03-11 weekly 0.2 https://thinkwee.top/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/ - 2024-01-31 + 2024-03-11 weekly 0.2 diff --git a/tags/GPT/index.html b/tags/GPT/index.html index a6d24daa..1743c442 100644 --- a/tags/GPT/index.html +++ b/tags/GPT/index.html @@ -140,6 +140,11 @@

    Thinkwee's Blog

    Memory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +