Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions src/StaticConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
* Static configuration values. These values are not expected to change, while the application is running.
*/
import { MBSpecs } from 'microbyte';
import { PinTurnOnState } from './lib/PinTurnOnState';
import { type LayersModelTrainingSettings as NeuralNetworkModelTrainerSettings } from './lib/mlmodels/LayersModelTrainer';
import { PinTurnOnState } from './core/entities/PinTurnOnState';
import { HexOrigin } from './lib/microbit-interfacing/HexOrigin';
import type { LayersModelTrainingSettings } from './core/entities/classifier/models/LayersModelTrainer';

class StaticConfiguration {
// in milliseconds, how long should be wait for reconnect before determining something catestrophic happened during the process?
Expand Down Expand Up @@ -122,14 +122,13 @@ class StaticConfiguration {
/**
* The neural network training settings
*/
public static readonly defaultNeuralNetworkSettings: NeuralNetworkModelTrainerSettings =
{
noOfEpochs: 80,
batchSize: 16,
learningRate: 0.1,
validationSplit: 0.1,
noOfUnits: 16, // size of hidden layer
};
public static readonly defaultNeuralNetworkSettings: LayersModelTrainingSettings = {
noOfEpochs: 80,
batchSize: 16,
learningRate: 0.1,
validationSplit: 0.1,
noOfUnits: 16, // size of hidden layer
};

/**
* How many samples should the KNN model use for prediction? i.e the k-value.
Expand Down
14 changes: 7 additions & 7 deletions src/__tests__/csv/csv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import { writable } from 'svelte/store';
import { locale } from 'svelte-i18n';
import type { RecordingData } from '../../lib/domain/RecordingData';
import Gesture from '../../lib/domain/stores/gesture/Gesture';
import type { RecordingData } from '../../core/entities/RecordingData';
import GestureState from '../../lib/domain/stores/gesture/GestureState';
import type { PersistedGestureData } from '../../lib/domain/stores/gesture/Gestures';
import type GestureConfidence from '../../lib/domain/stores/gesture/GestureConfidence';
import {
Expand Down Expand Up @@ -41,7 +41,7 @@ describe('CSV Test', () => {
name: 'Test;Gesture',
} as PersistedGestureData);
const confidence = writable({}) as unknown as GestureConfidence;
const gesture: Gesture = new Gesture(data, confidence, () => void 0);
const gesture: GestureState = new GestureState(data, confidence, () => void 0);
const result = serializeGestureRecordingsToCSV([gesture]);
expect(result).toBe(
'gesture;sample;x;y;z\nTest\\;Gesture;0;1;2;3\nTest\\;Gesture;1;4;5;6\nTest\\;Gesture;2;7;8;9',
Expand Down Expand Up @@ -82,8 +82,8 @@ describe('CSV Test', () => {
name: 'Gesture2',
} as PersistedGestureData);
const confidence = writable({}) as unknown as GestureConfidence;
const gesture1: Gesture = new Gesture(data1, confidence, () => void 0);
const gesture2: Gesture = new Gesture(data2, confidence, () => void 0);
const gesture1: GestureState = new GestureState(data1, confidence, () => void 0);
const gesture2: GestureState = new GestureState(data2, confidence, () => void 0);
const result = serializeGestureRecordingsToCSV([gesture1, gesture2]);
expect(result).toBe(
'gesture;sample;x;y;z\n' +
Expand Down Expand Up @@ -133,13 +133,13 @@ describe('CSV Test', () => {
],
});

const createTestGestureWithDecimals = (name: string): Gesture => {
const createTestGestureWithDecimals = (name: string): GestureState => {
const data = writable({
recordings: [createTestRecordingWithDecimals()],
name,
} as PersistedGestureData);
const confidence = writable({}) as unknown as GestureConfidence;
return new Gesture(data, confidence, () => void 0);
return new GestureState(data, confidence, () => void 0);
};

test('English locale uses period as decimal separator', () => {
Expand Down
46 changes: 23 additions & 23 deletions src/__tests__/ml/classifier.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
*/

import { get, writable } from 'svelte/store';
import BaseLiveDataVector from '../../lib/domain/BaseLiveDataVector';
import BaseLiveDataVector from '../../core/entities/vector/BaseLiveDataVector';
import { ClassifierInput } from '../../lib/domain/ClassifierInput';
import Filters from '../../lib/domain/Filters';
import { stores } from '../../lib/stores/Stores';
import TestMLModelTrainer from '../mocks/mlmodel/TestMLModelTrainer';
import type { Filter } from '../../lib/domain/Filter';
import FilterTypes, { FilterType } from '../../lib/domain/FilterTypes';
import ClassifierFactory from '../../lib/domain/ClassifierFactory';
import LayersModelTrainer from '../../lib/mlmodels/LayersModelTrainer';
import StaticConfiguration from '../../StaticConfiguration';
import TestTrainingDataRepository from '../mocks/TestTrainingDataRepository';
import TestGestureRepository from '../mocks/TestGestureRepository';
import Confidences from '../../lib/domain/stores/Confidences';
import BaseVector from '../../lib/domain/BaseVector';
import BaseVector from '../../core/entities/vector/BaseVector';
import Snackbar from '../../lib/stores/Snackbar';
import { FilterType, type Filter } from '../../core/entities/filter/Filter';
import { createFilter } from '../../core/entities/filter/FilterUtils';
import LayersModelTrainer from '../../core/entities/classifier/models/LayersModelTrainer';

describe('Classifier tests', () => {
test('Changing matrix does not mark model as untrained', async () => {
Expand Down Expand Up @@ -62,9 +62,9 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([3, 3, 3]), ['x', 'y', 'z']),
];
const input = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMean: Filter = FilterTypes.createFilter(FilterType.MEAN);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMean: Filter = createFilter(FilterType.MEAN);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMean, filterMin]));
expect(input.getInput(filters).length).toBe(3 * 3);
});
Expand All @@ -75,7 +75,7 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([4, 5, 6]), ['x', 'y', 'z']),
];
const input = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMax: Filter = createFilter(FilterType.MAX);
const filters: Filters = new Filters(writable([filterMax]));
expect(input.getInput(filters)).toStrictEqual([4, 5, 6]);
});
Expand All @@ -87,9 +87,9 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([10]), ['x']),
];
const input = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMean: Filter = FilterTypes.createFilter(FilterType.MEAN);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMean: Filter = createFilter(FilterType.MEAN);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMean, filterMin]));
expect(input.getInput(filters).length).toBe(3);
expect(input.getInput(filters)).toStrictEqual([10, 5, 1]);
Expand All @@ -102,8 +102,8 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([10, 20]), ['x', 'y']),
];
const input = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMin]));
expect(input.getInput(filters)).toStrictEqual([
// x value max/min
Expand All @@ -120,9 +120,9 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([10, 20, 40]), ['x', 'y', 'z']),
];
const classifierInput = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMean: Filter = FilterTypes.createFilter(FilterType.MEAN);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMean: Filter = createFilter(FilterType.MEAN);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMean, filterMin]));

let iterations = 0;
Expand Down Expand Up @@ -177,9 +177,9 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([10, 20, 40]), ['x', 'y', 'z']),
];
const classifierInput = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMean: Filter = FilterTypes.createFilter(FilterType.MEAN);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMean: Filter = createFilter(FilterType.MEAN);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMean, filterMin]));

let iterations = 0;
Expand Down Expand Up @@ -239,9 +239,9 @@ describe('Classifier tests', () => {
new BaseLiveDataVector(new BaseVector([10, 20, 40]), ['x', 'y', 'z']),
];
const classifierInput = new ClassifierInput(vectors);
const filterMax: Filter = FilterTypes.createFilter(FilterType.MAX);
const filterMean: Filter = FilterTypes.createFilter(FilterType.MEAN);
const filterMin: Filter = FilterTypes.createFilter(FilterType.MIN);
const filterMax: Filter = createFilter(FilterType.MAX);
const filterMean: Filter = createFilter(FilterType.MEAN);
const filterMin: Filter = createFilter(FilterType.MIN);
const filters: Filters = new Filters(writable([filterMax, filterMean, filterMin]));

let iterations = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/ml/data-representation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
* SPDX-License-Identifier: MIT
*/

import LiveDataBuffer from '../../lib/domain/LiveDataBuffer';
import LiveDataBuffer from '../../core/LiveDataBuffer';
import MicrobitAccelerometerLiveData, {
MicrobitAccelerometerDataVector,
} from '../../lib/livedata/MicrobitAccelerometerData';
import { repeat } from '../testUtils';
import { get } from 'svelte/store';
import { type LiveDataVector } from '../../lib/domain/stores/LiveDataVector';
import { type LiveDataVector } from '../../core/entities/vector/LiveDataVector';
import SmoothedLiveData from '../../lib/livedata/SmoothedLiveData';
import { smoothNewValue } from '../../lib/utils/graphUtils';
import type { LiveData } from '../../lib/domain/stores/LiveData';
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/ml/engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { get } from 'svelte/store';
import LiveDataBuffer from '../../lib/domain/LiveDataBuffer';
import LiveDataBuffer from '../../core/LiveDataBuffer';
import MicrobitAccelerometerLiveData from '../../lib/livedata/MicrobitAccelerometerData';
import { stores } from '../../lib/stores/Stores';

Expand Down
6 changes: 3 additions & 3 deletions src/__tests__/ml/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
* SPDX-License-Identifier: MIT
*/
import TestTrainingDataRepository from '../mocks/TestTrainingDataRepository';
import LayersModelTrainer from '../../lib/mlmodels/LayersModelTrainer';
import StaticConfiguration from '../../StaticConfiguration';
import KNNNonNormalizedModelTrainer from '../../lib/mlmodels/KNNNonNormalizedModelTrainer';
import BaseVector from '../../lib/domain/BaseVector';
import BaseVector from '../../core/entities/vector/BaseVector';
import LayersModelTrainer from '../../core/entities/classifier/models/LayersModelTrainer';
import KNNNonNormalizedModelTrainer from '../../core/entities/classifier/models/KNNNonNormalizedModelTrainer';

describe('ML Model tests', async () => {
describe('Layers Model', async () => {
Expand Down
14 changes: 7 additions & 7 deletions src/__tests__/mocks/TestGestureRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import {
get,
} from 'svelte/store';
import type { GestureRepository } from '../../lib/domain/GestureRepository';
import Gesture from '../../lib/domain/stores/gesture/Gesture';
import GestureState from '../../lib/domain/stores/gesture/GestureState';
import type { PersistedGestureData } from '../../lib/domain/stores/gesture/Gestures';
import GestureConfidence from '../../lib/domain/stores/gesture/GestureConfidence';

class TestGestureRepository implements GestureRepository {
private gestures = writable<Gesture[]>([]);
private gestures = writable<GestureState[]>([]);

getGesture(gestureId: number): Gesture {
getGesture(gestureId: number): GestureState {
const foundGesture = get(this.gestures).find(g => g.getId() === gestureId);
if (!foundGesture) {
throw new Error('Could not find gesture with id ' + gestureId);
Expand All @@ -31,8 +31,8 @@ class TestGestureRepository implements GestureRepository {
this.gestures.set([]);
}

addGesture(gestureData: PersistedGestureData): Gesture {
const gesture = new Gesture(
addGesture(gestureData: PersistedGestureData): GestureState {
const gesture = new GestureState(
writable(gestureData),
new GestureConfidence(0.5, writable(0)),
() => void 0,
Expand All @@ -50,8 +50,8 @@ class TestGestureRepository implements GestureRepository {
}

subscribe(
run: Subscriber<Gesture[]>,
invalidate?: Invalidator<Gesture[]> | undefined,
run: Subscriber<GestureState[]>,
invalidate?: Invalidator<GestureState[]> | undefined,
): Unsubscriber {
return this.gestures.subscribe(run, invalidate);
}
Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/mocks/TestTrainingDataRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* SPDX-License-Identifier: MIT
*/

import BaseVector from '../../lib/domain/BaseVector';
import type { TrainingData } from '../../lib/domain/ModelTrainer';
import type { TrainingDataRepository } from '../../lib/domain/TrainingDataRepository';
import type { Vector } from '../../lib/domain/Vector';
import BaseVector from '../../core/entities/vector/BaseVector';
import type { TrainingData } from '../../core/entities/classifier/models/ModelTrainer';
import type { TrainingDataRepository } from '../../core/repository/TrainingDataRepository';
import type { Vector } from '../../core/entities/vector/Vector';

class TestTrainingDataRepository implements TrainingDataRepository {
getTrainingDataMean(): Vector {
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/mocks/mlmodel/TestMLModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: MIT
*/

import type { MLModel } from '../../../lib/domain/MLModel';
import type { Vector } from '../../../lib/domain/Vector';
import type { MLModel } from '../../../core/entities/classifier/models/MLModel';
import type { Vector } from '../../../core/entities/vector/Vector';

class TestMLModel implements MLModel {
constructor(private numberOfGestures: number) {}
Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/mocks/mlmodel/TestMLModelTrainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
*
* SPDX-License-Identifier: MIT
*/
import type { ModelInfo } from '../../../lib/domain/ModelRegistry';
import ModelRegistry from '../../../lib/domain/ModelRegistry';
import type { ModelTrainer } from '../../../lib/domain/ModelTrainer';
import type { TrainingDataRepository } from '../../../lib/domain/TrainingDataRepository';
import type { ModelInfo } from '../../../core/entities/classifier/models/ModelRegistry';
import ModelRegistry from '../../../core/entities/classifier/models/ModelRegistry';
import type { ModelTrainer } from '../../../core/entities/classifier/models/ModelTrainer';
import type { TrainingDataRepository } from '../../../core/repository/TrainingDataRepository';
import TestMLModel from './TestMLModel';

class TestMLModelTrainer implements ModelTrainer<TestMLModel> {
Expand Down
4 changes: 4 additions & 0 deletions src/assets/messages/ui.da.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@
"content.index.MLExplainer3": "Data repræsentationerne af eksemplerne vises til et neuralt netværk. Det neurale netværk “lærer” fra disse eksempler ved at finde mønstre i og imellem eksemplerne.",
"content.index.MLExplainer4": "Denne træningsprocess resulterer i et trænet neuralt netværk (vi kalder det også en machine learning model), der kan gætte/forudsige, hvordan micro:bit’en bevæges, når de samme egenskaber (standardafvigelse, samlet acceleration, den maximale værdi m.m.) beregnes fra det live accelerometer data.",
"content.data.classPlaceholderNewClass": "Klik for at ændre navnet",
"content.data.print": "Print",
"content.data.delete": "Slet",
"content.data.record": "Optag",
"content.data.addData": "Tilføj data",
"content.data.select": "Vælg",
"content.data.csv": "Download som csv",
"content.data.classHelpHeader": "Klasse",
"content.data.classHelpBody": "En klasse beskriver en type af bevægelse. Vi kan optage eksempler af en bestemt type bevægelse og putte eksemplerne i samme klasse. Træneren kan finde mønstre i eksemplerne/dataet og bruge disse mønstre til at træne en model, der kan genkende denne type bevægelse. Flere eksmpler vil typisk reulstere i en bedre model, men overvej på hvor mange forskellige måder en bevægelse kan laves.",
"content.data.classification": "Klasser",
Expand Down
4 changes: 4 additions & 0 deletions src/assets/messages/ui.de.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@
"content.index.MLExplainer3": "Die Datendarstellungen der Datenbeispiele werden einem neuronalen Netz gezeigt. Das neuronale Netz \"lernt\" aus diesen Beispielen, indem es Muster in und zwischen den Beispielen findet.",
"content.index.MLExplainer4": "Das Ergebnis dieses Trainingsprozesses ist ein trainiertes neuronales Netzwerk (wir nennen es auch ein maschinelles Lernmodell), das erraten/vorhersagen kann, wie der micro:bit bewegt wird, wenn dieselben Eigenschaften (Standardabweichung, kumulierte Beschleunigung, Maximalwert usw.) aus den Live-Beschleunigungsdaten berechnet werden.",
"content.data.classPlaceholderNewClass": "Drücke hier, um den Namen zu ändern",
"content.data.print": "Drucken",
"content.data.delete": "Löschen",
"content.data.record": "Aufnehmen",
"content.data.addData": "Daten hinzufügen",
"content.data.select": "Auswählen",
"content.data.csv": "Als CSV herunterladen",
"content.data.classHelpHeader": "Klasse",
"content.data.classHelpBody": "Eine Klasse beschreibt eine Art von Geste. Wir können Beispiele für eine bestimmte Art von Geste aufzeichnen und die Beispiele in dieselbe Klasse einordnen. Das Training kann Muster in den Beispielen/Daten finden und diese Muster verwenden, um ein Modell zu 'trainieren', das diese Klasse von Gesten erkennen kann. Mehrere Beispiele führen in der Regel zu einem besseren Modell, wobei zu berücksichtigen ist, auf wie viele verschiedene Arten eine Geste ausgeführt werden kann.",
"content.data.classification": "Klassen",
Expand Down
4 changes: 4 additions & 0 deletions src/assets/messages/ui.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@
"content.index.MLExplainer3": "The data representations of the data samples are shown to a neural network. The neural network “learns” from these examples by finding patterns in and between the samples.",
"content.index.MLExplainer4": "This training process results in a trained neural network (we also call it a machine learning model) that can guess/predict how the micro:bit is moved when the same properties (standard deviation, cumulated acceleration, maximum value, etc.) are calculated from the live accelerometer data.",
"content.data.classPlaceholderNewClass": "Press here to change name",
"content.data.print": "Print",
"content.data.delete": "Delete",
"content.data.record": "Record",
"content.data.addData": "Add Data",
"content.data.select": "Select",
"content.data.csv": "Download as csv",
"content.data.classHelpHeader": "Class",
"content.data.classHelpBody": "A class describes a type of gesture. We can record examples of a certain type of gesture and put the examples in the same class. The trainer can find patterns in the examples/data and use these patterns to 'train' a model that can recognize this class of gestures. Multiple examples will typically result in a better model, and consider how many different ways a gesture can be performed.",
"content.data.classification": "Classes",
Expand Down
22 changes: 0 additions & 22 deletions src/components/features/GoToPlaygroundButton.svelte

This file was deleted.

Loading
Loading