From af3333a77e254b3268de38ec397921b43f357949 Mon Sep 17 00:00:00 2001 From: Danijel Andjelkovic Date: Wed, 6 Apr 2022 13:08:32 +0200 Subject: Dodao stranicu za eksperimente, ova stranica je zamena za add-model stranicu. --- .../app/_pages/add-model/add-model.component.ts | 104 ++++++++++----------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'frontend/src/app/_pages/add-model/add-model.component.ts') diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts index b35b9fa4..d47b24e6 100644 --- a/frontend/src/app/_pages/add-model/add-model.component.ts +++ b/frontend/src/app/_pages/add-model/add-model.component.ts @@ -110,55 +110,55 @@ export class AddModelComponent implements OnInit { } saveModelWithNewDataset(callback: ((arg0: any) => void)) { - - this.getCheckedInputCols(); - this.getCheckedOutputCol(); - this.getMetrics(); - - if (this.validationInputsOutput()) { - console.log('ADD MODEL: STEP 1 - UPLOAD FILE'); - if (this.datasetLoadComponent) { - console.log("this.datasetLoadComponent.files:", this.datasetLoadComponent.files); - this.models.uploadData(this.datasetLoadComponent.files[0]).subscribe((file) => { - console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id); + /* + this.getCheckedInputCols(); + this.getCheckedOutputCol(); + this.getMetrics(); + + if (this.validationInputsOutput()) { + console.log('ADD MODEL: STEP 1 - UPLOAD FILE'); if (this.datasetLoadComponent) { - this.datasetLoadComponent.dataset.fileId = file._id; - this.datasetLoadComponent.dataset.username = shared.username; - - this.datasets.addDataset(this.datasetLoadComponent.dataset).subscribe((dataset) => { - console.log('ADD MODEL: STEP 3 - ADD MODEL WITH DATASET ID ', dataset._id); - this.newModel.datasetId = dataset._id; - - //da se doda taj dataset u listu postojecih, da bude izabran - this.refreshMyDatasetList(); - this.showMyDatasets = true; - this.selectThisDataset(dataset); - - this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; - this.tempTestSetDistribution = 90; - this.newModel.username = shared.username; - - this.newModel.nullValuesReplacers = this.getNullValuesReplacersArray(); - - this.models.addModel(this.newModel).subscribe((response) => { - callback(response); - }, (error) => { - alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom."); - }); //kraj addModel subscribe + console.log("this.datasetLoadComponent.files:", this.datasetLoadComponent.files); + this.models.uploadData(this.datasetLoadComponent.files[0]).subscribe((file) => { + console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id); + if (this.datasetLoadComponent) { + this.datasetLoadComponent.dataset.fileId = file._id; + this.datasetLoadComponent.dataset.username = shared.username; + + this.datasets.addDataset(this.datasetLoadComponent.dataset).subscribe((dataset) => { + console.log('ADD MODEL: STEP 3 - ADD MODEL WITH DATASET ID ', dataset._id); + this.newModel.datasetId = dataset._id; + + //da se doda taj dataset u listu postojecih, da bude izabran + this.refreshMyDatasetList(); + this.showMyDatasets = true; + this.selectThisDataset(dataset); + + this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; + this.tempTestSetDistribution = 90; + this.newModel.username = shared.username; + + this.newModel.nullValuesReplacers = this.getNullValuesReplacersArray(); + + this.models.addModel(this.newModel).subscribe((response) => { + callback(response); + }, (error) => { + alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom."); + }); //kraj addModel subscribe + }, (error) => { + alert("Dataset sa unetim nazivom već postoji u Vašoj kolekciji.\nIzmenite naziv ili iskoristite postojeći dataset."); + }); //kraj addDataset subscribe + } //kraj treceg ifa }, (error) => { - alert("Dataset sa unetim nazivom već postoji u Vašoj kolekciji.\nIzmenite naziv ili iskoristite postojeći dataset."); - }); //kraj addDataset subscribe - } //kraj treceg ifa - }, (error) => { - //alert("greska uploadData"); - }); //kraj uploadData subscribe - - } //kraj drugog ifa - } //kraj prvog ifa + //alert("greska uploadData"); + }); //kraj uploadData subscribe + + } //kraj drugog ifa + } //kraj prvog ifa*/ } saveModelWithExistingDataset(callback: ((arg0: any) => void)): any { - if (this.selectedDataset) { //dataset je izabran + /*if (this.selectedDataset) { //dataset je izabran this.getCheckedInputCols(); this.getCheckedOutputCol(); this.getMetrics(); @@ -180,11 +180,11 @@ export class AddModelComponent implements OnInit { } else { alert("Molimo Vas da izaberete neki dataset iz kolekcije."); - } + }*/ } getCheckedInputCols() { - this.newModel.inputColumns = []; + /*this.newModel.inputColumns = []; let checkboxes: any; checkboxes = document.getElementsByName("cbsNew"); @@ -193,11 +193,11 @@ export class AddModelComponent implements OnInit { let thatCb = checkboxes[i]; if (thatCb.checked == true) // && thatCb.disabled == false ne treba nam ovo vise this.newModel.inputColumns.push(thatCb.value); - } + }*/ //console.log(this.checkedInputCols); } getCheckedOutputCol() { - this.newModel.columnToPredict = ''; + /*this.newModel.columnToPredict = ''; let radiobuttons: any; radiobuttons = document.getElementsByName("rbsNew"); @@ -208,11 +208,11 @@ export class AddModelComponent implements OnInit { this.newModel.columnToPredict = thatRb.value; break; } - } + }*/ //console.log(this.checkedOutputCol); } - validationInputsOutput(): boolean { - if (this.newModel.inputColumns.length == 0 && this.newModel.columnToPredict == '') { + validationInputsOutput() { + /*if (this.newModel.inputColumns.length == 0 && this.newModel.columnToPredict == '') { alert("Molimo Vas da izaberete ulazne i izlazne kolone za mrežu."); return false; } @@ -231,7 +231,7 @@ export class AddModelComponent implements OnInit { return false; } } - return true; + return true;*/ } selectThisDataset(dataset: Dataset) { -- cgit v1.2.3 From 093c0d2eeefa6e1a55524727d301753412486284 Mon Sep 17 00:00:00 2001 From: Danijel Andjelkovic Date: Wed, 6 Apr 2022 21:06:06 +0200 Subject: Add model stranica zamenjena sa eksperiment stranicom. --- frontend/angular.json | 5 +- frontend/src/app/_data/Dataset.ts | 18 +- frontend/src/app/_data/Experiment.ts | 22 + frontend/src/app/_data/Model.ts | 5 - .../_elements/model-load/model-load.component.html | 222 ++++++++- .../_elements/model-load/model-load.component.ts | 66 ++- .../app/_pages/add-model/add-model.component.css | 42 -- .../app/_pages/add-model/add-model.component.html | 428 ----------------- .../_pages/add-model/add-model.component.spec.ts | 25 - .../app/_pages/add-model/add-model.component.ts | 508 --------------------- frontend/src/app/app.module.ts | 2 - .../src/app/experiment/experiment.component.html | 192 +++++++- .../src/app/experiment/experiment.component.ts | 105 ++++- 13 files changed, 620 insertions(+), 1020 deletions(-) delete mode 100644 frontend/src/app/_pages/add-model/add-model.component.css delete mode 100644 frontend/src/app/_pages/add-model/add-model.component.html delete mode 100644 frontend/src/app/_pages/add-model/add-model.component.spec.ts delete mode 100644 frontend/src/app/_pages/add-model/add-model.component.ts (limited to 'frontend/src/app/_pages/add-model/add-model.component.ts') diff --git a/frontend/angular.json b/frontend/angular.json index f9825281..6653e4b1 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -33,10 +33,7 @@ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" ], "scripts": [ - "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js", - "node_modules/jquery/dist/jquery.min.js", - "node_modules/popper.js/dist/popper.min.js", - "node_modules/bootstrap/dist/js/bootstrap.min.js" + "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" ] }, "configurations": { diff --git a/frontend/src/app/_data/Dataset.ts b/frontend/src/app/_data/Dataset.ts index c5b56957..dd751947 100644 --- a/frontend/src/app/_data/Dataset.ts +++ b/frontend/src/app/_data/Dataset.ts @@ -12,6 +12,22 @@ export default class Dataset { public lastUpdated: Date = new Date(), public username: string = '', public delimiter: string = '', - public hasHeader: boolean = true + public hasHeader: boolean = true, + + public columnInfo: ColumnInfo[] = [], + public preview: string[][] = [[]] + ) { } +} + +export class ColumnInfo { + constructor( + public name: string = '', + public isNumber: boolean = false, + public numNull: number = 0, + public uniqueValues?: string[], + public median?: number, + public mean?: number, + public min?: number, + public max?: number ) { } } \ No newline at end of file diff --git a/frontend/src/app/_data/Experiment.ts b/frontend/src/app/_data/Experiment.ts index 706231c7..10320ab6 100644 --- a/frontend/src/app/_data/Experiment.ts +++ b/frontend/src/app/_data/Experiment.ts @@ -6,7 +6,29 @@ export default class Experiment { public datasetId: string = '', public inputColumns: string[] = [], public columnToPredict: string = '', + public nullValues: NullValueOptions = NullValueOptions.DeleteRows, + public nullValuesReplacers: NullValReplacer[] = [], public dateCreated: Date = new Date(), public lastUpdated: Date = new Date() ) { } +} + +export enum NullValueOptions { + DeleteRows = 'delete_rows', + DeleteColumns = 'delete_columns', + Replace = 'replace' +} + +export enum ReplaceWith { + None = 'Popuni...', + Mean = 'Srednja vrednost', + Median = 'Medijana', + Min = 'Minimum', + Max = 'Maksimum' +} + +export class NullValReplacer { + "column": string; + "option": NullValueOptions; + "value": string; } \ No newline at end of file diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts index 85b6db2b..9ea437b1 100644 --- a/frontend/src/app/_data/Model.ts +++ b/frontend/src/app/_data/Model.ts @@ -24,11 +24,8 @@ export default class Model { public hiddenLayers: number = 1, public batchSize: number = 5, public hiddenLayerActivationFunctions: string[] = ['sigmoid'], - //public inputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid, public outputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid, public username: string = '', - public nullValues: NullValueOptions = NullValueOptions.DeleteRows, - public nullValuesReplacers: NullValReplacer[] = [], public metrics: string[] = [], // TODO add to add-model form public epochs: number = 5 // TODO add to add-model form ) { } @@ -83,7 +80,6 @@ export enum ActivationFunction { Linear = 'linear', //Sigmoid='sigmoid', Softmax = 'softmax', - } /* export enum ActivationFunctionHiddenLayer @@ -115,7 +111,6 @@ export enum LossFunction { MeanSquaredError = 'mean_squared_error', MeanSquaredLogarithmicError = 'mean_squared_logarithmic_error', HuberLoss = 'Huber' - } export enum LossFunctionRegression { MeanAbsoluteError = 'mean_absolute_error', diff --git a/frontend/src/app/_elements/model-load/model-load.component.html b/frontend/src/app/_elements/model-load/model-load.component.html index ced9b0d6..0c6735a9 100644 --- a/frontend/src/app/_elements/model-load/model-load.component.html +++ b/frontend/src/app/_elements/model-load/model-load.component.html @@ -1 +1,221 @@ -

model-load works!

+
+
+

Nov model:

+
+ + +
+
+ +
+ +
+
+
+    + +
+
+

Parametri treniranja:

+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+ +
+
+ trening + + + test +
+
+ +
+
+ +
+
+ +
+
+
+

Aktivacione funkcije:

+ +
+
+ +
+
+
+
+
+ #{{i+1}} +
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+

+
+
+

Izaberite metrike:

+
+ +
+ + + +
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/frontend/src/app/_elements/model-load/model-load.component.ts b/frontend/src/app/_elements/model-load/model-load.component.ts index 00532bea..1d38de68 100644 --- a/frontend/src/app/_elements/model-load/model-load.component.ts +++ b/frontend/src/app/_elements/model-load/model-load.component.ts @@ -1,4 +1,7 @@ import { Component, OnInit } from '@angular/core'; +import Shared from 'src/app/Shared'; +import Model, { ActivationFunction, Encoding, LossFunction, LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, Metrics, MetricsBinaryClassification, MetricsMultiClassification, MetricsRegression, NullValueOptions, Optimizer, ProblemType } from 'src/app/_data/Model'; +import { ModelsService } from 'src/app/_services/models.service'; @Component({ selector: 'app-model-load', @@ -7,9 +10,70 @@ import { Component, OnInit } from '@angular/core'; }) export class ModelLoadComponent implements OnInit { - constructor() { } + newModel: Model = new Model(); + + ProblemType = ProblemType; + Encoding = Encoding; + ActivationFunction = ActivationFunction; + metrics: any = Metrics; + LossFunction = LossFunction; + Optimizer = Optimizer; + Object = Object; + document = document; + shared = Shared; + + term: string = ""; + selectedProblemType: string = ''; + selectedMetrics = []; + tempTestSetDistribution = 90; + lossFunction: any = LossFunction; + + constructor(private models: ModelsService) { } ngOnInit(): void { } + getMetrics() { + this.newModel.metrics = []; + let cb = document.getElementsByName("cbmetrics"); + + for (let i = 0; i < cb.length; i++) { + let chb = cb[i]; + if (chb.checked == true) + this.newModel.metrics.push(chb.value); + } + } + + addModel() { + this.getMetrics(); + + this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; + this.newModel.username = Shared.username; + + this.models.addModel(this.newModel).subscribe((response) => { + Shared.openDialog('Model dodat', 'Model je uspešno dodat u bazu.'); + // treba da se selektuje nov model u listi modela + }, (error) => { + Shared.openDialog('Greška', 'Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom.'); + }); + } + + filterOptions() { + switch (this.newModel.type) { + case 'regresioni': + this.lossFunction = LossFunctionRegression; + this.metrics = MetricsRegression; + break; + case 'binarni-klasifikacioni': + this.lossFunction = LossFunctionBinaryClassification; + this.metrics = MetricsBinaryClassification; + break; + case 'multi-klasifikacioni': + this.lossFunction = LossFunctionMultiClassification; + this.metrics = MetricsMultiClassification; + break; + default: + break; + } + } } diff --git a/frontend/src/app/_pages/add-model/add-model.component.css b/frontend/src/app/_pages/add-model/add-model.component.css deleted file mode 100644 index 7f05af0f..00000000 --- a/frontend/src/app/_pages/add-model/add-model.component.css +++ /dev/null @@ -1,42 +0,0 @@ -#header { - background-color: #003459; - padding-top: 30px; - padding-bottom: 20px; -} -#header h1 { - font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; - text-align: center; - color: white; -} - -#container { - border-radius: 8px; -} - -#wrapper { - color: #003459; -} - -.btnType1 { - background-color: #003459; - color: white; -} -.btnType2 { - background-color: white; - color: #003459; - border-color: #003459; -} -.selectedDatasetClass { - /*border-color: 2px solid #003459;*/ - background-color: lightblue; -} -ul li:hover { - background-color: lightblue; -} - -#divInputs { - margin-left: 20px; -} -#divOutputs { - margin-left: 20px; -} diff --git a/frontend/src/app/_pages/add-model/add-model.component.html b/frontend/src/app/_pages/add-model/add-model.component.html deleted file mode 100644 index 179e9aea..00000000 --- a/frontend/src/app/_pages/add-model/add-model.component.html +++ /dev/null @@ -1,428 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/app/_pages/add-model/add-model.component.spec.ts b/frontend/src/app/_pages/add-model/add-model.component.spec.ts deleted file mode 100644 index 2926e1c4..00000000 --- a/frontend/src/app/_pages/add-model/add-model.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { AddModelComponent } from './add-model.component'; - -describe('AddModelComponent', () => { - let component: AddModelComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ AddModelComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(AddModelComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts deleted file mode 100644 index ba8f7d01..00000000 --- a/frontend/src/app/_pages/add-model/add-model.component.ts +++ /dev/null @@ -1,508 +0,0 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; -import Model, { LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, NullValReplacer, ReplaceWith } from 'src/app/_data/Model'; -import { ProblemType, Encoding, ActivationFunction, LossFunction, Optimizer, NullValueOptions, Metrics, MetricsRegression, MetricsBinaryClassification, MetricsMultiClassification } from 'src/app/_data/Model'; -import { DatasetLoadComponent } from 'src/app/_elements/dataset-load/dataset-load.component'; -import { ModelsService } from 'src/app/_services/models.service'; -import shared from 'src/app/Shared'; -import Dataset from 'src/app/_data/Dataset'; -import { DatasetsService } from 'src/app/_services/datasets.service'; -import { CsvParseService } from 'src/app/_services/csv-parse.service'; - - -@Component({ - selector: 'app-add-model', - templateUrl: './add-model.component.html', - styleUrls: ['./add-model.component.css'] -}) -export class AddModelComponent implements OnInit { - - newModel: Model; - - ProblemType = ProblemType; - Encoding = Encoding; - ActivationFunction = ActivationFunction; - metrics: any = Metrics; - LossFunction = LossFunction; - lossFunction: any = LossFunction; - Optimizer = Optimizer; - NullValueOptions = NullValueOptions; - ReplaceWith = ReplaceWith; - Object = Object; - document = document; - shared = shared; - - selectedOutputColumnVal: string = ''; - - showMyDatasets: boolean = true; - myDatasets?: Dataset[]; - existingDatasetSelected: boolean = false; - selectedDataset?: Dataset; - otherDataset?: Dataset; - otherDatasetFile?: any[]; - datasetFile?: any[]; - datasetHasHeader?: boolean = true; - - tempTestSetDistribution: number = 90; - - //accepted: Boolean; - term: string = ""; - - selectedProblemType: string = ''; - selectedMetrics = []; - - trainingResult: string | undefined; - - constructor(private models: ModelsService, private datasets: DatasetsService, private csv: CsvParseService) { - this.newModel = new Model(); - - this.datasets.getMyDatasets().subscribe((datasets) => { - this.myDatasets = datasets; - }); - } - - ngOnInit(): void { - (document.getElementById("btnMyDataset")).focus(); - } - - datasetHasChanged(selectedDataset: Dataset) { - this.selectedDataset = selectedDataset; - this.resetCbsAndRbs(); - this.refreshThreeNullValueRadioOptions(); - } - - /*viewMyDatasetsForm() { - this.showMyDatasets = true; - this.resetSelectedDataset(); - //this.datasetLoaded = false; - this.resetCbsAndRbs(); - } - viewNewDatasetForm() { - this.showMyDatasets = false; - this.resetSelectedDataset(); - this.resetCbsAndRbs(); - }*/ - - addModel() { - if (!this.showMyDatasets) - this.saveModelWithNewDataset(_ => { console.log('MODEL ADDED (with new dataset).') }); - else - this.saveModelWithExistingDataset(_ => { console.log('MODEL ADDED (with existing dataset).') }); - } - - trainModel() { - let saveFunc; - this.trainingResult = undefined; - - if (!this.showMyDatasets) - saveFunc = (x: (arg0: any) => void) => { this.saveModelWithNewDataset(x) }; - else - saveFunc = (x: (arg0: any) => void) => { this.saveModelWithExistingDataset(x) }; - - saveFunc(((model: any) => { - console.log('Saved, training model...', model); - this.models.trainModel(model).subscribe(response => { - console.log('Train model complete!', response); - this.trainingResult = response; - }); - })); //privremeno cuvanje modela => vraca id sacuvanog modela koji cemo da treniramo sad - } - - saveModelWithNewDataset(callback: ((arg0: any) => void)) { - /* - this.getCheckedInputCols(); - this.getCheckedOutputCol(); - this.getMetrics(); - - if (this.validationInputsOutput()) { - console.log('ADD MODEL: STEP 1 - UPLOAD FILE'); - if (this.datasetLoadComponent) { - console.log("this.datasetLoadComponent.files:", this.datasetLoadComponent.files); - this.models.uploadData(this.datasetLoadComponent.files[0]).subscribe((file) => { - console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id); - if (this.datasetLoadComponent) { - this.datasetLoadComponent.dataset.fileId = file._id; - this.datasetLoadComponent.dataset.username = shared.username; - - this.datasets.addDataset(this.datasetLoadComponent.dataset).subscribe((dataset) => { - console.log('ADD MODEL: STEP 3 - ADD MODEL WITH DATASET ID ', dataset._id); - this.newModel.datasetId = dataset._id; - - //da se doda taj dataset u listu postojecih, da bude izabran - this.refreshMyDatasetList(); - this.showMyDatasets = true; - this.selectThisDataset(dataset); - - this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; - this.tempTestSetDistribution = 90; - this.newModel.username = shared.username; - - this.newModel.nullValuesReplacers = this.getNullValuesReplacersArray(); - - this.models.addModel(this.newModel).subscribe((response) => { - callback(response); - }, (error) => { - alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom."); - }); //kraj addModel subscribe - }, (error) => { - alert("Dataset sa unetim nazivom već postoji u Vašoj kolekciji.\nIzmenite naziv ili iskoristite postojeći dataset."); - }); //kraj addDataset subscribe - } //kraj treceg ifa - }, (error) => { - //alert("greska uploadData"); - }); //kraj uploadData subscribe - - } //kraj drugog ifa - } //kraj prvog ifa*/ - } - - saveModelWithExistingDataset(callback: ((arg0: any) => void)): any { - /*if (this.selectedDataset) { //dataset je izabran - this.getCheckedInputCols(); - this.getCheckedOutputCol(); - this.getMetrics(); - if (this.validationInputsOutput()) { - this.newModel.datasetId = this.selectedDataset._id; - - this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; - this.tempTestSetDistribution = 90; - this.newModel.username = shared.username; - - this.newModel.nullValuesReplacers = this.getNullValuesReplacersArray(); - - this.models.addModel(this.newModel).subscribe((response) => { - callback(response); - }, (error) => { - shared.openDialog("Neuspeo pokušaj!", "Model sa unetim nazivom već postoji u Vašoj kolekciji. Promenite naziv modela i nastavite sa kreiranim datasetom."); - }); - } - } - else { - alert("Molimo Vas da izaberete neki dataset iz kolekcije."); - }*/ - } - - getCheckedInputCols() { - /*this.newModel.inputColumns = []; - let checkboxes: any; - - checkboxes = document.getElementsByName("cbsNew"); - - for (let i = 0; i < checkboxes.length; i++) { - let thatCb = checkboxes[i]; - if (thatCb.checked == true) // && thatCb.disabled == false ne treba nam ovo vise - this.newModel.inputColumns.push(thatCb.value); - }*/ - //console.log(this.checkedInputCols); - } - getCheckedOutputCol() { - /*this.newModel.columnToPredict = ''; - let radiobuttons: any; - - radiobuttons = document.getElementsByName("rbsNew"); - - for (let i = 0; i < radiobuttons.length; i++) { - let thatRb = radiobuttons[i]; - if (thatRb.checked) { - this.newModel.columnToPredict = thatRb.value; - break; - } - }*/ - //console.log(this.checkedOutputCol); - } - validationInputsOutput() { - /*if (this.newModel.inputColumns.length == 0 && this.newModel.columnToPredict == '') { - alert("Molimo Vas da izaberete ulazne i izlazne kolone za mrežu."); - return false; - } - else if (this.newModel.inputColumns.length == 0) { - shared.openDialog("Neuspeo pokušaj!", "Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu."); - return false; - } - else if (this.newModel.columnToPredict == '') { - shared.openDialog("Neuspeo pokušaj!", "Molimo Vas da izaberete izlaznu kolonu za mrežu."); - return false; - } - for (let i = 0; i < this.newModel.inputColumns.length; i++) { - if (this.newModel.inputColumns[i] == this.newModel.columnToPredict) { - let colName = this.newModel.columnToPredict; - shared.openDialog("Neuspeo pokušaj!", "Izabrali ste istu kolonu (" + colName + ") kao ulaznu i izlaznu iz mreže. Korigujte izbor."); - return false; - } - } - return true;*/ - } - - /*selectThisDataset(dataset: Dataset) { - this.selectedDataset = dataset; - //this.selectedDatasetLoaded = false; - this.existingDatasetSelected = true; - this.datasetHasHeader = this.selectedDataset.hasHeader; - - this.datasets.getDatasetFile(dataset.fileId).subscribe((file: string | undefined) => { - if (file) { - this.datasetFile = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter); - //for (let i = this.datasetFile.length - 1; i >= 0; i--) { //moguce da je vise redova na kraju fajla prazno i sl. - //if (this.datasetFile[i].length != this.datasetFile[0].length) - //this.datasetFile[i].pop(); - //else - // break; //nema potrebe dalje - //} - //console.log(this.datasetFile); - this.resetCbsAndRbs(); - this.refreshThreeNullValueRadioOptions(); - //this.selectedDatasetLoaded = true; - this.scrollToNextForm(); - } - }); - //this.datasetHasHeader = false; - }*/ - - scrollToNextForm() { - (document.getElementById("selectInAndOuts")).scrollIntoView({ - behavior: "smooth", - block: "start", - inline: "nearest" - }); - } - - /*resetSelectedDataset(): boolean { - const temp = this.selectedDataset; - this.selectedDataset = this.otherDataset; - this.otherDataset = temp; - const tempFile = this.datasetFile; - this.datasetFile = this.otherDatasetFile; - this.otherDatasetFile = tempFile; - return true; - }*/ - resetCbsAndRbs(): boolean { - this.uncheckRbs(); - this.checkAllCbs(); - return true; - } - checkAllCbs() { - let checkboxes: any; - - checkboxes = document.getElementsByName("cbsNew"); - for (let i = 0; i < checkboxes.length; i++) { - (checkboxes[i]).checked = true; - (checkboxes[i]).disabled = false; - } - } - uncheckRbs() { - this.selectedOutputColumnVal = ''; - let radiobuttons: any; - - radiobuttons = document.getElementsByName("rbsNew"); - for (let i = 0; i < radiobuttons.length; i++) - (radiobuttons[i]).checked = false; - } - - refreshMyDatasetList() { - this.datasets.getMyDatasets().subscribe((datasets) => { - this.myDatasets = datasets; - }); - } - - refreshThreeNullValueRadioOptions() { - this.newModel.nullValues = NullValueOptions.DeleteRows; - } - - isChecked(someId: string) { //proveri ako je element sa datim ID-em cek - return (document.getElementById(someId)).checked; - } - - isNumber(value: string | number): boolean { - return ((value != null) && - (value !== '') && - !isNaN(Number(value.toString()))); - } - - findColIndexByName(colName: string): number { - if (this.datasetFile) - for (let i = 0; i < this.datasetFile[0].length; i++) - if (colName === this.datasetFile[0][i]) - return i; - return -1; - } - findColNameByIndex(index: number): string { - if (this.datasetFile) - if (this.datasetHasHeader && index < this.datasetFile[0].length) - return this.datasetFile[0][index]; - return ''; - } - emptyFillTextInput(colName: string) { - (document.getElementById("fillText_" + colName)).value = ""; - } - - checkFillColRadio(colName: string) { - (document.getElementById("fillCol_" + colName)).checked = true; - } - calculateSumOfNullValuesInCol(colName: string): number { - //console.log(this.datasetFile); - if (this.datasetFile) { - let colIndex = this.findColIndexByName(colName); - let sumOfNulls = 0; - - let startValue = (this.selectedDataset!.hasHeader) ? 1 : 0; - for (let i = startValue; i < this.datasetFile.length; i++) { - if (this.datasetFile[i][colIndex] == "" || this.datasetFile[i][colIndex] == undefined) - ++sumOfNulls; - } - return sumOfNulls; - } - return -1; - } - calculateMeanColValue(colName: string): number { - if (this.datasetFile) { - let colIndex = this.findColIndexByName(colName); - let sum = 0; - let n = 0; - - let startValue = (this.selectedDataset!.hasHeader) ? 1 : 0; - for (let i = startValue; i < this.datasetFile.length; i++) - if (this.datasetFile[i][colIndex] != '') { - sum += Number(this.datasetFile[i][colIndex]); - ++n; - } - console.log(sum / n); - return (sum != 0) ? (sum / n) : 0; - } - return 0; - } - calculateMedianColValue(colName: string): number { - if (this.datasetFile) { - let array = []; - let colIndex = this.findColIndexByName(colName); - - let startValue = (this.datasetHasHeader) ? 1 : 0; - for (let i = startValue; i < this.datasetFile.length; i++) - if (this.datasetFile[i][colIndex] != '') - array.push(Number(this.datasetFile[i][colIndex])); - - array.sort(); - if (array.length % 2 == 0) - return array[array.length / 2 - 1] / 2; - else - return array[(array.length - 1) / 2]; - } - return 0; - } - replaceWithSelectedString(event: Event) { - let value = (event.target).value; - let colIndex = Number(((event.target).id).split("replaceOptions")[1]); - let colName = this.findColNameByIndex(colIndex); - - (document.getElementById("fillCol_" + colName)).checked = true; - - if (!this.datasetHasHeader) - (document.getElementById("fillText_" + colName)).value = value; - else { - if (value == colName) - (document.getElementById("fillText_" + colName)).value = ""; - else - (document.getElementById("fillText_" + colName)).value = value; - } - } - replaceWithSelectedNumber(event: Event) { - let option = (event.target).value; - let colIndex = Number(((event.target).id).split("replaceOptions")[1]); - let colName = this.findColNameByIndex(colIndex); - - (document.getElementById("fillCol_" + colName)).checked = true; - - if (option == ReplaceWith.Mean) - (document.getElementById("fillText_" + colName)).value = this.calculateMeanColValue(colName).toString(); - else if (option == ReplaceWith.Median) - (document.getElementById("fillText_" + colName)).value = this.calculateMedianColValue(colName).toString(); - else if (option == ReplaceWith.None) - (document.getElementById("fillText_" + colName)).value = ""; - } - - - getNullValuesReplacersArray(): NullValReplacer[] { - let array: NullValReplacer[] = []; - - if (this.datasetFile) { - - if (this.newModel.nullValues == NullValueOptions.Replace) { - - for (let i = 0; i < this.datasetFile[0].length; i++) { - let column = this.datasetFile[0][i]; - - if (this.calculateSumOfNullValuesInCol(column) > 0) { //ako kolona nema null vrednosti, ne dodajemo je u niz - if ((document.getElementById("delCol_" + column)).checked) { - array.push({ - column: column, - option: NullValueOptions.DeleteColumns, - value: "" - }); - } - else if ((document.getElementById("delRows_" + column)).checked) { - array.push({ - column: column, - option: NullValueOptions.DeleteRows, - value: "" - }); - } - else if (((document.getElementById("fillCol_" + column)).checked)) { - array.push({ - column: column, - option: NullValueOptions.Replace, - value: (document.getElementById("fillText_" + column)).value - }); - } - } - } - } - } - //console.log(array); - return array; - } - - getInputById(id: string): HTMLInputElement { - return document.getElementById(id) as HTMLInputElement; - } - - arrayColumn = (arr: any[][], n: number) => [...this.dropEmptyString(new Set(arr.map(x => x[n])))]; - - dropEmptyString(set: Set): Set { - if (set.has("")) - set.delete(""); - if (set.has(null)) - set.delete(null); - if (set.has(undefined)) - set.delete(undefined); - return set; - } - - filterOptions() { - switch (this.newModel.type) { - case 'regresioni': - this.lossFunction = LossFunctionRegression; - this.metrics = MetricsRegression; - break; - case 'binarni-klasifikacioni': - this.lossFunction = LossFunctionBinaryClassification; - this.metrics = MetricsBinaryClassification; - break; - case 'multi-klasifikacioni': - this.lossFunction = LossFunctionMultiClassification; - this.metrics = MetricsMultiClassification; - break; - default: - break; - } - } - - getMetrics() { - this.newModel.metrics = []; - let cb = document.getElementsByName("cbmetrics"); - - for (let i = 0; i < cb.length; i++) { - let chb = cb[i]; - if (chb.checked == true) - this.newModel.metrics.push(chb.value); - } - - } -} diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 04523989..c3a2ce7a 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -11,7 +11,6 @@ import { Ng2SearchPipeModule } from 'ng2-search-filter'; import { AppComponent } from './app.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DatasetLoadComponent } from './_elements/dataset-load/dataset-load.component'; -import { AddModelComponent } from './_pages/add-model/add-model.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { LoginModalComponent } from './_modals/login-modal/login-modal.component'; import { ReactiveFormsModule } from '@angular/forms'; @@ -49,7 +48,6 @@ import { AddNewDatasetComponent } from './_elements/add-new-dataset/add-new-data declarations: [ AppComponent, DatasetLoadComponent, - AddModelComponent, LoginModalComponent, RegisterModalComponent, HomeComponent, diff --git a/frontend/src/app/experiment/experiment.component.html b/frontend/src/app/experiment/experiment.component.html index 42f2993d..8d2c86b3 100644 --- a/frontend/src/app/experiment/experiment.component.html +++ b/frontend/src/app/experiment/experiment.component.html @@ -1,13 +1,201 @@
+ +

1. Izvor podataka

+ +

2. Preprocesiranje

+

Biranje ulaznih i izlaznih kolona:

+
+
+
+

Izaberite ulazne kolone:

+
+
+
+   + +
+
+
+
+

Izaberite izlaznu kolonu:

+
+
+
+   + +
+
+
+
+
+

Popunjavanje nedostajućih vrednosti:

+
+ +
+ +
+ +

+
+
+ +
+
+
+ + {{column.name}} ( + + TODO BROJ null) + + + + + +
+ +
+
+
+ +
+ + +
+ + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+ + {{column}} (br + null) + + + + + + + + + + +
+
+ +
+
+
+
+ +

3. Podešavanja mreže

-

4. Rezultati treniranja

+ + +

4. Treniraj model

+ +

Rezultati treniranja

+
+

Rezultati treniranja:

+

+ {{trainingResult}} +

+
\ No newline at end of file diff --git a/frontend/src/app/experiment/experiment.component.ts b/frontend/src/app/experiment/experiment.component.ts index 16de7351..2309dcd7 100644 --- a/frontend/src/app/experiment/experiment.component.ts +++ b/frontend/src/app/experiment/experiment.component.ts @@ -1,4 +1,9 @@ import { Component, OnInit } from '@angular/core'; +import Experiment, { NullValReplacer, NullValueOptions, ReplaceWith } from '../_data/Experiment'; +import Model from '../_data/Model'; +import Dataset from '../_data/Dataset'; +import { ModelsService } from '../_services/models.service'; +import Shared from '../Shared'; @Component({ selector: 'app-experiment', @@ -7,9 +12,107 @@ import { Component, OnInit } from '@angular/core'; }) export class ExperimentComponent implements OnInit { - constructor() { } + experiment: Experiment = new Experiment(); + selectedModel?: Model; + selectedDataset?: Dataset; + trainingResult: any; // any za sad, promeni kasnije + + NullValueOptions = NullValueOptions; + ReplaceWith = ReplaceWith; + Object = Object; + + selectedOutputColumnVal: string = ''; + + constructor(private models: ModelsService) { } ngOnInit(): void { } + getInputById(id: string): HTMLInputElement { + return document.getElementById(id) as HTMLInputElement; + } + + arrayColumn = (arr: any[][], n: number) => [...this.dropEmptyString(new Set(arr.map(x => x[n])))]; + + dropEmptyString(set: Set): Set { + if (set.has("")) + set.delete(""); + if (set.has(null)) + set.delete(null); + if (set.has(undefined)) + set.delete(undefined); + return set; + } + + emptyFillTextInput(colName: string) { + (document.getElementById("fillText_" + colName)).value = ""; + } + + checkFillColRadio(colName: string) { + (document.getElementById("fillCol_" + colName)).checked = true; + } + + replace(event: Event) { + let option = (event.target).value; + // TODO + } + + getNullValuesReplacersArray()/*: NullValReplacer[]*/ { + let array: NullValReplacer[] = []; + + // TODO ispravi + /*if (this.datasetFile) { + + if (this.newModel.nullValues == NullValueOptions.Replace) { + + for (let i = 0; i < this.datasetFile[0].length; i++) { + let column = this.datasetFile[0][i]; + + if (this.calculateSumOfNullValuesInCol(column) > 0) { //ako kolona nema null vrednosti, ne dodajemo je u niz + if ((document.getElementById("delCol_" + column)).checked) { + array.push({ + column: column, + option: NullValueOptions.DeleteColumns, + value: "" + }); + } + else if ((document.getElementById("delRows_" + column)).checked) { + array.push({ + column: column, + option: NullValueOptions.DeleteRows, + value: "" + }); + } + else if (((document.getElementById("fillCol_" + column)).checked)) { + array.push({ + column: column, + option: NullValueOptions.Replace, + value: (document.getElementById("fillText_" + column)).value + }); + } + } + } + } + } + //console.log(array); + return array;*/ + } + + trainModel() { + this.trainingResult = undefined; + console.log('Training model...', this.selectedModel); + if (!this.selectedDataset) { + Shared.openDialog('Greška', 'Izvor podataka nije izabran!'); + return; + } + // TODO proveri nullValues + if (!this.selectedModel) { + Shared.openDialog('Greška', 'Model nije izabran!'); + return; + } + this.models.trainModel(this.selectedModel).subscribe((response: any) => { + console.log('Train model complete!', response); + this.trainingResult = response; + }); + } } -- cgit v1.2.3