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

Threshold in arcface loss #117

Open
mohamedamara7 opened this issue Jul 6, 2023 · 3 comments
Open

Threshold in arcface loss #117

mohamedamara7 opened this issue Jul 6, 2023 · 3 comments

Comments

@mohamedamara7
Copy link

In arcface loss a certain threshlod is used: theta_valid = tf.where(y_pred_vals > self.threshold, theta, self.theta_min - theta). I didn't understand why we should use this threshold, how to determine its value and finally if we violet the threshold we set the value to 'self.theta_min - theta' based on what this value is chosen? Thanks in advance.

@leondgarse
Copy link
Owner

leondgarse commented Jul 7, 2023

That threshold is actually added by me, and it just controls the adjusted y_pred_vals will not go beyond its original value. We can plot to see how arcface is modifying the y_pred_vals.

  • Without the threshold check, that there will be some value on the tail go larger than its original value.
    xx = np.arange(-1, 1, 0.01)
    
    for margin in np.arange(0.1, 1.5, 0.2):
        margin_cos, margin_sin = tf.cos(margin), tf.sin(margin)
        threshold = tf.cos(np.pi - margin)
        theta_min = -2
    
        theta = xx * margin_cos - tf.sqrt(1 - tf.pow(xx, 2)) * margin_sin
        # theta = tf.where(xx > threshold, theta, theta_min - theta)
        plt.plot(xx, theta, label="margin: {}".format(margin))
    plt.grid(True)
    plt.legend()
    aaa
  • With the threshold check, and its just a simple adjust on the value, that turning the up down. The threshold value is actually where the line gradiend == 0.
    xx = np.arange(-1, 1, 0.01)
    
    for margin in np.arange(0.1, 1.5, 0.2):
        margin_cos, margin_sin = tf.cos(margin), tf.sin(margin)
        threshold = tf.cos(np.pi - margin)
        theta_min = -2
    
        theta = xx * margin_cos - tf.sqrt(1 - tf.pow(xx, 2)) * margin_sin
        theta = tf.where(xx > threshold, theta, theta_min - theta)
        plt.plot(xx, theta, label="margin: {}".format(margin))
    plt.grid(True)
    plt.legend()
    bbb
  • Anyway, it's not an important change, as mostly the value is too small even it truns up. You can also modify above plotting function to check your thoughts.

@mohamedamara7
Copy link
Author

I really appreciate your effort but when I calculate cos(theta+margin) manually, I found that the first plot is correct and I think mathematically, the second plot is wrong as the cos of any angle should be within [-1, 1] but it exceeds -1.

@leondgarse
Copy link
Owner

Ya, if feed back into cos, it's not correct, Just this value here will multiply with scale and then go into categorical_crossentropy with from_logits=self.from_logits in next step, the value range doesn't matter. You can also use something like theta_valid = tf.where(y_pred_vals > self.threshold, theta, -1) or just comment off it.

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

2 participants