Skip to content

Commit 47de5bc

Browse files
authored
Merge pull request #97 from firefly-cpp/84-cli
🧑‍💻added `niaaml` CLI
2 parents 62229b3 + f45afac commit 47de5bc

File tree

8 files changed

+245
-5
lines changed

8 files changed

+245
-5
lines changed

.github/images/niaaml_cli_help.png

47.7 KB
Loading
51.2 KB
Loading
70.2 KB
Loading

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<p align="center">
3434
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-installation">📦 Installation</a> •
3535
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-graphical-user-interface">💻 Graphical User Interface</a> •
36+
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-command-line-interface">🧑‍💻 Command Line Interface</a> •
3637
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-api">📮 API</a> •
3738
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-implemented-components">✨ Implemented Components</a> •
3839
<a href="https://github.com/firefly-cpp/NiaAML?tab=readme-ov-file#-optimization-process-and-parameter-tuning">💪 Optimization Process And Parameter Tuning</a> •
@@ -117,6 +118,22 @@ $ nix-shell -p python311Packages.niaaml
117118

118119
There is a simple Graphical User Interface for the NiaAML package available [here](https://github.com/lukapecnik/NiaAML-GUI).
119120

121+
## 🧑‍💻 Command Line Interface
122+
123+
We also provide a CLI for quick pipeline optimizations and inference from the terminal without the need to write custom scripts.
124+
125+
When you install the package as instructed above, you will already have access to the `niaaml` command with sub-commands `optimize` and `infer`
126+
127+
For usage information, add the `--help` flag:
128+
129+
![niaaml help](.github/images/niaaml_cli_help.png)
130+
131+
![niaaml infer help](.github/images/niaaml_cli_infer_help.png)
132+
133+
An example Invocation of `optimize`:
134+
135+
![niaaml optimize example](.github/images/niaaml_cli_optimize_example.png)
136+
120137
## 📮 API
121138

122139
There is a simple API for remote work with NiaAML package available [here](https://github.com/alenrajsp/NiaAML-API).

niaaml/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from niaaml.pipeline import Pipeline
1212
from niaaml.pipeline_component import PipelineComponent
1313
from niaaml.logger import Logger
14+
from niaaml import cli
1415

1516
__all__ = [
1617
"classifiers",
@@ -26,6 +27,7 @@
2627
"Pipeline",
2728
"PipelineComponent",
2829
"Logger",
30+
"cli",
2931
]
3032

3133
__project__ = "niaaml"

niaaml/cli.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""🧑‍💻 command line interface for NiaAML"""
2+
3+
from pathlib import Path
4+
from typing import Optional
5+
6+
from loguru import logger
7+
import pandas as pd
8+
import typer
9+
from typing_extensions import Annotated
10+
11+
from niaaml import PipelineOptimizer, Pipeline
12+
from niaaml.data.csv_data_reader import CSVDataReader
13+
14+
15+
app = typer.Typer(
16+
help="🌳 a command line interface for NiaAML.",
17+
no_args_is_help=True
18+
)
19+
20+
21+
@app.command()
22+
def optimize(
23+
data_csv_file: Path,
24+
has_header: bool = True,
25+
ignore_columns: list[int] = [],
26+
classifiers: list[str] = ['AdaBoost', 'Bagging', 'MultiLayerPerceptron', 'RandomForest', 'ExtremelyRandomizedTrees', 'LinearSVC'],
27+
feature_selection_algorithms: list[str] = ['SelectKBest', 'SelectPercentile', 'ParticleSwarmOptimization', 'VarianceThreshold'],
28+
feature_transform_algorithms: list[str] = ['Normalizer', 'StandardScaler'],
29+
categorical_features_encoder: Annotated[Optional[str], typer.Option()] = "OneHotEncoder",
30+
imputer: Annotated[Optional[str], typer.Option()] = None,
31+
fitness_name: str = 'Accuracy',
32+
pipeline_population_size: int = 15,
33+
inner_population_size: int = 15,
34+
number_of_pipeline_evaluations: int = 100,
35+
number_of_inner_evaluations: int = 100,
36+
optimization_algorithm: str = 'ParticleSwarmAlgorithm',
37+
inner_optimization_algorithm: Annotated[Optional[str], typer.Option()] = None,
38+
result_file: Path = Path("pipeline.ppln"),
39+
) -> None:
40+
"""🦾 optimizes a NiaAML pipeline on a given dataset."""
41+
# 📄 load and setup data
42+
logger.info(f"📄 reading `{data_csv_file}`")
43+
data_reader = CSVDataReader(
44+
src=str(data_csv_file),
45+
has_header=has_header,
46+
contains_classes=True,
47+
ignore_columns=ignore_columns
48+
)
49+
50+
# 🦾 setup pipeline
51+
logger.info("🦾 start the optimization process ...")
52+
pipeline_optimizer = PipelineOptimizer(
53+
data=data_reader,
54+
classifiers=classifiers,
55+
feature_selection_algorithms=feature_selection_algorithms,
56+
feature_transform_algorithms=feature_transform_algorithms,
57+
categorical_features_encoder=categorical_features_encoder,
58+
imputer=imputer,
59+
)
60+
61+
# 📈 optimize pipeline
62+
pipeline = pipeline_optimizer.run(fitness_name, pipeline_population_size, inner_population_size, number_of_pipeline_evaluations, number_of_inner_evaluations, optimization_algorithm, inner_optimization_algorithm)
63+
64+
# 💾 save pipeline
65+
logger.success(f"💾 saving optimized pipeline to `{result_file}`")
66+
pipeline.export(result_file)
67+
68+
@app.command()
69+
def infer(
70+
data_csv_file: Path,
71+
has_header: bool = True,
72+
ignore_columns: list[int] = [],
73+
pipeline_file: Path = Path("pipeline.ppln"),
74+
predictions_csv_file: Path = Path("preds.csv"),
75+
) -> None:
76+
"""🔮 use an optimized NiaAML pipeline to make predictions."""
77+
# 💾 load pipeline
78+
pipeline = Pipeline.load(pipeline_file)
79+
80+
# 📄 load and setup data
81+
logger.info(f"📄 reading `{data_csv_file}`")
82+
reader = CSVDataReader(
83+
src=str(data_csv_file),
84+
has_header=has_header,
85+
contains_classes=True,
86+
ignore_columns=ignore_columns
87+
)
88+
reader._read_data()
89+
x: pd.DataFrame = reader._x
90+
91+
# 🔮 make predictions
92+
logger.info(f"🔮 using `{pipeline_file}` to make predictions on the data")
93+
x['preds'] = pipeline.run(x)
94+
95+
# 💾 save predictions
96+
logger.success(f"💾 saving predictions to `{predictions_csv_file}`")
97+
x.to_csv(predictions_csv_file)
98+
99+
def main():
100+
"""🚪 typer entry point for the CLI."""
101+
app()
102+
103+
if __name__ == "__main__":
104+
main()

poetry.lock

Lines changed: 116 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "NiaAML"
3-
version = "2.0.0"
3+
version = "2.1.0"
44
description = "Python automated machine learning framework"
55
license = "MIT"
66
authors = ["Luka Pečnik <lukapecnik96@gmail.com>", "Iztok Fister Jr. <iztok@iztok-jr-fister.eu>", "Laurenz Farthofer <laurenz@hey.com>"]
@@ -16,12 +16,17 @@ include = [
1616
{ path="COMPONENTS.md", format="sdist" }
1717
]
1818

19+
[tool.poetry.scripts]
20+
niaaml = "niaaml.cli:main"
21+
1922
[tool.poetry.dependencies]
2023
python = "^3.9"
2124
numpy = "^1.19.1"
2225
scikit-learn = "^1.1.2"
2326
niapy = "^2.0.5"
2427
pandas = "^2.1.1"
28+
typer = "^0.12.3"
29+
loguru = "^0.7.2"
2530

2631
[tool.poetry.dev-dependencies]
2732
sphinx = "^3.3.1"

0 commit comments

Comments
 (0)