【CS231n】Spring 2020 Assignments - Assignment1 - Two Layer Net


前言

我的作业是在 Google Colaboratory 上完成的,还是挺方便的。

注意:该次作业应该是听完卷积神经网络才做的


1. Implementing a Neural Network

1.1. TwoLayerNet.loss

1.1.1. Scores

首先计算得分 Scores ,即正向传播。虽然很简单,但是别忘了两个全联接层之间还有一个非线形层(RELU),直接放代码:

XW1 = X.dot(W1)
XW1pb1 = XW1 + b1
H = np.maximum(0, XW1pb1)
HW2 = H.dot(W2)
HW2pb2 = HW2 + b2

scores = HW2pb2

1.1.2. Loss

接下来是计算损失 Loss 。其实在前面的作业中我们已经推导出了 Softmax 的损失是什么了(如下),这边也差不多:

L i = −   l o g ( e s y i ∑ j e s j ) L_i = -\ log(\frac{e^{s_{y_i}}}{\sum_{j}{e^{s_j}}}) Li= log(jesjesyi)

但是需要注意的是:我们现在有两个特征矩阵 W1 和 W2 了,所以正则化惩罚就有两项了。

positive_scores = np.exp(scores)
softmax = positive_scores / np.sum(positive_scores, axis=1).reshape((N, 1))
loss = np.sum((-np.log(softmax))[range(N), y])
loss /= N
loss += (reg * np.sum(W1*W1) + reg * np.sum(W2*W2))

1.1.3. dW

虽然计算梯度矩阵 dW 看起来非常复杂,但是细心一点还是没问题的。

整体思路就是画出计算图(Computational Graph),根据链式法则一步一步反向传播,千万不要傻傻得想要推出损失函数对每个超参数的求导公式!

计算图如下:

计算图

完整代码如下:

W1 = np.zeros_like(W1)
dW2 = np.zeros_like(W2)
db1 = np.zeros_like(b1)
db2 = np.zeros_like(b2)

# reg = softmax + (reg * np.sum(W1*W1) + reg * np.sum(W2*W2)
dW1 += 2 * reg * W1
dW2 += 2 * reg * W2
# softmax( H * W2 + b2 )
softmax[range(N), y] -= 1.0
dsoftmax = softmax / N
# b2
db2 += np.sum(dsoftmax, axis=0)
# W2
dW2 += H.T.dot(dsoftmax)
# H = X * w1+ b1
dH = dsoftmax.dot(W2.T)
# Max gate
dH[np.where(H <= 0)] = 0.0
# b1
db1 += np.sum(dH, axis=0)
# W1
dW1 += X.T.dot(dH)

grads['W1'] = dW1
grads['b1'] = db1
grads['W2'] = dW2
grads['b2'] = db2

1.2. TwoLayerNet.train

这部分和之前的作业中写的都差不多,不赘述。

1.2.1 Create a random minibatch of training data and labels

indices = np.random.choice(num_train, batch_size, replace=True)
X_batch = X[indices]
y_batch = y[indices]

1.2.2. Update the parameters

for param in self.params:
	self.params[param] -= learning_rate * grads[param]

1.3. TwoLayerNet.predict

这部分和之前的作业中写的都差不多,不赘述。

scores = self.loss(X)
y_pred = scores.argmax(axis=1)

2. Tune Your Hyperparameters

因为参数较多,所以一下子就将所有参数联合起来训练、找合理范围是不太现实的。我的做法是先在每个参数中找出能得出最高得分的范围,例如下面各个参数后面的备注,一般是找 3 次,最后得出一个较小的范围。最后将这四个较小范围联合起来训练。最后在测试集上得出了 0.529 的分数,还不错。

下面是代码:

best_acc = 0.0
best_lr = 0.0
best_bs = 0
best_r = 0.0

num_expriment = 5
hs = 78     # 76~80, 78 is best
lr = 7.4e-4 # 6.6e-4~8.2e-4, 7.4e-4 is best
r = 0.32    # 0.30~0.34, 0.32 is best
bs = 550    # 550~650, 550 is best

hs_rate = (80 - 76) / (num_expriment - 1)
lr_rate = (8.2e-4 - 6.6e-4) / (num_expriment - 1)
r_rate = (0.34 - 0.30) / (num_expriment - 1)
bs_rate = (650 - 550) / (num_expriment - 1)

for hsi in range(num_expriment):
  for bsi in range(num_expriment):
    for lri in range(num_expriment):
      for ri in range(num_expriment):
        input_size = 32 * 32 * 3
        hidden_size = hs + hsi * hs_rate
        num_classes = 10
        net = TwoLayerNet(input_size, hidden_size, num_classes)

        # Train the network
        stats = net.train(X_train, y_train, X_val, y_val,
                    num_iters=3000, batch_size=(bs + bsi * bs_rate),
                    learning_rate=(lr + lri * lr_rate), learning_rate_decay=0.95,
                    reg=(r + ri * r_rate), verbose=False)

        # Predict on the validation set
        val_acc = (net.predict(X_val) == y_val).mean()
        print('hs: ', (hs + hsi * hs_rate), '; lr: ', (lr + lri * lr_rate), '; r: ', (r + ri * r_rate), '; bs: ', (bs + bsi * bs_rate), '; VA: ', val_acc)

        if val_acc > best_acc:
          best_acc = val_acc
          best_net = net
          best_bs = bs + bsi * bs_rate
          best_lr = lr + lri * lr_rate
          best_r = r + ri * r_rate

总结

主要考察的是反向传播的思想,这点真的很重要!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值