Skip to content
Back to skills

Spearman Correlation Callback

ASecurity

Custom Keras callback that evaluates Spearman correlation on validation data each epoch with optional early stopping.

  • 61 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 12, 2026
toolspythongo

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add wenmin-wu/ds-skills --skill spearman-correlation-callback --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Spearman Correlation Callback?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Spearman Correlation Callback
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wenmin-wu-spearman-correlation-callback/badge)](https://www.skillsdirectory.com/skills/wenmin-wu-spearman-correlation-callback)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: nlp-spearman-correlation-callback
description: >
  Custom Keras callback that evaluates Spearman correlation on validation data each epoch with optional early stopping.
---
# Spearman Correlation Callback

## Overview

For ranking tasks where Spearman correlation is the evaluation metric, build a custom Keras callback that computes per-target Spearman rho on validation data after each epoch. Enables early stopping on the actual competition metric rather than a proxy loss like MSE.

## Quick Start

```python
import numpy as np
from scipy.stats import spearmanr
from tensorflow.keras.callbacks import Callback

class SpearmanCallback(Callback):
    """Evaluate mean Spearman correlation per epoch."""

    def __init__(self, val_data, val_targets, patience=3):
        super().__init__()
        self.val_data = val_data
        self.val_targets = val_targets
        self.patience = patience
        self.best_score = -1
        self.wait = 0

    def on_epoch_end(self, epoch, logs=None):
        preds = self.model.predict(self.val_data, verbose=0)
        scores = []
        for i in range(self.val_targets.shape[1]):
            rho, _ = spearmanr(self.val_targets[:, i], preds[:, i])
            scores.append(rho)
        mean_rho = np.mean(scores)
        print(f"  val_spearman: {mean_rho:.4f}")
        if mean_rho > self.best_score:
            self.best_score = mean_rho
            self.wait = 0
        else:
            self.wait += 1
            if self.wait >= self.patience:
                self.model.stop_training = True
```

## Workflow

1. Prepare validation data separately from training generator
2. Instantiate callback with val features and targets
3. Pass callback to `model.fit(callbacks=[spearman_cb])`
4. Monitor `val_spearman` in logs for convergence
5. Combine with `ModelCheckpoint` to save best-scoring weights

## Key Decisions

- **Per-target vs mean**: Compute per-target rho then average; some targets may be noisier
- **Patience**: 2-3 epochs is typical for fine-tuned transformers
- **Batch prediction**: Use full validation set, not batches, for stable Spearman estimates
- **Tie handling**: Add small noise (`1e-7 * np.random.randn`) if targets have many ties

## References

- Google QUEST Q&A Labeling competition (Kaggle)
- Source: [quest-bert-base-tf2-0](https://www.kaggle.com/code/akensert/quest-bert-base-tf2-0)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…