PyTorch - Superior Model Performance by Misusing Loss Function (Negative Log Likelihood)?

RylanSchaeffer: <p>I misread PyTorch’s <code>NLLLoss()</code> and accidentally passed my model’s probabilities to the loss function instead of my model’s log probabilities, which is what the function expects. However, when I train a model under this misused loss function, the model (a) learns faster, (b) learns more stably, (b) reaches a lower loss, and (d) performs better at the classification task.</p>
<p>I don’t have a minimal working example, but I’m curious if anyone else has experienced this or knows why this is? Any possible hypotheses?</p>
<p>One hypothesis I have is that the gradient with respect to the misused loss function is more stable because the derivative isn’t scaled by 1/model output probability.</p>

ptrblck: <p>Without the <code>log</code> term you wouldn’t calculate the entropy, would you?<br>
From the Wikipedia article on <a href="https://en.wikipedia.org/wiki/Cross_entropy">Cross entropy</a>, you would calculate <code>p(x) * q(x)</code> I think.<br>
I haven’t seen this outcome yet, but are you sure your model learns generally better or could the current hyperparameters be just “bad” for the proper usage of <code>nn.NLLLoss</code> with the log probabilities?</p>

googlebot: <p>Interesting. Here’s my “hypothesis”. You can optimize individual prob instead of log(prob), no problem. But training has standard interpretation as maximization of joint density over dataset, that’s product of sample densities, or their sum on log domain.<br>
You can also view this as optimization of geometric mean, while your procedure maximizes arithmetic mean of probabilities. From this, you can deduce the consequences. My guess would be overfit for “easy” samples.</p>

RylanSchaeffer: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> that’s correct. Without the log, the loss is no longer cross entropy and your <code>p(x) * q(x)</code> is computed instead.</p>
<p>The wrong loss function appears to work better with different learning rates as well as with or without momentum, but I haven’t extensively compared the two loss functions (e.g. I could try switching optimizers).</p>
<p><a class="mention" href="/u/googlebot">@googlebot</a> Can you walk me through “you can deduce the consequences?” I’m not sure I understand how cross entropy relates to geometric and arithmetic means.</p>
<p>The task isn’t a typical supervised classification task, so it’s difficult to define what an easy sample is, but the task admits an exact Bayesian baseline and the wrong loss function does better than the correct loss function on datum requiring using inferred latent variables. We think of these datum as the “harder” cases.</p>

googlebot: <aside class="quote no-group" data-username="RylanSchaeffer" data-post="4" data-topic="86211">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/rylanschaeffer/48/17130_2.png" class="avatar"> RylanSchaeffer:</div>
<blockquote>
<p>I’m not sure I understand how cross entropy relates to geometric and arithmetic means.</p>
</blockquote>
</aside>
<p>In wikipedia’s page linked above, see “relation to log-likelihood” section.</p>
<p>Then consider a dataset with two samples, you optimize their likelihoods independently, and total likelihood is represented by their product, P_total = P1*P2, or log(P_total) = log(P1)+log(P2). So, geometric mean of P1 and P2, or log-average of likelihoods is what “sample loss” normally implicitly maximizes. In other words, increasing smaller likelihoods has bigger effect, due to log transform.</p>
<p>Now if you optimize P1+P2, it is possible to get to the same parameters, but optimization path will be different, less robust I think.</p>

RylanSchaeffer: <p>Ok makes sense. Thanks for explaining!</p>

RylanSchaeffer: <p><a class="mention" href="/u/googlebot">@googlebot</a> why do you say the optimization path will be less robust? I would intuitively think taking the gradient w.r.t <code>- sum p(x_i | theta)</code> would be more stable than <code>-sum log p(x_i|theta)</code>, no?</p>

googlebot: <p>Yes, but the challenge is to learn the function that produces amortized thetas, theta_i = neural_net(input_i), that will also generalize well. log() acts like a gradient booster for small likelihoods, so samples with smaller “true probability” are not considered less important.</p>
<p>Networks with big enough capacity can learn optimal thetas without this “importance balancing”, but then they’re prone to overfitting.</p>