genetic-classifier 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. genetic_classifier-3.0.0/.github/workflows/publish.yml +37 -0
  2. genetic_classifier-3.0.0/.gitignore +12 -0
  3. genetic_classifier-3.0.0/LICENSE +21 -0
  4. genetic_classifier-3.0.0/PKG-INFO +298 -0
  5. genetic_classifier-3.0.0/README.md +277 -0
  6. genetic_classifier-3.0.0/docs/.gitignore +7 -0
  7. genetic_classifier-3.0.0/docs/README.md +34 -0
  8. genetic_classifier-3.0.0/docs/genetic_algorithm.md +197 -0
  9. genetic_classifier-3.0.0/docs/genetic_algorithm.tex +327 -0
  10. genetic_classifier-3.0.0/examples/.gitkeep +0 -0
  11. genetic_classifier-3.0.0/examples/diabetes_classification/diabetes_classification.ipynb +235 -0
  12. genetic_classifier-3.0.0/examples/diabetes_classification/diabetes_data.xlsx +0 -0
  13. genetic_classifier-3.0.0/examples/example_1_binary/binary_data_1.xlsx +0 -0
  14. genetic_classifier-3.0.0/examples/example_1_binary/binary_data_2.xlsx +0 -0
  15. genetic_classifier-3.0.0/examples/example_1_binary/binary_example.ipynb +558 -0
  16. genetic_classifier-3.0.0/examples/example_2_multiclass/multiclass_data.xlsx +0 -0
  17. genetic_classifier-3.0.0/examples/example_2_multiclass/multiclass_example.ipynb +607 -0
  18. genetic_classifier-3.0.0/examples/heart_disease_classification/heart.csv +919 -0
  19. genetic_classifier-3.0.0/examples/heart_disease_classification/heart_data.xlsx +0 -0
  20. genetic_classifier-3.0.0/examples/heart_disease_classification/heart_disease_classification.ipynb +1568 -0
  21. genetic_classifier-3.0.0/examples/mushroom_classification/mushroom_classification.ipynb +228 -0
  22. genetic_classifier-3.0.0/examples/mushroom_classification/mushroom_data.xlsx +0 -0
  23. genetic_classifier-3.0.0/examples/mushroom_classification/mushrooms.csv +8125 -0
  24. genetic_classifier-3.0.0/examples/template/template.xlsx +0 -0
  25. genetic_classifier-3.0.0/pyproject.toml +39 -0
  26. genetic_classifier-3.0.0/requirements.txt +3 -0
  27. genetic_classifier-3.0.0/src/genetic_classifier/__init__.py +10 -0
  28. genetic_classifier-3.0.0/src/genetic_classifier/core.py +339 -0
  29. genetic_classifier-3.0.0/src/genetic_classifier/creation.py +47 -0
  30. genetic_classifier-3.0.0/src/genetic_classifier/crossover.py +53 -0
  31. genetic_classifier-3.0.0/src/genetic_classifier/evaluation.py +233 -0
  32. genetic_classifier-3.0.0/src/genetic_classifier/fitness.py +194 -0
  33. genetic_classifier-3.0.0/src/genetic_classifier/mutation.py +53 -0
  34. genetic_classifier-3.0.0/src/genetic_classifier/reading.py +100 -0
  35. genetic_classifier-3.0.0/src/genetic_classifier/selection.py +91 -0
  36. genetic_classifier-3.0.0/src/genetic_classifier/split.py +110 -0
  37. genetic_classifier-3.0.0/src/genetic_classifier/update.py +84 -0
  38. genetic_classifier-3.0.0/tests/.gitkeep +0 -0
@@ -0,0 +1,37 @@
1
+ # Publishes to PyPI when a version tag (e.g. v3.0.0) is pushed to GitHub,
2
+ # or manually from the Actions tab -> "Publish to PyPI" -> Run workflow.
3
+ # Uses Trusted Publishing: no token needed, PyPI trusts this repository.
4
+ name: Publish to PyPI
5
+
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+ - run: python -m pip install build
20
+ - run: python -m build
21
+ - uses: actions/upload-artifact@v4
22
+ with:
23
+ name: dist
24
+ path: dist/
25
+
26
+ publish:
27
+ needs: build
28
+ runs-on: ubuntu-latest
29
+ environment: pypi
30
+ permissions:
31
+ id-token: write # required for Trusted Publishing
32
+ steps:
33
+ - uses: actions/download-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ venv_ag/
2
+ __pycache__/
3
+ *.pyc
4
+ .DS_Store
5
+ tests/*.ipynb
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .dist/
10
+
11
+ # PDF and LaTeX guide: delivered separately, kept out of Git
12
+ documentacao/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fellipe Almassy and Matheus Gomes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.5
2
+ Name: genetic-classifier
3
+ Version: 3.0.0
4
+ Summary: Linear classifier (binary and ordinal) trained by a genetic algorithm, built with NumPy
5
+ Project-URL: Repository, https://github.com/FeAlmassy/Genetic-Classifier
6
+ Project-URL: Issues, https://github.com/FeAlmassy/Genetic-Classifier/issues
7
+ Author: Fellipe Almassy, Matheus Gomes
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: classification,evolutionary algorithm,genetic algorithm,machine learning,ordinal classification
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Natural Language :: English
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: numpy>=2.1
18
+ Requires-Dist: openpyxl>=3.1
19
+ Requires-Dist: pandas>=2.2
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Genetic Classifier
23
+
24
+ A Python library that trains a **linear classifier with a genetic algorithm**, written from scratch with NumPy.
25
+
26
+ Instead of using gradients (like logistic regression), the model **evolves** a population of solutions: the best ones reproduce, mutate and, generation after generation, the classification improves.
27
+
28
+ It works for:
29
+ - **Binary classification** (2 classes: 0 and 1)
30
+ - **Ordinal classification** (K ordered classes, e.g. bad < average < good)
31
+
32
+ ---
33
+
34
+ ## How it works
35
+
36
+ Each **chromosome** is a list of numbers: one **bias** and one **weight** per feature. With them the model computes a score for each sample:
37
+
38
+ ```
39
+ score = bias + weight₁·x₁ + weight₂·x₂ + ... + weightₙ·xₙ
40
+ ```
41
+
42
+ - **Binary:** score ≥ 0 → class 1, score < 0 → class 0
43
+ - **Ordinal:** the score is split into ranges by the **thresholds** (cut points), and each range is a class
44
+
45
+ ### The fitness
46
+
47
+ The score of each chromosome (its fitness) is the **product of the recall of each class**:
48
+
49
+ ```
50
+ fitness = recall(class 0) × recall(class 1) × ... × recall(class K-1)
51
+ ```
52
+
53
+ If the model gets every sample of a class wrong, the fitness becomes 0. This forces the model to get **every** class right, not only the most common one, which is useful when the classes are imbalanced.
54
+
55
+ ### The algorithm cycle
56
+
57
+ ```
58
+ 1. create random population
59
+ │
60
+ ▼
61
+ 2. compute fitness ◄───────────────┐
62
+ │ │
63
+ ▼ │
64
+ 3. select two parents (roulette) │
65
+ │ │
66
+ ▼ │
67
+ 4. crossover (one cut point) │
68
+ │ │
69
+ ▼ │
70
+ 5. mutation │
71
+ │ │
72
+ ▼ │
73
+ 6. replace the worst with ─────────┘
74
+ the best offspring
75
+ ```
76
+
77
+ The cycle stops when it reaches the target fitness or runs out of generations.
78
+
79
+ | Step | What it does |
80
+ |---|---|
81
+ | **Creation** | Creates chromosomes with random genes between -1 and 1 |
82
+ | **Fitness** | Gives each chromosome a score from 0 to 1 |
83
+ | **Selection** | Draws two parents by roulette: the higher the fitness, the higher the chance |
84
+ | **Crossover** | The child takes the beginning of one parent and the end of the other, from a random cut point |
85
+ | **Mutation** | Replaces some genes of each child with new random values |
86
+ | **Update** | The worst of the population leave and the best offspring come in (elitism) |
87
+
88
+ ---
89
+
90
+ ## Installation
91
+
92
+ Requires **Python 3.10+**.
93
+
94
+ ```bash
95
+ pip install genetic-classifier
96
+ ```
97
+
98
+ Or straight from GitHub:
99
+
100
+ ```bash
101
+ pip install git+https://github.com/FeAlmassy/Genetic-Classifier.git
102
+ ```
103
+
104
+ ### For development
105
+
106
+ ```bash
107
+ git clone https://github.com/FeAlmassy/Genetic-Classifier.git
108
+ cd Genetic-Classifier
109
+ python -m venv venv_ag
110
+ source venv_ag/bin/activate # on Windows: venv_ag\Scripts\activate
111
+ pip install -e . # editable mode: code changes apply right away
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Quick start
117
+
118
+ ### Binary
119
+
120
+ ```python
121
+ from genetic_classifier import train, predict, evaluate, read_excel, train_test_split
122
+
123
+ X, y = read_excel("examples/example_1_binary/binary_data_1.xlsx")
124
+ X_train, X_test, y_train, y_test = train_test_split(X, y, seed=0)
125
+
126
+ model = train(X_train, y_train, seed=0) # learns from the training set only
127
+
128
+ y_pred = predict(model, X_test) # classifies data the model has never seen
129
+ results = evaluate(y_test, y_pred) # prints accuracy, fitness, recall and confusion matrix
130
+ ```
131
+
132
+ > The default values of `train` already give good results in most cases. Only tune the parameters if you need to.
133
+
134
+ The functions of each step (`create_chromosomes`, `binary_fitness`, `select_parents_roulette`, `one_point_crossover`, `mutate`, `update_population`) can also be used on their own, imported from their modules (e.g. `from genetic_classifier.mutation import mutate`).
135
+
136
+ ### Ordinal (several classes)
137
+
138
+ The classes must be numbers from `0` to `K-1`, ordered from lowest to highest. For K classes, pass K-1 thresholds in increasing order:
139
+
140
+ ```python
141
+ import numpy as np
142
+
143
+ thresholds = np.array([-1.5, -0.5, 0.5, 1.5]) # 4 cuts -> 5 classes
144
+
145
+ model = train(X, y, thresholds=thresholds, n_generations=2000)
146
+ y_pred = predict(model, X_new)
147
+ ```
148
+
149
+ ### `train` parameters
150
+
151
+ | Parameter | Default | Description |
152
+ |---|---|---|
153
+ | `X` | — | array (n_samples, n_features) with the data |
154
+ | `y` | — | vector with the class of each sample |
155
+ | `n_chromosomes` | `30` | population size |
156
+ | `n_mutated_genes` | `2` | how many genes change in each child |
157
+ | `n_offspring` | `16` | how many children per generation |
158
+ | `n_replacements` | `None` | how many of the worst in the population are swapped for the best children (at most the smaller of `n_chromosomes` and `n_offspring`). `None` = half of `n_offspring` |
159
+ | `n_generations` | `1000` | maximum number of generations |
160
+ | `target_fitness` | `1.0` | stops when the best fitness reaches this value (`1.0` = runs every generation unless it gets everything right) |
161
+ | `thresholds` | `None` | `None` = binary; array with K-1 cuts = ordinal |
162
+ | `gene_min` | `-1.0` | smallest gene value in the initial population |
163
+ | `gene_max` | `1.0` | largest gene value in the initial population |
164
+ | `seed` | `None` | random seed for reproducibility (`None` = different every run) |
165
+ | `verbose` | `True` | prints the best fitness and accuracy of every generation |
166
+
167
+ `train` returns a dictionary with `chromosome` (the best one found), `fitness`, `accuracy` (fraction right on the training data), `generation` (where it stopped), `thresholds` and `history` (lists `best`, `mean` and `accuracy` with the evolution per generation).
168
+
169
+ ### Tuning the parameters
170
+
171
+ The defaults work well in most cases. If you need to tune them, keep in mind that the parameters affect each other:
172
+
173
+ - **Renewal rate = `n_replacements` ÷ `n_chromosomes`:** fraction of the population replaced every generation (default: 8 ÷ 30 ≈ 27%). Too low makes evolution slow; close to 100% the whole population becomes children of the same couple and loses diversity. That is why **increasing only the population usually makes things worse**: increase the replacements too, or leave it as `None`.
174
+ - **`n_offspring` × `n_replacements`:** only the best children enter the population. With more children than replacements, the worst children are discarded.
175
+ - **`n_mutated_genes` × number of features:** what matters is the fraction of the chromosome that changes. With few features, use `1`; with many, `2` or `3`.
176
+ - **Cost ≈ `n_generations` × (`n_chromosomes` + `n_offspring`) × n_samples.**
177
+ - **Explore × refine:** a large population and more mutation search for new solutions; high renewal and little mutation improve the ones already found.
178
+
179
+ To find out whether more generations would help, look at the end of `model["history"]["best"]`: if the fitness is still going up, the model has not finished.
180
+
181
+ ---
182
+
183
+ ## Data format
184
+
185
+ The spreadsheet (`.xlsx` or `.csv`) must follow this layout:
186
+
187
+ | Lessons | X1 | X2 | ... | Xn | CLASS |
188
+ |---|---|---|---|---|---|
189
+ | Y001 | 1 | 0 | ... | 1 | 1 |
190
+ | Y002 | 0 | 1 | ... | 0 | 0 |
191
+
192
+ - **First column:** sample identifier (ignored)
193
+ - **Middle columns:** features
194
+ - **Last column:** class
195
+
196
+ To classify new data, which has no class column, use `has_labels=False`. In that case the function returns only `X`:
197
+
198
+ ```python
199
+ X_new = read_excel("new_data.xlsx", has_labels=False)
200
+ y_pred = predict(model, X_new)
201
+ ```
202
+
203
+ A ready-made template is in [`examples/template/template.xlsx`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/template/template.xlsx).
204
+
205
+ ---
206
+
207
+ ## Examples and results
208
+
209
+ | Notebook | Dataset | Classes | Test accuracy* |
210
+ |---|---|---|---|
211
+ | [`binary_example.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/example_1_binary/binary_example.ipynb) | `binary_data_1.xlsx` (539 samples, 18 features) | 2 | **87%** |
212
+ | [`multiclass_example.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/example_2_multiclass/multiclass_example.ipynb) | `multiclass_data.xlsx` (261 samples, 30 features) | 5 | **79%** |
213
+ | [`mushroom_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/mushroom_classification/mushroom_classification.ipynb) | `mushroom_data.xlsx` (8124 samples, 117 features) | 2 | **100%** |
214
+ | [`heart_disease_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/heart_disease_classification/heart_disease_classification.ipynb) | `heart_data.xlsx` (917 samples, 21 features) | 2 | **85%** |
215
+ | [`diabetes_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/diabetes_classification/diabetes_classification.ipynb) | `diabetes_data.xlsx` (40000 samples, 21 features) | 3 | **58%**† |
216
+
217
+ \* Trained on 80% of the data and tested on the remaining 20%, which the model never saw, always with seed 0.
218
+
219
+ † Prediabetes is very rare in this dataset, so the accuracy alone is misleading: the notebook shows the recall of each class.
220
+
221
+ The binary notebook shows **one generation step by step**, calling each function in the order of the algorithm. The multiclass one shows how to choose the order of the classes when it is not known.
222
+
223
+ ---
224
+
225
+ ## Project structure
226
+
227
+ ```
228
+ Genetic-Classifier/
229
+ ├── src/
230
+ │ └── genetic_classifier/
231
+ │ ├── __init__.py # public API: train, predict, evaluate, confusion_matrix, read_excel, read_csv, train_test_split
232
+ │ ├── core.py # main loop (train) and prediction (predict)
233
+ │ ├── evaluation.py # model evaluation (evaluate) and confusion matrix
234
+ │ ├── creation.py # 1. initial population
235
+ │ ├── fitness.py # 2. binary and ordinal fitness, roulette proportions
236
+ │ ├── selection.py # 3. roulette selection
237
+ │ ├── crossover.py # 4. one-point crossover
238
+ │ ├── mutation.py # 5. mutation
239
+ │ ├── update.py # 6. replacing the worst with the best offspring
240
+ │ ├── reading.py # reading .xlsx and .csv files
241
+ │ └── split.py # train/test split (stratified)
242
+ ├── docs/ # how the algorithm works, with math and examples (Markdown and LaTeX)
243
+ ├── examples/ # example notebooks and datasets
244
+ ├── tests/ # automated tests (coming soon)
245
+ ├── pyproject.toml # package configuration (name, version, dependencies)
246
+ ├── LICENSE # MIT license
247
+ └── requirements.txt
248
+ ```
249
+
250
+ Each step of the algorithm lives in its own module, so you can swap one piece (for example, try another selection method) without touching the others. Every function checks its parameters and gives clear error messages.
251
+
252
+ ---
253
+
254
+ ## Changelog
255
+
256
+ ### 3.0.0
257
+ - **The whole library is now in English** and is published on PyPI as **`genetic-classifier`** (import `genetic_classifier`). The Portuguese version stays available as `algoritmo-genetico` 2.0.0.
258
+ - Every docstring follows the same format: what the function does, each parameter with its type, and what it returns with its type and a suggested variable name.
259
+ - The deprecated alias `rodar` was removed.
260
+
261
+ Migrating from `algoritmo-genetico`:
262
+
263
+ | 2.x (Portuguese) | 3.0 (English) |
264
+ |---|---|
265
+ | `treinar`, `prever`, `avaliar`, `matriz_confusao` | `train`, `predict`, `evaluate`, `confusion_matrix` |
266
+ | `ler_excel`, `ler_csv` (`tem_classe`) | `read_excel`, `read_csv` (`has_labels`) |
267
+ | `dividir_treino_teste` (`proporcao_treino`, `estratificar`) | `train_test_split` (`train_size`, `stratify`) |
268
+ | `qtd_cromossomos`, `qtd_genes_mutados`, `qtd_filhos`, `qtd_substituicoes` | `n_chromosomes`, `n_mutated_genes`, `n_offspring`, `n_replacements` |
269
+ | `geracoes`, `fitness_alvo`, `minimo`, `maximo` | `n_generations`, `target_fitness`, `gene_min`, `gene_max` |
270
+ | `y_real`, `y_previsto`, `nomes_classes` | `y_true`, `y_pred`, `class_names` |
271
+ | keys `cromossomo`, `acuracia`, `geracao`, `historico` (`melhor`, `medio`) | keys `chromosome`, `accuracy`, `generation`, `history` (`best`, `mean`) |
272
+ | key `matriz` of `avaliar` | key `confusion_matrix` of `evaluate` |
273
+ | `criar_cromossomos`, `fitness_binario`, `fitness_ordinal`, `fitness_percentual` | `create_chromosomes`, `binary_fitness`, `ordinal_fitness`, `fitness_proportions` |
274
+ | `selecionar_pais_roleta`, `cruzar_um_ponto`, `mutar`, `atualizar_populacao` | `select_parents_roulette`, `one_point_crossover`, `mutate`, `update_population` |
275
+
276
+ ### 2.0.0
277
+ - New **`evaluate`** function (`avaliar`), which prints and returns accuracy, fitness, recall per class and the confusion matrix. The matrix can also be obtained on its own with **`confusion_matrix`**.
278
+ - `read_excel` and `read_csv` got the **`has_labels`** parameter: with `has_labels=False` they read new data without the class column.
279
+ - New checks: empty cells, text in the features and text classes in ordinal mode now raise clear error messages instead of silently giving wrong results.
280
+ - Training no longer creates offspring in the last generation, since they would never be compared with the best chromosome.
281
+
282
+ ### 1.1.0
283
+ - `rodar` was renamed to **`treinar`** (now `train`), pairing with `prever` (now `predict`).
284
+ - **New default values**, which give much better results without tuning: 30 chromosomes, 2 mutated genes, 16 offspring, replacements = half of the offspring, 1000 generations and target fitness 1.0.
285
+ - Training converts `X` to float internally, which makes it up to ~6x faster when the data is integer (as read by `read_csv`).
286
+
287
+ ---
288
+
289
+ ## License
290
+
291
+ Distributed under the [MIT license](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/LICENSE): you can use, modify and redistribute it freely, as long as you keep the copyright notice.
292
+
293
+ ---
294
+
295
+ ## Authors
296
+
297
+ - **Fellipe Almassy** — [GitHub](https://github.com/FeAlmassy)
298
+ - **Matheus Gomes** — [GitHub](https://github.com/matheos-hash)
@@ -0,0 +1,277 @@
1
+ # Genetic Classifier
2
+
3
+ A Python library that trains a **linear classifier with a genetic algorithm**, written from scratch with NumPy.
4
+
5
+ Instead of using gradients (like logistic regression), the model **evolves** a population of solutions: the best ones reproduce, mutate and, generation after generation, the classification improves.
6
+
7
+ It works for:
8
+ - **Binary classification** (2 classes: 0 and 1)
9
+ - **Ordinal classification** (K ordered classes, e.g. bad < average < good)
10
+
11
+ ---
12
+
13
+ ## How it works
14
+
15
+ Each **chromosome** is a list of numbers: one **bias** and one **weight** per feature. With them the model computes a score for each sample:
16
+
17
+ ```
18
+ score = bias + weight₁·x₁ + weight₂·x₂ + ... + weightₙ·xₙ
19
+ ```
20
+
21
+ - **Binary:** score ≥ 0 → class 1, score < 0 → class 0
22
+ - **Ordinal:** the score is split into ranges by the **thresholds** (cut points), and each range is a class
23
+
24
+ ### The fitness
25
+
26
+ The score of each chromosome (its fitness) is the **product of the recall of each class**:
27
+
28
+ ```
29
+ fitness = recall(class 0) × recall(class 1) × ... × recall(class K-1)
30
+ ```
31
+
32
+ If the model gets every sample of a class wrong, the fitness becomes 0. This forces the model to get **every** class right, not only the most common one, which is useful when the classes are imbalanced.
33
+
34
+ ### The algorithm cycle
35
+
36
+ ```
37
+ 1. create random population
38
+ │
39
+ ▼
40
+ 2. compute fitness ◄───────────────┐
41
+ │ │
42
+ ▼ │
43
+ 3. select two parents (roulette) │
44
+ │ │
45
+ ▼ │
46
+ 4. crossover (one cut point) │
47
+ │ │
48
+ ▼ │
49
+ 5. mutation │
50
+ │ │
51
+ ▼ │
52
+ 6. replace the worst with ─────────┘
53
+ the best offspring
54
+ ```
55
+
56
+ The cycle stops when it reaches the target fitness or runs out of generations.
57
+
58
+ | Step | What it does |
59
+ |---|---|
60
+ | **Creation** | Creates chromosomes with random genes between -1 and 1 |
61
+ | **Fitness** | Gives each chromosome a score from 0 to 1 |
62
+ | **Selection** | Draws two parents by roulette: the higher the fitness, the higher the chance |
63
+ | **Crossover** | The child takes the beginning of one parent and the end of the other, from a random cut point |
64
+ | **Mutation** | Replaces some genes of each child with new random values |
65
+ | **Update** | The worst of the population leave and the best offspring come in (elitism) |
66
+
67
+ ---
68
+
69
+ ## Installation
70
+
71
+ Requires **Python 3.10+**.
72
+
73
+ ```bash
74
+ pip install genetic-classifier
75
+ ```
76
+
77
+ Or straight from GitHub:
78
+
79
+ ```bash
80
+ pip install git+https://github.com/FeAlmassy/Genetic-Classifier.git
81
+ ```
82
+
83
+ ### For development
84
+
85
+ ```bash
86
+ git clone https://github.com/FeAlmassy/Genetic-Classifier.git
87
+ cd Genetic-Classifier
88
+ python -m venv venv_ag
89
+ source venv_ag/bin/activate # on Windows: venv_ag\Scripts\activate
90
+ pip install -e . # editable mode: code changes apply right away
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Quick start
96
+
97
+ ### Binary
98
+
99
+ ```python
100
+ from genetic_classifier import train, predict, evaluate, read_excel, train_test_split
101
+
102
+ X, y = read_excel("examples/example_1_binary/binary_data_1.xlsx")
103
+ X_train, X_test, y_train, y_test = train_test_split(X, y, seed=0)
104
+
105
+ model = train(X_train, y_train, seed=0) # learns from the training set only
106
+
107
+ y_pred = predict(model, X_test) # classifies data the model has never seen
108
+ results = evaluate(y_test, y_pred) # prints accuracy, fitness, recall and confusion matrix
109
+ ```
110
+
111
+ > The default values of `train` already give good results in most cases. Only tune the parameters if you need to.
112
+
113
+ The functions of each step (`create_chromosomes`, `binary_fitness`, `select_parents_roulette`, `one_point_crossover`, `mutate`, `update_population`) can also be used on their own, imported from their modules (e.g. `from genetic_classifier.mutation import mutate`).
114
+
115
+ ### Ordinal (several classes)
116
+
117
+ The classes must be numbers from `0` to `K-1`, ordered from lowest to highest. For K classes, pass K-1 thresholds in increasing order:
118
+
119
+ ```python
120
+ import numpy as np
121
+
122
+ thresholds = np.array([-1.5, -0.5, 0.5, 1.5]) # 4 cuts -> 5 classes
123
+
124
+ model = train(X, y, thresholds=thresholds, n_generations=2000)
125
+ y_pred = predict(model, X_new)
126
+ ```
127
+
128
+ ### `train` parameters
129
+
130
+ | Parameter | Default | Description |
131
+ |---|---|---|
132
+ | `X` | — | array (n_samples, n_features) with the data |
133
+ | `y` | — | vector with the class of each sample |
134
+ | `n_chromosomes` | `30` | population size |
135
+ | `n_mutated_genes` | `2` | how many genes change in each child |
136
+ | `n_offspring` | `16` | how many children per generation |
137
+ | `n_replacements` | `None` | how many of the worst in the population are swapped for the best children (at most the smaller of `n_chromosomes` and `n_offspring`). `None` = half of `n_offspring` |
138
+ | `n_generations` | `1000` | maximum number of generations |
139
+ | `target_fitness` | `1.0` | stops when the best fitness reaches this value (`1.0` = runs every generation unless it gets everything right) |
140
+ | `thresholds` | `None` | `None` = binary; array with K-1 cuts = ordinal |
141
+ | `gene_min` | `-1.0` | smallest gene value in the initial population |
142
+ | `gene_max` | `1.0` | largest gene value in the initial population |
143
+ | `seed` | `None` | random seed for reproducibility (`None` = different every run) |
144
+ | `verbose` | `True` | prints the best fitness and accuracy of every generation |
145
+
146
+ `train` returns a dictionary with `chromosome` (the best one found), `fitness`, `accuracy` (fraction right on the training data), `generation` (where it stopped), `thresholds` and `history` (lists `best`, `mean` and `accuracy` with the evolution per generation).
147
+
148
+ ### Tuning the parameters
149
+
150
+ The defaults work well in most cases. If you need to tune them, keep in mind that the parameters affect each other:
151
+
152
+ - **Renewal rate = `n_replacements` ÷ `n_chromosomes`:** fraction of the population replaced every generation (default: 8 ÷ 30 ≈ 27%). Too low makes evolution slow; close to 100% the whole population becomes children of the same couple and loses diversity. That is why **increasing only the population usually makes things worse**: increase the replacements too, or leave it as `None`.
153
+ - **`n_offspring` × `n_replacements`:** only the best children enter the population. With more children than replacements, the worst children are discarded.
154
+ - **`n_mutated_genes` × number of features:** what matters is the fraction of the chromosome that changes. With few features, use `1`; with many, `2` or `3`.
155
+ - **Cost ≈ `n_generations` × (`n_chromosomes` + `n_offspring`) × n_samples.**
156
+ - **Explore × refine:** a large population and more mutation search for new solutions; high renewal and little mutation improve the ones already found.
157
+
158
+ To find out whether more generations would help, look at the end of `model["history"]["best"]`: if the fitness is still going up, the model has not finished.
159
+
160
+ ---
161
+
162
+ ## Data format
163
+
164
+ The spreadsheet (`.xlsx` or `.csv`) must follow this layout:
165
+
166
+ | Lessons | X1 | X2 | ... | Xn | CLASS |
167
+ |---|---|---|---|---|---|
168
+ | Y001 | 1 | 0 | ... | 1 | 1 |
169
+ | Y002 | 0 | 1 | ... | 0 | 0 |
170
+
171
+ - **First column:** sample identifier (ignored)
172
+ - **Middle columns:** features
173
+ - **Last column:** class
174
+
175
+ To classify new data, which has no class column, use `has_labels=False`. In that case the function returns only `X`:
176
+
177
+ ```python
178
+ X_new = read_excel("new_data.xlsx", has_labels=False)
179
+ y_pred = predict(model, X_new)
180
+ ```
181
+
182
+ A ready-made template is in [`examples/template/template.xlsx`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/template/template.xlsx).
183
+
184
+ ---
185
+
186
+ ## Examples and results
187
+
188
+ | Notebook | Dataset | Classes | Test accuracy* |
189
+ |---|---|---|---|
190
+ | [`binary_example.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/example_1_binary/binary_example.ipynb) | `binary_data_1.xlsx` (539 samples, 18 features) | 2 | **87%** |
191
+ | [`multiclass_example.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/example_2_multiclass/multiclass_example.ipynb) | `multiclass_data.xlsx` (261 samples, 30 features) | 5 | **79%** |
192
+ | [`mushroom_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/mushroom_classification/mushroom_classification.ipynb) | `mushroom_data.xlsx` (8124 samples, 117 features) | 2 | **100%** |
193
+ | [`heart_disease_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/heart_disease_classification/heart_disease_classification.ipynb) | `heart_data.xlsx` (917 samples, 21 features) | 2 | **85%** |
194
+ | [`diabetes_classification.ipynb`](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/examples/diabetes_classification/diabetes_classification.ipynb) | `diabetes_data.xlsx` (40000 samples, 21 features) | 3 | **58%**† |
195
+
196
+ \* Trained on 80% of the data and tested on the remaining 20%, which the model never saw, always with seed 0.
197
+
198
+ † Prediabetes is very rare in this dataset, so the accuracy alone is misleading: the notebook shows the recall of each class.
199
+
200
+ The binary notebook shows **one generation step by step**, calling each function in the order of the algorithm. The multiclass one shows how to choose the order of the classes when it is not known.
201
+
202
+ ---
203
+
204
+ ## Project structure
205
+
206
+ ```
207
+ Genetic-Classifier/
208
+ ├── src/
209
+ │ └── genetic_classifier/
210
+ │ ├── __init__.py # public API: train, predict, evaluate, confusion_matrix, read_excel, read_csv, train_test_split
211
+ │ ├── core.py # main loop (train) and prediction (predict)
212
+ │ ├── evaluation.py # model evaluation (evaluate) and confusion matrix
213
+ │ ├── creation.py # 1. initial population
214
+ │ ├── fitness.py # 2. binary and ordinal fitness, roulette proportions
215
+ │ ├── selection.py # 3. roulette selection
216
+ │ ├── crossover.py # 4. one-point crossover
217
+ │ ├── mutation.py # 5. mutation
218
+ │ ├── update.py # 6. replacing the worst with the best offspring
219
+ │ ├── reading.py # reading .xlsx and .csv files
220
+ │ └── split.py # train/test split (stratified)
221
+ ├── docs/ # how the algorithm works, with math and examples (Markdown and LaTeX)
222
+ ├── examples/ # example notebooks and datasets
223
+ ├── tests/ # automated tests (coming soon)
224
+ ├── pyproject.toml # package configuration (name, version, dependencies)
225
+ ├── LICENSE # MIT license
226
+ └── requirements.txt
227
+ ```
228
+
229
+ Each step of the algorithm lives in its own module, so you can swap one piece (for example, try another selection method) without touching the others. Every function checks its parameters and gives clear error messages.
230
+
231
+ ---
232
+
233
+ ## Changelog
234
+
235
+ ### 3.0.0
236
+ - **The whole library is now in English** and is published on PyPI as **`genetic-classifier`** (import `genetic_classifier`). The Portuguese version stays available as `algoritmo-genetico` 2.0.0.
237
+ - Every docstring follows the same format: what the function does, each parameter with its type, and what it returns with its type and a suggested variable name.
238
+ - The deprecated alias `rodar` was removed.
239
+
240
+ Migrating from `algoritmo-genetico`:
241
+
242
+ | 2.x (Portuguese) | 3.0 (English) |
243
+ |---|---|
244
+ | `treinar`, `prever`, `avaliar`, `matriz_confusao` | `train`, `predict`, `evaluate`, `confusion_matrix` |
245
+ | `ler_excel`, `ler_csv` (`tem_classe`) | `read_excel`, `read_csv` (`has_labels`) |
246
+ | `dividir_treino_teste` (`proporcao_treino`, `estratificar`) | `train_test_split` (`train_size`, `stratify`) |
247
+ | `qtd_cromossomos`, `qtd_genes_mutados`, `qtd_filhos`, `qtd_substituicoes` | `n_chromosomes`, `n_mutated_genes`, `n_offspring`, `n_replacements` |
248
+ | `geracoes`, `fitness_alvo`, `minimo`, `maximo` | `n_generations`, `target_fitness`, `gene_min`, `gene_max` |
249
+ | `y_real`, `y_previsto`, `nomes_classes` | `y_true`, `y_pred`, `class_names` |
250
+ | keys `cromossomo`, `acuracia`, `geracao`, `historico` (`melhor`, `medio`) | keys `chromosome`, `accuracy`, `generation`, `history` (`best`, `mean`) |
251
+ | key `matriz` of `avaliar` | key `confusion_matrix` of `evaluate` |
252
+ | `criar_cromossomos`, `fitness_binario`, `fitness_ordinal`, `fitness_percentual` | `create_chromosomes`, `binary_fitness`, `ordinal_fitness`, `fitness_proportions` |
253
+ | `selecionar_pais_roleta`, `cruzar_um_ponto`, `mutar`, `atualizar_populacao` | `select_parents_roulette`, `one_point_crossover`, `mutate`, `update_population` |
254
+
255
+ ### 2.0.0
256
+ - New **`evaluate`** function (`avaliar`), which prints and returns accuracy, fitness, recall per class and the confusion matrix. The matrix can also be obtained on its own with **`confusion_matrix`**.
257
+ - `read_excel` and `read_csv` got the **`has_labels`** parameter: with `has_labels=False` they read new data without the class column.
258
+ - New checks: empty cells, text in the features and text classes in ordinal mode now raise clear error messages instead of silently giving wrong results.
259
+ - Training no longer creates offspring in the last generation, since they would never be compared with the best chromosome.
260
+
261
+ ### 1.1.0
262
+ - `rodar` was renamed to **`treinar`** (now `train`), pairing with `prever` (now `predict`).
263
+ - **New default values**, which give much better results without tuning: 30 chromosomes, 2 mutated genes, 16 offspring, replacements = half of the offspring, 1000 generations and target fitness 1.0.
264
+ - Training converts `X` to float internally, which makes it up to ~6x faster when the data is integer (as read by `read_csv`).
265
+
266
+ ---
267
+
268
+ ## License
269
+
270
+ Distributed under the [MIT license](https://github.com/FeAlmassy/Genetic-Classifier/blob/main/LICENSE): you can use, modify and redistribute it freely, as long as you keep the copyright notice.
271
+
272
+ ---
273
+
274
+ ## Authors
275
+
276
+ - **Fellipe Almassy** — [GitHub](https://github.com/FeAlmassy)
277
+ - **Matheus Gomes** — [GitHub](https://github.com/matheos-hash)
@@ -0,0 +1,7 @@
1
+ *.aux
2
+ *.fdb_latexmk
3
+ *.fls
4
+ *.log
5
+ *.out
6
+ *.synctex.gz
7
+ *.toc