separated components

master
parent b203a417ae
commit 0b2262cffd
  1. BIN
      __pycache__/run.cpython-37.pyc
  2. 2
      cache_dir/joblib/run/GridSearch/4b9f779431c047e8a87f8756bac85d64/metadata.json
  3. BIN
      cache_dir/joblib/run/GridSearch/4b9f779431c047e8a87f8756bac85d64/output.pkl
  4. 2
      cache_dir/joblib/run/GridSearch/a32924a20c3a8483b7f841d3c9c7508f/metadata.json
  5. BIN
      cache_dir/joblib/run/GridSearch/a32924a20c3a8483b7f841d3c9c7508f/output.pkl
  6. 36
      cache_dir/joblib/run/GridSearch/func_code.py
  7. 1724
      frontend/package-lock.json
  8. 59
      frontend/package.json
  9. 4
      frontend/src/App.vue
  10. 1
      frontend/src/assets/logo.svg
  11. 230
      frontend/src/components/BarChart.vue
  12. 253
      frontend/src/components/LoadFile.vue
  13. 197
      frontend/src/components/Main.vue
  14. 24
      frontend/src/components/ParametersSetting.vue
  15. 88
      frontend/src/components/ScatterPlot.vue
  16. 582
      frontend/src/components/StretchedChord.vue
  17. 67
      frontend/src/components/Tuning.vue
  18. 2
      frontend/src/main.js
  19. 0
      frontend/static/.gitkeep
  20. 10
      frontend/vue.config.js
  21. 101
      run.py

Binary file not shown.

@ -1 +1 @@
{"duration": 0.13759469985961914, "input_args": {"clf": "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n weights='uniform')", "params": "{'n_neighbors': [1, 2, 10]}", "scoring": "{'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}", "FI": "0"}}
{"duration": 0.26462531089782715, "input_args": {"clf": "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n weights='uniform')", "params": "{'n_neighbors': [1, 2, 10]}", "scoring": "{'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}", "FI": "0"}}

@ -1 +1 @@
{"duration": 0.6970040798187256, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators='warn',\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [10, 50]}", "scoring": "{'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}", "FI": "1"}}
{"duration": 0.792708158493042, "input_args": {"clf": "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n max_depth=None, max_features='auto', max_leaf_nodes=None,\n min_impurity_decrease=0.0, min_impurity_split=None,\n min_samples_leaf=1, min_samples_split=2,\n min_weight_fraction_leaf=0.0, n_estimators='warn',\n n_jobs=None, oob_score=False, random_state=None,\n verbose=0, warm_start=False)", "params": "{'n_estimators': [10, 50]}", "scoring": "{'accuracy': 'accuracy', 'f1_macro': 'f1_weighted', 'precision': 'precision_weighted', 'recall': 'recall_weighted', 'jaccard': 'jaccard_weighted'}", "FI": "1"}}

@ -1,4 +1,4 @@
# first line: 84
# first line: 85
def GridSearch(clf, params, scoring, FI):
grid = GridSearchCV(estimator=clf,
@ -9,7 +9,7 @@ def GridSearch(clf, params, scoring, FI):
n_jobs = -1)
grid.fit(XData, yData)
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
@ -28,20 +28,24 @@ def GridSearch(clf, params, scoring, FI):
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
parameters = df_cv_results_classifiers['params']
FeatureImp = []
if (FI == 1):
for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items():
Listvalue = []
Listvalue.append(value)
eachClassifierParamsDictList[key] = Listvalue
grid = GridSearchCV(estimator=clf,
param_grid=eachClassifierParamsDictList,
scoring=scoring,
cv=5,
refit='accuracy',
n_jobs = -1)
grid.fit(XData, yData)
target_names = ['class 0', 'class 1', 'class 2']
for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items():
Listvalue = []
Listvalue.append(value)
eachClassifierParamsDictList[key] = Listvalue
grid = GridSearchCV(estimator=clf,
param_grid=eachClassifierParamsDictList,
scoring=scoring,
cv=5,
refit='accuracy',
n_jobs = -1)
print(eachClassifierParamsDictList)
grid.fit(XData, yData)
yPredict = grid.predict(XData)
print(classification_report(yData, yPredict, target_names=target_names))
if (FI == 1):
FeatureImp.append(grid.best_estimator_.feature_importances_)
return df_cv_results_classifiers, parameters, FeatureImp

File diff suppressed because it is too large Load Diff

@ -1,23 +1,23 @@
{
"name": "istacking",
"version": "1.0.0",
"private": true,
"description": "ISOVIS Group",
"author": "Angelos Chatzimparmpas <angelos.chatzimparmpas@gmail.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev"
},
"dependencies": {
"@babel/core": "^7.5.4",
"@babel/core": "^7.5.5",
"@fortawesome/fontawesome-free": "^5.9.0",
"@fortawesome/fontawesome-svg-core": "^1.2.19",
"@fortawesome/free-solid-svg-icons": "^5.9.0",
"@fortawesome/vue-fontawesome": "^0.1.6",
"@statnett/vue-plotly": "^0.3.2",
"@types/node": "^12.6.6",
"@types/node": "^12.6.8",
"ajv": "^6.10.2",
"audit": "0.0.6",
"axios": "^0.19.0",
@ -27,6 +27,7 @@
"bootstrap-vue": "^2.0.0-rc.26",
"clean-webpack-plugin": "^3.0.0",
"d3": "^5.9.7",
"d3-loom": "^1.0.2",
"file-saver": "^2.0.2",
"file-system": "^2.2.2",
"fix": "0.0.6",
@ -34,24 +35,26 @@
"fs-es6": "0.0.2",
"ify-loader": "^1.1.0",
"jquery": "^3.4.1",
"mdbvue": "^5.6.0",
"mdbvue": "^5.7.0",
"mini-css-extract-plugin": "^0.8.0",
"npm-check-updates": "^3.1.20",
"papaparse": "^5.0.0",
"papaparse": "^5.0.1",
"plotly": "^1.0.6",
"plotly.js": "^1.48.3",
"plotly.js": "^1.49.0",
"popper.js": "^1.15.0",
"strip-loader": "^0.1.2",
"toposort": "^2.0.2",
"transform-loader": "^0.2.4",
"vega": "^5.4.0",
"vue": "^2.6.10",
"vue-papa-parse": "^1.2.1",
"vue-plotly": "^1.0.0",
"vue-router": "^3.0.7",
"vue-slider-component": "^3.0.33",
"webpack-cli": "^3.3.6"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.5.0",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-proposal-export-namespace-from": "^7.5.2",
"@babel/plugin-proposal-function-sent": "^7.5.0",
@ -61,27 +64,27 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/plugin-syntax-jsx": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.5.0",
"@babel/preset-env": "^7.5.4",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"autoprefixer": "^9.6.1",
"babel-eslint": "^10.0.2",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"chalk": "^2.4.2",
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^3.0.0",
"eslint": "^6.0.1",
"copy-webpack-plugin": "^5.0.4",
"css-loader": "^3.1.0",
"eslint": "^6.1.0",
"eslint-config-standard": "^13.0.1",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.2.1",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.2.3",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^4.0.0",
"file-loader": "^4.1.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^3.2.0",
"node-notifier": "^5.4.0",
@ -92,27 +95,31 @@
"postcss-loader": "^3.0.0",
"postcss-url": "^8.0.0",
"rimraf": "^2.6.3",
"semver": "^6.2.0",
"sass": "^1.22.7",
"sass-loader": "^7.1.0",
"semver": "^6.3.0",
"shelljs": "^0.8.3",
"uglifyjs-webpack-plugin": "^2.1.3",
"url-loader": "^2.0.1",
"url-loader": "^2.1.0",
"vue-class-component": "^7.1.0",
"vue-loader": "^15.7.0",
"vue-cli-plugin-vuetify": "^0.6.1",
"vue-loader": "^15.7.1",
"vue-property-decorator": "^8.2.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.35.3",
"vuetify-loader": "^1.3.0",
"webpack": "^4.38.0",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-server": "^3.7.2",
"webpack-merge": "^4.2.1"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
],
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
}

@ -14,8 +14,8 @@ export default {
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
font-size: 16px;
font-family: 'sans-serif';
font-size: 18px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;

@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg>

After

Width:  |  Height:  |  Size: 539 B

@ -0,0 +1,230 @@
<template>
<b-row>
<b-col cols="4">
<div id="barChartPrecision0" class="barChartPrecision0"></div>
<div id="barChartPrecision1" class="barChartPrecision1"></div>
<div id="barChartPrecision2" class="barChartPrecision2"></div>
</b-col>
<b-col cols="4">
<div id="barChartRecall0" class="barChartRecall0"></div>
<div id="barChartRecall1" class="barChartRecall1"></div>
<div id="barChartRecall2" class="barChartRecall2"></div>
</b-col>
<b-col cols="4">
<div id="barChartf1Score0" class="barChartf1Score0"></div>
<div id="barChartf1Score1" class="barChartf1Score1"></div>
<div id="barChartf1Score2" class="barChartf1Score2"></div>
</b-col>
</b-row>
</template>
<script>
import * as Plotly from 'plotly.js'
import { EventBus } from '../main.js'
export default {
name: 'BarChart',
data () {
return {
BarChartResults: '',
}
},
methods: {
BarChartView () {
const PerClassMetrics = JSON.parse(this.BarChartResults[4])
const ClassNames = JSON.parse(this.BarChartResults[5])
const precisionPerClass = []
const recallPerClass = []
const f1ScorePerClass = []
for (let j = 0; j < ClassNames.length; j++) {
precisionPerClass[j] = []
recallPerClass[j] = []
f1ScorePerClass[j] = []
for (let i = 0; i < PerClassMetrics.length; i++) {
precisionPerClass[j].push(PerClassMetrics[i][ClassNames[j]].precision)
recallPerClass[j].push(PerClassMetrics[i][ClassNames[j]].recall)
f1ScorePerClass[j].push(PerClassMetrics[i][ClassNames[j]]['f1-score'])
}
}
var precisionData
var recallData
var f1ScoreData
var layoutPrec = {
autosize: false,
width: 400,
height: 400,
xaxis: {
title: 'Classifier ID',
type:"category",
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
},
showticklabels: true,
tickangle: 'auto',
tickfont: {
family: 'Old Standard TT, serif',
size: 14,
color: 'black'
},
exponentformat: 'e',
showexponent: 'all'
},
yaxis: {
title: 'Precision',
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
}
}
}
var layoutRec = {
autosize: false,
width: 400,
height: 400,
xaxis: {
title: 'Classifier ID',
type:"category",
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
},
showticklabels: true,
tickangle: 'auto',
tickfont: {
family: 'Old Standard TT, serif',
size: 14,
color: 'black'
},
exponentformat: 'e',
showexponent: 'all'
},
yaxis: {
title: 'Recall',
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
}
}
}
var layoutf1Score = {
autosize: false,
width: 400,
height: 400,
xaxis: {
title: 'Classifier ID',
type:"category",
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
},
showticklabels: true,
tickangle: 'auto',
tickfont: {
family: 'Old Standard TT, serif',
size: 14,
color: 'black'
},
exponentformat: 'e',
showexponent: 'all'
},
yaxis: {
title: 'F1-Score',
titlefont: {
family: 'Arial, sans-serif',
size: 18,
color: 'lightgrey'
}
}
}
for (let j = 0; j < ClassNames.length; j++) {
let len = precisionPerClass[j].length
let indices = new Array(len)
for (let i = 0; i < len; ++i) indices[i] = i
indices.sort(function (a, b) { return precisionPerClass[j][b] < precisionPerClass[j][a] ? -1 : precisionPerClass[j][b] > precisionPerClass[j][a] ? 1 : 0 })
precisionPerClass[j].sort((function(a, b){return b-a}))
precisionData = [
{
x: indices.map(String),
y: precisionPerClass[j],
type: 'bar',
marker: {
color: 'rgb(158,202,225)',
opacity: 0.6,
line: {
color: 'rgb(8,48,107)',
width: 1.5
}
}
}
]
Plotly.newPlot('barChartPrecision' + j, precisionData, layoutPrec)
}
for (let j = 0; j < ClassNames.length; j++) {
let len = recallPerClass[j].length
let indices = new Array(len)
for (let i = 0; i < len; ++i) indices[i] = i
indices.sort(function (a, b) { return recallPerClass[j][b] < recallPerClass[j][a] ? -1 : recallPerClass[j][b] > recallPerClass[j][a] ? 1 : 0 })
recallPerClass[j].sort((function(a, b){return b-a}))
recallData = [
{
x: indices.map(String),
y: recallPerClass[j],
type: 'bar',
marker: {
color: 'rgb(158,202,225)',
opacity: 0.6,
line: {
color: 'rgb(8,48,107)',
width: 1.5
}
}
}
]
Plotly.newPlot('barChartRecall' + j, recallData, layoutRec)
}
for (let j = 0; j < ClassNames.length; j++) {
let len = f1ScorePerClass[j].length
let indices = new Array(len)
for (let i = 0; i < len; ++i) indices[i] = i
indices.sort(function (a, b) { return f1ScorePerClass[j][b] < f1ScorePerClass[j][a] ? -1 : f1ScorePerClass[j][b] > f1ScorePerClass[j][a] ? 1 : 0 })
f1ScorePerClass[j].sort((function(a, b){return b-a}))
f1ScoreData = [
{
x: indices.map(String),
y: f1ScorePerClass[j],
type: 'bar',
marker: {
color: 'rgb(158,202,225)',
opacity: 0.6,
line: {
color: 'rgb(8,48,107)',
width: 1.5
}
}
}
]
Plotly.newPlot('barChartf1Score' + j, f1ScoreData, layoutf1Score)
}
}
},
mounted() {
EventBus.$on('emittedEventCallingBarChart', data => { this.BarChartResults = data })
EventBus.$on('emittedEventCallingBarChart', this.BarChartView)
}
}
</script>

@ -1,245 +1,58 @@
<template>
<b-container fluid class="bv-example-row">
<b-row>
<b-col cols="4">
<mdb-card style="width: 22rem;">
<mdb-card-header color="primary-color" tag="h5" class="text-center">Hyper-Parameters Panel</mdb-card-header>
<mdb-card-body>
<mdb-card-text class="text-center">
<select id="selectFile">
<option value="DiabetesC.csv">Pima Indian Diabetes</option>
<option value="BreastC.csv">Breast Cancer Winconsin</option>
<option value="IrisC.csv" selected>Iris</option>
<option value="" hidden></option>
</select>
<button
id="fileInput"
type="file"
@click="upload">
<font-awesome-icon icon="upload" />
Upload</button>
<button
id="Execute"
@click="execute">
<font-awesome-icon icon="play" />
Execute</button>
</mdb-card-text>
</mdb-card-body>
</mdb-card>
</b-col>
<b-col cols="4">
<mdb-card style="width: 80rem;">
<mdb-card-header color="primary-color" tag="h5" class="text-center">Stacking Ensemble Learning Overview</mdb-card-header>
<mdb-card-body>
<div id="OverviewPlotly" class="OverviewPlotly"></div>
</mdb-card-body>
</mdb-card>
</b-col>
</b-row>
</b-container>
<div>
<select id="selectFile" v-on:change="SelectedFileChange">
<option value="DiabetesC.csv">Pima Indian Diabetes</option>
<option value="BreastC.csv">Breast Cancer Winconsin</option>
<option value="IrisC.csv" selected>Iris</option>
<option value="" hidden></option>
</select>
<button
id="fileInput"
type="file"
@click="upload"
class="mt-2 ml-2">
<font-awesome-icon icon="upload"/>
Upload</button>
</div>
</template>
<script>
// import Papa from 'papaparse'
import axios from 'axios'
import { mdbCard, mdbCardBody, mdbCardText, mdbCardHeader } from 'mdbvue'
import * as Plotly from 'plotly.js'
export default {
name: 'LoadFile',
data () {
return {
Collection: 0,
RetrieveValueCSV: 'IrisC',
OverviewResults: 0
RetrieveValueCSV: 'IrisC'
}
},
methods: {
DataBaseRequestDataSetName (fileName) {
const path = `http://127.0.0.1:5000/data/ServerRequest`
const postData = {
fileName: fileName
}
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.post(path, postData, axiosConfig)
.then(response => {
console.log('Send request to server! Excellent!')
})
.catch(error => {
console.log(error)
})
SelectedFileChange () {
const fileName = document.getElementById('selectFile')
this.RetrieveValueCSV = fileName.options[fileName.selectedIndex].value
this.RetrieveValueCSV = this.RetrieveValueCSV.split('.')[0]
this.$emit('RetrieveValueCSVEvent', this.RetrieveValueCSV)
},
execute () {
upload () {
// const that = this
// const fileToLoad = event.target.files[0]
// const reader = new FileReader()
const fileName = document.getElementById('selectFile')
this.RetrieveValueCSV = fileName.options[fileName.selectedIndex].value
this.RetrieveValueCSV = this.RetrieveValueCSV.split('.')[0]
this.DataBaseRequestDataSetName(this.RetrieveValueCSV)
this.getCollection()
this.getOverviewResults()
/*
reader.onload = fileLoadedEvent => {
Papa.parse(fileLoadedEvent.target.result, {
header: true,
complete (results) {
console.log('complete', results)
that.doc = JSON.stringify(results.data, null, 2)
},
error (errors) {
console.log('error', errors)
}
})
Papa.parse(fileLoadedEvent.target.result, {
header: true,
complete (results) {
console.log('complete', results)
that.doc = JSON.stringify(results.data, null, 2)
},
error (errors) {
console.log('error', errors)
}
})
}
reader.readAsText(fileToLoad)
*/
},
upload () {
},
getCollection () {
this.Collection = this.getCollectionFromBackend()
},
getCollectionFromBackend () {
const path = `http://localhost:5000/data/ClientRequest`
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.get(path, axiosConfig)
.then(response => {
this.Collection = response.data.Collection
console.log(this.Collection)
})
.catch(error => {
console.log(error)
})
},
getOverviewResults () {
this.OverviewResults = this.getScatterplotDataFromBackend()
},
getScatterplotDataFromBackend () {
const path = `http://localhost:5000/data/PlotClassifiers`
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.get(path, axiosConfig)
.then(response => {
this.OverviewResults = response.data.OverviewResults
const colors = JSON.parse(this.OverviewResults[0])
const MDSData = JSON.parse(this.OverviewResults[1])
const classifiersInfo = JSON.parse(this.OverviewResults[2])
var classifiersInfoProcessing = []
let step = 0
let doubleStep = 1
for (let i = 0; i < classifiersInfo.length / 2; i++) {
step++
classifiersInfoProcessing[i] = 'ClassifierID: ' + step + '; Details: '
for (let j = 0; j < Object.values(classifiersInfo[doubleStep]).length; j++) {
classifiersInfoProcessing[i] = classifiersInfoProcessing[i] + Object.keys(classifiersInfo[doubleStep])[j] + ': ' + Object.values(classifiersInfo[doubleStep])[j]
}
doubleStep = doubleStep + 2
}
const trace = {
x: MDSData[0],
y: MDSData[1],
mode: 'markers',
text: classifiersInfoProcessing,
marker: {
color: colors,
size: 12,
colorscale: 'Viridis',
colorbar: {
title: 'Metrics Sum',
titleside: 'Top'
},
reversescale: true
}
}
const data = [trace]
const layout = {
title: 'Classifiers Performance MDS',
xaxis: {
visible: false
},
yaxis: {
visible: false
}
}
Plotly.newPlot('OverviewPlotly', data, layout)
this.selectedPointsOverview()
})
.catch(error => {
console.log(error)
})
},
selectedPointsOverview () {
const OverviewPlotly = document.getElementById('OverviewPlotly')
OverviewPlotly.on('plotly_selected', function (evt) {
const ClassifierIDsList = []
for (let i = 0; evt.points.length; i++) {
if (evt.points[i] === undefined) {
break
} else {
const OnlyId = evt.points[i].text.split(';')
ClassifierIDsList.push(OnlyId[0])
}
}
const path = `http://127.0.0.1:5000/data/ServerRequestSelPoin`
const postData = {
ClassifiersList: ClassifierIDsList
}
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.post(path, postData, axiosConfig)
.then(response => {
console.log('Send request to server! Excellent!')
})
.catch(error => {
console.log(error)
})
})
}
},
components: {
mdbCard,
mdbCardBody,
mdbCardHeader,
mdbCardText
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

@ -1,32 +1,209 @@
<!-- Main Visualization View -->
<template>
<div>
<LoadFile
/>
</div>
<b-container fluid class="bv-example-row">
<b-row class="md-3">
<b-col cols="3">
<mdb-card>
<mdb-card-header color="primary-color" tag="h5" class="text-center">Data Set Selection</mdb-card-header>
<mdb-card-body>
<mdb-card-text class="text-center" >
<LoadFile
v-on:RetrieveValueCSVEvent="updateCSVName($event)"
/>
</mdb-card-text>
</mdb-card-body>
</mdb-card>
</b-col>
<b-col cols="4">
<mdb-card>
<mdb-card-header color="primary-color" tag="h5" class="text-center">Base Classifiers Overview</mdb-card-header>
<mdb-card-body>
<ScatterPlot/>
</mdb-card-body>
</mdb-card>
</b-col>
<b-col cols="5">
<mdb-card>
<mdb-card-header color="primary-color" tag="h5" class="text-center">Classifiers, Features, and Classes Chord Visualization</mdb-card-header>
<mdb-card-body>
<StretchedChord/>
</mdb-card-body>
</mdb-card>
</b-col>
</b-row>
<b-row class="mb-3 mt-3">
<b-col cols="3">
<mdb-card >
<mdb-card-header color="primary-color" tag="h5" class="text-center">Hyper-Parameters Setting</mdb-card-header>
<mdb-card-body>
<mdb-card-text class="text-center">
<ParametersSetting
v-on:InitializeEnsembleLearningEvent="DataBaseRequestDataSetName()"
/>
</mdb-card-text>
</mdb-card-body>
</mdb-card>
</b-col>
<b-col cols="6">
<mdb-card>
<mdb-card-header color="primary-color" tag="h5" class="text-center">Per Class Metrics Exploration</mdb-card-header>
<mdb-card-body>
<BarChart/>
</mdb-card-body>
</mdb-card>
</b-col>
</b-row>
<b-row>
<b-col cols="3">
<mdb-card>
<mdb-card-header color="primary-color" tag="h5" class="text-center">Visual Mapping</mdb-card-header>
<mdb-card-body>
<mdb-card-text class="text-center">
<Tuning/>
</mdb-card-text>
</mdb-card-body>
</mdb-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
import Vue from 'vue'
import LoadFile from './LoadFile.vue'
import ParametersSetting from './ParametersSetting.vue'
import ScatterPlot from './ScatterPlot.vue'
import BarChart from './BarChart.vue'
import StretchedChord from './StretchedChord.vue'
import Tuning from './Tuning.vue'
import axios from 'axios'
import { mdbCard, mdbCardBody, mdbCardText, mdbCardHeader } from 'mdbvue'
import { EventBus } from '../main.js'
export default Vue.extend({
name: 'Main',
components: {
LoadFile
LoadFile,
ParametersSetting,
ScatterPlot,
BarChart,
StretchedChord,
Tuning,
mdbCard,
mdbCardBody,
mdbCardHeader,
mdbCardText
},
data: function () {
data () {
return {
nothing: 0
Collection: 0,
OverviewResults: 0,
RetrieveValueFile: 'IrisC',
ClassifierIDsList: ''
}
},
methods: {
updateCSVName (retrieving) {
this.RetrieveValueFile = retrieving
},
DataBaseRequestDataSetName () {
const path = `http://127.0.0.1:5000/data/ServerRequest`
const postData = {
fileName: this.RetrieveValueFile
}
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.post(path, postData, axiosConfig)
.then(response => {
console.log('Send request to server! FileName was sent successfully!')
})
.catch(error => {
console.log(error)
})
this.getCollection()
this.getOverviewResults()
},
getCollection () {
this.Collection = this.getCollectionFromBackend()
},
getCollectionFromBackend () {
const path = `http://localhost:5000/data/ClientRequest`
},
props: [],
computed: {
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.get(path, axiosConfig)
.then(response => {
this.Collection = response.data.Collection
console.log('Collection was overwritten with new data sent by the server!')
})
.catch(error => {
console.log(error)
})
},
getOverviewResults () {
this.OverviewResults = this.getScatterplotDataFromBackend()
},
getScatterplotDataFromBackend () {
const path = `http://localhost:5000/data/PlotClassifiers`
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.get(path, axiosConfig)
.then(response => {
this.OverviewResults = response.data.OverviewResults
console.log('Server successfully sent all the data related to visualizations!')
EventBus.$emit('emittedEventCallingScatterPlot', this.OverviewResults)
EventBus.$emit('emittedEventCallingBarChart', this.OverviewResults)
EventBus.$emit('emittedEventCallingChordView', this.OverviewResults)
})
.catch(error => {
console.log(error)
})
},
SendSelectedPointsToServer () {
const path = `http://127.0.0.1:5000/data/ServerRequestSelPoin`
const postData = {
ClassifiersList: this.ClassifierIDsList
}
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, OPTIONS'
}
}
axios.post(path, postData, axiosConfig)
.then(response => {
console.log('Sent the selected points to the server (scatterplot)!')
})
.catch(error => {
console.log(error)
})
}
},
mounted() {
EventBus.$on('SendSelectedPointsToServerEvent', data => { this.ClassifierIDsList = data })
EventBus.$on('SendSelectedPointsToServerEvent', this.SendSelectedPointsToServer)
}
})
</script>

@ -0,0 +1,24 @@
<template>
<button
id="Execute"
v-on:click="execute">
<font-awesome-icon icon="play" />
Execute</button>
</template>
<script>
export default {
name: 'ParametersSetting',
data () {
return {
InitializeEnsemble: false,
};
},
methods: {
execute () {
this.InitializeEnsemble = true
this.$emit('InitializeEnsembleLearningEvent')
}
}
}
</script>

@ -0,0 +1,88 @@
<template>
<div id="OverviewPlotly" class="OverviewPlotly"></div>
</template>
<script>
import * as Plotly from 'plotly.js'
import { EventBus } from '../main.js'
export default {
name: 'ScatterPlot',
data () {
return {
ScatterPlotResults: ''
}
},
methods: {
ScatterPlotView () {
const colorsforScatterPlot = JSON.parse(this.ScatterPlotResults[0])
const MDSData = JSON.parse(this.ScatterPlotResults[1])
const classifiersInfo = JSON.parse(this.ScatterPlotResults[2])
var classifiersInfoProcessing = []
let step = 0
let doubleStep = 1
for (let i = 0; i < classifiersInfo.length / 2; i++) {
classifiersInfoProcessing[i] = 'ClassifierID: ' + step + '; Details: '
step++
for (let j = 0; j < Object.values(classifiersInfo[doubleStep]).length; j++) {
classifiersInfoProcessing[i] = classifiersInfoProcessing[i] + Object.keys(classifiersInfo[doubleStep])[j] + ': ' + Object.values(classifiersInfo[doubleStep])[j]
}
doubleStep = doubleStep + 2
}
const DataforMDS = [{
x: MDSData[0],
y: MDSData[1],
mode: 'markers',
text: classifiersInfoProcessing,
marker: {
color: colorsforScatterPlot,
size: 12,
colorscale: 'Viridis',
colorbar: {
title: 'Metrics Sum',
titleside: 'Top'
},
reversescale: true
}
}]
const layout = {
title: 'Classifiers Performance MDS',
xaxis: {
visible: false
},
yaxis: {
visible: false
}
}
Plotly.newPlot('OverviewPlotly', DataforMDS, layout)
this.selectedPointsOverview()
},
selectedPointsOverview () {
const OverviewPlotly = document.getElementById('OverviewPlotly')
OverviewPlotly.on('plotly_selected', function (evt) {
const ClassifierIDsList = []
for (let i = 0; evt.points.length; i++) {
if (evt.points[i] === undefined) {
break
} else {
const OnlyId = evt.points[i].text.split(';')
ClassifierIDsList.push(OnlyId[0])
}
}
if (ClassifierIDsList != '') {
EventBus.$emit('SendSelectedPointsToServerEvent', ClassifierIDsList)
}
})
}
},
mounted() {
EventBus.$on('emittedEventCallingScatterPlot', data => {
this.ScatterPlotResults = data})
EventBus.$on('emittedEventCallingScatterPlot', this.ScatterPlotView)
}
}
</script>

@ -0,0 +1,582 @@
<template>
<div id="chart"></div>
</template>
<script>
import * as d3Base from 'd3'
import { loom, string } from 'd3-loom'
import { EventBus } from '../main.js'
// attach all d3 plugins to the d3 library
const d3 = Object.assign(d3Base, { loom, string })
export default {
name: "StretchedChord",
data () {
return {
AllResults: '',
}
},
methods: {
StretchChord () {
const FeatureImportance = JSON.parse(this.AllResults[3])
const ClassNames = JSON.parse(this.AllResults[5])
var SortFeaturesPerClass = []
FeatureImportance.forEach(classifier => {
for (let i = 0; i < length; i++) {
SortFeaturesPerClass.push(this.sortObject(classifier[i]))
}
})
var margin = {left:80, top:40, right:120, bottom:50},
width = Math.max( Math.min(window.innerWidth, 1100) - margin.left - margin.right - 20, 400),
height = Math.max( Math.min(window.innerHeight - 250, 900) - margin.top - margin.bottom - 20, 400),
innerRadius = Math.min(width * 0.33, height * .45),
outerRadius = innerRadius * 1.05;
//Recalculate the width and height now that we know the radius
width = outerRadius * 2 + margin.right + margin.left;
height = outerRadius * 2 + margin.top + margin.bottom;
//Reset the overall font size
var newFontSize = Math.min(70, Math.max(40, innerRadius * 62.5 / 250));
d3.select("html").style("font-size", newFontSize + "%");
////////////////////////////////////////////////////////////
////////////////// Set-up Chord parameters /////////////////
////////////////////////////////////////////////////////////
var pullOutSize = 20 + 30/135 * innerRadius;
var numFormat = d3.format(",.0f");
var defaultOpacity = 0.85,
fadeOpacity = 0.075;
var loom = d3.loom()
.padAngle(0.05)
//.sortSubgroups(sortAlpha)
//.heightInner(28)
.emptyPerc(0.2)
.widthInner(30)
//.widthInner(function(d) { return 6 * d.length; })
.value(function(d) { return d.words; })
.inner(function(d) { return d.character; })
.outer(function(d) { return d.location; });
var arc = d3.arc()
.innerRadius(innerRadius*1.01)
.outerRadius(outerRadius);
var string = d3.string()
.radius(innerRadius)
.pullout(pullOutSize);
var characterNotes = [];
characterNotes["Iris Setosa"] = "Speaking almost twice as many words as the second most abundant speaker, Gandalf is taking up a large portion of dialogue in almost every location he's in, but stays rather quiet in Mordor";
characterNotes["Iris Versicolour"] = "An unexpected runner up to having spoken the most words, Sam flourishes after the battle at Amon Hen, taking up a considerable portion of the words said in both Mordor and Gondor";
characterNotes["Iris Virginica"] = "Although eventually being crowned in Minas Tirith, Gondor, Aragorn is by far most talkative in that other human region, Rohan, fighting a battle at Helm's Deep and convincing an army of dead";
////////////////////////////////////////////////////////////
////////////////////// Create SVG //////////////////////////
////////////////////////////////////////////////////////////
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
////////////////////////////////////////////////////////////
///////////////////// Read in data /////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
///////////////////// Prepare the data /////////////////////
////////////////////////////////////////////////////////////
//Sort the inner characters based on the total number of words spoken
var dataAgg = [
{
"location": "Classifier 1",
"character": "Iris Setosa",
"words": 94
},
{
"location": "Classifier 1",
"character": "Iris Versicolour",
"words": 100
},
{
"location": "Classifier 1",
"character": "Iris Virginica",
"words": 100
},
{
"location": "Feature 1",
"character": "Iris Virginica",
"words": 40
},
{
"location": "Feature 2",
"character": "Iris Virginica",
"words": 60
},
]
//Find the total number of words per character
var dataChar = d3.nest()
.key(function(d) { return d.character; })
.rollup(function(leaves) { return d3.sum(leaves, function(d) { return d.words; }); })
.entries(dataAgg)
.sort(function(a, b){ return d3.descending(a.value, b.value); });
//Unflatten the result
var characterOrder = dataChar.map(function(d) { return d.key })
//Sort the characters on a specific order
function sortCharacter(a, b) {
return characterOrder.indexOf(a) - characterOrder.indexOf(b)
}//sortCharacter
//Set more loom functions
loom
.sortSubgroups(sortCharacter)
.heightInner(innerRadius*0.75/characterOrder.length)
////////////////////////////////////////////////////////////
///////////////////////// Colors ///////////////////////////
////////////////////////////////////////////////////////////
var locations = ["Iris Setosa", "Iris Versicolour", "Iris Virginica"]
var colors = ["#5a3511", "#47635f", "#223e15"]
var color = d3.scaleOrdinal()
.domain(locations)
.range(colors)
//Create a group that already holds the data
var g = svg.append("g")
.attr("transform", "translate(" + (width/2 + margin.left) + "," + (height/2 + margin.top) + ")")
.datum(loom(dataAgg))
////////////////////////////////////////////////////////////
///////////////////// Set-up title /////////////////////////
////////////////////////////////////////////////////////////
var titles = g.append("g")
.attr("class", "texts")
.style("opacity", 0)
titles.append("text")
.attr("class", "name-title")
.attr("x", 0)
.attr("y", -innerRadius*5/6)
titles.append("text")
.attr("class", "value-title")
.attr("x", 0)
.attr("y", -innerRadius*5/6 + 25)
//The character pieces
titles.append("text")
.attr("class", "character-note")
.attr("x", 0)
.attr("y", innerRadius/2)
.attr("dy", "0.35em")
////////////////////////////////////////////////////////////
////////////////////// Draw outer arcs /////////////////////
////////////////////////////////////////////////////////////
var arcs = g.append("g")
.attr("class", "arcs")
.selectAll("g")
.data(function(s) {
return s.groups
})
.enter().append("g")
.attr("class", "arc-wrapper")
.each(function(d) {
d.pullOutSize = (pullOutSize * ( d.startAngle > Math.PI + 1e-2 ? -1 : 1))
})
.on("mouseover", function(d) {
//Hide all other arcs
d3.selectAll(".arc-wrapper")
.transition()
.style("opacity", function(s) { return s.outername === d.outername ? 1 : 0.5 })
//Hide all other strings
d3.selectAll(".string")
.transition()
.style("opacity", function(s) { return s.outer.outername === d.outername ? 1 : fadeOpacity })
//Find the data for the strings of the hovered over location
var locationData = loom(dataAgg).filter(function(s) { return s.outer.outername === d.outername })
//Hide the characters who haven't said a word
d3.selectAll(".inner-label")
.transition()
.style("opacity", function(s) {
//Find out how many words the character said at the hovered over location
var char = locationData.filter(function(c) { return c.outer.innername === s.name })
return char.length === 0 ? 0.1 : 1
})
})
.on("mouseout", function(d) {
//Sjow all arc labels
d3.selectAll(".arc-wrapper")
.transition()
.style("opacity", 1)
//Show all strings again
d3.selectAll(".string")
.transition()
.style("opacity", defaultOpacity)
//Show all characters again
d3.selectAll(".inner-label")
.transition()
.style("opacity", 1)
})
var outerArcs = arcs.append("path")
.attr("class", "arc")
.style("fill", function(d) { return color(d.innername) })
.attr("d", arc)
.attr("transform", function(d, i) { //Pull the two slices apart
return "translate(" + d.pullOutSize + ',' + 0 + ")"
})
////////////////////////////////////////////////////////////
//////////////////// Draw outer labels /////////////////////
////////////////////////////////////////////////////////////
//The text needs to be rotated with the offset in the clockwise direction
var outerLabels = arcs.append("g")
.each(function(d) { d.angle = ((d.startAngle + d.endAngle) / 2) })
.attr("class", "outer-labels")
.attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null })
.attr("transform", function(d,i) {
var c = arc.centroid(d)
return "translate(" + (c[0] + d.pullOutSize) + "," + c[1] + ")"
+ "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + 26 + ",0)"
+ (d.angle > Math.PI ? "rotate(180)" : "")
})
//The outer name
outerLabels.append("text")
.attr("class", "outer-label")
.attr("dy", ".35em")
.text(function(d,i){ return d.outername })
//The value below it
outerLabels.append("text")
.attr("class", "outer-label-value")
.attr("dy", "1.5em")
.text(function(d,i){ return numFormat(d.value) + " words" })
////////////////////////////////////////////////////////////
////////////////// Draw inner strings //////////////////////
////////////////////////////////////////////////////////////
var strings = g.append("g")
.attr("class", "stringWrapper")
.style("isolation", "isolate")
.selectAll("path")
.data(function(strings) {
return strings
})
.enter().append("path")
.attr("class", "string")
.style("mix-blend-mode", "multiply")
.attr("d", string)
.style("fill", function(d) { return d3.rgb( color(d.outer.innername) ).brighter(0.2) })
.style("opacity", defaultOpacity)
////////////////////////////////////////////////////////////
//////////////////// Draw inner labels /////////////////////
////////////////////////////////////////////////////////////
//The text also needs to be displaced in the horizontal directions
//And also rotated with the offset in the clockwise direction
var innerLabels = g.append("g")
.attr("class","inner-labels")
.selectAll("text")
.data(function(s) {
return s.innergroups
})
.enter().append("text")
.attr("class", "inner-label")
.attr("x", function(d,i) { return d.x })
.attr("y", function(d,i) { return d.y })
.style("text-anchor", "middle")
.attr("dy", ".35em")
.text(function(d,i) { return d.name })
.on("mouseover", function(d) {
//Show all the strings of the highlighted character and hide all else
d3.selectAll(".string")
.transition()
.style("opacity", function(s) {
return s.outer.innername !== d.name ? fadeOpacity : 1
})
//Update the word count of the outer labels
var characterData = loom(dataAgg).filter(function(s) { return s.outer.innername === d.name })
d3.selectAll(".outer-label-value")
.text(function(s,i){
//Find which characterData is the correct one based on location
var loc = characterData.filter(function(c) { return c.outer.outername === s.outername })
if(loc.length === 0) {
var value = 0
} else {
var value = loc[0].outer.value
}
return numFormat(value) + (value === 1 ? " word" : " words")
})
//Hide the arc where the character hasn't said a thing
d3.selectAll(".arc-wrapper")
.transition()
.style("opacity", function(s) {
//Find which characterData is the correct one based on location
var loc = characterData.filter(function(c) { return c.outer.outername === s.outername })
return loc.length === 0 ? 0.1 : 1
})
//Update the title to show the total word count of the character
d3.selectAll(".texts")
.transition()
.style("opacity", 1)
d3.select(".name-title")
.text(d.name)
d3.select(".value-title")
.text(function() {
var words = dataChar.filter(function(s) { return s.key === d.name })
return numFormat(words[0].value)
})
//Show the character note
d3.selectAll(".character-note")
.text(characterNotes[d.name])
.call(wrap, 2.25*pullOutSize)
})
.on("mouseout", function(d) {
//Put the string opacity back to normal
d3.selectAll(".string")
.transition()
.style("opacity", defaultOpacity)
//Return the word count to what it was
d3.selectAll(".outer-label-value")
.text(function(s,i){ return numFormat(s.value) + " words" })
//Show all arcs again
d3.selectAll(".arc-wrapper")
.transition()
.style("opacity", 1)
//Hide the title
d3.selectAll(".texts")
.transition()
.style("opacity", 0)
})
////////////////////////////////////////////////////////////
///////////////////// Extra functions //////////////////////
////////////////////////////////////////////////////////////
//Sort alphabetically
function sortAlpha(a, b){
if(a < b) return -1
if(a > b) return 1
return 0
}//sortAlpha
//Sort on the number of words
function sortWords(a, b){
if(a.words < b.words) return -1
if(a.words > b.words) return 1
return 0
}//sortWords
/*Taken from http://bl.ocks.org/mbostock/7555321
//Wraps SVG text*/
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.2, // ems
y = parseFloat(text.attr("y")),
x = parseFloat(text.attr("x")),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em")
while (word = words.pop()) {
line.push(word)
tspan.text(line.join(" "))
if (tspan.node().getComputedTextLength() > width) {
line.pop()
tspan.text(line.join(" "))
line = [word]
tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word)
}
}
})
}//wrap
},
sortObject (obj) {
var arr = []
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
if ((this.LimitFeatureImportance/100) < Math.abs(obj[prop])) {
arr.push({
'FeatureID': prop,
'ImportanceValue': obj[prop]
})
}
}
}
arr = arr.sort(function (a, b) { return Math.abs(b.ImportanceValue) - Math.abs(a.ImportanceValue) })
return arr
},
ObjectSize (obj) {
let size = 0
let key
for (key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) size++
}
return size
}
},
mounted () {
EventBus.$on('emittedEventCallingChordView', data => { this.AllResults = data })
EventBus.$on('emittedEventCallingChordView', this.StretchChord)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
html { font-size: 62.5%; }
body {
font-family: 'Cormorant', serif;
font-size: 1.2rem;
fill: #b9b9b9;
}
.lotr-content-wrapper {
max-width: 900px;
margin: 0 auto;
}
#lotr-title {
font-size: 42px;
font-weight: 300;
margin: 40px 30px 0px 30px;
color: #272727;
}
#lotr-subtitle {
font-size: 14px;
color: #b1b1b1;
margin: 0px 30px 20px 30px;
font-weight: 300;
}
#lotr-intro {
font-size: 16px;
margin: 0px 30px 10px 30px;
max-width: 800px;
}
#lotr-note {
font-size: 14px;
margin: 0px 30px 10px 30px;
max-width: 800px;
color: #b1b1b1;
font-weight: 300;
}
#chart {
text-align: center;
}
#lotr-credit {
font-size: 14px;
margin: 10px 30px 5px 30px;
}
#lotr-sources {
font-size: 11px;
max-width: 300px;
margin: 15px 30px 5px 30px;
color: #9e9e9e;
font-weight: 300;
padding-bottom: 20px;
}
a:hover {
text-decoration: none;
border-bottom: 1px solid black;
}
a, a:link, a:visited, a:active {
text-decoration: none;
color: black;
border-bottom: 1px dotted rgba(0, 0, 0, .5);
}
.MiddleEarth {
font-family: 'Macondo', cursive;
color: #53821a;
}
/*--- chart ---*/
.name-title {
font-family: 'Macondo Swash Caps', cursive;
font-size: 2.8rem;
fill: #232323;
cursor: default;
text-anchor: middle;
}
.value-title {
text-anchor: middle;
font-size: 1.8rem;
fill: #b9b9b9;
}
.character-note {
text-anchor: middle;
font-size: 1.4rem;
fill: #232323;
}
.inner-label {
font-family: 'Macondo Swash Caps', cursive;
font-size: 1.4rem;
fill: #232323;
cursor: default;
}
.outer-label {
font-family: 'Macondo', cursive;
font-size: 1.6rem;
fill: #5f5f5f;
cursor: default;
}
.outer-label-value {
font-size: 1.2rem;
fill: #b9b9b9;
}
</style>

@ -0,0 +1,67 @@
<template>
<div>
<div>Limiting Feature Importance<vue-slider v-model="LimitFeatureImportance"></vue-slider></div>
<div>{{ LimitFeatureImportance }}</div>
</div>
</template>
<script>
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
export default {
name: 'Tuning',
components: {
VueSlider
},
data () {
return {
LimitFeatureImportance: 10
}
},
mounted () {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.slidecontainer {
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 15px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
</style>

@ -16,6 +16,8 @@ Vue.use(BootstrapVue)
Vue.config.productionTip = false
export const EventBus = new Vue()
/* eslint-disable no-new */
new Vue({
el: '#app',

@ -0,0 +1,10 @@
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].chunksSortMode = 'none'
return args
})
}
}

101
run.py

@ -5,6 +5,7 @@ from flask_cors import CORS, cross_origin
import json
import collections
import numpy as np
from numpy import array
import pandas as pd
import warnings
import copy
@ -18,6 +19,8 @@ from mlxtend.classifier import StackingCVClassifier
from sklearn import model_selection
from sklearn.model_selection import GridSearchCV
from sklearn.manifold import MDS
from sklearn.metrics import classification_report
from sklearn.preprocessing import scale
# This block of code is for the connection between the server, the database, and the client (plus routing).
@ -81,7 +84,7 @@ def catch_all(path):
global mem
mem = Memory("./cache_dir")
def GridSearch(clf, params, scoring, FI):
def GridSearch(clf, params, scoring, FI, target_names):
grid = GridSearchCV(estimator=clf,
param_grid=params,
@ -89,9 +92,11 @@ def GridSearch(clf, params, scoring, FI):
cv=5,
refit='accuracy',
n_jobs = -1)
global subset
subset = XData
grid.fit(subset, yData)
grid.fit(XData, yData)
cv_results = []
cv_results.append(grid.cv_results_)
df_cv_results = pd.DataFrame.from_dict(cv_results)
@ -109,26 +114,48 @@ def GridSearch(clf, params, scoring, FI):
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
parameters = df_cv_results_classifiers['params']
PerClassMetrics = []
FeatureImp = []
if (FI == 1):
for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items():
Listvalue = []
Listvalue.append(value)
eachClassifierParamsDictList[key] = Listvalue
grid = GridSearchCV(estimator=clf,
param_grid=eachClassifierParamsDictList,
scoring=scoring,
cv=5,
refit='accuracy',
n_jobs = -1)
grid.fit(XData, yData)
FeatureImp.append(grid.best_estimator_.feature_importances_)
return df_cv_results_classifiers, parameters, FeatureImp
GridSearch = mem.cache(GridSearch)
for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items():
Listvalue = []
Listvalue.append(value)
eachClassifierParamsDictList[key] = Listvalue
grid = GridSearchCV(estimator=clf,
param_grid=eachClassifierParamsDictList,
scoring=scoring,
cv=5,
refit='accuracy',
n_jobs = -1)
grid.fit(subset, yData)
yPredict = grid.predict(subset)
PerClassMetrics.append(classification_report(yData, yPredict, target_names=target_names, digits=2, output_dict=True))
if (FI == 1):
X = subset.values
Y = array(yData)
FeatureImp.append(class_feature_importance(X, Y, grid.best_estimator_.feature_importances_))
FeatureImpPandas = pd.DataFrame(FeatureImp)
PerClassMetricsPandas = pd.DataFrame(PerClassMetrics)
return df_cv_results_classifiers, parameters, FeatureImpPandas, PerClassMetricsPandas
def class_feature_importance(X, Y, feature_importances):
N, M = X.shape
X = scale(X)
out = {}
for c in set(Y):
out[c] = dict(
zip(range(N), np.mean(X[Y==c, :], axis=0)*feature_importances)
)
return out
#GridSearch = mem.cache(GridSearch)
def InitializeEnsemble():
DataResults = copy.deepcopy(DataResultsRaw)
@ -149,15 +176,19 @@ def InitializeEnsemble():
AllTargets = [o[target] for o in DataResultsRaw]
AllTargetsFloatValues = []
previous = None
Class = 0
target_names = []
for i, value in enumerate(AllTargets):
if (i == 0):
previous = value
target_names.append(value)
if (value == previous):
AllTargetsFloatValues.append(Class)
else:
Class = Class + 1
target_names.append(value)
AllTargetsFloatValues.append(Class)
previous = value
@ -186,28 +217,29 @@ def InitializeEnsemble():
# 'weights': ['uniform', 'distance'],
# 'metric': ['euclidean', 'manhattan']}
results.append(GridSearch(clf, params, scoring, IF))
results.append(GridSearch(clf, params, scoring, IF, target_names))
clf = RandomForestClassifier()
params = {'n_estimators': [10, 50]}
IF = 1
results.append(GridSearch(clf, params, scoring, IF))
results.append(GridSearch(clf, params, scoring, IF, target_names))
df_cv_results_classifiers = pd.concat([results[0][0], results[1][0]], ignore_index=True, sort=False)
parameters = pd.concat([results[0][1], results[1][1]], ignore_index=True, sort=False)
FeatureImportance = pd.concat([results[0][2], results[1][2]], ignore_index=True, sort=False)
PerClassMetrics = pd.concat([results[0][3], results[1][3]], ignore_index=True, sort=False)
classifiersIDPlusParams = []
classifierID = 0
for oneClassifier in parameters:
classifierID = classifierID + 1
classifiersIDPlusParams.append(classifierID)
classifiersIDPlusParams.append(oneClassifier)
classifierID = classifierID + 1
del df_cv_results_classifiers['params']
df_cv_results_classifiers_metrics = df_cv_results_classifiers.copy()
df_cv_results_classifiers_metrics = df_cv_results_classifiers_metrics.ix[:, 0:NumberofscoringMetrics+1]
del df_cv_results_classifiers_metrics['mean_fit_time']
del df_cv_results_classifiers_metrics['mean_score_time']
@ -229,9 +261,14 @@ def InitializeEnsemble():
global ResultsforOverview
ResultsforOverview = []
FeatureImportance = FeatureImportance.to_json(orient='records')
PerClassMetrics = PerClassMetrics.to_json(orient='records')
ResultsforOverview.append(json.dumps(sumPerClassifier))
ResultsforOverview.append(json.dumps(X_transformed))
ResultsforOverview.append(json.dumps(classifiersIDPlusParams))
ResultsforOverview.append(FeatureImportance)
ResultsforOverview.append(PerClassMetrics)
ResultsforOverview.append(json.dumps(target_names))
return ResultsforOverview
@ -263,7 +300,7 @@ def EnsembleModel (ClassifierIDsList, keyRetrieved):
for clf, label in zip([sclf],
['StackingClassifierAllClassifiers']):
scores = model_selection.cross_val_score(clf, XData, yData,
scores = model_selection.cross_val_score(clf, subset, yData,
cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]"
% (scores.mean(), scores.std(), label))
@ -272,13 +309,13 @@ def EnsembleModel (ClassifierIDsList, keyRetrieved):
ClassifierIDsList = ClassifierIDsList.split('"')
for loop in ClassifierIDsList:
if ('ClassifierID' in loop):
if (loop == 'ClassifierID: 1'):
if (loop == 'ClassifierID: 0'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=1))
elif (loop == 'ClassifierID: 2'):
elif (loop == 'ClassifierID: 1'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=2))
elif (loop == 'ClassifierID: 3'):
elif (loop == 'ClassifierID: 2'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=10))
elif (loop == 'ClassifierID: 4'):
elif (loop == 'ClassifierID: 3'):
all_classifiers.append(RandomForestClassifier(random_state=RANDOM_SEED, n_estimators = 1))
else:
all_classifiers.append(RandomForestClassifier(random_state=RANDOM_SEED, n_estimators = 50))
@ -293,7 +330,7 @@ def EnsembleModel (ClassifierIDsList, keyRetrieved):
for clf, label in zip([sclf],
['StackingClassifierSelectedClassifiers']):
scores = model_selection.cross_val_score(clf, XData, yData,
scores = model_selection.cross_val_score(clf, subset, yData,
cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]"
% (scores.mean(), scores.std(), label))

Loading…
Cancel
Save