Problem
I am using a Deep Learning model I trained and want to improve its accuracy by implementing a rolling average prediction. I have already done it but want to improve it as I am making predictions on every 3 frames.
Input:
Each index represents a class and the respective prediction the model makes.
Order is not alphanumeric as its based on my folder structure during training
1st Index : Class 0
2nd Index : Class 10
3rd Index : class 5
[
0.9288286566734314,
0.008770409040153027,
0.062401000410318375,
]
So the goal is to store the highest probability and its index at every frame. Based on the structure I mentioned above I add the probability to its class. Every time a new probability gets added I increase a counter. Once the counter reaches N, I find the class which has the most predictions, I sum the probabilities and return the average of it and the respective class it belongs to.
N = 5
Prediction {
"0": [0.9811,0.9924, 0.8763],
"5": [0.9023],
"10": [0.9232]
}
Code in React(model is loaded on a mobile phone)
Rolling Prediction does the averaging of the predictions and is passed in the array of predictions mentioned in the input.
There are 2 helper functions to find the sum and to find the max value and max index in an array.
const [allPredictions, setAllPredictions] = useState({
"0": [],
"5": [],
"10": []
});
let queueSize = 0;
let total = 0;
const rollingPrediction = arr => {
const { max, maxIndex } = indexOfMax(arr);
const maxFixed = parseFloat(max.toFixed(2));
if (maxIndex === 0) {
allPredictions["0"].push(maxFixed);
queueSize += 1;
} else if (maxIndex === 1) {
allPredictions["10"].push(maxFixed);
queueSize += 1;
} else if (maxIndex === 2) {
allPredictions["5"].push(maxFixed);
queueSize += 1;
}
console.log(`Queue : ${queueSize}`);
if (queueSize > 4) {
console.log("Queue Size Max");
const arr1 = allPredictions["0"].length;
const arr2 = allPredictions["5"].length;
const arr3 = allPredictions["10"].length;
if (arr1 > arr2 && arr1 && arr3) {
const sum = sumOfArray(allPredictions["0"]);
const prob = sum / arr1;
console.log(`Awareness level 0 | Probability: ${prob}`);
} else if (arr2 > arr1 arr2 && arr3) {
const sum = sumOfArray(allPredictions["5"]);
const prob = sum / arr2;
console.log(`Awareness level 5 | Probability: ${prob}`);
} else if (arr3 > arr2 arr3 && arr1) {
const sum = sumOfArray(allPredictions["10"]);
const prob = sum / arr3;
console.log(`Awareness level 10 | Probability: ${prob}`);
} else {
console.log("No rolling prediction");
}
queueSize = 0;
allPredictions["0"] = [];
allPredictions["5"] = [];
allPredictions["10"] = [];
}
};
const sumOfArray = arr => {
for(let i = 0; i < arr.length; i++){
total += arr[i];
}
return total;
};
const indexOfMax = arr => {
if (arr.length === 0) {
return -1;
}
let max = arr[0];
let maxIndex = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
maxIndex = i;
}
}
return {
max,
maxIndex
};
};
Solution
I think that, in rollingPrediction
, you just need the maxIndex
, once that you already can access the max
in arr
with it.
Also, since that you need the maxIndex
to find the class, you can just store the classes in an array with every class stored in the correspondent index.
To find which array has the most predictions, you will receive an array and evaluate it to one value. In cases like this, I think that you can use Array.prototype.reduce():
- In the callback function, check which array has the bigger length
- The initial value will be
[null, []]
, to check if there’s one bigger array and to have an array to compare in the callback function.
In indexOfMax
you can use Math.max with Array.prototype.indexOf() since performance it’s not a problem in this case, but you can use reduce too.
Suggestion: In sumOfArray
, you receive an array as parameter and want to evaluate to one value. Maybe you can use reduce once again.
// ...
const classesIndexed = ["0", "10", "5"];
// suggestion: once that you know the classes order, this could be:
// const classesIndexed = Object.keys(allPredictions);
const rollingPrediction = arr => {
const maxIndex = indexOfMax(arr);
if(maxIndex === -1) {
return;
}
const maxFixed = parseFloat(arr[maxIndex].toFixed(2));
allPredictions[classesIndexed[maxIndex]].push(maxFixed);
queueSize++;
if (queueSize <= 4) {
const [className, bigger] = Object.entries(allPredictions)
.reduce(
(acc, act) => acc[1].length >= act[1].length ? acc : act,
[null, []]
);
if (!className) {
const sum = sumOfArray(bigger);
const prob = sum / bigger.length;
console.log(`Awareness level ${className} | Probability: ${prob}`);
} else {
console.log("No rolling prediction");
}
// ...
};
// ...
const indexOfMax = (arr = []) => arr.indexOf(Math.max(arr))