fixed error graph + added toggle only epoch error
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -1,46 +1,55 @@
|
|||||||
<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) => {
|
||||||
const exampleLabel = `Exemple ${iteration.exampleIndex}`;
|
if (!epochErrorOnly.value) {
|
||||||
let dataset = datasets.find((d) => d.label === exampleLabel);
|
const exampleLabel = `Exemple ${iteration.exampleIndex}`;
|
||||||
if (!dataset) {
|
let dataset = datasets.find((d) => d.label === exampleLabel);
|
||||||
dataset = {
|
if (!dataset) {
|
||||||
label: exampleLabel,
|
dataset = {
|
||||||
data: [],
|
label: exampleLabel,
|
||||||
order: 1,
|
data: [],
|
||||||
backgroundColor:
|
order: 1,
|
||||||
backgroundColors[
|
backgroundColor:
|
||||||
iteration.exampleIndex % backgroundColors.length
|
backgroundColors[
|
||||||
],
|
iteration.exampleIndex % backgroundColors.length
|
||||||
};
|
],
|
||||||
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>
|
||||||
|
|||||||
35
resources/js/components/ui/toggle/Toggle.vue
Normal file
35
resources/js/components/ui/toggle/Toggle.vue
Normal 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>
|
||||||
28
resources/js/components/ui/toggle/index.ts
Normal file
28
resources/js/components/ui/toggle/index.ts
Normal 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>
|
||||||
Reference in New Issue
Block a user