Skip to content
Back to skills

Quadratic Weighted Kappa Callback

ASecurity

Custom training callback that computes Quadratic Weighted Kappa on validation data each epoch and checkpoints the best model.

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

Works with

  • cli

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add wenmin-wu/ds-skills --skill quadratic-weighted-kappa-callback --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Quadratic Weighted Kappa Callback?

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

Security grade badge for Quadratic Weighted Kappa Callback
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wenmin-wu-quadratic-weighted-kappa-callback/badge)](https://www.skillsdirectory.com/skills/wenmin-wu-quadratic-weighted-kappa-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: cv-quadratic-weighted-kappa-callback
description: >
  Custom training callback that computes Quadratic Weighted Kappa on validation data each epoch and checkpoints the best model.
---
# Quadratic Weighted Kappa Callback

## Overview

Quadratic Weighted Kappa (QWK) measures agreement between predicted and true ordinal labels, penalizing larger disagreements quadratically. It's the standard metric for medical grading tasks (diabetic retinopathy, pathology staging) but isn't available as a built-in training metric. This callback computes QWK at epoch end using sklearn, tracks the best score, and saves the model only when QWK improves — replacing loss-based checkpointing with metric-based checkpointing.

## Quick Start

```python
from sklearn.metrics import cohen_kappa_score
import numpy as np

# PyTorch version
def compute_qwk(model, val_loader, device):
    model.eval()
    all_preds, all_labels = [], []
    with torch.no_grad():
        for images, labels in val_loader:
            preds = model(images.to(device)).cpu().numpy()
            all_preds.extend(np.rint(preds).clip(0, 4).flatten())
            all_labels.extend(labels.numpy().flatten())
    return cohen_kappa_score(all_labels, all_preds, weights='quadratic')

# Keras version
class QWKCallback(tf.keras.callbacks.Callback):
    def __init__(self, val_data, save_path='best_model.h5'):
        self.val_data = val_data
        self.save_path = save_path
        self.best_kappa = -1

    def on_epoch_end(self, epoch, logs=None):
        X_val, y_val = self.val_data
        y_pred = np.rint(self.model.predict(X_val)).astype(int).clip(0, 4)
        kappa = cohen_kappa_score(y_val, y_pred.flatten(), weights='quadratic')
        print(f" - val_kappa: {kappa:.4f}")
        if kappa > self.best_kappa:
            self.best_kappa = kappa
            self.model.save(self.save_path)
```

## Workflow

1. At each epoch end, generate predictions on the validation set
2. Round continuous predictions to nearest integer class
3. Clip to valid class range (e.g., 0-4)
4. Compute QWK using `cohen_kappa_score(weights='quadratic')`
5. Save model if QWK improves over previous best

## Key Decisions

- **Rounding**: Use `np.rint` for nearest-integer; or optimized thresholds for better QWK
- **Clipping**: Essential — predictions outside [0, n_classes-1] crash kappa computation
- **vs loss-based**: QWK can improve while loss plateaus; metric-based checkpointing is more reliable
- **Patience**: Add early stopping based on QWK plateau (e.g., 5 epochs without improvement)

## References

- [APTOS 2019 DenseNet Keras Starter](https://www.kaggle.com/code/xhlulu/aptos-2019-densenet-keras-starter)
- [EfficientNetB5 with Keras (APTOS 2019)](https://www.kaggle.com/code/carlolepelaars/efficientnetb5-with-keras-aptos-2019)

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.