|
2 | 2 |
|
3 | 3 | import ai.djl.MalformedModelException; |
4 | 4 | import ai.djl.inference.Predictor; |
5 | | -import ai.djl.ndarray.NDArray; |
6 | 5 | import ai.djl.ndarray.NDList; |
7 | | -import ai.djl.ndarray.NDManager; |
8 | 6 | import ai.djl.ndarray.types.Shape; |
9 | 7 | import ai.djl.repository.zoo.Criteria; |
10 | 8 | import ai.djl.repository.zoo.ModelNotFoundException; |
|
13 | 11 | import ai.djl.translate.TranslateException; |
14 | 12 | import ai.djl.translate.Translator; |
15 | 13 | import ai.djl.translate.TranslatorContext; |
16 | | - |
17 | | -import org.jlab.utils.CLASResources; |
18 | | - |
19 | 14 | import java.io.IOException; |
20 | 15 | import java.nio.file.Paths; |
21 | 16 | import java.util.logging.Logger; |
| 17 | +import org.jlab.utils.CLASResources; |
22 | 18 |
|
23 | 19 | public class ModelPrePID { |
24 | | - |
25 | | - static final Logger LOGGER = Logger.getLogger(ModelPrePID.class.getName()); |
26 | | - // Must match training class order |
27 | | - private static final int[] CLASS_IDS = new int[]{2212, 45, 46, 47, 49}; |
28 | | - |
29 | | - private final ZooModel<float[], float[]> model; |
30 | | - |
31 | | - public ModelPrePID() { |
32 | 20 |
|
33 | | - Translator<float[], float[]> my_translator = new Translator<>() { |
| 21 | + private static final Logger LOGGER = Logger.getLogger(ModelPrePID.class.getName()); |
| 22 | + private static final int[] CLASS_IDS = {2212, 45, 46, 49, 47}; |
34 | 23 |
|
35 | | - @Override |
36 | | - public NDList processInput(TranslatorContext ctx, float[] floats) { |
37 | | - NDManager manager = ctx.getNDManager(); |
| 24 | + private final ZooModel<float[], float[]> ahdcModel; |
| 25 | + private final ZooModel<float[], float[]> atofModel; |
38 | 26 |
|
39 | | - // IMPORTANT: model expects (batch, 23). Provide (1, 23). |
40 | | - NDArray x = manager.create(floats, new Shape(1, 23)); |
41 | | - return new NDList(x); |
42 | | - } |
| 27 | + public ModelPrePID() { |
| 28 | + System.setProperty("ai.djl.pytorch.num_interop_threads", "1"); |
| 29 | + System.setProperty("ai.djl.pytorch.num_threads", "1"); |
| 30 | + System.setProperty("ai.djl.pytorch.graph_optimizer", "false"); |
43 | 31 |
|
44 | | - @Override |
45 | | - public float[] processOutput(TranslatorContext ctx, NDList ndList) { |
46 | | - NDArray logits = ndList.get(0); // (1,5) |
47 | | - NDArray probs = logits.softmax(1); // (1,5) |
| 32 | + ahdcModel = loadModel("model_prePID_AHDC", 11); |
| 33 | + atofModel = loadModel("model_prePID_ATOF", 16); |
| 34 | + } |
48 | 35 |
|
49 | | - float[] p = probs.toFloatArray(); // length 5 (row-major) |
| 36 | + public ZooModel<float[], float[]> getModel() { |
| 37 | + return ahdcModel; |
| 38 | + } |
50 | 39 |
|
51 | | - // argmax |
52 | | - int bestIdx = 0; |
53 | | - float best = p[0]; |
54 | | - for (int k = 1; k < 5; k++) { |
55 | | - if (p[k] > best) { best = p[k]; bestIdx = k; } |
56 | | - } |
57 | | - int prepid = CLASS_IDS[bestIdx]; |
| 40 | + public float[] prediction(float[] features) throws TranslateException { |
| 41 | + if (features != null && features.length == 16) { |
| 42 | + return predictionATOF(features); |
| 43 | + } |
| 44 | + return predictionAHDC(features); |
| 45 | + } |
58 | 46 |
|
59 | | - // Return: prepid + probabilities in fixed class order |
60 | | - return new float[]{ |
61 | | - (float) prepid, |
62 | | - p[0], p[1], p[2], p[3], p[4] |
63 | | - }; |
64 | | - } |
65 | | - }; |
| 47 | + public float[] predictionAHDC(float[] features) throws TranslateException { |
| 48 | + return predict(ahdcModel, features, 11); |
| 49 | + } |
66 | 50 |
|
67 | | - System.setProperty("ai.djl.pytorch.num_interop_threads", "1"); |
68 | | - System.setProperty("ai.djl.pytorch.num_threads", "1"); |
69 | | - System.setProperty("ai.djl.pytorch.graph_optimizer", "false"); |
| 51 | + public float[] predictionATOF(float[] features) throws TranslateException { |
| 52 | + return predict(atofModel, features, 16); |
| 53 | + } |
70 | 54 |
|
71 | | - String path = CLASResources.getResourcePath("etc/data/nnet/rg-l/model_PrePID/"); |
| 55 | + private static float[] predict(ZooModel<float[], float[]> model, float[] features, |
| 56 | + int expectedSize) throws TranslateException { |
| 57 | + if (features == null || features.length != expectedSize) { |
| 58 | + LOGGER.warning("PrePID input must be float[" + expectedSize + "]"); |
| 59 | + return null; |
| 60 | + } |
| 61 | + try (Predictor<float[], float[]> predictor = model.newPredictor()) { |
| 62 | + return predictor.predict(features); |
| 63 | + } |
| 64 | + } |
72 | 65 |
|
| 66 | + private static ZooModel<float[], float[]> loadModel(String directory, int inputSize) { |
| 67 | + String path = CLASResources.getResourcePath("etc/data/nnet/rg-l/" + directory + "/"); |
73 | 68 | Criteria<float[], float[]> criteria = Criteria.builder() |
74 | 69 | .setTypes(float[].class, float[].class) |
75 | 70 | .optModelPath(Paths.get(path)) |
76 | 71 | .optEngine("PyTorch") |
77 | | - .optTranslator(my_translator) |
| 72 | + .optTranslator(translator(inputSize)) |
78 | 73 | .optProgress(new ProgressBar()) |
79 | 74 | .build(); |
80 | | - |
81 | 75 | try { |
82 | | - model = criteria.loadModel(); |
| 76 | + return criteria.loadModel(); |
83 | 77 | } catch (IOException | ModelNotFoundException | MalformedModelException e) { |
84 | 78 | throw new RuntimeException(e); |
85 | 79 | } |
86 | 80 | } |
87 | 81 |
|
88 | | - public ZooModel<float[], float[]> getModel() { |
89 | | - return model; |
90 | | - } |
| 82 | + private static Translator<float[], float[]> translator(int inputSize) { |
| 83 | + return new Translator<>() { |
| 84 | + @Override |
| 85 | + public NDList processInput(TranslatorContext ctx, float[] features) { |
| 86 | + return new NDList(ctx.getNDManager().create(features, new Shape(1, inputSize))); |
| 87 | + } |
91 | 88 |
|
92 | | - /** Returns float[]{prepid} where prepid in {2212,45,46,47,49}. |
93 | | - * @param features23 |
94 | | - * @return |
95 | | - * @throws ai.djl.translate.TranslateException */ |
96 | | - public float[] prediction(float[] features23) throws TranslateException { |
97 | | - if (features23 == null || features23.length != 23) { |
98 | | - LOGGER.warning("PrePID input must be float[23]"); |
99 | | - return null; |
100 | | - } |
101 | | - Predictor<float[], float[]> predictor = model.newPredictor(); |
102 | | - return predictor.predict(features23); |
| 89 | + @Override |
| 90 | + public float[] processOutput(TranslatorContext ctx, NDList output) { |
| 91 | + float[] probabilities = output.get(0).toFloatArray(); |
| 92 | + int bestIndex = 0; |
| 93 | + for (int i = 1; i < probabilities.length; i++) { |
| 94 | + if (probabilities[i] > probabilities[bestIndex]) { |
| 95 | + bestIndex = i; |
| 96 | + } |
| 97 | + } |
| 98 | + return new float[]{ |
| 99 | + CLASS_IDS[bestIndex], |
| 100 | + probabilities[0], probabilities[1], probabilities[2], |
| 101 | + probabilities[3], probabilities[4] |
| 102 | + }; |
| 103 | + } |
| 104 | + }; |
103 | 105 | } |
104 | 106 | } |
0 commit comments