Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could you please share an official torch or numpy implementation for GNN reranking? #379

Open
jifeiluo opened this issue Aug 7, 2023 · 13 comments

Comments

@jifeiluo
Copy link

jifeiluo commented Aug 7, 2023

My suggestion is about project Understanding Image Retrieval Re-Ranking: A Graph Neural Network Perspective. The current cuda version seems not that easy for a fast verification due to unexpected compilation problem. In addition to the GPU acceleration effect, the GNN algorithm itself is worth for a further research. Can you share an official torch or numpy implementation? Thanks.

@layumi
Copy link
Owner

layumi commented Aug 10, 2023

Hi @jifeiluo

Could you provide more details about cuda problem?
The version is too old? I guess it is relatively easy to modify.
The author xuanmeng zhang is on vacation right now. I will let him know later.

@jifeiluo
Copy link
Author

I guess the code is a little out of date. For example, when I compile the code with torch 2.0, one of the errors I received is as follows.

/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

And when compiling the code with python 3.7 and torch 1.4, different problem appears. My CUDA version is over 11, I hope whether you can test this code with newest torch version on Ubuntu, and specify the gcc version when compiling more specifically. Thanks for your response and I'm looking forward for your CPU version.

@liguopeng0923
Copy link

I have the same problems.

@Xuanmeng-Zhang
Copy link
Contributor

@jifeiluo @liguopeng0923 Hell, I followed the pytorch cuda extension tutorial to write the code. You can modify the code to the corresponding version by checking the new tutorial.

@jifeiluo
Copy link
Author

@Xuanmeng-Zhang @layumi Thanks for your response. What about the CPU version you mentioned in this paper? Can you share it? Since I have little experience with the c++ extension, I still hope you can share the torch or numpy based code first so we can quickly analyse the GNN's contribution. It will help us a lot than if we modify the code according to the new tutorial. And if possible, can you keep the code up to date since you are more familiar with the pytorch cuda extension. Thanks!

@liguopeng0923
Copy link

liguopeng0923 commented Aug 27, 2023 via email

@jifeiluo
Copy link
Author

Hello, are you still there? @layumi, I made some rough adjustments to the code today, and it only depends on numpy and torch now. But there are some details I'm not quite sure, like the aggregation function. Can you help verify and determine the specific parameters? Thanks!

import torch
import numpy as np


def gnn_reranking(X_q, X_g, k1=26, k2=7):
    query_num, gallery_num = X_q.shape[0], X_g.shape[0]
    all_num = query_num + gallery_num

    X_u = torch.cat((X_q, X_g), axis = 0)
    original_score = torch.mm(X_u, X_u.t())
    del X_u, X_q, X_g

    # initial ranking list
    S, initial_rank = original_score.topk(k=k1, dim=-1, largest=True, sorted=True)
    # stage 1
    initial_rank_numpy = initial_rank.numpy()
    A_numpy = np.zeros((all_num, all_num))
    for i in range(all_num):
        A_numpy[i, initial_rank_numpy[i]] = 1.0
    A = torch.from_numpy(A_numpy)
    S = S * S
    S_numpy = S.numpy()
    
    # stage 2
    if k2 != 1:      
        for i in range(2):
            A_numpy = A.numpy()
            A_numpy = (A_numpy + A_numpy.T)/2
            A_numpy_copy = np.copy(A_numpy)
            for j in range(all_num):
                A_numpy[j] = A_numpy_copy[j] +  np.dot(S_numpy[j,1:k2], A_numpy_copy[initial_rank_numpy[j,1:k2],:])/(k2-1)
            A = torch.from_numpy(A_numpy)
            A_norm = torch.norm(A, p=2, dim=1, keepdim=True)
            A = A.div(A_norm.expand_as(A)) 

    cosine_similarity = torch.mm(A[:query_num,], A[query_num:, ].t())

    dist = -cosine_similarity.numpy()
    return dist

@Xuanmeng-Zhang
Copy link
Contributor

Hi Jiefei, what is the mAP before and after re-ranking

@liguopeng0923
Copy link

@jifeiluo @Xuanmeng-Zhang What I should do when I miss a large dataset? (query and reference are about one hundred thousand)

@jifeiluo
Copy link
Author

For a baseline mAP of 88.01, k-reciprocal can achieve an mAP rate of 94.77 and the code above is 94.54. Is it normal? Could you please check the code? @Xuanmeng-Zhang @layumi

@Xuanmeng-Zhang
Copy link
Contributor

@jifeiluo @Xuanmeng-Zhang What I should do when I miss a large dataset? (query and reference are about one hundred thousand)

maybe you can use the CPU version

@Xuanmeng-Zhang
Copy link
Contributor

For a baseline mAP of 88.01, k-reciprocal can achieve an mAP rate of 94.77 and the code above is 94.54. Is it normal? Could you please check the code? @Xuanmeng-Zhang @layumi

Yes, the implementation seems no problem. You can adjust the number of propagation time to see the performance.

@jifeiluo
Copy link
Author

All right, thanks for your response!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants