yangze0930 / NTS-Net

This is a PyTorch implementation of the ECCV2018 paper "Learning to Navigate for Fine-grained Classification" (Ze Yang, Tiange Luo, Dong Wang, Zhiqiang Hu, Jun Gao, Liwei Wang).
MIT License
452 stars 118 forks source link

The way to compute rank loss #18

Open yaojunr opened 5 years ago

yaojunr commented 5 years ago

Hi, I have some question of computing the rank loss. The original code is :

part_loss = model.list_loss(part_logits.view(batch_size * PROPOSAL_NUM, -1), 
    label.unsqueeze(1).repeat(1,PROPOSAL_NUM).view(-1)).view(batch_size, PROPOSAL_NUM)
rank_loss = model.ranking_loss(top_n_prob, part_loss) 

def ranking_loss(score, targets, proposal_num=PROPOSAL_NUM):
    loss = Variable(torch.zeros(1).cuda())
    batch_size = score.size(0)
    for i in range(proposal_num):
        targets_p = (targets > targets[:, i].unsqueeze(1)).type(torch.cuda.FloatTensor)
        pivot = score[:, i].unsqueeze(1) 
        loss_p = (1 - pivot + score) * targets_p
        loss_p = torch.sum(F.relu(loss_p))
        loss += loss_p
    return loss / batch_size

def list_loss(logits, targets):
    temp = F.log_softmax(logits, -1)
    loss = [-temp[i][targets[i].item()] for i in range(logits.size(0))]
    return torch.stack(loss)

See the code here targets_p = (targets > targets[:, i].unsqueeze(1)).type(torch.cuda.FloatTensor). I think the variable targets_p is the mask of target where other value is larger than the index value. However, i think targets_p is just determined by the relative value. The way to compute part_loss is just reverse the order of the relative value and fetch the specific index. I think just fetch the specific index is enough. Then why compute the value of part_loss?

TonyDongLB commented 5 years ago

I have the same question as your, I think thetargets > targets[:, i].unsqueeze(1) should be targets < targets[:, i].unsqueeze(1)

xyy19920105 commented 5 years ago

I also think the code of rank loss is not match with the description in the paper. I think loss_p should be 1 + pivot - score

mo-vic commented 4 years ago

As the pivot column moving from left to right, suppose the union of s1, pivot and s2 is equal to the total set of anchor scores, the individual loss term is defined by L = max(0, 1 - pivot + score), minimizing the individual loss can be viewed as making 1 - pivot + score less or equal to 0, which can be further rewrite as pivot - score >= 1:

For s1: Let score be s1. We have score > pivot, pivot - score < 0, if the part loss L_score > L_pivot, then target_p is equal to True, the individial loss term contributes to the total loss in order to reverse the order and make sure they have a margin of 1.

For s2: Let score be s2. We have score < pivot, pivot - score > 0, if the part loss L_score > L_pivot, then target_p is equal to True, the individial loss term contributes to the total loss in order to make sure they have a margin of 1.

My question is: The part loss is used only for constructing a mask and have no contribution to the gradient, why not use the class probabilities of the parts directly?