# How to Examine the Raw Model Prediction vs Final Magika Output

> Examine raw model prediction vs final Magika output. Access prediction.dl for raw DL labels and prediction.output for final content type. Inspect probabilities with _get_raw_predictions().

- Repository: [Google/magika](https://github.com/google/magika)
- Tags: deep-dive
- Published: 2026-04-16

---

**Access `result.prediction.dl` for the raw deep-learning label and `result.prediction.output` for the final content-type after thresholding; call `_get_raw_predictions()` to inspect the complete probability distribution.**

When using the `google/magika` library to identify file types, the final result returned to you has passed through confidence thresholds and overwrite rules that may differ from the neural network's original guess. Examining the raw model prediction versus the final Magika output allows you to debug low-confidence classifications and understand exactly when and why specific content-type overrides occur. This guide shows you how to surface both the intermediate DL label and the full raw probability vector using the Python API.

## Understanding the Two-Stage Inference Pipeline

The Magika classifier operates in two distinct phases before returning a result.

### Stage 1: Raw Deep-Learning Inference

First, Magika extracts byte-token features from the file and feeds them into an ONNX deep-learning model. This stage produces a **raw probability distribution** over all supported content-type labels. The model votes for a single label—the one with the highest probability—which is stored internally as the "dl" prediction.

### Stage 2: Post-Processing and Confidence Rules

After the model runs, Magika applies business logic defined in [`magika/types/prediction_mode.py`](https://github.com/google/magika/blob/main/magika/types/prediction_mode.py) to determine the final output. If the confidence score falls below a threshold or if an overwrite rule applies (for example, generic text overrides), the raw label may be replaced. The result after this stage is what you see in `result.prediction.output`.

## Accessing the Raw DL Label vs Final Output

The simplest way to compare stages is through the `MagikaResult` object returned by `identify_path()`. This object exposes both the raw and final predictions via the `prediction` attribute.

- **`result.prediction.dl`**: A `ContentTypeInfo` instance representing the label the model selected before any post-processing.
- **`result.prediction.output`**: A `ContentTypeInfo` instance representing the final content-type after thresholds and overwrites.

```python
from pathlib import Path
from magika import Magika

mag = Magika()
result = mag.identify_path(Path("example.pdf"))

# Final output (after confidence thresholds)

print(f"Final label: {result.prediction.output.label}")
print(f"Final MIME:  {result.prediction.output.mime_type}")

# Raw DL prediction (before post-processing)

print(f"Raw label:   {result.prediction.dl.label}")
print(f"Raw MIME:    {result.prediction.dl.mime_type}")

```

When these values differ, the confidence score was likely low or an overwrite rule triggered in [`magika/magika.py`](https://github.com/google/magika/blob/main/magika/magika.py).

## Extracting the Full Raw Probability Vector

To see *why* the model favored a particular label—including the exact probability scores for every supported content-type—you must access the internal `_get_raw_predictions` method in [`magika/magika.py`](https://github.com/google/magika/blob/main/magika/magika.py). This method returns the complete logits or probability vector before any argmax selection occurs.

The process requires three steps:

1. Extract features using `_extract_features_from_path()`
2. Pass features to `_get_raw_predictions()`
3. Map indices to labels using `mag._target_labels_space`

```python
from pathlib import Path
from magika import Magika

mag = Magika()
path = Path("example.pdf")

# Step 1: Extract raw features exactly as the model expects

features = Magika._extract_features_from_path(
    path,
    beg_size=mag._model_config.beg_size,
    mid_size=mag._model_config.mid_size,
    end_size=mag._model_config.end_size,
    padding_token=mag._model_config.padding_token,
    block_size=mag._model_config.block_size,
    use_inputs_at_offsets=mag._model_config.use_inputs_at_offsets,
)

# Step 2: Get raw predictions (returns List[List[float]])

raw_scores = mag._get_raw_predictions([(path, features)])
score_vec = raw_scores[0]  # Single file results

# Step 3: Map to labels and display top 3

labels = mag._target_labels_space
top3 = sorted(
    enumerate(score_vec),
    key=lambda x: x[1],
    reverse=True,
)[:3]

print("Top 3 raw predictions:")
for idx, prob in top3:
    print(f"  {labels[idx]:<15} {prob:.5f}")

# Verify the argmax matches result.prediction.dl

best_idx = max(range(len(score_vec)), key=score_vec.__getitem__)
print(f"\nHighest raw label: {labels[best_idx]}")

```

Note that `_get_raw_predictions` and `_extract_features_from_path` are internal methods (prefixed with underscore) in the `Magika` class, but they are deliberately exposed for testing and debugging purposes.

## Key Source Files and Implementation Details

Understanding these internal structures helps when building custom analysis pipelines:

| File | Purpose |
|------|---------|
| [`magika/magika.py`](https://github.com/google/magika/blob/main/magika/magika.py) | Contains the `Magika` class with `_get_raw_predictions()` and feature extraction logic. |
| [`magika/types/magika_prediction.py`](https://github.com/google/magika/blob/main/magika/types/magika_prediction.py) | Defines the `MagikaPrediction` dataclass storing both `dl` (raw) and `output` (final) as `ContentTypeInfo` objects. |
| [`magika/types/magika_result.py`](https://github.com/google/magika/blob/main/magika/types/magika_result.py) | Wrapper class returned to users; provides access to `prediction.dl` and `prediction.output`. |
| [`magika/types/prediction_mode.py`](https://github.com/google/magika/blob/main/magika/types/prediction_mode.py) | Implements confidence-mode logic that determines when raw predictions are overridden. |

## Summary

- **Raw DL label**: Access via `result.prediction.dl` to see the model's original choice before thresholds.
- **Final output**: Access via `result.prediction.output` to see the post-processed content-type.
- **Full probability vector**: Call `_get_raw_predictions()` after extracting features with `_extract_features_from_path()` to inspect scores for all labels.
- **Label mapping**: Use `mag._target_labels_space` to convert vector indices to human-readable content-type names.

## Frequently Asked Questions

### What does it mean when the raw DL label differs from the final output?

This indicates that Magika's confidence thresholding or overwrite rules modified the result. According to the [`prediction_mode.py`](https://github.com/google/magika/blob/main/prediction_mode.py) implementation, if the model's confidence score falls below a specific threshold or if the file matches certain overwrite patterns (such as generic text detection), the library replaces the raw prediction with a more conservative or accurate label.

### Can I access raw predictions without calling private methods?

No, the full probability vector is only available through the private `_get_raw_predictions()` method in [`magika/magika.py`](https://github.com/google/magika/blob/main/magika/magika.py). However, the raw DL label (the argmax of that vector) is publicly accessible via `result.prediction.dl` on any `MagikaResult` object returned by the standard API.

### Why would I need to examine the full probability distribution instead of just the top label?

Examining the full distribution in `mag._target_labels_space` lets you detect ambiguous classifications where two content-types have nearly identical scores, identify when the model is uncertain (flat probability distribution), and build custom confidence metrics that differ from Magika's default thresholds defined in the library configuration.

### Are the internal methods stable across versions?

While `_get_raw_predictions()` and `_extract_features_from_path()` are technically private, they are maintained as stable debugging interfaces within the `google/magika` repository. The method signatures and return types (List of floats for scores, List of strings for labels) have remained consistent across recent releases, though you should pin your dependency version if your analysis pipeline depends on these internals.