Naive Softmax&Negative Sampling

Naive Softmax&Negative Sampling

1 Naive Softmax

引入两个向量:对于词汇表 V \mathbf{V} V(vocabulary)中的每个单词w,当 w w w是center单词的时候,使用 d d d维向量 v w \mathbf{v_w} vw表示,当 w w w是context单词的时候,使用 u w \mathbf{u_w} uw表示。

所以对于给定center单词 c预测context单词o出现的概率:
p ( o ∣ c ) = e x p ( u o T v c ) ∑ w ∈ V e x p ( u w T v c ) p(o|c)=\frac{exp(\mathbf{u_o^T}\mathbf{v_c})}{\sum_{w\in {V}}exp(\mathbf{u_w^T}\mathbf{v_c})} p(oc)=wVexp(uwTvc)exp(uoTvc)
其中 V V V代表词汇表(vocabulary) u o T v c \mathbf{u_o^T}\mathbf{v_c} uoTvc即向量的点积(dot product),点积的大小暗示了o与c之间的相似度,这里引入指数的目的是最后生成规范的概率(softmax的概念)。

损失定义为:
J = − log ⁡ e x p ( u o T v c ) ∑ w = 1 V e x p ( u w T v c ) = − log ⁡ e x p ( u o T v c ) + log ⁡ ∑ w = 1 V e x p ( u w T v c ) = − u o T v c + log ⁡ ∑ w = 1 V e x p ( u x T v c ) \begin{aligned} J &= -\log \frac{exp(\mathbf{u_o^T}\mathbf{v_c})}{\sum_{w=1}^{V} exp(\mathbf{u_w^T}\mathbf{v_c})} \\ &=-\log exp(\mathbf{u_o^T}\mathbf{v_c})+ \log \sum_{w=1}^{V} exp(\mathbf{u_w^T}\mathbf{v_c})\\ &=-\mathbf{u_o^T}\mathbf{v_c} + \log \sum_{w=1}^{V} exp(\mathbf{u_x^T}\mathbf{v_c})\\ \end{aligned} J=logw=1Vexp(uwTvc)exp(uoTvc)=logexp(uoTvc)+logw=1Vexp(uwTvc)=uoTvc+logw=1Vexp(uxTvc)

对于 v c v_c vc的梯度为:
∂ ∂ v c − log ⁡ e x p ( u o T v c ) ∑ w ∈ V e x p ( u w T v c ) = − ∂ ∂ v c log ⁡ e x p ( u o T v c ) + ∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) = − ∂ ∂ v c u o T v c + ∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) \begin{aligned} \frac{\partial}{\partial \mathbf{v_c}}-\log\frac{exp(\mathbf{u_o^T}\mathbf{v_c})}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}&=-\frac{\partial}{\partial \mathbf{v_c}}\log exp(\mathbf{u_o^T}\mathbf{v_c})+\frac{\partial}{\partial \mathbf{v_c}}\log \sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})\\ &=-\frac{\partial}{\partial \mathbf{v_c}}\mathbf{u_o^T}\mathbf{v_c}+\frac{\partial}{\partial \mathbf{v_c}}\log \sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c}) \end{aligned} vclogwVexp(uwTvc)exp(uoTvc)=vclogexp(uoTvc)+vclogwVexp(uwTvc)=vcuoTvc+vclogwVexp(uwTvc)
到这里左边的 ∂ ∂ v c u o T v c \frac{\partial}{\partial \mathbf{v_c}}\mathbf{u_o^T}\mathbf{v_c} vcuoTvc结果为 u o u_o uo,右边的 ∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) \frac{\partial}{\partial \mathbf{v_c}}\log \sum_{w\in V}exp(\mathbf{u_w}^T\mathbf{v_c}) vclogwVexp(uwTvc)求解要用到链式法则(chain rule):
∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) = 1 ∑ w ∈ V e x p ( u w T v c ) ∂ ∂ v c ∑ x ∈ V e x p ( u x T v c ) = 1 ∑ w ∈ V e x p ( u w T v c ) ∑ x ∈ V ∂ ∂ v c e x p ( u x T v c ) = 1 ∑ w ∈ V e x p ( u w T v c ) ∑ x ∈ V e x p ( u x T v c ) ∂ ∂ v c u x T v c = 1 ∑ w ∈ V e x p ( u w T v c ) ∑ x ∈ V e x p ( u x T v c ) u x = ∑ x ∈ V e x p ( u x T v c ) u x ∑ w ∈ V e x p ( u w T v c ) = ∑ x ∈ V e x p ( u x T v c ) ∑ w ∈ V e x p ( u w T v c ) u x \begin{aligned} \frac{\partial}{\partial v_c}\log \sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})&=\frac{1}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\frac{\partial}{\partial \mathbf{v_c}}\sum_{x\in V}exp(\mathbf{u_x^T}\mathbf{v_c})\\ &=\frac{1}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\sum_{x\in V}\frac{\partial}{\partial \mathbf{v_c}}exp(\mathbf{u_x^T}\mathbf{v_c})\\ &=\frac{1}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\sum_{x\in V}exp(\mathbf{u_x^T}\mathbf{v_c})\frac{\partial}{\partial v_c}\mathbf{u_x^T}\mathbf{v_c}\\ &=\frac{1}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\sum_{x\in V}exp(\mathbf{u_x^T}\mathbf{v_c})\mathbf{u_x}\\ &=\frac{\sum_{x\in V}exp(\mathbf{u_x^T}\mathbf{v_c})\mathbf{u_x}}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\\ &=\sum_{x\in V}\frac{exp(\mathbf{u_x^T}\mathbf{v_c})}{\sum_{w\in V}exp(\mathbf{u_w^T}\mathbf{v_c})}\mathbf{u_x} \end{aligned} vclogwVexp(uwTvc)=wVexp(uwTvc)1vcxVexp(uxTvc)=wVexp(uwTvc)1xVvcexp(uxTvc)=wVexp(uwTvc)1xVexp(uxTvc)vcuxTvc=wVexp(uwTvc)1xVexp(uxTvc)ux=wVexp(uwTvc)xVexp(uxTvc)ux=xVwVexp(uwTvc)exp(uxTvc)ux

将两个结果带回原式:
∂ ∂ v c log ⁡ e x p ( u o T v c ) ∑ w ∈ V e x p ( u w T v c ) = − ∂ ∂ v c log ⁡ e x p ( u o T v c ) + ∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) = − ∂ ∂ v c u o T v c + ∂ ∂ v c log ⁡ ∑ w ∈ V e x p ( u w T v c ) = − u o + ∑ x ∈ V e x p ( u x T v c ) ∑ w ∈ V e x p ( u w T v c ) u x = u o + ∑ x ∈ V p ( x ∣ c ) u x \begin{aligned} \frac{\partial}{\partial v_c}\log\frac{exp(u_o^Tv_c)}{\sum_{w\in V}exp(u_w^Tv_c)}&=-\frac{\partial}{\partial v_c}\log exp(u_o^Tv_c)+\frac{\partial}{\partial v_c}\log \sum_{w\in V}exp(u_w^Tv_c)\\ &=-\frac{\partial}{\partial v_c}u_o^Tv_c+\frac{\partial}{\partial v_c}\log \sum_{w\in V}exp(u_w^Tv_c)\\ &=-u_o+\sum_{x\in V}\frac{exp(u_x^Tv_c)}{\sum_{w\in V}exp(u_w^Tv_c)}u_x\\ &=u_o+\sum_{x\in V}p(x|c)u_x \end{aligned} vclogwVexp(uwTvc)exp(uoTvc)=vclogexp(uoTvc)+vclogwVexp(uwTvc)=vcuoTvc+vclogwVexp(uwTvc)=uo+xVwVexp(uwTvc)exp(uxTvc)ux=uo+xVp(xc)ux

下面求 u o u_o uo的梯度
∂ J ∂ u o = ∂ ∂ u o ( − u o T v c + log ⁡ ∑ w = 1 V e x p ( u w T v c ) ) = ∂ ∂ u o − u o T v c + ∂ ∂ u o log ⁡ ∑ w = 1 V e x p ( u w T v c ) = − v c + 1 ∑ w = 1 V e x p ( u w T v c ) ∑ w = 1 V ∂ ∂ u o e x p ( u w T v c ) = − v c + 1 ∑ w = 1 V e x p ( u w T v c ) e x p ( u w T v c ) v c = − v c + p ( o ∣ c ) v c = ( p ( o ∣ c ) − 1 ) v c \begin{aligned} \frac{\partial J}{\partial u_o}&=\frac{\partial}{\partial u_o}\left ( -u_o^Tv_c + \log \sum_{w=1}^V exp(u_w^Tv_c) \right)\\ &=\frac{\partial}{\partial u_o}-u_o^Tv_c+\frac{\partial}{\partial u_o}\log \sum_{w=1}^V exp(u_w^Tv_c)\\ &=-v_c+\frac{1}{\sum_{w=1}^V exp(u_w^Tv_c)}\sum_{w=1}^V\frac{\partial}{\partial u_o} exp(u_w^Tv_c)\\ &=-v_c+\frac{1}{\sum_{w=1}^V exp(u_w^Tv_c)} exp(u_w^Tv_c)v_c\\ &=-v_c+p(o|c)v_c\\ &=(p(o|c)-1)v_c \end{aligned} uoJ=uo(uoTvc+logw=1Vexp(uwTvc))=uouoTvc+uologw=1Vexp(uwTvc)=vc+w=1Vexp(uwTvc)1w=1Vuoexp(uwTvc)=vc+w=1Vexp(uwTvc)1exp(uwTvc)vc=vc+p(oc)vc=(p(oc)1)vc
下面求除 u o u_o uo之外outside vector的梯度,不失一般性,令其为 u x u_x ux
∂ J ∂ u x = ∂ ∂ u x ( − u o T v c + log ⁡ ∑ w = 1 V e x p ( u w T v c ) ) = ∂ ∂ u x log ⁡ ∑ w = 1 V e x p ( u w T v c ) = 1 ∑ w = 1 V e x p ( u w T v c ) ∑ w = 1 V ∂ ∂ u x e x p ( u w T v c ) = 1 ∑ w = 1 V e x p ( u w T v c ) e x p ( u x T v c ) v c = p ( x ∣ c ) v c \begin{aligned} \frac{\partial J}{\partial u_x}&=\frac{\partial}{\partial u_x}\left ( -u_o^Tv_c + \log \sum_{w=1}^V exp(u_w^Tv_c) \right)\\ &=\frac{\partial}{\partial u_x}\log \sum_{w=1}^V exp(u_w^Tv_c)\\ &=\frac{1}{\sum_{w=1}^V exp(u_w^Tv_c)}\sum_{w=1}^V\frac{\partial}{\partial u_x} exp(u_w^Tv_c)\\ &=\frac{1}{\sum_{w=1}^V exp(u_w^Tv_c)} exp(u_x^Tv_c)v_c\\ &=p(x|c)v_c \end{aligned} uxJ=ux(uoTvc+logw=1Vexp(uwTvc))=uxlogw=1Vexp(uwTvc)=w=1Vexp(uwTvc)1w=1Vuxexp(uwTvc)=w=1Vexp(uwTvc)1exp(uxTvc)vc=p(xc)vc

2 Negative Sampling

关于训练,一个非常消耗计算资源的问题就是softmax的计算
p ( o ∣ c ) = e x p ( u o T v c ) ∑ w ∈ V e x p ( u w T v c ) p(o|c) = \frac{exp(u_o^Tv_c)}{\sum_{w\in V}exp(u_w^Tv_c)} p(oc)=wVexp(uwTvc)exp(uoTvc)
可以看出分母要计算词汇表(vacabulary)里所有单词与目标单词的点积,然后计算其自然指数的和,所以Mikilov在Distributed representations of words and phrases and their compositionality 中提出了Negative Sampling的技巧来解决这个问题。

负采样目的就是避免计算 v c \mathbf{v_c} vc与整个单词表 U \mathbf{U} U的点积,所以作者的做法是从词汇表中抽出一部分共现概率低的单词作为负样本,损失函数定义如下。这样优化的过程中,会使单词 o o o与单词 c c c的共现(co-occurrence)概率变大,而 K K K个负样本单词与单词 c c c的共现(co-occurrence)概率变低。

negative sampling的损失函数定义如下:
J n e g − s a m p l e ( o , v c , U ) = − log ⁡ σ ( u o T v c ) − ∑ j = 1 K [ log ⁡ σ ( − u j T v c ) ] J_{neg-sample}(o,v_c,U) = -\log\sigma(u_o^Tv_c)- \sum_{j=1}^{K}[\log\sigma(-u_j^Tv_c)] Jnegsample(o,vc,U)=logσ(uoTvc)j=1K[logσ(ujTvc)]
σ ( − u j T v c ) = 1 − σ ( u j T v c ) \sigma(-u_j^Tv_c)=1-\sigma(u_j^Tv_c) σ(ujTvc)=1σ(ujTvc),所以损失可以写为:
J n e g − s a m p l e ( o , v c , U ) = − log ⁡ σ ( u o T v c ) − ∑ j = 1 K log ⁡ ( 1 − σ ( u j T v c ) ) J_{neg-sample}(o,v_c,U) = -\log\sigma(u_o^Tv_c)- \sum_{j=1}^{K}\log\left ( 1-\sigma(u_j^Tv_c) \right ) Jnegsample(o,vc,U)=logσ(uoTvc)j=1Klog(1σ(ujTvc))
然后用向量化表示,使用 W \mathbf{W} W(K+1, d)代表用到的参数, W = ( u o T u 1 T . . . u K T ) \mathbf{W}=\left(\begin{array}{ccc} \mathbf{u_o}^T \\ \mathbf{u_1}^T\\ ...\\ \mathbf{u_K}^T \end{array} \right) W=uoTu1T...uKT,令 y = ( 1 0 . . . 0 ) \mathbf{y}=\left(\begin{array}{ccc} 1 \\ 0\\ ...\\ 0\end{array} \right) y=10...0,令 L ( W , v c , y ) = y ⋅ σ ( W v c ) + ( 1 − y ) ⋅ σ ( W v c ) L(\mathbf{W}, \mathbf{v_c}, \mathbf{y})=y\cdot\sigma(\mathbf{W}\mathbf{v_c}) +(1-y)\cdot \sigma(\mathbf{W}\mathbf{v_c}) L(W,vc,y)=yσ(Wvc)+(1y)σ(Wvc),上述损失可写成:
J n e g − s a m p l e ( L ) = ∑ i = 1 K + 1 − L i J_{neg-sample}(\mathbf{L}) = \sum_{i=1}^{K+1}-L_i Jnegsample(L)=i=1K+1Li
首先计算 v c v_c vc的偏导,其中用到了sigmoid的导数, σ ′ ( z ) = σ ( z ) [ 1 − σ ( z ) ] \sigma'(z)=\sigma(z)[1-\sigma(z)] σ(z)=σ(z)[1σ(z)]
∂ J ∂ v c = − ( ∂ ∂ v c log ⁡ σ ( u o T v c ) + ∂ ∂ v c ∑ j = 1 K log ⁡ ( 1 − σ ( u j T v c ) ) ) = − ( 1 σ ( u o T v c ) ∂ ∂ v c σ ( u o T v c ) + ∑ j = 1 K ∂ ∂ v c log ⁡ ( 1 − σ ( u j T v c ) ) ) = − ( 1 σ ( u o T v c ) σ ( u o T v c ) ( 1 − σ ( u o T v c ) ) ∂ ∂ v c u o T v c + ∑ j = 1 K 1 1 − σ ( u j T v c ) ∂ ∂ v c σ ( u j T v c ) ) = − ( ( 1 − σ ( u o T v c ) ) u o + ∑ j = 1 K 1 1 − σ ( u j T v c ) σ ( u j T v c ) ( 1 − σ ( u j T v c ) ) ∂ ∂ v c u j T v c ) = − ( ( 1 − σ ( u o T v c ) ) u o + ∑ j = 1 K σ ( u j T v c ) u j ) \begin{aligned} \frac{\partial J}{\partial v_c} &= -\left ( \frac{\partial}{\partial v_c}\log\sigma(u_o^Tv_c)+ \frac{\partial}{\partial v_c}\sum_{j=1}^{K}\log\left ( 1-\sigma(u_j^Tv_c) \right) \right)\\ &=-\left ( \frac{1}{\sigma(u_o^Tv_c)}\frac{\partial}{\partial v_c}\sigma(u_o^Tv_c)+ \sum_{j=1}^{K}\frac{\partial}{\partial v_c}\log\left ( 1-\sigma(u_j^Tv_c) \right) \right)\\ &=-\left ( \frac{1}{\sigma(u_o^Tv_c)}\sigma(u_o^Tv_c)(1-\sigma(u_o^Tv_c))\frac{\partial}{\partial v_c}u_o^Tv_c+ \sum_{j=1}^{K}\frac{1}{1-\sigma(u_j^Tv_c)} \frac{\partial}{\partial v_c}\sigma(u_j^Tv_c) \right)\\ &=-\left ( \left(1-\sigma(u_o^Tv_c)\right)u_o+ \sum_{j=1}^{K}\frac{1}{1-\sigma(u_j^Tv_c)} \sigma(u_j^Tv_c) \left(1-\sigma(u_j^Tv_c)\right) \frac{\partial}{\partial v_c}u_j^Tv_c \right)\\ &=-\left ( \left(1-\sigma(u_o^Tv_c)\right)u_o+ \sum_{j=1}^{K}\sigma(u_j^Tv_c) u_j\right)\\ \end{aligned} vcJ=(vclogσ(uoTvc)+vcj=1Klog(1σ(ujTvc)))=(σ(uoTvc)1vcσ(uoTvc)+j=1Kvclog(1σ(ujTvc)))=(σ(uoTvc)1σ(uoTvc)(1σ(uoTvc))vcuoTvc+j=1K1σ(ujTvc)1vcσ(ujTvc))=((1σ(uoTvc))uo+j=1K1σ(ujTvc)1σ(ujTvc)(1σ(ujTvc))vcujTvc)=((1σ(uoTvc))uo+j=1Kσ(ujTvc)uj)
然后是对于 u o u_o uo的求导
∂ J ∂ u o = − ∂ ∂ u o log ⁡ σ ( u o T v c ) = − 1 σ ( u o T v c ) ∂ ∂ u o σ ( u o T v c ) = − 1 σ ( u o T v c ) σ ( u o T v c ) ( 1 − σ ( u o T v c ) ) v c = − ( 1 − σ ( u o T v c ) ) v c = ( σ ( u o T v c ) − 1 ) v c \begin{aligned} \frac{\partial J}{\partial u_o} &= - \frac{\partial}{\partial u_o}\log\sigma(u_o^Tv_c)\\ &= - \frac{1}{\sigma(u_o^Tv_c)}\frac{\partial}{\partial u_o}\sigma(u_o^Tv_c)\\ &= - \frac{1}{\sigma(u_o^Tv_c)}\sigma(u_o^Tv_c)\left (1-\sigma(u_o^Tv_c) \right)v_c\\ &= - \left (1-\sigma(u_o^Tv_c) \right)v_c\\ &= \left (\sigma(u_o^Tv_c)-1 \right)v_c\\ \end{aligned} uoJ=uologσ(uoTvc)=σ(uoTvc)1uoσ(uoTvc)=σ(uoTvc)1σ(uoTvc)(1σ(uoTvc))vc=(1σ(uoTvc))vc=(σ(uoTvc)1)vc
对于negative samples u j u_j uj的求导:
∂ J ∂ u j = − ∂ ∂ u j log ⁡ ( 1 − σ ( u j T v c ) ) = 1 1 − σ ( u j T v c ) ∂ ∂ u j σ ( u j T v c ) = 1 1 − σ ( u j T v c ) σ ( u j T v c ) ( 1 − σ ( u j T v c ) ) v c = σ ( u j T v c ) v c \begin{aligned} \frac{\partial J}{\partial u_j} &= - \frac{\partial}{\partial u_j}\log\left ( 1-\sigma(u_j^Tv_c) \right) \\ &= \frac{1}{1-\sigma(u_j^Tv_c)} \frac{\partial}{\partial u_j}\sigma(u_j^Tv_c) \\ &= \frac{1}{1-\sigma(u_j^Tv_c)}\sigma(u_j^Tv_c) \left( 1-\sigma(u_j^Tv_c) \right)v_c\\ &= \sigma(u_j^Tv_c)v_c\\ \end{aligned} ujJ=ujlog(1σ(ujTvc))=1σ(ujTvc)1ujσ(ujTvc)=1σ(ujTvc)1σ(ujTvc)(1σ(ujTvc))vc=σ(ujTvc)vc

3 An implementation of Naive Softmax

def softmax(x):
    """Compute the softmax function for each row of the input x.

    Arguments:
    x -- A D dimensional vector or N x D dimensional numpy matrix.
    Return:
    x -- You are allowed to modify x in-place
    """
    orig_shape = x.shape

    if len(x.shape) > 1:
        # Matrix
        tmp = np.max(x, axis=1)
        x -= tmp.reshape((x.shape[0], 1))
        x = np.exp(x)
        tmp = np.sum(x, axis=1)
        x /= tmp.reshape((x.shape[0], 1))
    else:
        # Vector
        tmp = np.max(x)
        x -= tmp
        x = np.exp(x)
        tmp = np.sum(x)
        x /= tmp

    assert x.shape == orig_shape
    return x
    
def naiveSoftmaxLossAndGradient(
    centerWordVec,
    outsideWordIdx,
    outsideVectors,
    dataset
):
    """ Naive Softmax loss & gradient function for word2vec models

    Arguments:
    centerWordVec -- numpy ndarray, center word's embedding
                    (v_c in the pdf handout)
    outsideWordIdx -- integer, the index of the outside word
                    (o of u_o in the pdf handout)
    outsideVectors -- outside vectors (rows of matrix) for all words in vocab
                      (U in the pdf handout)
    dataset -- needed for negative sampling, unused here.

    Return:
    loss -- naive softmax loss
    gradCenterVec -- the gradient with respect to the center word vector
                     (dJ / dv_c)
    gradOutsideVecs -- the gradient with respect to all the outside word vectors
                    (dJ / dU)
    """

    # Forward
    centerWordVec = centerWordVec.reshape((centerWordVec.shape[0], 1))        # (d, 1)
    z = np.dot(outsideVectors, centerWordVec)       # (V, 1) = (V, d)x(d, 1)
    prob = softmax(z.reshape(-1)).reshape(-1, 1)        # (V, 1)
    loss = -np.log(prob[outsideWordIdx])        # negative log-probability

    # Back propagation
    cProb = prob.copy() # (V, 1)
    cProb[outsideWordIdx] -= 1.0
    gradCenterVec = np.dot(outsideVectors.T, cProb)     # (d, 1) = (d, V)x(V, 1)
    gradOutsideVecs = np.dot(cProb, centerWordVec.T)        # (V, d) = (V, 1)x(1, d)
    gradCenterVec = gradCenterVec.flatten()

    return loss, gradCenterVec, gradOutsideVecs

4 An implementation of Negative Sampling

def sigmoid(x):
    """
    Compute the sigmoid function for the input here.
    Arguments:
    x -- A scalar or numpy array.
    Return:
    s -- sigmoid(x)
    """

    s = 1/(1 + np.exp(-x))

    return s
    
def negSamplingLossAndGradient(
    centerWordVec,
    outsideWordIdx,
    outsideVectors,
    dataset,
    K=10
):
    """ Negative sampling loss function for word2vec models

    Implement the negative sampling loss and gradients for a centerWordVec
    and a outsideWordIdx word vector as a building block for word2vec
    models. K is the number of negative samples to take.

    Note: The same word may be negatively sampled multiple times. For
    example if an outside word is sampled twice, you shall have to
    double count the gradient with respect to this word. Thrice if
    it was sampled three times, and so forth.

    Arguments/Return Specifications: same as naiveSoftmaxLossAndGradient
    """

    # Negative sampling of words is done for you. Do not modify this if you
    # wish to match the autograder and receive points!
    negSampleWordIndices = getNegativeSamples(outsideWordIdx, dataset, K)
    indices = [outsideWordIdx] + negSampleWordIndices       # len(indices) = K+1

	# Fill up W(negative samples + outside word) by indices array
    W = np.zeros((len(indices), outsideVectors.shape[1]))       # (K+1, d)
    for i in range(len(indices)):           
        W[i] = outsideVectors[indices[i]]

    # Forward
    centerWordVec = centerWordVec.reshape((centerWordVec.shape[0], 1))      # (d, 1)
    z = np.dot(W, centerWordVec)        # (K+1, 1)
    prob = sigmoid(z)

    # Backprop
    y = np.zeros((prob.shape[0], 1))        # (K+1, 1)
    y[0] = 1  # index 0 is target
    
    loss = -(y * np.log(prob) + (1 - y) * np.log(1 - prob)).sum()

    delta = prob - y
    gradCenterVec = np.dot(W.T, delta)      # (V, 1)
    gradW = np.dot(delta, centerWordVec.T)      # (K+1, V)
    gradCenterVec = gradCenterVec.flatten()

    gradOutsideVecs = np.zeros_like(outsideVectors)
    for i in range(len(indices)):
        gradOutsideVecs[indices[i]] += gradW[i]

    return loss, gradCenterVec, gradOutsideVecs

以上代码来自CS224:Natural Language Processing with Deep Learning, assignment 2的实现

你可能感兴趣的:(NLP,CS224n,NLP,with,DL)