Raw-milk composition from NIR transmittance (PLS, ONNX)
Predicts fat, protein and lactose (%) of raw cow milk from a long-wave NIR transmittance spectrum (960–1690 nm, 256 pixels, ~2.86 nm/pixel). Preprocessing is inside the model: feed raw transmittance, get percentages.
Built by Amazeng as an open reference model for on-farm and in-line milk analysis on edge hardware.
▶ Try it in your browser: Milk NIR Simulator
Usage
import numpy as np, onnxruntime as ort
sess = ort.InferenceSession("milk_nir_pls.onnx")
t = np.asarray(spectra, dtype=np.float32) # (batch, 256) transmittance, 960 -> 1690 nm
fat, protein, lactose = sess.run(None, {"transmittance": t})[0].T
Input: dark/white-corrected transmittance (S - D) / (W - D), 256 values on the wavelength grid of the training
spectrometer (960–1690 nm). A different spectrometer must resample to this grid and be recalibrated (see Limitations).
Inside the model: transmittance → absorbance (−log10) → SNV → Savitzky–Golay 1st derivative (window 15, order 2) → one PLS regression per target, collapsed to a single linear layer. 7.7 KB, three outputs.
Results
Temporal split: trained on weeks 1–6 (n=894), tested on weeks 7–8 (n=330) — a calibration used in the weeks after it was built.
| Target | RMSE (%) | R² | PLS components |
|---|---|---|---|
| Fat | 0.112 | 0.979 | 19 |
| Protein | 0.063 | 0.965 | 39 |
| Lactose | 0.126 | 0.48 | 36 |
A 1D-CNN trained on the same data was worse on every released target (fat R² 0.95, protein 0.41); with ~900 spectra, linear chemometrics wins.
Robustness: what your spectrometer must deliver
RMSE (%) on 24 test spectra when instrument effects are simulated on top of the real measurements
(noise: 20 random draws per spectrum; reproduce with the simulator's nir.js).
| Effect | Fat | Protein | Lactose |
|---|---|---|---|
| None | 0.09 | 0.07 | 0.12 |
| +0.02% detector noise | 0.10 | 0.14 | 0.15 |
| +0.1% detector noise | 0.17 | 0.56 | 0.47 |
| 0.05 px (0.14 nm) wavelength shift | 0.14 | 0.28 | 0.44 |
| 0.2 px (0.57 nm) wavelength shift | 0.35 | 1.00 | 1.96 |
| Lamp intensity ×0.5–1.5 | unchanged | unchanged | unchanged |
The model is calibrated to one cooled InGaAs spectrometer. Protein and lactose need extra noise below ~0.02% and wavelength registration better than ~0.05 px; anything coarser needs recalibration on the target instrument. Lamp intensity has no effect because SNV removes it.
Limitations
- Very sensitive to the instrument (see Robustness). It will not transfer to another spectrometer without recalibration.
- One instrument, one farm, eight weeks (41 Holstein cows, Belgium, 2017). Expect a bias on any other spectrometer or herd; recalibrate with your own reference samples before trusting absolute values.
- Lactose is weak (R² ~0.5, sensitive to the PLS component count). Use fat and protein; treat lactose as indicative.
- Not included: somatic cell count and urea. Neither was predictable from these spectra (test R² ≤ 0.13); SCC > 200k cells/mL screening reached only AUC 0.76. This model is not a mastitis or bacteria test.
- Not a substitute for certified laboratory analysis.
Training data and attribution
J.A. Diaz-Olivares, I. Adriaens, E. Stevens, W. Saeys, B. Aernouts — Near-infrared spectra dataset of milk composition in transmittance mode, Zenodo, 10.5281/zenodo.8263430, CC BY 4.0. Data in Brief (2023) 109767, 10.1016/j.dib.2023.109767.
Related: Diaz-Olivares et al., Online milk composition analysis with an on-farm near-infrared sensor, Comput. Electron. Agric. 178 (2020) 105734.
This model is released under CC BY 4.0. Cite the dataset above when you use it.



