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. 8
      cache_dir/joblib/run/GridSearch/func_code.py
  7. 1728
      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. 213
      frontend/src/components/LoadFile.vue
  13. 191
      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. 71
      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): def GridSearch(clf, params, scoring, FI):
grid = GridSearchCV(estimator=clf, grid = GridSearchCV(estimator=clf,
@ -28,7 +28,7 @@ def GridSearch(clf, params, scoring, FI):
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns) df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
parameters = df_cv_results_classifiers['params'] parameters = df_cv_results_classifiers['params']
FeatureImp = [] FeatureImp = []
if (FI == 1): target_names = ['class 0', 'class 1', 'class 2']
for eachClassifierParams in grid.cv_results_['params']: for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {} eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items(): for key, value in eachClassifierParams.items():
@ -41,7 +41,11 @@ def GridSearch(clf, params, scoring, FI):
cv=5, cv=5,
refit='accuracy', refit='accuracy',
n_jobs = -1) n_jobs = -1)
print(eachClassifierParamsDictList)
grid.fit(XData, yData) 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_) FeatureImp.append(grid.best_estimator_.feature_importances_)
return df_cv_results_classifiers, parameters, FeatureImp return df_cv_results_classifiers, parameters, FeatureImp

File diff suppressed because it is too large Load Diff

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

@ -14,8 +14,8 @@ export default {
<style> <style>
#app { #app {
font-family: 'Avenir', Helvetica, Arial, sans-serif; font-family: 'sans-serif';
font-size: 16px; font-size: 18px;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: #2c3e50; 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,12 +1,6 @@
<template> <template>
<b-container fluid class="bv-example-row"> <div>
<b-row> <select id="selectFile" v-on:change="SelectedFileChange">
<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="DiabetesC.csv">Pima Indian Diabetes</option>
<option value="BreastC.csv">Breast Cancer Winconsin</option> <option value="BreastC.csv">Breast Cancer Winconsin</option>
<option value="IrisC.csv" selected>Iris</option> <option value="IrisC.csv" selected>Iris</option>
@ -15,77 +9,34 @@
<button <button
id="fileInput" id="fileInput"
type="file" type="file"
@click="upload"> @click="upload"
class="mt-2 ml-2">
<font-awesome-icon icon="upload"/> <font-awesome-icon icon="upload"/>
Upload</button> Upload</button>
<button </div>
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>
</template> </template>
<script> <script>
// import Papa from 'papaparse' // import Papa from 'papaparse'
import axios from 'axios'
import { mdbCard, mdbCardBody, mdbCardText, mdbCardHeader } from 'mdbvue'
import * as Plotly from 'plotly.js'
export default { export default {
name: 'LoadFile',
data () { data () {
return { return {
Collection: 0, RetrieveValueCSV: 'IrisC'
RetrieveValueCSV: 'IrisC',
OverviewResults: 0
} }
}, },
methods: { methods: {
DataBaseRequestDataSetName (fileName) { SelectedFileChange () {
const path = `http://127.0.0.1:5000/data/ServerRequest` const fileName = document.getElementById('selectFile')
const postData = { this.RetrieveValueCSV = fileName.options[fileName.selectedIndex].value
fileName: fileName this.RetrieveValueCSV = this.RetrieveValueCSV.split('.')[0]
} this.$emit('RetrieveValueCSVEvent', this.RetrieveValueCSV)
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)
})
}, },
execute () { upload () {
// const that = this // const that = this
// const fileToLoad = event.target.files[0] // const fileToLoad = event.target.files[0]
// const reader = new FileReader() // 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 => { reader.onload = fileLoadedEvent => {
Papa.parse(fileLoadedEvent.target.result, { Papa.parse(fileLoadedEvent.target.result, {
@ -101,145 +52,7 @@ export default {
} }
reader.readAsText(fileToLoad) 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> </script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

@ -1,32 +1,209 @@
<!-- Main Visualization View --> <!-- Main Visualization View -->
<template> <template>
<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 <LoadFile
v-on:RetrieveValueCSVEvent="updateCSVName($event)"
/> />
</div> </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> </template>
<script> <script>
import Vue from 'vue' import Vue from 'vue'
import LoadFile from './LoadFile.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({ export default Vue.extend({
name: 'Main', name: 'Main',
components: { components: {
LoadFile LoadFile,
ParametersSetting,
ScatterPlot,
BarChart,
StretchedChord,
Tuning,
mdbCard,
mdbCardBody,
mdbCardHeader,
mdbCardText
}, },
data: function () { data () {
return { return {
nothing: 0 Collection: 0,
OverviewResults: 0,
RetrieveValueFile: 'IrisC',
ClassifierIDsList: ''
} }
}, },
methods: { 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`
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)
})
}, },
props: [], getOverviewResults () {
computed: { 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> </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 Vue.config.productionTip = false
export const EventBus = new Vue()
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
el: '#app', el: '#app',

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

@ -5,6 +5,7 @@ from flask_cors import CORS, cross_origin
import json import json
import collections import collections
import numpy as np import numpy as np
from numpy import array
import pandas as pd import pandas as pd
import warnings import warnings
import copy import copy
@ -18,6 +19,8 @@ from mlxtend.classifier import StackingCVClassifier
from sklearn import model_selection from sklearn import model_selection
from sklearn.model_selection import GridSearchCV from sklearn.model_selection import GridSearchCV
from sklearn.manifold import MDS 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). # 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 global mem
mem = Memory("./cache_dir") mem = Memory("./cache_dir")
def GridSearch(clf, params, scoring, FI): def GridSearch(clf, params, scoring, FI, target_names):
grid = GridSearchCV(estimator=clf, grid = GridSearchCV(estimator=clf,
param_grid=params, param_grid=params,
@ -89,8 +92,10 @@ def GridSearch(clf, params, scoring, FI):
cv=5, cv=5,
refit='accuracy', refit='accuracy',
n_jobs = -1) n_jobs = -1)
global subset
subset = XData
grid.fit(XData, yData) grid.fit(subset, yData)
cv_results = [] cv_results = []
cv_results.append(grid.cv_results_) cv_results.append(grid.cv_results_)
@ -109,8 +114,8 @@ def GridSearch(clf, params, scoring, FI):
df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns) df_cv_results_classifiers = pd.DataFrame(data = df_cv_results_per_row, columns= df_cv_results.columns)
parameters = df_cv_results_classifiers['params'] parameters = df_cv_results_classifiers['params']
PerClassMetrics = []
FeatureImp = [] FeatureImp = []
if (FI == 1):
for eachClassifierParams in grid.cv_results_['params']: for eachClassifierParams in grid.cv_results_['params']:
eachClassifierParamsDictList = {} eachClassifierParamsDictList = {}
for key, value in eachClassifierParams.items(): for key, value in eachClassifierParams.items():
@ -123,12 +128,34 @@ def GridSearch(clf, params, scoring, FI):
cv=5, cv=5,
refit='accuracy', refit='accuracy',
n_jobs = -1) n_jobs = -1)
grid.fit(XData, yData) grid.fit(subset, yData)
FeatureImp.append(grid.best_estimator_.feature_importances_) 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 df_cv_results_classifiers, parameters, FeatureImp return out
GridSearch = mem.cache(GridSearch) #GridSearch = mem.cache(GridSearch)
def InitializeEnsemble(): def InitializeEnsemble():
DataResults = copy.deepcopy(DataResultsRaw) DataResults = copy.deepcopy(DataResultsRaw)
@ -149,15 +176,19 @@ def InitializeEnsemble():
AllTargets = [o[target] for o in DataResultsRaw] AllTargets = [o[target] for o in DataResultsRaw]
AllTargetsFloatValues = [] AllTargetsFloatValues = []
previous = None previous = None
Class = 0 Class = 0
target_names = []
for i, value in enumerate(AllTargets): for i, value in enumerate(AllTargets):
if (i == 0): if (i == 0):
previous = value previous = value
target_names.append(value)
if (value == previous): if (value == previous):
AllTargetsFloatValues.append(Class) AllTargetsFloatValues.append(Class)
else: else:
Class = Class + 1 Class = Class + 1
target_names.append(value)
AllTargetsFloatValues.append(Class) AllTargetsFloatValues.append(Class)
previous = value previous = value
@ -186,28 +217,29 @@ def InitializeEnsemble():
# 'weights': ['uniform', 'distance'], # 'weights': ['uniform', 'distance'],
# 'metric': ['euclidean', 'manhattan']} # 'metric': ['euclidean', 'manhattan']}
results.append(GridSearch(clf, params, scoring, IF)) results.append(GridSearch(clf, params, scoring, IF, target_names))
clf = RandomForestClassifier() clf = RandomForestClassifier()
params = {'n_estimators': [10, 50]} params = {'n_estimators': [10, 50]}
IF = 1 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) 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) 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 = [] classifiersIDPlusParams = []
classifierID = 0 classifierID = 0
for oneClassifier in parameters: for oneClassifier in parameters:
classifierID = classifierID + 1
classifiersIDPlusParams.append(classifierID) classifiersIDPlusParams.append(classifierID)
classifiersIDPlusParams.append(oneClassifier) classifiersIDPlusParams.append(oneClassifier)
classifierID = classifierID + 1
del df_cv_results_classifiers['params'] 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.copy()
df_cv_results_classifiers_metrics = df_cv_results_classifiers_metrics.ix[:, 0:NumberofscoringMetrics+1] 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_fit_time']
del df_cv_results_classifiers_metrics['mean_score_time'] del df_cv_results_classifiers_metrics['mean_score_time']
@ -229,9 +261,14 @@ def InitializeEnsemble():
global ResultsforOverview global ResultsforOverview
ResultsforOverview = [] ResultsforOverview = []
FeatureImportance = FeatureImportance.to_json(orient='records')
PerClassMetrics = PerClassMetrics.to_json(orient='records')
ResultsforOverview.append(json.dumps(sumPerClassifier)) ResultsforOverview.append(json.dumps(sumPerClassifier))
ResultsforOverview.append(json.dumps(X_transformed)) ResultsforOverview.append(json.dumps(X_transformed))
ResultsforOverview.append(json.dumps(classifiersIDPlusParams)) ResultsforOverview.append(json.dumps(classifiersIDPlusParams))
ResultsforOverview.append(FeatureImportance)
ResultsforOverview.append(PerClassMetrics)
ResultsforOverview.append(json.dumps(target_names))
return ResultsforOverview return ResultsforOverview
@ -263,7 +300,7 @@ def EnsembleModel (ClassifierIDsList, keyRetrieved):
for clf, label in zip([sclf], for clf, label in zip([sclf],
['StackingClassifierAllClassifiers']): ['StackingClassifierAllClassifiers']):
scores = model_selection.cross_val_score(clf, XData, yData, scores = model_selection.cross_val_score(clf, subset, yData,
cv=5, scoring='accuracy') cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]" print("Accuracy: %0.2f (+/- %0.2f) [%s]"
% (scores.mean(), scores.std(), label)) % (scores.mean(), scores.std(), label))
@ -272,13 +309,13 @@ def EnsembleModel (ClassifierIDsList, keyRetrieved):
ClassifierIDsList = ClassifierIDsList.split('"') ClassifierIDsList = ClassifierIDsList.split('"')
for loop in ClassifierIDsList: for loop in ClassifierIDsList:
if ('ClassifierID' in loop): if ('ClassifierID' in loop):
if (loop == 'ClassifierID: 1'): if (loop == 'ClassifierID: 0'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=1)) all_classifiers.append(KNeighborsClassifier(n_neighbors=1))
elif (loop == 'ClassifierID: 2'): elif (loop == 'ClassifierID: 1'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=2)) all_classifiers.append(KNeighborsClassifier(n_neighbors=2))
elif (loop == 'ClassifierID: 3'): elif (loop == 'ClassifierID: 2'):
all_classifiers.append(KNeighborsClassifier(n_neighbors=10)) 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)) all_classifiers.append(RandomForestClassifier(random_state=RANDOM_SEED, n_estimators = 1))
else: else:
all_classifiers.append(RandomForestClassifier(random_state=RANDOM_SEED, n_estimators = 50)) 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], for clf, label in zip([sclf],
['StackingClassifierSelectedClassifiers']): ['StackingClassifierSelectedClassifiers']):
scores = model_selection.cross_val_score(clf, XData, yData, scores = model_selection.cross_val_score(clf, subset, yData,
cv=5, scoring='accuracy') cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]" print("Accuracy: %0.2f (+/- %0.2f) [%s]"
% (scores.mean(), scores.std(), label)) % (scores.mean(), scores.std(), label))

Loading…
Cancel
Save