斯坦福大学NLP课程CS224N课第一次作业第二部分(下)

斯坦福大学NLP课程CS224N课第一次作业第二部分(下)

上一个博客我们详细讲解了第一次作业第二部分的前两个函数,下面我们来详细讲解第三个函数,也就是q2_neural.py文件,该文件想让我们实现一个简单神经网络的前向和反向算法,我们从开始到最后仔细分析一下这个程序,要做到知其然也并且知其所以然也。

1. 程序结构

这个程序主要包含两个函数,分别是forward_backward_prop()和sanity_check(),前者是做前向和反向传播,后者是用来进行梯度校验,检验梯度所求梯度是否正确。
先看那个函数无所谓,我们就先看sanity_check()开始,因为文件是先执行这个函数,然后在这个函数里面调用的forward_backward_prop()函数:

def sanity_check():
    """
    Set up fake data and parameters for the neural network, and test using
    gradcheck.
    """
    print "Running sanity check..."

    N = 20
    dimensions = [10, 5, 10]
    data = np.random.randn(N, dimensions[0])   # each row will be a datum
    labels = np.zeros((N, dimensions[2]))
    for i in xrange(N):
        labels[i, random.randint(0,dimensions[2]-1)] = 1

    params = np.random.randn((dimensions[0] + 1) * dimensions[1] + (
        dimensions[1] + 1) * dimensions[2], )

    gradcheck_naive(lambda params:
        forward_backward_prop(data, labels, params, dimensions), params)

首先定义N和dimensions,然后定义data,根据函数名猜测data是网络的输入,说明输入时2010的矩阵。而labels是网络的输出,也是一个2010的矩阵,然后下面一个循环(这是基于python2的,所以存在函数xrange,在python3中xrange移除了,使用range即可),循环是将每行随机一个为1的元素,很显然这是产生一个one-hot矩阵。然后params就是网络的参数,网络只有一个隐层,所以有w1,b1,w2,b2,他这里吧参数放在一起写了。最后是调用梯度校验的函数,梯度校验函数的输入见上一篇博客,即函数和函数的参数,这里函数就是我们接下来要说的forward_backward_prop,这里参数只有params。
刚才是函数的功能,我们也要看看各个部分使用什么实现,这里主要用到随机的函数,其中np.random.randn(a,b)是返回0-1之间的随机数,返回的矩阵大小是(a,b)。random.randint(a,b)是返回从a-b的整数,包括a,但是不包括b。
下面是forward_backward_prop()函数,包括前向传播和反向传播:

def forward_backward_prop(X, labels, params, dimensions):
    """
    Forward and backward propagation for a two-layer sigmoidal network

    Compute the forward propagation and for the cross entropy cost,
    the backward propagation for the gradients for all parameters.

    Notice the gradients computed here are different from the gradients in
    the assignment sheet: they are w.r.t. weights, not inputs.

    Arguments:
    X -- M x Dx matrix, where each row is a training example x.
    labels -- M x Dy matrix, where each row is a one-hot vector.
    params -- Model parameters, these are unpacked for you.
    dimensions -- A tuple of input dimension, number of hidden units
                  and output dimension
    """

    ### Unpack network parameters (do not modify)
    ofs = 0
    Dx, H, Dy = (dimensions[0], dimensions[1], dimensions[2])

    W1 = np.reshape(params[ofs:ofs+ Dx * H], (Dx, H))
    ofs += Dx * H
    b1 = np.reshape(params[ofs:ofs + H], (1, H))
    ofs += H
    W2 = np.reshape(params[ofs:ofs + H * Dy], (H, Dy))
    ofs += H * Dy
    b2 = np.reshape(params[ofs:ofs + Dy], (1, Dy))

    # Note: compute cost based on `sum` not `mean`.
    ### YOUR CODE HERE: forward propagation
    raise NotImplementedError
    ### END YOUR CODE

    ### YOUR CODE HERE: backward propagation
    raise NotImplementedError
    ### END YOUR CODE

    ### Stack gradients (do not modify)
    grad = np.concatenate((gradW1.flatten(), gradb1.flatten(),
        gradW2.flatten(), gradb2.flatten()))

    return cost, grad

我们可以看到前向算法的输入和各个层的参数都已经给定了,我们只需要做矩阵乘法即可,需要注意的是维度需要对应,只要把维度对好,基本不会出错:

#forword_prop
A1 = np.matmul(X,W1)+b1  
A1 = sigmoid(A1) 
A2 = np.matmul(A1,W2)+b2
A2 = softmax(A2)
cost = np.sum(-labels*np.log(A2))/ X.shape[0]

然后就是实现反向算法,实现反向算法的难点主要在softmax求导这里,这里其实就是直接使用求导法则即可,我手推一下:
在这里插入图片描述
之后我们的求导就比较简单了,我们接着直接写结果了:

    gradA2 = (A2 - labels) / X.shape[0]
    gradW2 = np.matmul(A1.T,gradA2)
    gradb2 = np.sum(gradA2,axis=0,keepdims=True)
    gradA1 = np.matmul(gradA2,W2.T)
    gradA1 =sigmoid_grad(A1)*gradA1
    gradW1 = np.matmul(X.T,gradA1)
    gradb1 = np.sum(gradA1,axis=0,keepdims=True)
    grad = np.concatenate((gradW1.flatten(), gradb1.flatten(),
        gradW2.flatten(), gradb2.flatten()))

然后下面就是返回两个W和两个b的梯度,就这样结束了。
其中np.concatenate()是合并两个矩阵的函数,而flatten()是将多维矩阵变成一维的向量,大家可以自己尝试一下这两个函数,本期作业讲解结束,下一次就是word2vec了。
欢迎评论交流,也欢迎关注,会将CS224N的所有作业写成博客的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值