Fixed double code and scaling for dectree

This commit is contained in:
Arne van Iterson 2023-10-22 13:50:29 +02:00
parent 4aa97d72a5
commit 49fd6576a0
7 changed files with 87 additions and 83 deletions

View File

@ -53,6 +53,12 @@ $ ./.venv/Scripts/activate(.bat/.ps1)
$ pip install -r ./requirements.txt
```
### Fix relative imports
1. Install the local package as editable using `pip`:
```sh
$ pip install -e .
```
### Create a dataset
1. Rename all images to include a tag and unique id, seperated by an underscore '_'
- e.g. `accasia_1210262`
@ -84,6 +90,9 @@ $ python ./src/helpers/test/knn.py -i ./out/result-(date/time).csv -o ./out/mode
```
4. Edit your `config.json` to include the newly created model
> :memo: **Please note:**<br>
> The KNN Training script also generates the scaler required to make the decision tree model
---
Arne van Iterson<br>

Binary file not shown.

2
setup.py Normal file
View File

@ -0,0 +1,2 @@
from setuptools import setup, find_packages
setup(name='CVSuite', version='1.0', packages=find_packages())

2
src/helpers/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from .logger import *
from .tags import *

View File

@ -7,27 +7,14 @@ import csv
import argparse
import os
from ..tags import Tree
parser = argparse.ArgumentParser(prog='DecisionTree CLI')
parser.add_argument('-i', '--input', help='Input CSV file', required=True)
parser.add_argument('-o', '--output', help='Output model folder', required=True)
parser.add_argument(
'-m',
'--model',
help='Chosen model (\'dectree\', \'randforest\' or \'extratree\')',
required=True
)
parser.add_argument('-m', '--model', help='Chosen model (\'dectree\', \'randforest\' or \'extratree\')', required=True)
parser.add_argument('-s', '--scaler', help='Scaler preprocesser', required=True)
class Tree(Enum):
ACCASIA = 0
BERK = 1
EIK = 2
ELS = 3
ESDOORN = 4
ES = 5
LINDE = 6
PLATAAN = 7
class CVSuiteTestTree:
def __init__(self, model_path = None):
self.model_path = model_path
@ -40,12 +27,11 @@ class CVSuiteTestTree:
reader = csv.reader(file, delimiter= ',')
matrix = list(reader)
i = 0
labels = []
data = [[] for x in range(len(matrix)-1)]
# Load all but the headers
for row in matrix[1:]:
for ridx, row in enumerate(matrix[1:]):
## append data to lists
label = row.pop(0).upper()
labels.append(Tree[label].value)
@ -54,12 +40,12 @@ class CVSuiteTestTree:
row.pop(0)
# append all but ID and tree
for element in row:
data[i].append(float(element))
i += 1
for idx, element in enumerate(row):
value = self.scaler[idx].transform([[float(element)]])
data[ridx].append(value[0][0])
# normalize data
#TODO: Arne help
# normalize data has been included in code above :D
#TODO: Check if data is normalized correctly
# train model
self.train(data, labels, output)

View File

@ -9,20 +9,13 @@ import joblib
import datetime
import os
from ..logger import C_DBUG
from ..tags import Tree
parser = argparse.ArgumentParser(prog='KNN Train CLI')
parser.add_argument('-i', '--input', help='Input CSV file', required=True)
parser.add_argument('-o', '--output', help='Output model file', required=True)
class Tree(Enum):
ACCASIA = 0
BERK = 1
EIK = 2
ELS = 3
ESDOORN = 4
ES = 5
LINDE = 6
PLATAAN = 7
class CVSuiteTestKNN:
def __init__(self, model = None):
self.scale = []
@ -113,7 +106,12 @@ class CVSuiteTestKNN:
self.knn.save(os.path.join(output, F"model_knn_{now.strftime('%Y-%m-%dT%H.%M.%S')}.yaml"))
def predict(self, data, nr = 3):
return self.knn.findNearest(data, nr)
ret, results, neighbours ,dist = self.knn.findNearest(data, nr)
print(C_DBUG, "KNN Raw:")
print("\t\tresult: \t{}".format(results) )
print("\t\tneighbours:\t{}".format(neighbours) )
print("\t\tdistance:\t{}".format(dist) )
return neighbours[0]
if __name__ == "__main__":
args = parser.parse_args()

View File

@ -28,14 +28,13 @@ import matplotlib.pyplot as plt
# Helpers
from helpers.statistics import imgStats
from helpers.logger import CVSuiteLogger, C_DBUG, C_WARN
from helpers.logger import CVSuiteLogger, C_INFO, C_DBUG, C_WARN, C_DONE
from helpers.canvas import CVSuiteCanvas
from helpers.sift import getSiftData
from helpers.tags import Tree
# Tests
from helpers.test.knn import CVSuiteTestKNN
from helpers.test.decision_tree import CVSuiteTestDecisionTree
## UI config load
@ -48,10 +47,18 @@ CONFIG_PATH = "./src/config/config.json"
config_file = open(CONFIG_PATH, encoding="utf-8")
config_json = json.load(config_file)
print(
f"""
Welcome to CVSuite aka {TITLE}!
Powered by ARNweb.nl and TomSelier.com
"""
)
## UI class setup
class CVSuite:
def __init__(self, master=None):
### UI setup ###
# Pygubu builder
self.builder = builder = pygubu.Builder()
builder.add_resource_path(PROJECT_PATH)
@ -102,28 +109,45 @@ class CVSuite:
)
builder.connect_callbacks(self)
# Load values from config after UI has been initialised
self.img_path.set(config_json["path"])
self.img_size.set(config_json["size"])
### End of UI setup ###
### Model tests setup ###
# Attempt to load scaler
if config_json["scaler"] != "":
self.scaler = joblib.load(config_json["scaler"])
else:
self.scaler = None
# Model tests
if self.scaler is not None and config_json["models"]["knn"] != "":
self.test_knn = CVSuiteTestKNN(config_json["models"]["knn"])
else:
self.test_knn = None
self.models = []
if self.scaler is not None:
for model in config_json["models"]:
if config_json["models"][model] != "":
print(C_INFO, f"Loading model {model}")
if model == "knn":
self.models.append(
("KNN", CVSuiteTestKNN(config_json["models"]["knn"]))
)
elif model == "dectree":
self.models.append(
(
"Decision Tree",
CVSuiteTestDecisionTree(
config_json["models"]["dectree"]
),
)
)
else:
print(C_WARN, f"Model {model} does not exist!")
else:
print(C_WARN, f"Model {model} not configured!")
print(C_DONE, f"{len(self.models)} models loaded!")
if config_json["models"]["dectree"] != "":
self.test_dectree = CVSuiteTestDecisionTree(
config_json["models"]["dectree"]
)
else:
self.test_dectree = None
# Load values from config after UI has been initialised
self.img_path.set(config_json["path"])
self.img_size.set(config_json["size"])
print(C_DONE, "CVSuite initialised!\n")
### End of model tests setup ###
def on_quit(self, event=None):
"""
@ -311,7 +335,7 @@ class CVSuite:
# Don't run the test if there's no scaler
if self.scaler is None:
return
output = self.builder.get_object("testdata")
output.configure(state="normal")
output.delete(1.0, "end")
@ -319,42 +343,26 @@ class CVSuite:
# Remove tag and photoId
tag = data.pop(0)
photoId = data.pop(1)
# Add actual name
output.insert("end", f"Actual:\n\t{tag.upper()}\n")
# Add actual name
output.insert("end", f"Actual type:\n\t{tag.upper()}\n")
# Normalise data using loaded scalers
for idx, value in enumerate(data):
d = np.array(value)
data[idx] = self.scaler[idx].transform(d.astype(np.float32).reshape(1, -1))[0][0]
data = np.array([data], dtype=np.float32)
if self.test_knn is not None:
# Do knn test
output.insert("end", "KNN Result:\n")
ret, results, neighbours ,dist = self.test_knn.predict(data)
for name, ins in self.models:
output.insert("end", f"{name} Result:\n")
for idx, res_id in enumerate(neighbours[0]):
output.insert("end", f" {idx}:\t{Tree(res_id).name}\n")
print(C_DBUG, "KNN Result:")
print("\t\tresult: \t{}".format(results) )
print("\t\tneighbours:\t{}".format(neighbours) )
print("\t\tdistance:\t{}".format(dist) )
else:
print(C_WARN, "KNN Model not configured!")
# Predict result using model instance
result = ins.predict(data)
if self.test_dectree is not None:
result = self.test_dectree.predict(data)
output.insert("end", "Decision Tree Result:\n")
output.insert("end", f"\t{Tree(result).name}\n")
print(C_DBUG, "Decision Tree Result:")
print("\t\t result: \t{}".format(result))
else:
print(C_WARN, "Decison Tree Model not configured!")
# Prediciton result should be an array
for idx, value in enumerate(result):
output.insert("end", f" [{idx + 1}]\t{Tree(value).name}\n")
output.configure(state="disabled")
@ -381,9 +389,8 @@ class CVSuite:
def update(self, event=None, part_update=None):
## Check if hist and canny hm have to be rerendered
if (
part_update is None
): ## If partial update has not been forced, check if full update is required
if part_update is None:
## If partial update has not been forced, check if full update is required
if self.img_current != self.img_old or self.img_size != self.img_size_old:
part_update = False
self.img_old = self.img_current
@ -397,7 +404,7 @@ class CVSuite:
print("Full update forced!")
if self.updatePath():
print(C_DBUG, f"Processing {self.img_name}")
print(C_INFO, f"Processing {self.img_name}")
self.mainwindow.title(f"{TITLE} - {self.img_name}")
self.log.add("Tree", self.img_name.split("_")[0])