AI Applications for Medical Accelerators

Accelerator Side

CAS Topical Course on Medical Accelerators · Jurmala, Latvia · June 2026

Dr. Adnan Ghribi — GANIL / CNRS-IN2P3 · adnan.ghribi@ganil.fr

Lecture outline

Part 1  —  Introduction

Context  ·  Brief history of AI  ·  AI through the physicist lens

Part 2  —  AI in accelerators

A 30 years dive  ·  Practical foundations Practical applications  ·  Future directions & opportunities

Summary  ·  References

aghribi/cas2026-ai-medical-accelerators AccML review: aghribi.github.io/acc-ml-living-review

Three companion notebooks — open on Colab now:

  • 01_fault_detection — autoencoder on RF waveforms
  • 02_beam_tuning — Bayesian optimisation with Cheetah
  • 03_surrogate_model — MLP surrogate + ensemble UQ

Disclaimer — scope & slide guide

In scope — accelerator side

  • RF fault detection
  • Beam tuning & daily startup
  • Surrogate models for beam physics
  • Digital twins

Out of scope today

  • Treatment planning
  • Patient-facing clinical AI
  • Radiobiology · Regulatory certification

→ covered in the companion lecture “AI — the medical side”.

Slide elements you will encounter
① Code block — executable companion notebook
model.fit(X_train)
anomaly_scores = model.predict(X_test)
② Concept box — key physics or ML idea
CONCEPT
Langevin dynamics ≡ stochastic gradient descent
③ Article references — bottom of slide
Kaiser et al., PRAB 27 (2024) · Duris et al., PRL 124 (2020)
④ GitHub — slides, notebooks & living review

aghribi/cas2026-ai-medical-accelerators

⑤ Colab notebook — open in browser, zero install

▶ Open in Colab 01_fault_detection · 02_beam_tuning · 03_surrogate

A glossary of acronyms is at the end of the deck, before the backup slides.

What AI is — and isn’t

Artificial Intelligence
symbolic logic · expert systems · search & planning
Machine Learning
classical ML (SVM · RF · kNN) · probabilistic models · ★ Bayesian opt. / GP
Neural networks · Deep learning

★ autoencoders · ★ MLP surrogates · CNN / Transformer · deep RL · generative (VAE · diffusion · LLM)

★ Our BO/GP tool lives in this ring — classical ML, not a neural network: “AI” ≠ “deep learning”.

Demystified today — with live code

  • ★ Autoencoder — fault detection
  • ★ Bayesian opt. / GP — beam tuning
  • ★ MLP surrogate — fast beam physics

Not covered here: symbolic AI · LLMs & agents · generative models — touched only in future directions.

Key idea
Match the method to your data — how much you have, and whether it is labelled — not to the hype.

A Brief History of AI

From the first neuron to the Nobel Prize in Physics

From neuron to Nobel Prize (1943–2024)

McCulloch & Pitts — the first artificial neuron (1943)

Warren McCulloch & Walter Pitts — first mathematical model of a neuron, mapping neural firing onto Boolean logic (1943).

How a neuron works:

  • Dendrites collect incoming signals from neighbouring neurons
  • Soma integrates them as a weighted sum \(\sum w_i x_i\)
  • Neuron fires if the sum exceeds threshold θ → signal propagates down the axon

McCulloch & Pitts (1943). A logical calculus of the ideas immanent in nervous activity. Bull. Math. Biophysics 5, 115–133.

The perceptron — first learning algorithm (1957)

Frank Rosenblatt, 1957 — the Perceptron:

\[y = \text{sign}\!\left(\sum_i w_i x_i - \theta\right)\]

One neuron: \(N\) weighted inputs \(x_i\), one binary output \(y\). Unlike McCulloch-Pitts, the weights \(w_i\) are not fixed — they are learned from labelled examples via an error-correction rule.

The perceptron learning rule:

\[w_i \leftarrow w_i + \eta \cdot (y - \hat{y}) \cdot x_i\]

Every modern network still follows this principle.

Rosenblatt’s Mark 1 Perceptron (1958) was a physical hardware device — it made the front page of the New York Times.

Rosenblatt, F. (1958). The perceptron: a probabilistic model for information storage and organization in the brain. Psychol. Rev. 65(6), 386–408.

AI winters and the deep learning renaissance

1969 — First winter Minsky & Papert prove perceptron cannot solve XOR.

1986 — Backpropagation Gradients through layers — the key mathematical unlock.

2012 — AlexNet cuts ImageNet error by 10 pp. Same idea, scaled. Deep learning era begins.

AI Through the Physicist Lens

Energy, spins, and statistical mechanics

Hopfield networks · Boltzmann machines · the physics–ML bridge

Physics at the core of AI

J. Hopfield
G. Hinton

John Hopfield, 1982 — stores memories as energy minima of the Ising Hamiltonian:

\[E = -\frac{1}{2} \sum_{ij} w_{ij} s_i s_j\]

Geoffrey Hinton extended this with the Boltzmann distribution \(P(s) \propto e^{-E/T}\) — giving neural networks a thermodynamic learning rule.

Nobel Prize in Physics 2024

“for foundational discoveries enabling machine learning with artificial neural networks”

John J. Hopfield & Geoffrey E. Hinton

Awarded in Physics, not Computer Science.

Hopfield networks — neurons as spins

A collective-effects view: a beam’s coherent modes emerge from pairwise particle interactions; a Hopfield memory emerges from pairwise neuron couplings. Both are many-body systems governed by an energy function.

The same mathematics describes Ising spins and neural networks:

Ising model Hopfield network
Spin \(s_i \in \{-1,+1\}\) Neuron state
Coupling \(J_{ij}\) Synaptic weight \(w_{ij}\)
\(E = -\tfrac{1}{2}\sum J_{ij}s_is_j\) Same Hamiltonian
Ground state Stored memory

Red = −1 (spin ↓) · Cyan = +1 (spin ↑)

Hebbian learning — to store pattern \(\xi^\mu\): \[w_{ij} = \frac{1}{N}\sum_\mu \xi_i^\mu \xi_j^\mu\]

Hopfield, J.J. (1982). Neural networks and physical systems with emergent collective computational abilities. PNAS 79, 2554–2558.

Statistical mechanics → deep learning

Physics concept ML analogue
Hamiltonian / energy \(H(s)\) Loss function \(\mathcal{L}(\theta)\)
Partition function \(Z = \sum_s e^{-H/T}\) Normalisation constant (softmax, VAE)
Temperature \(T\) Learning rate / annealing schedule
Boltzmann distribution \(P \propto e^{-E/T}\) Softmax output — Boltzmann machine
Phase transition Grokking (sharp generalisation threshold)
Langevin dynamics \(\dot{x} = -\nabla E + \eta\) Stochastic gradient descent (SGD)
Free energy \(F = -T\ln Z\) ELBO / variational lower bound (VAE)

Not metaphors — the same mathematics, rediscovered independently. As accelerator physicists we already speak this language.

A 30 Years Dive in AI for Accelerators

From research curiosity to operational tool

Milestones · concrete results · living review

30 years of AI at accelerators

Year Facility Approach Impact
1992–94 Ion source · storage rings Adaptive NN control (Mead+92); NN orbit correction (Bozoki & Friedman 94) First ML for accelerator control
2020 SLAC LCLS Bayesian optimisation in production setup hours → ~tens of evaluations
2020 JLab CEBAF ML on SRF cavity waveforms Cavity-fault classification
2024 DESY / KIT Cheetah differentiable simulator 10³–10⁵× faster than tracking codes
2020–23 CERN · DESY Reinforcement learning for control & tuning Autonomous closed-loop control
2024 KIT KARA Anomaly detection + energy management −30% energy footprint on real ring

Edelen et al., IEEE TNS 63 (2016) · Duris et al., PRL 124 (2020) · Kaiser et al., PRAB 27 (2024) · Ghribi et al., EPN 56 (2025)

AI in accelerators — concrete results

Fault detection — production ML triage

Beam tuning — BO + RL, closed-loop

Simulation — differentiable, fast surrogates

Optimisation toolboxes — facility-agnostic

Tennant et al., PRAB 23 (2020) · Duris et al., PRL 124 (2020) · Kaiser et al., PRAB 27 (2024) · Ghribi et al., EPN 56 (2025) · Zhang et al., IPAC 2022 (Badger)

Five ways AI helps accelerators today

  • Fault detection — classify anomalous events before interlocks trigger
  • Beam tuning & adaptive control — optimal settings in < 50 evaluations; online RL in the loop
  • Surrogate models — replace slow tracking codes (10³–10⁵× speedup)
  • Predictive maintenance — forecast failures before they occur
  • Digital twins — live virtual model of the actual machine, continuously updated

Practical Foundations

From raw signals to trained model

Data · Features · Method selection · Pipeline

The ML pipeline — from data to inference

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample
Feature extract
FFT · Gaussian fit
statistics · domain
Train & validate
80/20 split
cross-val · AUC
Deploy & infer
Sub-ms response
monitoring · retrain
UC1 · Fault detection
IQ waveforms → autoencoder → anomaly score
UC2 · Beam tuning
Quad settings → Cheetah → BO → proposal
UC3 · Surrogate
5 000 Cheetah calls → MLP → ~600× speedup

The ML pipeline — from data to inference

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample
Feature extract
FFT · Gaussian fit
statistics · domain
Train & validate
80/20 split
cross-val · AUC
Deploy & infer
Sub-ms response
monitoring · retrain
UC1 · Fault detection
IQ waveforms → autoencoder → anomaly score
UC2 · Beam tuning
Quad settings → Cheetah → BO → proposal
UC3 · Surrogate
5 000 Cheetah calls → MLP → ~600× speedup

① Data quality & preprocessing

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample

① Clean Remove corrupted pulses, stuck sensors, dropouts.

② Synchronise Align timestamps across RF, BPM, power supplies.

③ Normalise Scale to [−1, 1] — prevents one channel dominating.

④ Balance SRF faults < 0.1 % of pulses — naïve model learns to ignore them.

A model trained on bad data learns bad behaviour.
No algorithm compensates for this.

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample
Feature extract
FFT · Gaussian fit
statistics · domain
Train & validate
80/20 split
cross-val · AUC
Deploy & infer
Sub-ms response
monitoring · retrain
UC1 · Fault detection
IQ waveforms → autoencoder → anomaly score
UC2 · Beam tuning
Quad settings → Cheetah → BO → proposal
UC3 · Surrogate
5 000 Cheetah calls → MLP → ~600× speedup

② Feature engineering

Feature extract
FFT · Gaussian fit
statistics · domain

Feature extract
FFT · Gaussian fit
statistics · domain

this case: 256 IQ samples → 3 scalars · 99 % compression, fault information retained

The feature map depends on the data — RF waveform → FFT peaks · Q · phase drift  ·  beam image → Gaussian-fit σ, centroid, image moments  ·  bunch → 6-D phase-space stats (emittance, Twiss α/β)  ·  BPM stream → orbit harmonics

Good features = simpler models + better generalisation.
Domain knowledge beats brute force.

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample
Feature extract
FFT · Gaussian fit
statistics · domain
Train & validate
80/20 split
cross-val · AUC
Deploy & infer
Sub-ms response
monitoring · retrain
UC1 · Fault detection
IQ waveforms → autoencoder → anomaly score
UC2 · Beam tuning
Quad settings → Cheetah → BO → proposal
UC3 · Surrogate
5 000 Cheetah calls → MLP → ~600× speedup

③ Train & validate

Train & validate
80/20 split
cross-val · AUC

Train & validate
80/20 split
cross-val · AUC

The task decides what “validate” means — and which metric.

Anomaly detection · UC1 unsupervised autoencoder
Validate on held-out normal + unseen fault types
✓ ROC-AUC · PR-AUC · F1
✗ accuracy — 99.9 % normal hides everything
Surrogate regression · UC3 supervised MLP
Validate on inputs outside the training points
✓ R² · RMSE · residual / σ
✗ extrapolation past the training envelope
Optimisation · UC2 Bayesian optimisation
No train/test split — judge best-so-far vs budget, across seeds
✓ regret · convergence · reproducibility
✗ trusting one lucky run

Same word, three protocols.
Anomaly & surrogate split the data; optimisation measures regret over a budget — there is no test set.

Train & validate
80/20 split
cross-val · AUC

Train / validate / test — and the overfitting trap (supervised tasks)

Train · 70 %
Val · 15 %
Test · 15 %
fit the weights
tune & early-stop
touch once — unbiased estimate
⚡  Definition — Epoch

One epoch = one complete forward + backward pass over every training sample.
Example: 10 000 pulses, batch 32 → 313 weight updates per epoch.
Training halts when validation loss stops improving — the dashed line marks that minimum (early stopping).

Validate on data the model has never seen — and on faults it has never seen.
Temporal splits matter more than random splits in accelerator data — and stratify to preserve the < 0.1 % fault rate.

Raw Data
Waveforms · images
logs · set-points
Pre-process
Clean · sync
normalise · resample
Feature extract
FFT · Gaussian fit
statistics · domain
Train & validate
80/20 split
cross-val · AUC
Deploy & infer
Sub-ms response
monitoring · retrain
UC1 · Fault detection
IQ waveforms → autoencoder → anomaly score
UC2 · Beam tuning
Quad settings → Cheetah → BO → proposal
UC3 · Surrogate
5 000 Cheetah calls → MLP → ~600× speedup

④ Deploy & infer

Deploy & infer
Sub-ms response
monitoring · retrain

Deploy & infer
Sub-ms response
monitoring · retrain

① Latency budget Set by the control loop, not the model: fast feedback may need sub-ms, daily tuning tolerates seconds.

② Export & serve Deterministic runtime (e.g. ONNX, TorchScript) embeddable in EPICS / TANGO / DOOCS — no Python in the loop.

③ Compress to hardware Pruning + quantisation (FP32→INT8) cut latency — at some accuracy cost; trade-off depends on CPU / GPU / FPGA.

④ Monitor & retrain Track output rate and input distributions; retrain when drift crosses a threshold.

A model in a notebook is not a deployed model.
Latency, reliability and drift monitoring are engineering problems.

Practical Applications

Three use cases · Three live notebooks

Use case 1 — RF fault detection  ·  Use case 2 — Beam tuning  ·  Use case 3 — Surrogate models

Use Case 1

RF Fault Detection

Autoencoders on cavity IQ waveforms · Notebook 01

The problem: rare faults, no labels

① Problem · ② Method · ③ Results · ④ Notebook

Every RF pulse → one IQ waveform per cavity at ~1 kHz. Clinical machines are safe by design — faults are rare.

Supervised classifiers need thousands of labelled fault examples per class — unavailable in clinical operation.

Solution: train on normal pulses only. Anomaly score = reconstruction error.

~1 kHz
IQ samples per cavity per second
1M+ pulses/day in clinical operation

Four fault classes — superconducting cavity
Class Signature
Normal Clean trapezoid · Q ≈ 0
Quench Sudden drop mid flat-top
Detuning Off-resonance · large Q
Multipacting Oscillations on flat-top

No fault labels
needed

Anomaly detection trains on normal only

What the waveforms look like

① Problem · ② Method · ③ Results · ④ Notebook

The autoencoder — architecture

① Problem · ② Method · ③ Results · ④ Notebook
class RFAutoencoder(nn.Module):
    def __init__(self, latent_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Conv1d(2, 32, kernel_size=8, stride=4),
            nn.GELU(),
            nn.Conv1d(32, 64, kernel_size=4, stride=2),
            nn.GELU(),
            nn.Flatten(),
            nn.Linear(64 * 32, latent_dim),  # bottleneck
        )
        self.decoder = nn.Sequential(...)    # mirror
class RFAutoencoder(nn.Module):
    def __init__(self, latent_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Conv1d(2, 32, kernel_size=8, stride=4),
            nn.GELU(),
            nn.Conv1d(32, 64, kernel_size=4, stride=2),
            nn.GELU(),
            nn.Flatten(),
            nn.Linear(64 * 32, latent_dim),  # bottleneck
        )
        self.decoder = nn.Sequential(...)    # mirror
class RFAutoencoder(nn.Module):
    def __init__(self, latent_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Conv1d(2, 32, kernel_size=8, stride=4),
            nn.GELU(),
            nn.Conv1d(32, 64, kernel_size=4, stride=2),
            nn.GELU(),
            nn.Flatten(),
            nn.Linear(64 * 32, latent_dim),  # bottleneck
        )
        self.decoder = nn.Sequential(...)    # mirror
class RFAutoencoder(nn.Module):
    def __init__(self, latent_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Conv1d(2, 32, kernel_size=8, stride=4),
            nn.GELU(),
            nn.Conv1d(32, 64, kernel_size=4, stride=2),
            nn.GELU(),
            nn.Flatten(),
            nn.Linear(64 * 32, latent_dim),  # bottleneck
        )
        self.decoder = nn.Sequential(...)    # mirror
class RFAutoencoder(nn.Module):
    def __init__(self, latent_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Conv1d(2, 32, kernel_size=8, stride=4),
            nn.GELU(),
            nn.Conv1d(32, 64, kernel_size=4, stride=2),
            nn.GELU(),
            nn.Flatten(),
            nn.Linear(64 * 32, latent_dim),  # bottleneck
        )
        self.decoder = nn.Sequential(...)    # mirror

Input (batch, 2, 256) — I and Q as two channels

① Encoder · lines 4–11 — two Conv1d stages compress the (2, 256) waveform.

② 1D convolutions · lines 5, 7 — capture local features (rise, drop, oscillations) with few parameters.

③ Bottleneck · line 10 — the pulse is squeezed through 16 numbers; the net must learn what normal looks like.

④ Decoder · line 12 — mirrors the encoder, rebuilding (2, 256) from the 16-D code.

Anomaly score = reconstruction error · Normal → low · Faults → high

2×256
32 ch
64 ch
16
64 ch
32 ch
2×256

◀ encoder · compress bottleneck decoder · reconstruct ▶

Training and result

① Problem · ② Method · ③ Results · ④ Notebook
# Train on NORMAL pulses only
X_normal = X_train[y_train == 0]
for epoch in range(50):
    for (batch,) in loader:
        loss = ((batch - model(batch))**2).mean()
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# Score every pulse at inference
with torch.no_grad():
    scores = ((X - model(X))**2).mean(dim=(1,2))
threshold = scores[normal_mask].quantile(0.95)
# Train on NORMAL pulses only
X_normal = X_train[y_train == 0]
for epoch in range(50):
    for (batch,) in loader:
        loss = ((batch - model(batch))**2).mean()
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# Score every pulse at inference
with torch.no_grad():
    scores = ((X - model(X))**2).mean(dim=(1,2))
threshold = scores[normal_mask].quantile(0.95)
# Train on NORMAL pulses only
X_normal = X_train[y_train == 0]
for epoch in range(50):
    for (batch,) in loader:
        loss = ((batch - model(batch))**2).mean()
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# Score every pulse at inference
with torch.no_grad():
    scores = ((X - model(X))**2).mean(dim=(1,2))
threshold = scores[normal_mask].quantile(0.95)
# Train on NORMAL pulses only
X_normal = X_train[y_train == 0]
for epoch in range(50):
    for (batch,) in loader:
        loss = ((batch - model(batch))**2).mean()
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# Score every pulse at inference
with torch.no_grad():
    scores = ((X - model(X))**2).mean(dim=(1,2))
threshold = scores[normal_mask].quantile(0.95)

① Train on normal only · lines 1–2 — the model never sees a fault.

② Reconstruction loss · lines 3–8 — minimise the MSE between each pulse and its rebuild.

③ Unsupervised threshold · lines 10–13 — flag pulses above the 95th percentile of normal errors. No fault labels used.

1.000
ROC-AUC — on synthetic data

Concept — ROC-AUC

A detector needs a threshold — but which one? ROC-AUC sidesteps the choice.
Sweep every threshold; at each, plot true-positive rate (sensitivity) vs false-positive rate (1 − specificity). AUC = area under that curve.
0.5 → coin-flip   1.0 → perfect separation of normal vs fault.
Threshold-independent — the right metric when a sub-0.1 % fault rate makes any single fixed cut arbitrary.

Notebook 01 — live preview

① Problem · ② Method · ③ Results · ④ Notebook

▶ Open 01_fault_detection in Colab

Use Case 2

Beam Tuning with Bayesian Optimisation

Cheetah · differentiable accelerator simulation · Notebook 02

The daily startup problem

① Problem · ② Method · ③ Results · ④ Notebook

Every morning on a clinical machine:

  1. Run QA checks (output, flatness, energy)
  2. Tune magnets until beam is within spec
  3. Hand off to clinical staff

Currently: 20–45 min of physicist time, largely manual.

\(n\) correctors × \(k\) quads → high-dimensional space that grows exponentially for grid search.

Bayesian Optimisation fits naturally:

  • Works in 2–20 dimensions
  • ~50 evaluations to a good solution
  • Model-free — no simulator needed

Demonstrated in production at SLAC LCLS and across light sources, FELs, and linacs (Duris 2020; Roussel et al. 2024).

Concept — Bayesian prior

A prior P(f) encodes your belief before data — e.g. “the beam response is smooth in magnet space”.
Bayes’ theorem updates it: P(f | data) ∝ P(data | f) · P(f) — the result is the posterior.
BO uses the posterior to pick the next probe: explore where uncertain, exploit where promising.
Every measurement actively informs the next — no wasted machine evaluations.

Cheetah — PyTorch beam dynamics

① Problem · ② Method · ③ Results · ④ Notebook
import torch, cheetah

# Beam diverges after a 2 m upstream drift
upstream = cheetah.Segment([cheetah.Drift(length=torch.tensor(2.0))])
beam_in  = upstream.track(cheetah.ParameterBeam.from_twiss(
    energy=torch.tensor(1088.3e6),   # 150 MeV proton, eV
    beta_x=torch.tensor(0.3),
    emittance_x=torch.tensor(1e-6),
    species=cheetah.Species("proton"),
))

# Re-focusing doublet
segment = cheetah.Segment(elements=[
    cheetah.Drift(length=torch.tensor(0.1)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q1"),
    cheetah.Drift(length=torch.tensor(0.6)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q2"),
    cheetah.Drift(length=torch.tensor(0.3)),
    cheetah.Screen(name="monitor"),
])

beam_out = segment.track(beam_in)
import torch, cheetah

# Beam diverges after a 2 m upstream drift
upstream = cheetah.Segment([cheetah.Drift(length=torch.tensor(2.0))])
beam_in  = upstream.track(cheetah.ParameterBeam.from_twiss(
    energy=torch.tensor(1088.3e6),   # 150 MeV proton, eV
    beta_x=torch.tensor(0.3),
    emittance_x=torch.tensor(1e-6),
    species=cheetah.Species("proton"),
))

# Re-focusing doublet
segment = cheetah.Segment(elements=[
    cheetah.Drift(length=torch.tensor(0.1)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q1"),
    cheetah.Drift(length=torch.tensor(0.6)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q2"),
    cheetah.Drift(length=torch.tensor(0.3)),
    cheetah.Screen(name="monitor"),
])

beam_out = segment.track(beam_in)
import torch, cheetah

# Beam diverges after a 2 m upstream drift
upstream = cheetah.Segment([cheetah.Drift(length=torch.tensor(2.0))])
beam_in  = upstream.track(cheetah.ParameterBeam.from_twiss(
    energy=torch.tensor(1088.3e6),   # 150 MeV proton, eV
    beta_x=torch.tensor(0.3),
    emittance_x=torch.tensor(1e-6),
    species=cheetah.Species("proton"),
))

# Re-focusing doublet
segment = cheetah.Segment(elements=[
    cheetah.Drift(length=torch.tensor(0.1)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q1"),
    cheetah.Drift(length=torch.tensor(0.6)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q2"),
    cheetah.Drift(length=torch.tensor(0.3)),
    cheetah.Screen(name="monitor"),
])

beam_out = segment.track(beam_in)
import torch, cheetah

# Beam diverges after a 2 m upstream drift
upstream = cheetah.Segment([cheetah.Drift(length=torch.tensor(2.0))])
beam_in  = upstream.track(cheetah.ParameterBeam.from_twiss(
    energy=torch.tensor(1088.3e6),   # 150 MeV proton, eV
    beta_x=torch.tensor(0.3),
    emittance_x=torch.tensor(1e-6),
    species=cheetah.Species("proton"),
))

# Re-focusing doublet
segment = cheetah.Segment(elements=[
    cheetah.Drift(length=torch.tensor(0.1)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q1"),
    cheetah.Drift(length=torch.tensor(0.6)),
    cheetah.Quadrupole(length=torch.tensor(0.3), name="Q2"),
    cheetah.Drift(length=torch.tensor(0.3)),
    cheetah.Screen(name="monitor"),
])

beam_out = segment.track(beam_in)

① Beam setup · lines 3–10 — a 150 MeV proton beam; after a 2 m drift it has diverged.

② Re-focusing doublet · lines 12–21 — two independently powered quads (Q1, Q2) and a screen.

③ Track · line 22 — push the beam through; read σ at the screen.

Why Cheetah? PyTorch module → gradients flow through the simulation · ms per call · same API for a virtual or real machine.

At the screen, quads off: σ_x + σ_y = 13.2 mm (6.6 mm/plane) — the baseline BO must beat.

 ·  Kaiser, Xu, Eichler & Santamaria Garcia, PRAB 27, 054601 (2024)

BO finds focus in tens of evaluations

① Problem · ② Method · ③ Results · ④ Notebook
from skopt import gp_minimize
from skopt.space import Real

NOISE = 0.04  # 4% shot-to-shot noise

def objective(params):
    k1_q1, k1_q2 = params
    segment.Q1.k1 = torch.tensor(k1_q1)
    segment.Q2.k1 = torch.tensor(k1_q2)
    beam_out = segment.track(beam_in)
    sigma = (beam_out.sigma_x + beam_out.sigma_y).item()
    if not np.isfinite(sigma): return 0.20
    return sigma * (1 + np.random.normal(0, NOISE))

result = gp_minimize(
    func=objective,
    dimensions=[Real(-15, 15, name="k1_Q1"),
                Real(-15, 15, name="k1_Q2")],
    n_calls=60, n_initial_points=12,
    acq_func="EI",                # Expected Improvement
)
# → ~2.2 mm (8-seed) vs 13.2 mm — a ~6× cut
from skopt import gp_minimize
from skopt.space import Real

NOISE = 0.04  # 4% shot-to-shot noise

def objective(params):
    k1_q1, k1_q2 = params
    segment.Q1.k1 = torch.tensor(k1_q1)
    segment.Q2.k1 = torch.tensor(k1_q2)
    beam_out = segment.track(beam_in)
    sigma = (beam_out.sigma_x + beam_out.sigma_y).item()
    if not np.isfinite(sigma): return 0.20
    return sigma * (1 + np.random.normal(0, NOISE))

result = gp_minimize(
    func=objective,
    dimensions=[Real(-15, 15, name="k1_Q1"),
                Real(-15, 15, name="k1_Q2")],
    n_calls=60, n_initial_points=12,
    acq_func="EI",                # Expected Improvement
)
# → ~2.2 mm (8-seed) vs 13.2 mm — a ~6× cut
from skopt import gp_minimize
from skopt.space import Real

NOISE = 0.04  # 4% shot-to-shot noise

def objective(params):
    k1_q1, k1_q2 = params
    segment.Q1.k1 = torch.tensor(k1_q1)
    segment.Q2.k1 = torch.tensor(k1_q2)
    beam_out = segment.track(beam_in)
    sigma = (beam_out.sigma_x + beam_out.sigma_y).item()
    if not np.isfinite(sigma): return 0.20
    return sigma * (1 + np.random.normal(0, NOISE))

result = gp_minimize(
    func=objective,
    dimensions=[Real(-15, 15, name="k1_Q1"),
                Real(-15, 15, name="k1_Q2")],
    n_calls=60, n_initial_points=12,
    acq_func="EI",                # Expected Improvement
)
# → ~2.2 mm (8-seed) vs 13.2 mm — a ~6× cut
from skopt import gp_minimize
from skopt.space import Real

NOISE = 0.04  # 4% shot-to-shot noise

def objective(params):
    k1_q1, k1_q2 = params
    segment.Q1.k1 = torch.tensor(k1_q1)
    segment.Q2.k1 = torch.tensor(k1_q2)
    beam_out = segment.track(beam_in)
    sigma = (beam_out.sigma_x + beam_out.sigma_y).item()
    if not np.isfinite(sigma): return 0.20
    return sigma * (1 + np.random.normal(0, NOISE))

result = gp_minimize(
    func=objective,
    dimensions=[Real(-15, 15, name="k1_Q1"),
                Real(-15, 15, name="k1_Q2")],
    n_calls=60, n_initial_points=12,
    acq_func="EI",                # Expected Improvement
)
# → ~2.2 mm (8-seed) vs 13.2 mm — a ~6× cut

What the code does

① Objective · lines 6–13 — set the two quads, track in Cheetah, return σ_x + σ_y (with 4 % shot noise).

② gp_minimize · lines 15–21 — the BO loop: a GP surrogate + Expected-Improvement choose each next setting (60 calls, 12 random to start).

③ Result · line 22 — 13.2 → ~2.2 mm (8-seed mean), a ~6× cut in tens of evaluations.

Concept — Gaussian process vs Bayesian optimisation

Gaussian process = the model. Predicts a mean + variance at every untried setting; the kernel sets smoothness (Matérn 5/2 default).
Bayesian optimisation = the loop. Fit GP → maximise Expected Improvement (exploit low mean vs explore high variance) → evaluate → repeat.
GP = the engine (“what does it look like?”); BO = the driver (“where next?”).

Notebook 02 — live preview

① Problem · ② Method · ③ Results · ④ Notebook

▶ Open 02_beam_tuning in Colab

Use Case 3

Surrogate Models

Replacing tracking codes with neural networks · Notebook 03

The speed problem

① Problem · ② Method · ③ Results · ④ Notebook

Real-time control needs millisecond response — not minutes.

Workflow:

  1. Run the slow code offline for thousands of inputs
  2. Train a neural network on those pairs
  3. Call the NN instead of the simulator at runtime

Typical speedup: 10³–10⁵× · error < 1% in domain

Training the surrogate

① Problem · ② Method · ③ Results · ④ Notebook
# MLP: (k₁_QF, k₁_QD) → (σ_x, σ_y) in mm
surrogate = nn.Sequential(
    nn.Linear(2, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 2),
)
# 5 000 Cheetah calls offline (3 s total)
# 300 epochs · Adam · cosine LR schedule
# MLP: (k₁_QF, k₁_QD) → (σ_x, σ_y) in mm
surrogate = nn.Sequential(
    nn.Linear(2, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 2),
)
# 5 000 Cheetah calls offline (3 s total)
# 300 epochs · Adam · cosine LR schedule
# MLP: (k₁_QF, k₁_QD) → (σ_x, σ_y) in mm
surrogate = nn.Sequential(
    nn.Linear(2, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 2),
)
# 5 000 Cheetah calls offline (3 s total)
# 300 epochs · Adam · cosine LR schedule
# MLP: (k₁_QF, k₁_QD) → (σ_x, σ_y) in mm
surrogate = nn.Sequential(
    nn.Linear(2, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 128), nn.Tanh(),
    nn.Linear(128, 2),
)
# 5 000 Cheetah calls offline (3 s total)
# 300 epochs · Adam · cosine LR schedule

① Input → output · line 1 — two quad strengths (k₁) map to the two beam sizes (σ_x, σ_y).

② The network · lines 2–7 — a small MLP: three 128-wide Tanh hidden layers.

③ Training data · lines 8–9 — 5 000 Cheetah samples generated offline; 300 epochs with Adam.

1.0000
0.001 mm
MAE
~600×
speedup

Notebook 03 — live preview

① Problem · ② Method · ③ Results · ④ Notebook

▶ Open 03_surrogate_model in Colab

Future Directions & Opportunities

Open problems · What comes next · Community

Open problems

⚖ Explainability — EU AI Act: control-loop AI = high-risk.

🔁 Cross-facility transfer — Centre A model ≠ Centre B.

🔌 Agnostic integration — deploy one model into EPICS, TANGO or DOOCS; vendor-neutral adapter layer.

🗂 Data & model standards — no shared schema across facilities; FAIR ML models still missing.

🤖 Agentic orchestration — LLM agents coordinating multiple AI subsystems; emerging architecture.

EU AI Act 2024
High-risk class · SHAP / LIME audit

A → B gap
Few-shot domain adaptation: active research

EPICS · TANGO · DOOCS
vendor-neutral adapter layer
certification pipeline: active design work

FAIR + ONNX
Findable, Accessible, Interoperable, Reusable
ML-Exchange · open model registry emerging

Multi-agent
Fault-detect + tune + optimise, orchestrated
LLM planner → specialist ML tools

Active research — AI delivers value today.

Concept — Explainability (XAI)

SHAP: assigns each input a numerical contribution to the prediction (Shapley values from game theory, 1953 — model-agnostic).
LIME: fits a local linear model around one specific prediction to explain it locally.
EU AI Act (2024) classifies control-loop AI on clinical machines as high-risk — auditable, explainable decisions required.
In practice: SHAP tells you whether the model learned beam physics or a spurious data artefact.
→ XAI is developed in depth in the lecture proceedings.

What comes next — advanced AI for accelerators

Foundation models pretrain on multi-facility data  ·  RL closes the loop on the real machine (CERN, DESY)  ·  Generative models synthesise rare fault data  ·  Digital twins = surrogate + live sensors, enabled by the ~600× speedup (→ TwinRISE)

Stay connected — opportunities

AI-for-science missions
RAISE — EU “CERN for AI” · €107 M · Horizon Europe
GENESIS — US DOE · $293 M · 17 national labs

Hands-on — workshops & schools
RL4AA — workshop & challenge · Liverpool 2026
AISSAI Hackathon — Oct 11–16 2026 · IN2P3

Join the ARTIFACT network
ARTIFACT — 6 active initiatives · 14 countries · +40 partner institutions · 6 sister networks

€107 M
RAISE · Horizon Europe 2025–27
Resource for AI in Science in Europe

ec.europa.eu → RAISE

$293 M
GENESIS · US DOE · 17 national labs · 2025
energy.gov → Genesis

RL4AA · Liverpool 2026
Tutorials · challenge · open datasets
rl4aa.github.io

AISSAI · Oct 11–16 2026
AI for Particle Accelerators hackathon
indico.in2p3.fr/event/39704 · slides

ARTificial Intelligence For Accelerators, user Communities and associated Technologies

Shares data · beam-time · models · training material
Multi-project synergiesTwinRISE · IRIS · SCIANCE · ARTIFACT Doctoral Networks

TwinRISE links AI across accelerators & medical.

This work has received funding from the European Union’s Horizon Europe research & innovation programme — grant agreements No. 101275935 (iRIS), 101287548 (TwinRISE) & 101293570 (SCIANCE) — and from national & EU partner programmes.

Summary

AI is broader than deep learning. We built three methods end to end — two neural, one classical (BO/GP) — on real beam-physics problems: problem → method → result → runnable notebook.

  • Three use cases, end to end — fault detection (AUC ≈ 1) · beam tuning (BO + Cheetah, advantage grows with dimension) · surrogate (R² ≈ 1, ~600× faster).
  • Physics ↔︎ AI — Hopfield, Boltzmann machines, the 2024 Nobel in Physics: we are natural practitioners, not outsiders.
  • The model is rarely the bottleneck — data quality, features and the pipeline decide whether it works.
  • Deployment ≠ accuracy — latency, drift, explainability and certification are the real blockers to the clinic.

All code open & runnable on Colab — github.com/aghribi/cas2026-ai-medical-accelerators

References & Further Reading

Key papers — cited in this lecture

Ghribi et al., EPN 56(1), 15 (2025)
Roussel et al., PRAB 27, 084801 (2024)
Kaiser et al., PRAB 27, 054601 (2024)
Duris et al., PRL 124, 124801 (2020)
Tennant et al., PRAB 23, 114601 (2020)
Hopfield, PNAS 79, 2554 (1982)

RL4AA community
rl4aa.github.io — workshops · tutorials · challenge

Glossary — acronyms used in this lecture

AI — Artificial Intelligence
ML — Machine Learning
NN — Neural Network
MLP — Multi-Layer Perceptron
CNN — Convolutional Neural Network
LSTM — Long Short-Term Memory
AE — Autoencoder
VAE — Variational Autoencoder
RL — Reinforcement Learning
PINN — Physics-Informed Neural Network
SVM — Support Vector Machine

BO — Bayesian Optimisation
GP — Gaussian Process
EI — Expected Improvement
LHS — Latin Hypercube Sampling
PCA — Principal Component Analysis
UQ — Uncertainty Quantification
MC — Monte Carlo (dropout)
ROC — Receiver Operating Characteristic
AUC — Area Under the ROC Curve
MSE / MAE — Mean Squared / Absolute Error
— Coefficient of Determination

XAI — Explainable AI
SHAP — SHapley Additive exPlanations
LIME — Local Interpretable Model-agnostic Explanations
FAIR — Findable, Accessible, Interoperable, Reusable
ONNX — Open Neural Network Exchange
IQ — In-phase / Quadrature (RF)
SRF — Superconducting Radio-Frequency
BPM — Beam Position Monitor
EPICS · TANGO · DOOCS — control systems
TRL — Technology Readiness Level

Thank you · Questions welcome

Dr. Adnan Ghribi · GANIL / CNRS-IN2P3 · adnan.ghribi@ganil.fr

Backup

Hopfield — memory retrieval and capacity

① Ball in a valley — memories are energy minima. Noisy input rolls downhill → arrives at nearest stored pattern.

② Spin update\(s_i \leftarrow \text{sign}(\sum_j w_{ij} s_j)\) Energy decreases at every step: guaranteed convergence.

③ Capacity ≈ 0.14 N — beyond this, retrieval fails catastrophically (sharp phase transition, not gradual).

si ← sign(Σ wij sj)

Hebb rule · ΔE ≤ 0 per step
Same physics as spin relaxation

0.14 N
Capacity limit · recall error: 0 → 50%

Amit, Gutfreund & Sompolinsky (1985). Storing infinite numbers of patterns in a spin-glass model. PRL 55, 1530.

How Minsky & Papert froze the field (1969)

1969 — Perceptrons (Minsky & Papert) proved a single-layer perceptron cannot compute XOR, nor any non-linearly-separable function.

Impact as much sociological as mathematical:

  • US funding agencies read it as “neural nets are a dead end”
  • Connectionist funding collapsed through the 1970s
  • The field pivoted to symbolic AI / expert systems
  • Revived only by backprop (Werbos 1974; Rumelhart–Hinton–Williams 1986) — which trains the hidden layers they dismissed

The irony

XOR is solvable — with one hidden layer. The authors knew it, but wrongly argued such nets could never be trained at scale. Backprop proved them wrong 17 years later.

One influential “impossibility” result can freeze a direction for a decade. Scepticism cuts both ways.

Minsky & Papert (1969). Perceptrons, MIT Press. · Werbos (1974) · Rumelhart, Hinton & Williams (1986), Nature 323, 533.

Backup — Bayesian optimisation internals

Expected Improvement acquisition function:

\[\alpha_{\text{EI}}(x) = \mathbb{E}\big[\max(0,\; f_{\text{best}} - f(x))\big]\]

For a GP posterior with mean \(\mu(x)\), std \(\sigma(x)\), and \(z = \dfrac{f_{\text{best}} - \mu(x)}{\sigma(x)}\):

\[\alpha_{\text{EI}}(x) = \sigma(x)\,\big[\,z\,\Phi(z) + \phi(z)\,\big]\]

  • \(\Phi, \phi\) — standard-normal CDF / PDF
  • term 1 exploits (low predicted mean), term 2 explores (high variance)
  • next probe = \(\arg\max_x \alpha_{\text{EI}}(x)\)

The kernel is the prior on smoothness

  • Matérn 5/2 — twice-differentiable; default for physical systems
  • RBF — infinitely smooth (often too smooth for real data)
  • Periodic — cyclic signals (RF phase)

Kernel choice encodes physics — the single most consequential modelling decision in BO.

Backup — BO vs grid / random as dimension grows

Controlled experiment (notebook 02 §7b): a D-quad matching section, the same budget B = 120 evaluations for every method, log(σ_x+σ_y) objective, 4% noise, 3 seeds.

Dimension Grid Random Bayesian opt.
D = 2 (2 quads) 5.1 mm 4.7 mm 3.4 mm
D = 4 (4 quads) 7.2 mm 3.0 mm 1.2 mm
D = 6 (6 quads) 5.9 mm 4.6 mm 1.5 mm

At D = 6, BO is ~3× better than either baseline and every seed wins. A full-resolution 7ᴰ grid would need 7⁶ = 117,649 evaluations; BO used 120.

Why grid/random collapse: usable volume shrinks as ~rᴰ, so a fixed budget covers exponentially less of the space. BO builds a surrogate and spends evaluations where they matter. And note D = 4/6 reach a smaller spot than D = 2 — more quads give more focusing freedom, which BO exploits and classical methods cannot.

Backup — why an autoencoder, not a classifier?

Approach Needs fault labels? Detects unseen fault types? Fit for clinical RF
Threshold / interlock no no — only hard-coded limits safety net, not detection
Supervised classifier (Tennant 2020) yes — many per class no great when labels exist
Autoencoder (ours) no — normal data only yes fits label-scarce clinical ops

The autoencoder learns “normal”; anything it reconstructs poorly is flagged — including fault modes never seen in training. A supervised classifier can only recognise the classes it was trained on.

Trade-off: the autoencoder tells you something is wrong, not what. Pair it with a classifier once labels accumulate.

Backup — uncertainty quantification, in numbers

Two ways to make the MLP surrogate report confidence (notebook 03):

Deep ensemble — train N models from different initialisations; the spread of their predictions is the uncertainty.

MC-dropout — keep dropout active at inference and run K stochastic forward passes.

Measured — MC-dropout, σ_x+σ_y

  • R² ≈ 0.999
  • σ_MC ≈ 0.13 mm
  • ~99.7% empirical coverage (within ±3σ)

Epistemic (reducible by more data) vs aleatoric (irreducible noise). For control you want calibrated σ — the error bars should match the actual errors.

Backup — reinforcement learning in the control loop

Setup: the agent observes machine state \(s\) (BPMs, losses), takes action \(a\) (corrector / quad set-points), receives reward \(r\) (e.g. −beam loss), and learns a policy \(\pi(a\,|\,s)\) that maximises cumulative reward.

Why RL, not BO, here? RL amortises: it learns a reusable policy for a recurring sequential task, where BO re-optimises from scratch every time.

Demonstrated

  • CERN — sample-efficient RL for steering (Kain et al. 2020)
  • DESY — online RL + BO injector tuning (Kaiser et al. 2023)
  • RL4AA — community challenge & open benchmarks

Open problems on a clinical machine: sample efficiency and safe exploration.

Kain et al., PRAB 23, 124801 (2020) · Hirländer et al. (2020) · Kaiser et al. (2023)

Backup — EU AI Act & clinical certification

The EU AI Act (2024) is risk-tiered. AI in the control loop of a medical device falls in the high-risk class, which requires:

  • documented training data & provenance
  • demonstrable robustness and accuracy
  • meaningful human oversight
  • explainable, auditable decisions

Practical consequences

  • black-box models need an XAI layer (SHAP / LIME) for audit
  • versioned, reproducible models (FAIR + ONNX)
  • a certification pipeline that re-validates after every retrain

This is why “AUC = 1.0 in a notebook” is the start, not the end. Certification, not accuracy, is the bottleneck to clinical deployment.

Backup — anomaly detection: method landscape

This lecture: Autoencoder — unsupervised, normal-data only, scales to 1 kHz waveform streams.

Backup — optimisation: method landscape

Duris et al., PRL 124 (2020) · Roussel et al., PRAB 27 (2024) · Emma et al., Nat. Mach. Int. 1 (2019) · Kain et al., Phys. Rev. Accel. Beams 23 (2020)

Backup — surrogate models: method landscape

Edelen et al., IEEE TNS 63 (2016) · Kaiser et al., PRAB 27 (2024)

Concept — Uncertainty quantification

Epistemic (model) uncertainty: caused by insufficient data — reducible by collecting more samples.
Aleatoric (data) uncertainty: inherent measurement noise — irreducible.
Methods: deep ensembles (spread of N models) · MC Dropout (stochastic inference) · Gaussian processes (closed-form variance).
Knowing when the model is uncertain is as important as the prediction itself — especially for safety-critical beam control.