diff options
author | Danijel Anđelković <adanijel99@gmail.com> | 2022-06-04 01:17:55 +0200 |
---|---|---|
committer | Danijel Anđelković <adanijel99@gmail.com> | 2022-06-04 01:17:55 +0200 |
commit | 60782001174dc7f6f8f5670bff5aaca54667b734 (patch) | |
tree | 3839d149476115cbf7b954867a7c3bf2006c23f7 | |
parent | 854e21f08d1c876cf62c7a360bd5bd142675d705 (diff) |
Dodao poredjenje modela/prediktora nad eksperimentom. Popravio bug sa dodavanjem novog prediktora.
8 files changed, 154 insertions, 33 deletions
diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs index 6ff7746a..56095553 100644 --- a/backend/api/api/Controllers/PredictorController.cs +++ b/backend/api/api/Controllers/PredictorController.cs @@ -21,7 +21,7 @@ namespace api.Controllers private readonly IHubContext<ChatHub> _ichat; private readonly IModelService _modelService; - public PredictorController(IPredictorService predictorService, IConfiguration configuration, IJwtToken Token, IMlConnectionService mlConnectionService, IExperimentService experimentService,IUserService userService, IHubContext<ChatHub> ichat,IModelService modelService) + public PredictorController(IPredictorService predictorService, IConfiguration configuration, IJwtToken Token, IMlConnectionService mlConnectionService, IExperimentService experimentService, IUserService userService, IHubContext<ChatHub> ichat, IModelService modelService) { _predictorService = predictorService; jwtToken = Token; @@ -78,7 +78,7 @@ namespace api.Controllers //public ActionResult<List<Predictor>> Search(string name) //{ // string username = getUsername(); - + // if (username == null) // return BadRequest(); @@ -138,7 +138,7 @@ namespace api.Controllers List<Predictor> lista = _predictorService.SortPredictors(userId, ascdsc, latest); - if(latest == 0) + if (latest == 0) return lista; else { @@ -155,19 +155,23 @@ namespace api.Controllers [HttpPost("add")] public async Task<ActionResult<Predictor>> Post([FromBody] Predictor predictor) { - var user=_userService.GetUserById(predictor.uploaderId); + var user = _userService.GetUserById(predictor.uploaderId); predictor.dateCreated = DateTime.Now.ToUniversalTime(); var model = _modelService.GetOneModel(predictor.modelId); - if (model == null || user==null) + if (model == null || user == null) return BadRequest("Model not found or user doesnt exist"); - Predictor p=_predictorService.Exists(predictor.modelId, predictor.experimentId); - if (p == null) + Predictor p = _predictorService.Exists(predictor.modelId, predictor.experimentId); + + if (p == null) { _predictorService.Create(predictor); - else + } + else { + predictor._id = p._id; _predictorService.Update(p._id, predictor); + } if (ChatHub.CheckUser(user._id)) foreach(var connection in ChatHub.getAllConnectionsOfUser(user._id)) - await _ichat.Clients.Client(connection).SendAsync("NotifyPredictor", predictor._id,model.name); + await _ichat.Clients.Client(connection).SendAsync("NotifyPredictor", predictor._id, model._id); return CreatedAtAction(nameof(Get), new { id = predictor._id }, predictor); } diff --git a/backend/microservice/api/controller.py b/backend/microservice/api/controller.py index c82634a2..bc8c17a0 100644 --- a/backend/microservice/api/controller.py +++ b/backend/microservice/api/controller.py @@ -1,3 +1,4 @@ +from asyncio.windows_events import NULL from cmath import log from dataclasses import dataclass from distutils.command.upload import upload @@ -112,12 +113,12 @@ def train(): "metricsMse":histMetrics[6], "metricsValMse":histMetrics[7] } - #print(predictor) + print(predictor) url = config.api_url + "/Predictor/add" r = requests.post(url, json=predictor).text - #print(r) + print(r) return r @app.route('/predict', methods = ['POST']) diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css index 9694119d..862a86e1 100644 --- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css +++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.css @@ -4,7 +4,7 @@ } .bottom { - height: 10%; + height: 30px; } canvas { diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html index a81f9dc4..cc1c0121 100644 --- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html +++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.html @@ -1,28 +1,29 @@ -<div #wrapper class="position-relative" style="width:100%;height:95%;"> +<div #wrapper class="position-relative" style="width:100%;height:95%; border: 1px solid var(--ns-accent); background-color: var(--ns-bg-dark-100); border-radius: 15px;"> <div class="d-flex flex-column align-items-stretch" [ngClass]="{'hide':experiment.type != ProblemType.Regression}" style="width: 100%; height: 90%;"> <div class="canvas-container"> - <canvas id="myChartmae" #canvas> + <canvas #myChartmae> </canvas> </div> <div class="canvas-container"> - <canvas id="myChartmse" #canvas> + <canvas #myChartmse> </canvas> </div> </div> <div class="ns-row" [ngClass]="{'hide':experiment.type == ProblemType.Regression}"> <div class="ns-col"> - <canvas id="myChartloss" #canvas> + <canvas #myChartloss> </canvas> </div> <div class="ns-col"> - <canvas id="myChartacc" #canvas> + <canvas #myChartacc> </canvas> </div> </div> - <div class="bottom d-flex flex-row align-items-center"> - <button *ngIf="predictor" class="btn-clear dl-button d-flex flex-row" (click)="downloadFile();" style="display: inline-block;" matTooltip="Preuzmi H5" matTooltipPosition="above"> + <div class="bottom d-flex flex-row" style="justify-content: space-between; align-items: center;"> + <h3 class="mt-5 mx-2"><span *ngIf="modelName.length > 0 && predictor">Model treniran za konfiguraciju: {{modelName}}</span><span *ngIf="modelName.length > 0 && !predictor">Model se trenira za konfiguraciju: {{modelName}}</span></h3> + <button *ngIf="predictor" class="mt-5 mx-2 btn-clear dl-button d-flex flex-row" (click)="downloadFile();" style="display: inline-block;" matTooltip="Preuzmi H5" matTooltipPosition="above"> <mat-icon>download</mat-icon> <div>H5</div> </button> </div> diff --git a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts index ceff02bd..b2eec377 100644 --- a/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts +++ b/frontend/src/app/_elements/_charts/line-chart/line-chart.component.ts @@ -26,8 +26,12 @@ export class LineChartComponent implements AfterViewInit { @ViewChild('wrapper') wrapper!: ElementRef; - @ViewChildren('canvas') - canvas!: QueryList<ElementRef>; + + @ViewChild('myChartacc') myChartacc!: ElementRef; + @ViewChild('myChartloss') myChartloss!: ElementRef; + @ViewChild('myChartmse') myChartmse!: ElementRef; + @ViewChild('myChartmae') myChartmae!: ElementRef; + @Input() experiment!: Experiment; @Input() predictor?: Predictor; @@ -149,7 +153,7 @@ export class LineChartComponent implements AfterViewInit { window.addEventListener('resize', () => { this.resize() }); this.resize(); - this.myChartAcc = new Chart("myChartacc", + this.myChartAcc = new Chart(this.myChartacc.nativeElement, { type: 'line', data: { @@ -222,7 +226,7 @@ export class LineChartComponent implements AfterViewInit { ); if (this.experiment.type == ProblemType.BinaryClassification || this.experiment.type == ProblemType.MultiClassification) { } - this.myChartLoss = new Chart("myChartloss", + this.myChartLoss = new Chart(this.myChartloss.nativeElement, { type: 'line', data: { @@ -294,7 +298,7 @@ export class LineChartComponent implements AfterViewInit { }, ); - this.myChartMse = new Chart("myChartmse", + this.myChartMse = new Chart(this.myChartmse.nativeElement, { type: 'line', data: { @@ -366,7 +370,7 @@ export class LineChartComponent implements AfterViewInit { }, ); - this.myChartMae = new Chart("myChartmae", + this.myChartMae = new Chart(this.myChartmae.nativeElement, { type: 'line', data: { @@ -440,5 +444,12 @@ export class LineChartComponent implements AfterViewInit { ); } + + modelName: string = ''; + + setName(name: string) { + this.modelName = name; + this.predictor = undefined; + } } diff --git a/frontend/src/app/_pages/experiment/experiment.component.css b/frontend/src/app/_pages/experiment/experiment.component.css index 59e004e9..37edd3c2 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.css +++ b/frontend/src/app/_pages/experiment/experiment.component.css @@ -74,4 +74,34 @@ mat-stepper { .text-overflow-experiment-name { overflow-wrap: break-word; +} + +#compareButton { + position: absolute; + top: 10px; + right: 10px; +} + +.side-by-side { + display: flex; + flex-direction: row; + width: 100%; + height: 100%; +} + + +/* one item */ + +.side-by-side>*:first-child:nth-last-child(1) { + /* -or- li:only-child { */ + width: 100%; +} + + +/* two items */ + +.side-by-side>*:first-child:nth-last-child(2), +.side-by-side>*:first-child:nth-last-child(2)~li { + width: 50%; + margin: 5px; }
\ No newline at end of file diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index 2e5a269c..a0ed26ef 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -25,10 +25,10 @@ <ng-template matStepLabel> <span class="label addedElement text-overflow" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span> <span *ngIf="!this.step1" class="align-middle"><mat-icon>lock</mat-icon></span> - <span class="label text-overflow" *ngIf="experiment._id==''">Odabir kolona </span> + <span class="label text-overflow" *ngIf="experiment._id==''">Priprema podataka </span> </ng-template> <ng-template matStepContent> - <p class="text-left text-overflow">Pripremite podatke i izaberite izlazne kolone</p> + <p class="text-left text-overflow">Pripremite podatke i odaberite ulazne i izlaznu kolonu</p> </ng-template> </mat-step> <mat-step [completed]="this.step3"> @@ -62,12 +62,23 @@ </div> <div #steps id="step_3" class="step-content" *ngIf="step2"> <div class="step-content-inside"> - <app-folder #folderModel [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.NewFile" [tabsToShow]="[TabType.MyModels]" (okPressed)="goToPage(3); trainModel();" (selectedFileChanged)="setModel($event)"></app-folder> + <div id="compareButton"> + <button mat-raised-button color="accent" *ngIf="!comparing" (click)="toggleCompare()"><mat-icon>compare</mat-icon> Dodaj konfiguraciju za upoređivanje</button> + <button mat-raised-button *ngIf="comparing" (click)="toggleCompare()"><mat-icon>not_interested</mat-icon> Prekini upoređivanje</button> + </div> + <div class="side-by-side"> + <app-folder #folderModel [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.NewFile" [tabsToShow]="[TabType.MyModels]" (okPressed)="goToPage(3); trainModel();" (selectedFileChanged)="setModel($event);"></app-folder> + <app-folder #folderModelCompare [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.MyModels" [tabsToShow]="[TabType.MyModels]" (okPressed)="goToPage(3); trainModelCmp();" (selectedFileChanged)="setModelCmp($event);" style="width: 50%;" + *ngIf="comparing"></app-folder> + </div> </div> </div> <div #steps id="step_4" class="step-content" *ngIf="step3"> <div class="step-content-inside"> - <app-line-chart [experiment]="experiment" [predictor]="predictor!"></app-line-chart> + <div class="side-by-side"> + <app-line-chart #linechart [experiment]="experiment" [predictor]="predictor!"></app-line-chart> + <app-line-chart #linechartCompare [experiment]="experiment" style="width: 50%;" *ngIf="comparing"></app-line-chart> + </div> </div> </div> <!-- diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts index 4ceb9a03..5822eedf 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.ts +++ b/frontend/src/app/_pages/experiment/experiment.component.ts @@ -37,13 +37,27 @@ export class ExperimentComponent implements AfterViewInit { @ViewChild("folderDataset") folderDataset!: FolderComponent; @ViewChild(ColumnTableComponent) columnTable!: ColumnTableComponent; @ViewChild("folderModel") folderModel!: FolderComponent; - @ViewChild(LineChartComponent) linechartComponent!: LineChartComponent; + @ViewChild("folderModelCompare") folderModelCmp!: FolderComponent; + @ViewChild("linechart") linechartComponent!: LineChartComponent; + @ViewChild("linechartCompare") linechartComponentCmp!: LineChartComponent; step1: boolean = false; step2: boolean = false; step3: boolean = false; step4: boolean = false; + comparing: boolean = false; + + toggleCompare() { + this.comparing = !this.comparing; + setTimeout(() => { + if (this.folderModel.formModel) + this.folderModel.formModel.graph.resize(); + if (this.folderModel.formNewModel) + this.folderModel.formNewModel.graph.resize(); + }); + } + constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private predictorsService: PredictorsService, private signalRService: SignalRService, private route: ActivatedRoute) { this.experiment = new Experiment("exp1"); } @@ -65,6 +79,15 @@ export class ExperimentComponent implements AfterViewInit { } } + trainModelCmp() { + if (!this.modelToTrainCmp) { + Shared.openDialog('Greška', 'Morate odabrati konfiguraciju neuronske mreže'); + } else { + this.modelsService.trainModel(this.modelToTrainCmp._id, this.experiment._id).subscribe(() => { console.log("pocelo treniranje") }); + this.step4 = true; + } + } + stepHeight = this.calcStepHeight(); calcStepHeight() { @@ -87,16 +110,48 @@ export class ExperimentComponent implements AfterViewInit { if (this.signalRService.hubConnection) { this.signalRService.hubConnection.on("NotifyEpoch", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => { - if (currentEpoch == 0) { - this.history = []; - } + if (this.modelToTrain?._id == mId) { + if (currentEpoch == 0) { + this.linechartComponent.setName(mName); + this.history = []; + } + stat = stat.replace(/'/g, '"'); this.history.push(JSON.parse(stat)); + this.linechartComponent.updateAll(this.history, this.modelToTrain.epochs); } + + if (this.modelToTrainCmp?._id == mId) { + if (currentEpoch == 0) { + this.linechartComponentCmp.setName(mName); + this.historyCmp = []; + } + + stat = stat.replace(/'/g, '"'); + + this.historyCmp.push(JSON.parse(stat)); + this.linechartComponentCmp.updateAll(this.historyCmp, this.modelToTrainCmp.epochs); + } }); + this.signalRService.hubConnection.on("NotifyPredictor", (pId: string, mId: string) => { + console.log("Predictor trained: ", pId, "for model:", mId); + + if (this.modelToTrain && mId == this.modelToTrain._id) { + this.predictorsService.getPredictor(pId).subscribe((predictor) => { + this.linechartComponent.predictor = predictor; + }); + } + + if (this.modelToTrainCmp && mId == this.modelToTrainCmp._id) { + this.predictorsService.getPredictor(pId).subscribe((predictor) => { + this.linechartComponentCmp.predictor = predictor; + }); + } + }) + } this.route.queryParams.subscribe(params => { @@ -142,6 +197,7 @@ export class ExperimentComponent implements AfterViewInit { } history: any[] = []; + historyCmp: any[] = []; updatePageIfScrolled() { if (this.scrolling) return; @@ -227,10 +283,17 @@ export class ExperimentComponent implements AfterViewInit { } modelToTrain?: Model; + modelToTrainCmp?: Model; setModel(model: FolderFile) { const m = <Model>model; this.modelToTrain = m; this.step3 = true; } + + setModelCmp(model: FolderFile) { + const m = <Model>model; + this.modelToTrainCmp = m; + this.step3 = true; + } } |