2 神经网络基础(30 分)
(part a) (3 分)
推导 sigmoid 函数的导数,并且只以 sigmoid 函数值的形式写出来(导数的表达式里只包含,不包含 x)。证明针对这个问题没必要单独考虑 x。方便回忆:下面给出 sigmoid 函数形式:
旁白:我年纪轻轻干嘛要走上深度学习这条不归路,真是生无所恋了。
答案 :。
(part b) (3 分)
当使用交叉熵损失来作为评价标准时,推导出损失函数以 softmax 为预测结果的输入向量的梯度。注意,
其中是一个 one-hot 向量,
是所有类别的预测出的概率向量。(提示:你需要考虑
的许多元素为 0,并且假设
仅有第 k 个类别是 1)
答案:
或者等价于下面表达式,其中假设 k 是正确的类别
(part c) (6 分)
推导出单隐层神经网络关于输入的梯度(也就是推导出
,其中 J 是神经网络的损失函数)。这个神经网络在隐层和输出层采用了 sigmoid 激活函数,
是 one-hot 编码向量,使用了交叉熵损失。(使用
作为 sigmoid 梯度,并且你可以任意为推导过中的中间变量命名)
前向传播方程如下:
在编程问题中,我们假设输入向量(隐层变量和输出概率)始终是一个行向量。此处我们约定,当我们说要对向量使用 sigmoid 函数时,也就是说要对向量每一个元素使用 sigmoid 函数。和
(其中 i=1,2)分别是两层的权重和偏移。
旁白:好好的 100 分总分,硬要被你这么 5 分 6 分地拆,人家 5 分 6 分是一道选择题,你特么是一整个毕业设计!!好吧,不哭,跪着也要把题目做完,代码写完。哎,博主还是太年轻,要多学习啊。
答案 :令 ,
,于是可得:
(part d) (2 分)
上面所说的这个神经网络有多少个参数?我们可以假设输入是维,输出是
,隐层单元有 H 个。
旁白:还有 part d!!!
答案: .
(part e) (4 分) 在 q2_sigmoid.py 中补充写出 sigmoid 激活函数的和求它的梯度的对应代码。并使用 python q2_sigmoid.py 进行测试,同样的,测试用例有可能不太详尽,因此尽量检查下自己的代码。
旁白:如果博主没有阵亡,就在走向阵亡的路上…
def sigmoid_grad(f):
"""
计算 Sigmoid 的梯度
"""
#好在我有 numpy
f = f * ( 1 - f )
return f
(part f) (4 分)
为了方便 debugging,我们需要写一个梯度检查器。在 q2_gradcheck.py 中补充出来,使用 python q2_gradcheck.py 测试自己的代码。
旁白:做到昏天黑地,睡一觉起来又是一条好汉…
def gradcheck_naive(f, x):
"""
对一个函数 f 求梯度的梯度检验
- f 输入 x,然后输出 loss 和梯度的函数
- x 就是输入咯
"""
rndstate = random.getstate()
random.setstate(rndstate)
fx, grad = f(x)
h = 1e-4
# 遍历 x 的每一维
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
ix = it.multi_index
old_val = x[ix]
x[ix] = old_val - h
random.setstate(rndstate)
( fxh1, _ ) = f(x)
x[ix] = old_val + h
random.setstate(rndstate)
( fxh2, _ ) = f(x)
numgrad = (fxh2 - fxh1)/(2*h)
x[ix] = old_val
# 比对梯度
reldiff = abs(numgrad - grad[ix]) / max(1, abs(numgrad), abs(grad[ix]))
if reldiff > 1e-5:
print "Gradient check failed."
print "First gradient error found at index %s" % str(ix)
print "Your gradient: %f \t Numerical gradient: %f" % (grad[ix], numgrad)
return
it.iternext() # Step to next dimension
print "Gradient check passed!"
(part g) (8 分)
现在,在 q2 neural.py 中,写出只有一个隐层且激活函数为 sigmoid 的神经网络前向和后向传播代码。使用 python q2_neural.py 测试自己的代码。
旁白:一入 DL 深似海…
def forward_backward_prop(data, labels, params, verbose = False):
"""
2 个隐层的神经网络的前向运算和反向传播
"""
if len(data.shape) >= 2:
(N, _) = data.shape
### 展开每一层神经网络的参数
t = 0
W1 = np.reshape(params[t:t+dimensions[0]*dimensions[1]], (dimensions[0], dimensions[1]))
t += dimensions[0]*dimensions[1]
b1 = np.reshape(params[t:t+dimensions[1]], (1, dimensions[1]))
t += dimensions[1]
W2 = np.reshape(params[t:t+dimensions[1]*dimensions[2]], (dimensions[1], dimensions[2]))
t += dimensions[1]*dimensions[2]
b2 = np.reshape(params[t:t+dimensions[2]], (1, dimensions[2]))
### 前向运算
# 第一个隐层做内积
a1 = sigmoid(data.dot(W1) + b1)
# 第二个隐层做内积
a2 = softmax(a1.dot(W2) + b2)
cost = - np.sum(np.log(a2[labels == 1]))/N
### 反向传播
# Calculate analytic gradient for the cross entropy loss function
grad_a2 = ( a2 - labels ) / N
# Backpropagate through the second latent layer
gradW2 = np.dot( a1.T, grad_a2 )
gradb2 = np.sum( grad_a2, axis=0, keepdims=True )
# Backpropagate through the first latent layer
grad_a1 = np.dot( grad_a2, W2.T ) * sigmoid_grad(a1)
gradW1 = np.dot( data.T, grad_a1 )
gradb1 = np.sum( grad_a1, axis=0, keepdims=True )
if verbose: # Verbose mode for logging information
print "W1 shape: {}".format( str(W1.shape) )
print "W1 gradient shape: {}".format( str(gradW1.shape) )
print "b1 shape: {}".format( str(b1.shape) )
print "b1 gradient shape: {}".format( str(gradb1.shape) )
### 梯度拼起来
grad = np.concatenate((gradW1.flatten(), gradb1.flatten(), gradW2.flatten(), gradb2.flatten()))
return cost, grad
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论