NIMA / model /model.py
abhishek-kumar's picture
Add files from Neural-IMage-Assessment repo
1e8d169
"""
file - model.py
Implements the aesthemic model and emd loss used in paper.
Copyright (C) Yunxiao Shi 2017 - 2021
NIMA is released under the MIT license. See LICENSE for the fill license text.
"""
import torch
import torch.nn as nn
class NIMA(nn.Module):
"""Neural IMage Assessment model by Google"""
def __init__(self, base_model, num_classes=10):
super(NIMA, self).__init__()
self.features = base_model.features
self.classifier = nn.Sequential(
nn.Dropout(p=0.75),
nn.Linear(in_features=25088, out_features=num_classes),
nn.Softmax())
def forward(self, x):
out = self.features(x)
out = out.view(out.size(0), -1)
out = self.classifier(out)
return out
def single_emd_loss(p, q, r=2):
"""
Earth Mover's Distance of one sample
Args:
p: true distribution of shape num_classes × 1
q: estimated distribution of shape num_classes × 1
r: norm parameter
"""
assert p.shape == q.shape, "Length of the two distribution must be the same"
length = p.shape[0]
emd_loss = 0.0
for i in range(1, length + 1):
emd_loss += torch.abs(sum(p[:i] - q[:i])) ** r
return (emd_loss / length) ** (1. / r)
def emd_loss(p, q, r=2):
"""
Earth Mover's Distance on a batch
Args:
p: true distribution of shape mini_batch_size × num_classes × 1
q: estimated distribution of shape mini_batch_size × num_classes × 1
r: norm parameters
"""
assert p.shape == q.shape, "Shape of the two distribution batches must be the same."
mini_batch_size = p.shape[0]
loss_vector = []
for i in range(mini_batch_size):
loss_vector.append(single_emd_loss(p[i], q[i], r=r))
return sum(loss_vector) / mini_batch_size