【CS231n】Spring 2020 Assignments - Assignment1 - Softmax


前言

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

注意:最好听完神经网络中反向传播的课再来做SVM和Softmax,不然求导会把你逼疯!


一、Implement softmax_loss_naive(W, X, y, reg)

逻辑回归分类器(Softmax Classifier):希望正确类别得到的概率分数接近 1

Softmax 损失函数(常用,也叫多项式逻辑回归):我们用 softmax 对分数进行转化处理(即不直接使用),并得到正确类别的损失函数是 − l o g P -logP logP ;公式如下

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)

综上,损失的计算还是比较简单。先求出分数 Scores,将 Scores 正数化( e S e^S eS),再将 Scores 归一化,即除以每个数据样本在每个类的得分总和,这样就可以得出概率 P 了。那对于每个数据样本 X i X_i Xi 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)

可是计算梯度 dW 就比较复杂了,因为这个损失函数比较复杂,可以参考下面这篇文章:

多分类器softmax——绝对简单易懂的梯度推导 by 月下花弄影

里面讲得很详细。

下面是代码:

    num_train = X.shape[0]
    num_classes = W.shape[1]
    scores = X.dot(W)
    positive_scores = np.e ** scores
    softmax = positive_scores / np.sum(positive_scores, axis=1).reshape((num_train, 1))

    for i in range(num_train):
      for j in range(num_classes):
        if j == y[i]:
          loss += -np.log(softmax[i][j])
          dW[:, j] += (softmax[i][j] - 1) * X[i]
        else:
          dW[:, j] += softmax[i][j] * X[i]

    loss /= num_train
    loss += reg * np.sum(W*W)

    dW /= num_train
    dW += 2 * reg * W

二、Implement softmax_loss_vectorized(W, X, y, reg)

这题和 SVM 的第二题差不多。损失是比较好求的,比较难的仍然是梯度矩阵。

总体思路是构造出一个矩阵,让它和 X 点乘能够得到 dW 。从上一题中我们可以看到 dW[:, j] 都需要加上 X[i] ,只不过当 j = y[i] 时的系数需要减 1 ,那么很自然的我们先将 softmax 相应的项减去1,再与 X.T 点乘即可得到 dW。当然最后别忘了除以 num_train 以及 进行正则化惩罚。

    num_train = X.shape[0]
    num_classes = W.shape[1]
    dim = X.shape[1]
    scores = X.dot(W)
    positive_scores = np.e ** scores
    softmax = positive_scores / np.sum(positive_scores, axis=1).reshape((num_train, 1))

    loss = np.sum((-np.log(softmax))[range(num_train), y])
    softmax[range(num_train), y] -= 1
    dW = X.T.dot(softmax)

    loss /= num_train
    loss += reg * np.sum(W*W)

    dW /= num_train
    dW += 2 * reg * W

三、Write code that chooses the best hyperparameters

这一题的思路跟 SVM 里面的完全一样,想看思路的同学可以看我的上一篇博客。

需要注意的是,我选用的参数都是经过对比、选择最后得出来的,并不是一开始就将 learning_rate_step_size, regularization_strength_step_size, num_iters 这些参数设成这个值的。

其实研究了一下其他同学的代码之后,我尝试了一下,发现不怕耗费时间的同学真的可以将 num_iters 固定成一个比较大的值,这样训练出来的结果会准确很多,对于区间的选择也更精准。

learning_rate_step_size = (1.288000e-06 - 0.5e-7) / 15
regularization_strength_step_size = (4.200000e+04 - 1e4) / 15

lr = 1e-7 - learning_rate_step_size
regularization_strength = 1e4 - regularization_strength_step_size

best_lr = 0.
best_regularization_strength = 0.

for i in range(15):
  lr += learning_rate_step_size
  regularization_strength = 1e4
  for j in range(15):
    regularization_strength += regularization_strength_step_size
    new_softmax = Softmax()
    new_softmax.train(X_train, y_train, learning_rate=lr, reg=regularization_strength, num_iters=700, verbose=False)
    y_train_pred = new_softmax.predict(X_train)
    training_accuracy = np.mean(y_train == y_train_pred)
    y_val_pred = new_softmax.predict(X_val)
    validation_accuracy = np.mean(y_val == y_val_pred)
    if validation_accuracy > best_val:
      best_val = validation_accuracy
      best_softmax = new_softmax
      best_lr = lr
      best_regularization_strength = regularization_strength
    results[(lr, regularization_strength)] = (training_accuracy, validation_accuracy)

# Train best_softmax and update bast_value
best_softmax.train(X_train, y_train, best_lr, best_regularization_strength, num_iters=800, verbose=True)
y_val_pred = best_softmax.predict(X_val)
best_val = np.mean(y_val == y_val_pred)
print('best_lr:', best_lr, 'best_regularization_strength:', best_regularization_strength)

总结

学习CS231n对数学的要求真的蛮高的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值