diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35cf9368..8407105b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Marcelle changelog
+## 0.4.4
+
+- Various minor bugfixes
+
## 0.4.3
- Fixed svelte component compilation (reverted to svelte v3.39)
diff --git a/package.json b/package.json
index 395c3660..094e3d18 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@marcellejs/core",
"description": "Marcelle Core API",
- "version": "0.4.3",
+ "version": "0.4.4",
"repository": {
"type": "git",
"url": "https://github.com/marcellejs/marcelle"
diff --git a/src/components/dataset-browser/dataset-browser.view.svelte b/src/components/dataset-browser/dataset-browser.view.svelte
index a11b7c3e..3ac2d002 100644
--- a/src/components/dataset-browser/dataset-browser.view.svelte
+++ b/src/components/dataset-browser/dataset-browser.view.svelte
@@ -171,7 +171,6 @@
}
});
});
-
@@ -250,11 +249,10 @@
.browser-class-body img {
width: 60px;
box-sizing: content-box;
- @apply border-2 border-transparent rounded-md;
+ @apply border-solid border-2 border-transparent rounded-md;
}
.browser-class-body img.selected {
- @apply border-teal-700;
+ @apply border-gray-600;
}
-
diff --git a/src/components/mlp-classifier/mlp-classifier.component.ts b/src/components/mlp-classifier/mlp-classifier.component.ts
index 59cee498..6f844ae4 100644
--- a/src/components/mlp-classifier/mlp-classifier.component.ts
+++ b/src/components/mlp-classifier/mlp-classifier.component.ts
@@ -20,6 +20,7 @@ import {
import type { ServiceIterable } from '../../core/data-store/service-iterable';
import { Dataset, isDataset } from '../../core/dataset';
import { Catch, TrainingError } from '../../utils/error-handling';
+import { throwError } from '../../utils/error-handling';
interface TrainingData {
training_x: Tensor2D;
@@ -130,6 +131,13 @@ export class MLPClassifier extends TFJSBaseModel
: (this.labels = Array.from(new Set(await dataset.map(({ y }) => y).toArray())));
const ds = isDataset(dataset) ? dataset.items() : dataset;
this.$training.set({ status: 'start', epochs: this.parameters.epochs.value });
+ if (this.labels.length === 0) {
+ throwError(new TrainingError('This dataset is empty or is missing labels'));
+ this.$training.set({
+ status: 'error',
+ });
+ return;
+ }
setTimeout(async () => {
const data = await dataSplit(ds, 0.75, this.labels);
this.buildModel(data.training_x.shape[1], data.training_y.shape[1]);
diff --git a/src/components/training-history/training-history.component.ts b/src/components/training-history/training-history.component.ts
index 55c95f0b..82346c06 100644
--- a/src/components/training-history/training-history.component.ts
+++ b/src/components/training-history/training-history.component.ts
@@ -1,6 +1,7 @@
import { Paginated, Service } from '@feathersjs/feathers';
import { logger, Model, Component, Stream, TrainingRun, TrainingStatus } from '../../core';
import { DataStore } from '../../core/data-store';
+import { preventConcurrentCalls } from '../../utils/asynchronicity';
import { noop } from '../../utils/misc';
import View from './training-history.view.svelte';
@@ -38,9 +39,12 @@ export class TrainingHistory extends Component {
protected modelName: string;
protected nextIndex: number;
+ private lock = Promise.resolve();
+
constructor(public dataStore: DataStore, options: TrainingHistoryOptions = {}) {
super();
this.options = { ...defaultOptions, ...options };
+ this.lock = this.lock.then(noop);
this.start();
this.ready = this.ready
.then(() => this.dataStore.connect())
@@ -71,7 +75,7 @@ export class TrainingHistory extends Component {
})
.then(({ data: foundRuns }) => {
if (foundRuns.length > 0) {
- return parseInt(foundRuns[0].name.split(`${name}-`)[1]) + 1;
+ return parseInt(foundRuns[0].name.split(`${basename}-`)[1]) + 1;
}
return 1;
})
@@ -85,6 +89,7 @@ export class TrainingHistory extends Component {
return this;
}
+ @preventConcurrentCalls('lock')
protected async trackTrainingStream(x: TrainingStatus): Promise {
if (x.status === 'start') {
this.crtRun = await this.runService.create({
@@ -119,6 +124,10 @@ export class TrainingHistory extends Component {
},
]),
});
+ } else if (x.status === 'error') {
+ this.runService.patch(this.crtRun.id, {
+ status: x.status,
+ });
}
}
diff --git a/src/components/training-history/training-history.view.svelte b/src/components/training-history/training-history.view.svelte
index 690672e9..bae701e4 100644
--- a/src/components/training-history/training-history.view.svelte
+++ b/src/components/training-history/training-history.view.svelte
@@ -47,6 +47,10 @@
},
});
+ provider.data.subscribe(() => {
+ selection.set([]);
+ });
+
const columns: Column[] = [
{ name: 'name', sortable: true },
{ name: 'start', sortable: true, type: 'date' },
@@ -82,7 +86,7 @@
{provider}
actions={[
...actions.map((name) => (typeof name === 'string' ? { name } : name)),
- { name: 'remove', confirm: true },
+ { name: 'delete', confirm: true },
]}
bind:selection={$selection}
bind:this={mainTable}
diff --git a/src/ui/components/Select.svelte b/src/ui/components/Select.svelte
index a32de3e7..27a0537a 100644
--- a/src/ui/components/Select.svelte
+++ b/src/ui/components/Select.svelte
@@ -17,7 +17,7 @@
on:change={(e) => dispatch('change', e.target.value)}
>
{#if placeholder}
-
+
{/if}
{#each options as option}
diff --git a/src/ui/components/Table.svelte b/src/ui/components/Table.svelte
index 19908a70..0a1be66a 100644
--- a/src/ui/components/Table.svelte
+++ b/src/ui/components/Table.svelte
@@ -1,5 +1,5 @@