crossvalid

This commit is contained in:
Hubert Sokołowski
2022-04-19 16:36:25 +02:00
parent 12dc75d855
commit 4c74652f5b
9 changed files with 177 additions and 36 deletions

15
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}

View File

@@ -50,6 +50,7 @@ function ConfusionMatrix({ tree, onChange, data, allClasses, categoryAttr, disab
}
useEffect(() => {
console.log('Confusion Matrix', data.length);
try {
//console.log('use effect confusion matrix');
let CM = buildArray(allClasses.length);
@@ -101,7 +102,7 @@ function ConfusionMatrix({ tree, onChange, data, allClasses, categoryAttr, disab
size="sm"
disabled={disabled}
>
Confusion Matrix
Confusion Matrix [{accuracy}%]
</Button>
<Modal onClose={onClose} size={'xl'} isOpen={isOpen} blockScrollOnMount={false}>

View File

@@ -0,0 +1,54 @@
import React, { useState, useEffect } from 'react';
import { mergeChunksWithoutChosen } from '../../utils/cross-valid';
import ConfusionMatrix from '../ConfusionMatrix';
/**
*
* @param {Object} props
* @param {Object} props.builder
* @param {Array} props.builder.allAttributes
* @param {Array} props.builder.allClasses
* @param {string} props.builder.categoryAttr
* @param {string} props.builder.entropyThrehold
* @param {string} props.builder.minItemsCount
* @param {Array} props.builder.trainingSet
* @param {Array<string>} props.builder.ignoredAttributes
* @param {string} props.builder.algorithm
* @param {Boolean} props.headers
* @param {Boolean} props.isReady
* @param {Number} props.fold
* @returns
*/
function CrossValidator({ builder, chunks, treeModels }) {
useEffect(() => {
if (treeModels.lenght > 8) {
// do something
}
}, [treeModels]);
if (treeModels.lenght < 2) return 'Waiting for places';
return (
<div id="cv" className="main">
<div>
{treeModels.map((x, i) => (
<p key={Math.random() + 5}>
Tree {i}{' '}
<ConfusionMatrix
tree={x}
data={mergeChunksWithoutChosen(chunks, i)}
allClasses={builder.allClasses}
categoryAttr={builder.categoryAttr}
onChange={console.log}
disabled={false}
/>
</p>
))}
{/* <Tree options={builder} headers={headers} /> */}
</div>
</div>
);
}
export default CrossValidator;

View File

@@ -5,6 +5,7 @@ import Navigation from './Navigation';
import { AttributesProvider } from '../contexts/AttributesContext';
import { BuilderConfigProvider } from '../contexts/BuilderConfigContext';
import { TestTreeProvider } from '../contexts/TestTreeContext';
import ModelBuilder from './ModelBuilder';
function Main() {
const [builder, setBuilder] = useState({});
@@ -32,8 +33,11 @@ function Main() {
<div id="main" className="main">
<Navigation onPrepareConfig={StartDrawing} setHeaders={onSetHeaders} />
{/* <Button onClick={start}>Drzewo</Button> */}
<br></br>
<div>{isReady ? <Tree options={builder} headers={headers} /> : <div>Deploy your set</div>}</div>
<div>
{isReady ? <ModelBuilder builder={builder} headers={headers} /> : <div>Deploy your set</div>}
</div>
{/* <br></br>
<div>{isReady ? <Tree options={builder} headers={headers} /> : <div>Deploy your set</div>}</div> */}
</div>
</TestTreeProvider>
</AttributesProvider>

View File

@@ -12,6 +12,7 @@ import { DrawerMemo } from './DrawerRoll';
import { useLoadingContext } from '../../contexts/LoadingContext';
import { useAttributesContext } from '../../contexts/AttributesContext';
import { useBuilderConfigContext } from '../../contexts/BuilderConfigContext';
import { shuffleAndChunkArray } from '../../utils/cross-valid';
/**
* @typedef {import('../../utils/decision-tree.js').DecisionTreeBuilder} DecisionTreeBuilder
@@ -64,10 +65,11 @@ function Navigation({ onPrepareConfig, setHeaders }) {
function handleGetAllAttributes({ allAttributes, data }) {
setDecisionAttribute(null);
setIgnoredAttributes([]);
console.log(allAttributes, data);
//console.log(allAttributes, data);
setAllAttributes(allAttributes);
onAttributesChange(allAttributes);
setDataSet(data);
shuffleAndChunkArray(data);
}
/**
* @returns {DecisionTreeBuilder}

View File

@@ -67,32 +67,32 @@ function Leaf({ category, matchedCount, notMatchedCount, quality, requestLeafUnf
<div></div>
) : (
<Menu closeOnSelect closeOnBlur isLazy>
<Tooltip hasArrow label="Unfold to node" bg="yellow.500" placement="right">
<MenuButton
fontSize="sm"
w={20}
h={6}
as={Button}
rightIcon={<ChevronDownIcon />}
//bg={'#009c72'}
// _hover={{
// bg: '#00402f',
// }}
// _active={{
// bg: '#00402f',
// }}
bg={'#1560ab'}
_hover={{
bg: '#005069',
}}
_active={{
bg: '#005069',
}}
color={'white'}
>
Unfold
</MenuButton>
</Tooltip>
{/* <Tooltip hasArrow label="Unfold to node" bg="yellow.500" placement="right"> */}
<MenuButton
fontSize="sm"
w={20}
h={6}
as={Button}
rightIcon={<ChevronDownIcon />}
//bg={'#009c72'}
// _hover={{
// bg: '#00402f',
// }}
// _active={{
// bg: '#00402f',
// }}
bg={'#1560ab'}
_hover={{
bg: '#005069',
}}
_active={{
bg: '#005069',
}}
color={'white'}
>
Unfold
</MenuButton>
{/* </Tooltip> */}
<MenuList>
<MenuItem onClick={() => requestLeafUnfold(['c45'])}>C 4.5</MenuItem>
<MenuItem onClick={() => requestLeafUnfold(['tsp'])}>TSP</MenuItem>

View File

@@ -7,9 +7,9 @@ const workersMap = {
};
export function executeAlgorithm(options, changeOptions = {}) {
console.log(changeOptions);
//console.log(changeOptions);
return new Promise((resolve, reject) => {
console.time(options.algorithm);
//console.time(options.algorithm);
let worker;
if (options.algorithm.length > 1) {
console.log('mix');

65
src/utils/cross-valid.js Normal file
View File

@@ -0,0 +1,65 @@
export function shuffleAndChunkArray(data, fold = 10) {
console.log(data);
let shuffledData = [...data];
var chunks = splitToChunks(shuffledData, fold);
return chunks;
}
export function mergeChunksWithoutChosen(chunks, chosenIndex) {
return [].concat.apply([], arrayWithoutElementAtIndex(chunks, chosenIndex));
}
const arrayWithoutElementAtIndex = function (arr, index) {
return arr.filter(function (value, arrIndex) {
return index !== arrIndex;
});
};
function shuffle(array) {
let currentIndex = array.length,
randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}
return array;
}
function splitToChunks(array, parts) {
let result = [];
for (let i = parts; i > 0; i--) {
result.push(array.splice(0, Math.ceil(array.length / i)));
}
return result;
}
function abc(shuffledData, fold) {
let arrayLength = shuffledData.length;
let sizeOfTestGroup = Math.floor(arrayLength / fold);
let startPosition = 0;
let array = Array.from(Array(fold), () => new Array(2));
for (let i = 0; i < fold; i++) {
let tmpArray = [...shuffledData];
if (i === fold - 1) {
array[i][1] = tmpArray.splice(startPosition);
array[i][0] = tmpArray;
break;
}
array[i][1] = tmpArray.splice(startPosition, sizeOfTestGroup);
array[i][0] = tmpArray;
startPosition += sizeOfTestGroup;
//console.log(shuffledData);
}
console.log(array);
}

View File

@@ -20,8 +20,8 @@ export function predict(tree, item) {
predicate = predicates[tree.predicateName];
match = predicate(value, pivot);
console.log(value, pivot);
console.log('predict - c45', match);
//console.log(value, pivot);
//console.log('predict - c45', match);
}
if (tree.predicateName === '<') {
attr1 = tree.attr2;
@@ -32,8 +32,8 @@ export function predict(tree, item) {
predicate = predicates[tree.predicateName];
match = predicate(value, pivot);
console.log(value, pivot);
console.log('predict - tsp', match);
//console.log(value, pivot);
//console.log('predict - tsp', match);
}
//console.log(tree.weight);
if (tree.weight) {