pulsatrix
Loading...
Searching...
No Matches
integrated_gradients.hpp
Go to the documentation of this file.
1
6#pragma once
7
8#include <stdexcept>
9#include <string>
10#include <vector>
11
12#include "pulsatrix/assert.hpp"
17#include "pulsatrix/tensor.hpp"
18
19namespace pulsatrix {
20
37public:
50 [[nodiscard]] Attribution explain(ExplainerContext& ctx, const Tensor& input, const Tensor& baseline,
51 int64_t target_index, int64_t steps, DeviceBackend* backend) const {
52 // External boundary (Mission 2, finding 15 systemic sweep) -- escalated from
53 // PULSATRIX_ASSERT-only.
54 if (steps <= 0) {
55 throw std::invalid_argument("IntegratedGradients::explain: steps must be positive");
56 }
57 if (input.numel() != baseline.numel()) {
58 throw std::invalid_argument("IntegratedGradients::explain: input and baseline must have the same numel");
59 }
60
61 Saliency saliency;
62 DeviceBackend* input_backend = explainer_detail::backend_beside(input, backend);
63 Tensor accumulated_grad(input.shape(), input_backend, input.device()); // zero-initialized
64
65 const std::vector<float> input_values = input.to_host_vector();
66 const std::vector<float> baseline_values = baseline.to_host_vector();
67 const auto numel = static_cast<size_t>(input.numel());
68
69 std::vector<float> interpolated_values(numel);
70 for (int64_t k = 1; k <= steps; ++k) {
71 float alpha = static_cast<float>(k) / static_cast<float>(steps);
72 for (size_t i = 0; i < numel; ++i) {
73 interpolated_values[i] = baseline_values[i] + alpha * (input_values[i] - baseline_values[i]);
74 }
75 Tensor interpolated(input.shape(), input_backend, interpolated_values, input.device());
76
77 Attribution step = saliency.explain(ctx, interpolated, target_index, backend);
78 accumulated_grad.accumulate(step.values);
79 }
80
81 const std::vector<float> accumulated = accumulated_grad.to_host_vector();
82 std::vector<float> ig(numel);
83 for (size_t i = 0; i < numel; ++i) {
84 float avg_grad = accumulated[i] / static_cast<float>(steps);
85 ig[i] = (input_values[i] - baseline_values[i]) * avg_grad;
86 }
87 Tensor ig_values(input.shape(), input_backend, ig, input.device());
88
89 return Attribution{"integrated_gradients", std::move(ig_values),
90 {{"steps", std::to_string(steps)}, {"target_index", std::to_string(target_index)}}};
91 }
92};
93
94} // namespace pulsatrix
PULSATRIX_ASSERT – debug-only invariant check for programmer errors, distinct from throw (used for ca...
First-class explanation result type – values, method, and metadata together.
Vendor-agnostic compute/memory backend. CPUBackend, CUDABackend (Phase 1.5), and HIPBackend (Phase 1....
Definition device_backend.hpp:219
Wraps an ordered chain of Modules, running them via Module::forward_traced to build a real Computatio...
Definition explainer_context.hpp:67
IG_i(x) = (x_i - baseline_i) * (1/steps) * sum_{k=1}^{steps} d(F(baseline + (k/steps)(x - baseline)))...
Definition integrated_gradients.hpp:36
Attribution explain(ExplainerContext &ctx, const Tensor &input, const Tensor &baseline, int64_t target_index, int64_t steps, DeviceBackend *backend) const
Computes the Integrated Gradients attribution for one output index.
Definition integrated_gradients.hpp:50
Raw-gradient saliency: d(output[target_index])/d(input), computed by seeding ExplainerContext::backwa...
Definition saliency.hpp:29
Attribution explain(ExplainerContext &ctx, const Tensor &input, int64_t target_index, DeviceBackend *backend) const
Computes the saliency map for one output index.
Definition saliency.hpp:49
N-dimensional tensor. Owns its data buffer exclusively; a DeviceBackend* is injected (not owned) – th...
Definition tensor.hpp:29
DeviceType device() const
Which device this tensor's buffer conceptually resides on.
Definition tensor.hpp:122
Tensor & accumulate(const Tensor &other)
In-place elementwise accumulation: this[i] += other[i] for every element.
int64_t numel() const
Total element count – shape().numel().
Definition tensor.hpp:116
const Shape & shape() const
This tensor's shape.
Definition tensor.hpp:113
std::vector< float > to_host_vector() const
Copies the whole buffer to a host vector through the owning backend, on any device.
Abstract interface isolating vendor-specific memory/compute operations from Tensor/ComputationGraph.
Stable interface every explainer gets, regardless of type (charter Part 2 SS2).
DeviceBackend * backend_beside(const Tensor &like, DeviceBackend *backend)
The backend to allocate a tensor through that must live beside like.
Definition attribution.hpp:49
Definition acquisition_functions.hpp:16
Saliency maps – raw gradient of a target output w.r.t. the input (charter Part 1, Phase 2).
An explanation result: the raw attribution values, the method that produced them, and any relevant me...
Definition attribution.hpp:23
Tensor values
The raw attribution values, same shape as the explained input (or a method-specific shape,...
Definition attribution.hpp:29
N-dimensional tensor – owns a buffer via DeviceBackend*, RAII (Rule of Five).