2016-11-01 1 views
6

Я просмотрел код Caffe's SigmoidCrossEntropyLoss layer и docs, и я немного смущен. Документы перечисляют функцию потерь как потерю логита (я бы реплицировал ее здесь, но без Latex формулу было бы трудно прочитать. Посмотрите ссылку docs, она находится на самом верху).Caffe SigmoidCrossEntropyLoss Layer Loss Function

Однако сам код (Forward_cpu(...)) показывает другую формулу

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - 
     log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

Это потому, что это составляет функции сигмовидной, уже был применен к входу?

Однако даже в этом случае фотки (input_data[i] >= 0) меня тоже путают. Кажется, что они лежат на месте p_hat из формулы потерь в документах, которая, как предполагается, является предсказанием, подавленным сигмоидной функцией. Так почему они просто берут двоичный порог? Это еще более запутанно, поскольку эта потеря предсказывает [0,1] выходы, поэтому (input_data[i] >= 0) будет 1, если он не будет на 100% уверен, что это не так.

Может кто-нибудь, пожалуйста, объясните мне это?

ответ

6

SigmoidCrossEntropy слой CAFFE сочетает в себе 2 шага (Sigmoid + CrossEntropy), которые будут выполнять на input_data в один кусок кода:

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - 
     log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

В самом деле, независимо от того, является ли input_data >= 0 или нет, приведенный выше код всегда эквивалентен следующий код в математике:

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - 1) - 
     log(1 + exp(-input_data[i]); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

, этот код основан на простой математической формуле после применения Sigmoid и CrossEntropy на input_data и некоторые комбинации в математике.

Но первая часть коды (кофейный использует) владеет более численной устойчивостью и имеет меньший риск переполнения, поскольку это позволяет избежать вычислений большого exp(input_data) (или exp(-input_data)), когда абсолютное значение input_data слишком велико. Вот почему вы видели этот код в кофе.

+0

Итак, если бы кто-то использовал мягкие метки истины истины (т. Е. [0,1], а не {0,1}), что-нибудь нужно было бы изменить? – marcman

+0

Если сумма наземных символов истинности равна 1, то изменений этого слоя не должно быть. В противном случае вы должны внести некоторые изменения, которые применяют кросс-энтропию на каждом выходе сети. @marcman – Dale

+0

Я думаю, что понимаю, почему это так, но на практике, когда я нормализую каждую метку, я начал получать потери NaN, хотя это может быть проблема с уровнем обучения – marcman