векторизованный SVM (CS231n) - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь решить первое задание Стэнфорда CS231n. В частности, у меня возникают трудности при кодировании векторизованной версии SVM-градиента в svm_loss_vectorized. В скалярной функции мы использовали вложенный l oop для вычисления градиента:

for i in xrange(num_train):
    scores = X[i].dot(W)
    correct_class_score = scores[y[i]]
    for j in xrange(num_classes):
      if j == y[i]:
        continue    # run over all the all the classes except the right one
      margin = scores[j] - correct_class_score + 1 # note delta = 1
      if margin > 0:
        dW[:,j] += X[i]
        dW[:,y[i]] -= X[i]
        loss += margin

Словом, для каждого наблюдения i мы вычисляем для каждой категории, которая не является правильной j != y[i] наценка. Если оно больше 0, мы добавляем i-ю строку X к dW j -ому столбцу . В конечном итоге, dW[:,j] - это сумма всех X[i] с, из которых модель предсказала j метку неправильно, вместо истинной метки y[i] (верно?). Более того, для каждого i, в котором модель предсказывает более высокую вероятность неправильной метки, мы подставляем X[i] из dW[:,y[i]], то есть столбца, которому на самом деле принадлежит наблюдение i.

Теперь я закончил кодировать скалярную версию и пытаюсь получить те же числа в векторизованной форме.

SCORES = X.dot(W)
CORRECT_cs = SCORES[np.arange(SCORES.shape[0]),y]
MARGINs = (SCORES.T - CORRECT_cs.T + np.ones(CORRECT_cs.T.shape)).T # note delta = 1
MARGINs = MARGINs * (MARGINs != 1) * (MARGINs > 0)

Когда j==y[i], у нас есть MARGINs[i,j] = 1. Более того, нам нужны только положительные значения (аналогично утверждению if). Потеря - это сумма этой матрицы, деленная на общее количество наблюдений. Пока здесь все одинаково, но сейчас начинается сложная часть. Я хочу вычислить для каждого j сумму X[i] s, как в скалярной версии. Я думаю, что мне удалось сделать это:

for j in xrange(10):
    sumXi = X[(MARGINs>0)[:,j] * (np.repeat(j,500)!=y),:].sum(axis = 0)
    dW_vec[:,j] = sumXi 

Но теперь я хочу вычислить часть dW[:,y[i]] -= X[i]. Я думал об этих строках:

  for j in xrange(10):
    sumXi = X[(MARGINs>0)[:,j] * (np.repeat(j,500)!=y),:].sum(axis = 0)
    dW_vec[:,j] = sumXi 
    sumYj = X[(MARGINs>0)[:,j] * (np.repeat(j,500)==y),:].sum(axis = 0)
    dW_vec[:,j] -= sumYj

Но, к сожалению, значения градиента не совпадают. Что мне не хватает? Неправильные ли условия на X? Есть ли более удобный способ расчета градиента?

Спасибо!

...