-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiagnostic-stats.js
More file actions
131 lines (121 loc) · 4.45 KB
/
Copy pathdiagnostic-stats.js
File metadata and controls
131 lines (121 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* Shared diagnostic statistics module for unified data collection
* across WebGL and WebGPU inference paths.
*/
export {
createStatData,
addModelInfo,
addLabelStats,
markSuccess,
markFailure
};
/**
* Execution modes for diagnostics
*/
export const ExecutionModes = {
WEBGPU: 'webgpu',
WEBGL_WEBWORKER: 'webgl-webworker',
WEBGL_MAIN: 'webgl-main',
WEBGL_SEQUENTIAL: 'webgl-sequential'
};
/**
* Creates an initialized stat data object with common fields.
* @param {Object} modelEntry - The model configuration object
* @param {string} executionMode - One of ExecutionModes values
* @returns {Object} Initialized stat data object
*/
function createStatData(modelEntry, executionMode) {
return {
startTime: Date.now(),
Model_Name: modelEntry?.modelName || 'Unknown',
Execution_Mode: executionMode,
TF_Backend: executionMode === ExecutionModes.WEBGPU ? 'webgpu' : 'webgl',
isModelFullVol: null,
No_SubVolumes: 1,
Brainchop_Ver: 'FullVolume',
// Model info - populated by addModelInfo
Input_Shape: null,
Output_Shape: null,
Channel_Last: null,
Model_Param: null,
Model_Layers: null,
// Label stats - populated by addLabelStats
Actual_Labels: null,
Expect_Labels: null,
NumLabels_Match: null,
Missing_Labels: null,
// Timing - populated by markSuccess
Inference_t: null,
Postprocess_t: null,
// Status - populated by markSuccess/markFailure
Status: null,
Error_Type: null,
Extra_Err_Info: null
};
}
/**
* Adds model architecture information to stat data.
* @param {Object} statData - The stat data object to update
* @param {Object} model - The TensorFlow.js model object
* @param {Array} inputShape - The input shape array
* @param {boolean} isChannelLast - Whether model uses channel-last format
* @param {Function} getModelNumParameters - Function to get parameter count
* @param {Function} getModelNumLayers - Function to get layer count
*/
async function addModelInfo(statData, model, inputShape, isChannelLast, getModelNumParameters, getModelNumLayers) {
if (!model) return;
try {
statData.Input_Shape = JSON.stringify(inputShape);
statData.Output_Shape = JSON.stringify(model.output?.shape || model.outputs?.[0]?.shape);
statData.Channel_Last = isChannelLast;
if (getModelNumParameters) {
statData.Model_Param = await getModelNumParameters(model);
}
if (getModelNumLayers) {
statData.Model_Layers = await getModelNumLayers(model);
}
} catch (e) {
console.warn('Failed to add model info to diagnostics:', e);
}
}
/**
* Adds label statistics to stat data.
* @param {Object} statData - The stat data object to update
* @param {number} expectedLabels - Number of expected labels from model output channels
* @param {number} actualLabels - Number of unique labels actually predicted
* @param {Array<string>} missingLabelNames - Optional array of label names that were not predicted
*/
function addLabelStats(statData, expectedLabels, actualLabels, missingLabelNames = null) {
statData.Expect_Labels = expectedLabels;
statData.Actual_Labels = actualLabels;
statData.NumLabels_Match = expectedLabels === actualLabels;
if (missingLabelNames && missingLabelNames.length > 0) {
statData.Missing_Labels = missingLabelNames.join(', ');
}
}
/**
* Marks the stat data as successful with timing information.
* @param {Object} statData - The stat data object to update
* @param {string|number} inferenceTime - Inference time in seconds
* @param {string|number} postprocessTime - Post-processing time in seconds
*/
function markSuccess(statData, inferenceTime, postprocessTime) {
statData.Inference_t = inferenceTime;
statData.Postprocess_t = postprocessTime;
statData.Status = 'OK';
}
/**
* Marks the stat data as failed with error information.
* @param {Object} statData - The stat data object to update
* @param {Error|string} error - The error that occurred
* @param {string} extraInfo - Additional context about where the error occurred
*/
function markFailure(statData, error, extraInfo = null) {
statData.Inference_t = Infinity;
statData.Postprocess_t = Infinity;
statData.Status = 'Fail';
statData.Error_Type = error?.message || String(error);
if (extraInfo) {
statData.Extra_Err_Info = extraInfo;
}
}