fixed error graph + added toggle only epoch error
Some checks failed
linter / quality (push) Successful in 5m36s
tests / ci (8.4) (push) Failing after 4m11s
tests / ci (8.5) (push) Failing after 4m37s

This commit is contained in:
2026-03-22 14:58:53 +01:00
parent 42e07de287
commit af67830fbb
5 changed files with 109 additions and 31 deletions

8
package-lock.json generated
View File

@@ -14,7 +14,7 @@
"laravel-vite-plugin": "^2.0.0", "laravel-vite-plugin": "^2.0.0",
"lucide-vue-next": "^0.468.0", "lucide-vue-next": "^0.468.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"reka-ui": "^2.9.0", "reka-ui": "^2.9.2",
"tailwind-merge": "^3.2.0", "tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.1", "tailwindcss": "^4.1.1",
"tw-animate-css": "^1.2.5", "tw-animate-css": "^1.2.5",
@@ -7386,9 +7386,9 @@
} }
}, },
"node_modules/reka-ui": { "node_modules/reka-ui": {
"version": "2.9.0", "version": "2.9.2",
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.9.0.tgz", "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.9.2.tgz",
"integrity": "sha512-5dpp80u109iLTbRBu+jhAk8R/877/JN20gYGjb3GsuAgS7E/5QTX5ZxuzWtZAVbChBDYDpXc8pkaQAFpa6s+4w==", "integrity": "sha512-/t4e6y1hcG+uDuRfpg6tbMz3uUEvRzNco6NeYTufoJeUghy5Iosxos5YL/p+ieAsid84sdMX9OrgDqpEuCJhBw==",
"dependencies": { "dependencies": {
"@floating-ui/dom": "^1.6.13", "@floating-ui/dom": "^1.6.13",
"@floating-ui/vue": "^1.1.6", "@floating-ui/vue": "^1.1.6",

View File

@@ -45,7 +45,7 @@
"laravel-vite-plugin": "^2.0.0", "laravel-vite-plugin": "^2.0.0",
"lucide-vue-next": "^0.468.0", "lucide-vue-next": "^0.468.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"reka-ui": "^2.9.0", "reka-ui": "^2.9.2",
"tailwind-merge": "^3.2.0", "tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.1", "tailwindcss": "^4.1.1",
"tw-animate-css": "^1.2.5", "tw-animate-css": "^1.2.5",

View File

@@ -1,27 +1,33 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ChartData } from 'chart.js'; import type { ChartData } from 'chart.js';
import { computed, ref } from 'vue';
import { Bar } from 'vue-chartjs'; import { Bar } from 'vue-chartjs';
import { colors, gridColor, gridColorBold } from '@/types/graphs'; import { colors, gridColor, gridColorBold } from '@/types/graphs';
import type { Iteration } from '@/types/perceptron'; import type { Iteration } from '@/types/perceptron';
import Toggle from './ui/toggle/Toggle.vue';
const props = defineProps<{ const props = defineProps<{
iterations: Iteration[]; iterations: Iteration[];
}>(); }>();
const epochErrorOnly = ref<boolean>(false);
/** /**
* Return the datasets of the iterations with the form { label: `Exemple ${exampleIndex}`, data: [error for iteration 1, error for iteration 2, ...] } * Datasets of the iterations with the form { label: `Exemple ${exampleIndex}`, data: [error for iteration 1, error for iteration 2, ...] }
*/ */
function getPerceptronErrorsPerIteration(): ChartData< const datasets = computed<
'bar', ChartData<'bar', (number | [number, number] | null)[]>[]
(number | [number, number] | null)[] >(() => {
>[] {
const datasets: ChartData<'bar', (number | [number, number] | null)[]>[] = const datasets: ChartData<'bar', (number | [number, number] | null)[]>[] =
[]; [];
const epochAverageError: number[] = []; const epochAverageError: number[] = [];
const backgroundColors = colors; const backgroundColors = colors;
const exampleCountPerEpoch: Record<number, number> = {};
props.iterations.forEach((iteration) => { props.iterations.forEach((iteration) => {
if (!epochErrorOnly.value) {
const exampleLabel = `Exemple ${iteration.exampleIndex}`; const exampleLabel = `Exemple ${iteration.exampleIndex}`;
let dataset = datasets.find((d) => d.label === exampleLabel); let dataset = datasets.find((d) => d.label === exampleLabel);
if (!dataset) { if (!dataset) {
@@ -37,10 +43,13 @@ function getPerceptronErrorsPerIteration(): ChartData<
datasets.push(dataset); datasets.push(dataset);
} }
dataset.data.push(iteration.error); dataset.data.push(iteration.error);
}
exampleCountPerEpoch[iteration.epoch] = (exampleCountPerEpoch[iteration.epoch] || 0) + 1;
// Epoch error // Epoch error
epochAverageError[iteration.epoch - 1] = epochAverageError[iteration.epoch] =
(epochAverageError[iteration.epoch - 1] || 0) + (epochAverageError[iteration.epoch] || 0) +
iteration.error ** 2 / 2; iteration.error ** 2 / 2;
}); });
@@ -54,7 +63,7 @@ function getPerceptronErrorsPerIteration(): ChartData<
// Epoch error // Epoch error
const epochErrorDataset = { const epochErrorDataset = {
type: 'line', type: 'line',
label: "Erreur de l'époque", label: "Erreur quadratique moyenne de l'époque",
data: [], data: [],
backgroundColor: '#fff', backgroundColor: '#fff',
borderColor: '#fff', borderColor: '#fff',
@@ -62,14 +71,15 @@ function getPerceptronErrorsPerIteration(): ChartData<
tension: 0.3, tension: 0.3,
}; };
epochAverageError.forEach((error) => { epochAverageError.forEach((error, index) => {
epochErrorDataset.data.push(error); const exampleCount = exampleCountPerEpoch[index] || 1; // Avoid division by zero
epochErrorDataset.data.push(error / exampleCount);
}); });
datasets.push(epochErrorDataset); datasets.push(epochErrorDataset);
return datasets; return datasets;
} });
</script> </script>
<template> <template>
@@ -111,7 +121,12 @@ function getPerceptronErrorsPerIteration(): ChartData<
} }
return labels; return labels;
}, [] as string[]), }, [] as string[]),
datasets: getPerceptronErrorsPerIteration(), datasets: datasets,
}" }"
/> />
<div class="flex items-center gap-3">
<Toggle v-model="epochErrorOnly" class="cursor-pointer" variant="outline" id="epoch-error-only"
>Afficher uniquement l'erreur quadratique moyenne de l'époque</Toggle
>
</div>
</template> </template>

View File

@@ -0,0 +1,35 @@
<script setup lang="ts">
import type { ToggleEmits, ToggleProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ToggleVariants } from "."
import { reactiveOmit } from "@vueuse/core"
import { Toggle, useForwardPropsEmits } from "reka-ui"
import { cn } from "@/lib/utils"
import { toggleVariants } from "."
const props = withDefaults(defineProps<ToggleProps & {
class?: HTMLAttributes["class"]
variant?: ToggleVariants["variant"]
size?: ToggleVariants["size"]
}>(), {
variant: "default",
size: "default",
disabled: false,
})
const emits = defineEmits<ToggleEmits>()
const delegatedProps = reactiveOmit(props, "class", "size", "variant")
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<Toggle
v-slot="slotProps"
data-slot="toggle"
v-bind="forwarded"
:class="cn(toggleVariants({ variant, size }), props.class)"
>
<slot v-bind="slotProps" />
</Toggle>
</template>

View File

@@ -0,0 +1,28 @@
import type { VariantProps } from "class-variance-authority"
import { cva } from "class-variance-authority"
export { default as Toggle } from "./Toggle.vue"
export const toggleVariants = cva(
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
{
variants: {
variant: {
default: "bg-transparent",
outline:
"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-9 px-2 min-w-9",
sm: "h-8 px-1.5 min-w-8",
lg: "h-10 px-2.5 min-w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
)
export type ToggleVariants = VariantProps<typeof toggleVariants>