The default advice on explainable AI in production is to bolt a SHAP explainer onto a black box model and call the job done. In a Jupyter notebook that is fine. In a real-time system it is a performance bottleneck, and fraud detection is exactly where you cannot afford one.
I have seen plenty of pipelines described as production ready where inference takes 1ms and the explanation takes 30ms or more. The checkout or transaction flow feels sluggish, and you are now maintaining a second, stochastic component that can give different answers for the same input. That is not engineering, it is a patch. What I have been trying instead is a neuro-symbolic architecture that puts the explanation inside the forward pass.
The latency floor of post-hoc explainers
Lundberg and Lee’s SHAP framework is mathematically elegant, and its model-agnostic variant, KernelExplainer, is also expensive to compute. It runs weighted linear regressions over sampled coalitions of features, so even a small background dataset leaves you sitting on a latency floor. SHAP is stochastic too. Monte Carlo sampling means two identical transactions can leave slightly different numbers in your audit log.
A neuro-symbolic model treats explainability as an architectural requirement rather than a post-processing step. A neural backbone handles the latent representations, a symbolic rule layer produces the justification, and the human-readable output arrives in 0.9ms. That is about 33 times faster than the post-hoc route.
If you want the wider performance context, I wrote up my thinking on WordPress Core Performance and AI.
Building a neuro-symbolic fraud detector
Two paths run in parallel. The left one is an ordinary neural network picking up the non-linear patterns. The right one is a symbolic layer evaluating differentiable rules with learnable thresholds. Those thresholds are not hard coded. Gradient descent updates them during training on sets like the Kaggle Credit Card Fraud data.
class bbioon_NeuroSymbolicDetector(nn.Module):
def __init__(self, input_dim, feature_names):
super().__init__()
# Neural path for latent patterns
self.backbone = nn.Sequential(
nn.Linear(input_dim, 64), nn.BatchNorm1d(64),
nn.ReLU(), nn.Dropout(0.2),
nn.Linear(64, 32), nn.BatchNorm1d(32), nn.ReLU()
)
# Symbolic path for deterministic rules
self.symbolic = SymbolicRuleLayer(feature_names)
# Fusion layer to combine signals
self.fusion = nn.Sequential(
nn.Linear(32 + 1, 16), nn.ReLU(),
nn.Linear(16, 1), nn.Sigmoid()
)
def predict_with_explanation(self, x):
# The explanation is produced DURING the forward pass
rule_activations = self.symbolic(x)
neural_features = self.backbone(x)
# Combine and output
prob = self.fusion(torch.cat([neural_features, rule_activations.mean(dim=1, keepdim=True)], dim=1))
return prob, rule_activations
Watch out for weight collapse
One thing my benchmarks turned up that the tutorials tend to skip: weight collapse in the symbolic layer. With no regularization, a single rule (V4, in the Kaggle set) can end up holding half of the total symbolic weight, and your multi-rule explanation quietly becomes a single-feature gate. An entropy penalty on the rule weights is what stops it, because otherwise the model takes the cheapest path available to it.
The benchmarks
With explainable AI in production, latency is the number people actually argue about. On an i7-class CPU running PyTorch, here is what I measured:
- SHAP post-hoc, with 200 background samples: 30.0 ms per sample.
- Neuro-symbolic inline: 0.89 ms per sample.
- That works out to a 33x cut in latency.
The other half of it is determinism. Run the same transaction 1,000 times and the explanation comes back identical every time. That is what compliance work needs. Nobody wants to explain to a regulator why the fraud reasoning shifted between two runs because of random sampling.
For more on measuring systems like this, there is the WP-Bench AI Benchmark guide.
If this kind of work is eating your dev hours, I can take it on. I have been dealing with WordPress and high-performance backend logic since the 4.x days.
Where that leaves SHAP
SHAP is still the right tool for model debugging and offline analysis. It is the wrong tool inside a live request. If the explanation has to ship with the prediction, that logic belongs in the architecture. You give up a little precision and get speed and consistency back. For real-time fraud detection I will make that trade every time.