rbg-ml 0.1.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 (62) hide show
  1. rbg_ml-0.1.0/PKG-INFO +171 -0
  2. rbg_ml-0.1.0/README.md +154 -0
  3. rbg_ml-0.1.0/pyproject.toml +40 -0
  4. rbg_ml-0.1.0/pyproject.toml.orig +33 -0
  5. rbg_ml-0.1.0/src/rbg/Classification/KNN.py +178 -0
  6. rbg_ml-0.1.0/src/rbg/Classification/LDA.py +187 -0
  7. rbg_ml-0.1.0/src/rbg/Classification/Logistic.py +189 -0
  8. rbg_ml-0.1.0/src/rbg/Classification/QDA.py +198 -0
  9. rbg_ml-0.1.0/src/rbg/Classification/__init__.py +5 -0
  10. rbg_ml-0.1.0/src/rbg/Classification/classifier.py +63 -0
  11. rbg_ml-0.1.0/src/rbg/DecisionTree/_ClassificationTree.py +78 -0
  12. rbg_ml-0.1.0/src/rbg/DecisionTree/_ConstructionTree.py +623 -0
  13. rbg_ml-0.1.0/src/rbg/DecisionTree/_RegressionTree.py +76 -0
  14. rbg_ml-0.1.0/src/rbg/DecisionTree/__init__.py +6 -0
  15. rbg_ml-0.1.0/src/rbg/DecisionTree/decisiontree.py +459 -0
  16. rbg_ml-0.1.0/src/rbg/ModelSelection/GridSearch.py +91 -0
  17. rbg_ml-0.1.0/src/rbg/ModelSelection/GroupKFold.py +76 -0
  18. rbg_ml-0.1.0/src/rbg/ModelSelection/KFold.py +38 -0
  19. rbg_ml-0.1.0/src/rbg/ModelSelection/LOOCV.py +25 -0
  20. rbg_ml-0.1.0/src/rbg/ModelSelection/RandomizedSearch.py +94 -0
  21. rbg_ml-0.1.0/src/rbg/ModelSelection/StratifiedKFold.py +67 -0
  22. rbg_ml-0.1.0/src/rbg/ModelSelection/__init__.py +7 -0
  23. rbg_ml-0.1.0/src/rbg/ModelSelection/holdoutCV.py +39 -0
  24. rbg_ml-0.1.0/src/rbg/NeuralNetwork/MLP.py +220 -0
  25. rbg_ml-0.1.0/src/rbg/NeuralNetwork/NeuralNetwork.py +0 -0
  26. rbg_ml-0.1.0/src/rbg/NeuralNetwork/__init__.py +20 -0
  27. rbg_ml-0.1.0/src/rbg/NeuralNetwork/activations.py +58 -0
  28. rbg_ml-0.1.0/src/rbg/NeuralNetwork/data.py +39 -0
  29. rbg_ml-0.1.0/src/rbg/NeuralNetwork/gradcheck.py +69 -0
  30. rbg_ml-0.1.0/src/rbg/NeuralNetwork/layers.py +94 -0
  31. rbg_ml-0.1.0/src/rbg/NeuralNetwork/losses.py +63 -0
  32. rbg_ml-0.1.0/src/rbg/NeuralNetwork/metrics.py +25 -0
  33. rbg_ml-0.1.0/src/rbg/NeuralNetwork/model.py +180 -0
  34. rbg_ml-0.1.0/src/rbg/NeuralNetwork/optimizers.py +62 -0
  35. rbg_ml-0.1.0/src/rbg/Preprocessing/MinMaxScaler.py +58 -0
  36. rbg_ml-0.1.0/src/rbg/Preprocessing/Standard.py +34 -0
  37. rbg_ml-0.1.0/src/rbg/Preprocessing/ZScoreClipper.py +50 -0
  38. rbg_ml-0.1.0/src/rbg/Preprocessing/__init__.py +4 -0
  39. rbg_ml-0.1.0/src/rbg/Preprocessing/_base.py +75 -0
  40. rbg_ml-0.1.0/src/rbg/Regression/GLM.py +179 -0
  41. rbg_ml-0.1.0/src/rbg/Regression/Lasso.py +144 -0
  42. rbg_ml-0.1.0/src/rbg/Regression/Linear.py +43 -0
  43. rbg_ml-0.1.0/src/rbg/Regression/Polynomial.py +168 -0
  44. rbg_ml-0.1.0/src/rbg/Regression/Ridge.py +104 -0
  45. rbg_ml-0.1.0/src/rbg/Regression/__init__.py +18 -0
  46. rbg_ml-0.1.0/src/rbg/Regression/baseestimator.py +126 -0
  47. rbg_ml-0.1.0/src/rbg/Regression/linearmodel.py +74 -0
  48. rbg_ml-0.1.0/src/rbg/Unsupervised/KMeans.py +283 -0
  49. rbg_ml-0.1.0/src/rbg/Unsupervised/PCA.py +196 -0
  50. rbg_ml-0.1.0/src/rbg/Unsupervised/__init__.py +2 -0
  51. rbg_ml-0.1.0/src/rbg/Utilities/ClassificationMetrics.py +177 -0
  52. rbg_ml-0.1.0/src/rbg/Utilities/CoordinateDescent.py +89 -0
  53. rbg_ml-0.1.0/src/rbg/Utilities/ExponentialFamily.py +115 -0
  54. rbg_ml-0.1.0/src/rbg/Utilities/FisherScoring.py +123 -0
  55. rbg_ml-0.1.0/src/rbg/Utilities/MatrixDesign.py +35 -0
  56. rbg_ml-0.1.0/src/rbg/Utilities/Optimizer.py +79 -0
  57. rbg_ml-0.1.0/src/rbg/Utilities/RandomIntervals.py +15 -0
  58. rbg_ml-0.1.0/src/rbg/Utilities/RegressionMetrics.py +71 -0
  59. rbg_ml-0.1.0/src/rbg/Utilities/Resample.py +39 -0
  60. rbg_ml-0.1.0/src/rbg/Utilities/__init__.py +10 -0
  61. rbg_ml-0.1.0/src/rbg/Utilities/crossvalidation.py +134 -0
  62. rbg_ml-0.1.0/src/rbg/__init__.py +1 -0
rbg_ml-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.3
2
+ Name: rbg-ml
3
+ Version: 0.1.0
4
+ Summary: Basic Machine Learning Library
5
+ Keywords: machine learning,basic,regression
6
+ Author: fragadmsc, lucca moulin
7
+ Author-email: fragadmsc <damasceno.lucas512@gmail.com>
8
+ Requires-Dist: numpy
9
+ Requires-Dist: pandas
10
+ Requires-Dist: furo>=2025.12.19 ; extra == 'docs'
11
+ Requires-Dist: sphinx>=9.1.1 ; extra == 'docs'
12
+ Requires-Dist: pytest>=9.0 ; extra == 'test'
13
+ Requires-Python: >=3.12
14
+ Provides-Extra: docs
15
+ Provides-Extra: test
16
+ Description-Content-Type: text/markdown
17
+
18
+ # RBG (Regressão Bem Geral)
19
+ #### *a.k.a Rodrigo do Bigode Grosso*
20
+
21
+ This is the official repository for the machine learning library titled RBG.
22
+
23
+ The documentation is at: [docs](https://rbg.readthedocs.io/en/latest/)
24
+
25
+ This file contains the structure of the library, the workflow with git/github that should be used and the code style guides. This document should be referred to if you have some doubt (it is also a good context base for asking something to AI).
26
+
27
+ ### Table of Contents
28
+
29
+ - [Quickstart](#quickstart)
30
+ - [Project Structure](#library-structure)
31
+ - [Build System](#build-system)
32
+ - [File Structure](#file-structure)
33
+ - [Architecture & public API](#architecture--public-api)
34
+ - [Tests](#tests)
35
+ - [Git/GitHub Workflow](#gitgithub-workflow)
36
+ - [Good Practices](#good-practices)
37
+ - [Basic Git Workflow](#basic-git-workflow)
38
+ - [Code Style Guide](#code-style-guide)
39
+ - [General Rules](#general-rules)
40
+ - [Docstrings](#docstrings)
41
+
42
+ ### Quickstart
43
+
44
+ Clone the repository locally with `git clone`, and then run `uv sync` to install the necessary dependencies. You need to have Git installed and authenticated with GitHub (usually via SSH, it may be useful to look up a tutorial). You also need to have `uv` installed.
45
+
46
+ ```bash
47
+ git clone https://github.com/fragadmsc/rbg.git
48
+ cd rbg #go to the newly cloned repository
49
+ uv sync
50
+
51
+ ```
52
+
53
+ ### Project Structure
54
+
55
+ #### File Structure
56
+
57
+ The basic file structure is this:
58
+
59
+ ![File Structue](doc_images/file_structure.png)
60
+
61
+ The idea is that each person should usually work separately on some topic (like Unsupervised) and some separated branch.
62
+
63
+ #### Architecture & Public API
64
+
65
+ An API (Application Programming interface) is the interface someone will interact with if they use our library. So the public methods in a class are part of the API, whereas the private helper function in some class is not.
66
+
67
+ The final user will use the library with `rbg.Topic.specific.method()`. So, if you wanted to fit a linear regression model you would do: `rbg.Regression.Linear.fit(x)`. The specifics on what should be the interface of a specific model are in the `test` folder (we should add a documentation that describes the api sometime).
68
+
69
+ #### Build System
70
+
71
+ The build system used is `uv`. It provides some nice useful functionalities and it is quite fast. You can use it to create a virtual environment `uv venv`, to run your code `uv run main.py` You can refer to the [documentation](https://docs.astral.sh/uv/) if needed.
72
+
73
+ #### Tests
74
+
75
+ The tests will use pytest. We use a TDD (Test Driven Development) approach, so (usually) all of the tests are written before the function or classes, which in turn defines the classes interfaces. To use pytest, just do `uv run pytest` in the folder that you want to test.
76
+
77
+ ### Git/Github workflow
78
+
79
+ #### Good practices
80
+
81
+ Each feature should be developed in a separate branch, and no two people should work in the same branch or feature at the same time. The branches are meant to be incremental: don't create only one branch for all of your work. Instead, create a branch for every feature you want to implement, make a pull request to merge it into the main, and then delete it.
82
+
83
+ #### Basic git workflow
84
+
85
+ To make some change, you should first update your local main branch to the latest version:
86
+
87
+ ```bash
88
+ git switch main
89
+ git pull origin main
90
+ ```
91
+
92
+ Then create a branch we will follow a name convention: first the type of the change and then the name:
93
+
94
+ ```
95
+ feature/<name>
96
+ fix/<name>
97
+ refactor/<name>
98
+ docs/<name>
99
+ ```
100
+
101
+ So if we want to create a branch for crating a test for KNN we would create `feature/test-knn`. Fix is for code fixes and bug corrections, refactor is for refactoring the code (like changing an entire class logic to something else) and docs is for adding documentation or comments.
102
+
103
+ ```bash
104
+ git switch -c my-new-branch #the switch -c creates a new branch and switchs to it
105
+ ```
106
+
107
+ After making some changes (creating files, editing files or deleting files), save them with:
108
+
109
+ ```bash
110
+ git add . #the . adds all of the modified files
111
+ ```
112
+
113
+ And then commit them with:
114
+
115
+ ```bash
116
+ git commit -m "my commit message"
117
+ ```
118
+
119
+ When you have the necessary commits, tested the new feature you have implemented, and are ready to merge them into the main branch, you should create a pull request. To do this, make:
120
+
121
+ ```bash
122
+ git fetch #this updates your local information about the github repository without modifying your local branch
123
+ git merge origin/main #this merges the current version of the main branch into your feature branch
124
+ ```
125
+
126
+ Maybe (probably) the `git merge origin/main` will fail eventually, saying that there was a merge conflict. It is normal, and it is not a big problem (it will not completely destroy the repository or something like this, since you are isolated on your branch).
127
+
128
+ If you find some, conflicts, you can run `git status`, which will tell which files are conflicting, then you solve these conflicts (by directly editing the files, it may be useful to look up a tutorial) and then:
129
+
130
+ ```bash
131
+ git add .
132
+ git commit -m "a message"
133
+ ```
134
+
135
+ After solving the conflict (if necessary) and sucessfully merging the origin/main onto your branch, you can push your local branch:
136
+
137
+ ```bash
138
+ git push origin my-new-branch
139
+ ```
140
+
141
+ You need then to see why the merge conflict is happening, and then decide which changes you want to keep. Usually this means running a `git status` or a `git diff the-branch-you-are-in the-branch-you-want-to-merge` and then checking the differences. It might be useful looking up a tutorial when this happens or asking AI.
142
+
143
+ After doing this, you can open github, and an option to pull request will appear:
144
+
145
+ ![Pull Request Example](doc_images/pr.png)
146
+
147
+ This will show that your branch is now on github, and you can click `Compare e pull request` and then click `Create pull request`. This will create a pull request. A pull request is like asking for permission to put your new feature into the main branch. Someone will revise your code, and then choose to accept or reject your pull request.
148
+
149
+ After someone revises your pull request and merge it into the main branch, you can safely delete both the local and the github branch:
150
+
151
+ ```bash
152
+ git push origin --delete my-new-branch
153
+ git switch main
154
+ git branch -d my-new-branch
155
+ ```
156
+
157
+ You should not approve or merge your own pull requests. Every PR should be reviewed and approved by at least one other team member.
158
+
159
+ Also, when accepting pull request, we will always use the rebase option for merging on GitHub (this keeps the commit history clean):
160
+
161
+ ![Rebase](doc_images/rebase.png)
162
+
163
+ ### Code Style Guide
164
+
165
+ #### General rules
166
+
167
+ The code should follow general good practices for python code. Try to make the code pythonic, always use type annotations, make a self-explanatory code, this is, make a code that you can infer the objective of the code just from looking at it, and avoid obvious comments, while using comments when necessary on more complex steps of the code.
168
+
169
+ #### Docstrings
170
+
171
+ For the docstrings, we will follow the [Google style](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings). We will also refer to this document when we are in doubt of what is the best way to write something (it is a big and boring document, there is absolutely no need to read it all, just be aware of using good practices and referring to it when necessary).
rbg_ml-0.1.0/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # RBG (Regressão Bem Geral)
2
+ #### *a.k.a Rodrigo do Bigode Grosso*
3
+
4
+ This is the official repository for the machine learning library titled RBG.
5
+
6
+ The documentation is at: [docs](https://rbg.readthedocs.io/en/latest/)
7
+
8
+ This file contains the structure of the library, the workflow with git/github that should be used and the code style guides. This document should be referred to if you have some doubt (it is also a good context base for asking something to AI).
9
+
10
+ ### Table of Contents
11
+
12
+ - [Quickstart](#quickstart)
13
+ - [Project Structure](#library-structure)
14
+ - [Build System](#build-system)
15
+ - [File Structure](#file-structure)
16
+ - [Architecture & public API](#architecture--public-api)
17
+ - [Tests](#tests)
18
+ - [Git/GitHub Workflow](#gitgithub-workflow)
19
+ - [Good Practices](#good-practices)
20
+ - [Basic Git Workflow](#basic-git-workflow)
21
+ - [Code Style Guide](#code-style-guide)
22
+ - [General Rules](#general-rules)
23
+ - [Docstrings](#docstrings)
24
+
25
+ ### Quickstart
26
+
27
+ Clone the repository locally with `git clone`, and then run `uv sync` to install the necessary dependencies. You need to have Git installed and authenticated with GitHub (usually via SSH, it may be useful to look up a tutorial). You also need to have `uv` installed.
28
+
29
+ ```bash
30
+ git clone https://github.com/fragadmsc/rbg.git
31
+ cd rbg #go to the newly cloned repository
32
+ uv sync
33
+
34
+ ```
35
+
36
+ ### Project Structure
37
+
38
+ #### File Structure
39
+
40
+ The basic file structure is this:
41
+
42
+ ![File Structue](doc_images/file_structure.png)
43
+
44
+ The idea is that each person should usually work separately on some topic (like Unsupervised) and some separated branch.
45
+
46
+ #### Architecture & Public API
47
+
48
+ An API (Application Programming interface) is the interface someone will interact with if they use our library. So the public methods in a class are part of the API, whereas the private helper function in some class is not.
49
+
50
+ The final user will use the library with `rbg.Topic.specific.method()`. So, if you wanted to fit a linear regression model you would do: `rbg.Regression.Linear.fit(x)`. The specifics on what should be the interface of a specific model are in the `test` folder (we should add a documentation that describes the api sometime).
51
+
52
+ #### Build System
53
+
54
+ The build system used is `uv`. It provides some nice useful functionalities and it is quite fast. You can use it to create a virtual environment `uv venv`, to run your code `uv run main.py` You can refer to the [documentation](https://docs.astral.sh/uv/) if needed.
55
+
56
+ #### Tests
57
+
58
+ The tests will use pytest. We use a TDD (Test Driven Development) approach, so (usually) all of the tests are written before the function or classes, which in turn defines the classes interfaces. To use pytest, just do `uv run pytest` in the folder that you want to test.
59
+
60
+ ### Git/Github workflow
61
+
62
+ #### Good practices
63
+
64
+ Each feature should be developed in a separate branch, and no two people should work in the same branch or feature at the same time. The branches are meant to be incremental: don't create only one branch for all of your work. Instead, create a branch for every feature you want to implement, make a pull request to merge it into the main, and then delete it.
65
+
66
+ #### Basic git workflow
67
+
68
+ To make some change, you should first update your local main branch to the latest version:
69
+
70
+ ```bash
71
+ git switch main
72
+ git pull origin main
73
+ ```
74
+
75
+ Then create a branch we will follow a name convention: first the type of the change and then the name:
76
+
77
+ ```
78
+ feature/<name>
79
+ fix/<name>
80
+ refactor/<name>
81
+ docs/<name>
82
+ ```
83
+
84
+ So if we want to create a branch for crating a test for KNN we would create `feature/test-knn`. Fix is for code fixes and bug corrections, refactor is for refactoring the code (like changing an entire class logic to something else) and docs is for adding documentation or comments.
85
+
86
+ ```bash
87
+ git switch -c my-new-branch #the switch -c creates a new branch and switchs to it
88
+ ```
89
+
90
+ After making some changes (creating files, editing files or deleting files), save them with:
91
+
92
+ ```bash
93
+ git add . #the . adds all of the modified files
94
+ ```
95
+
96
+ And then commit them with:
97
+
98
+ ```bash
99
+ git commit -m "my commit message"
100
+ ```
101
+
102
+ When you have the necessary commits, tested the new feature you have implemented, and are ready to merge them into the main branch, you should create a pull request. To do this, make:
103
+
104
+ ```bash
105
+ git fetch #this updates your local information about the github repository without modifying your local branch
106
+ git merge origin/main #this merges the current version of the main branch into your feature branch
107
+ ```
108
+
109
+ Maybe (probably) the `git merge origin/main` will fail eventually, saying that there was a merge conflict. It is normal, and it is not a big problem (it will not completely destroy the repository or something like this, since you are isolated on your branch).
110
+
111
+ If you find some, conflicts, you can run `git status`, which will tell which files are conflicting, then you solve these conflicts (by directly editing the files, it may be useful to look up a tutorial) and then:
112
+
113
+ ```bash
114
+ git add .
115
+ git commit -m "a message"
116
+ ```
117
+
118
+ After solving the conflict (if necessary) and sucessfully merging the origin/main onto your branch, you can push your local branch:
119
+
120
+ ```bash
121
+ git push origin my-new-branch
122
+ ```
123
+
124
+ You need then to see why the merge conflict is happening, and then decide which changes you want to keep. Usually this means running a `git status` or a `git diff the-branch-you-are-in the-branch-you-want-to-merge` and then checking the differences. It might be useful looking up a tutorial when this happens or asking AI.
125
+
126
+ After doing this, you can open github, and an option to pull request will appear:
127
+
128
+ ![Pull Request Example](doc_images/pr.png)
129
+
130
+ This will show that your branch is now on github, and you can click `Compare e pull request` and then click `Create pull request`. This will create a pull request. A pull request is like asking for permission to put your new feature into the main branch. Someone will revise your code, and then choose to accept or reject your pull request.
131
+
132
+ After someone revises your pull request and merge it into the main branch, you can safely delete both the local and the github branch:
133
+
134
+ ```bash
135
+ git push origin --delete my-new-branch
136
+ git switch main
137
+ git branch -d my-new-branch
138
+ ```
139
+
140
+ You should not approve or merge your own pull requests. Every PR should be reviewed and approved by at least one other team member.
141
+
142
+ Also, when accepting pull request, we will always use the rebase option for merging on GitHub (this keeps the commit history clean):
143
+
144
+ ![Rebase](doc_images/rebase.png)
145
+
146
+ ### Code Style Guide
147
+
148
+ #### General rules
149
+
150
+ The code should follow general good practices for python code. Try to make the code pythonic, always use type annotations, make a self-explanatory code, this is, make a code that you can infer the objective of the code just from looking at it, and avoid obvious comments, while using comments when necessary on more complex steps of the code.
151
+
152
+ #### Docstrings
153
+
154
+ For the docstrings, we will follow the [Google style](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings). We will also refer to this document when we are in doubt of what is the best way to write something (it is a big and boring document, there is absolutely no need to read it all, just be aware of using good practices and referring to it when necessary).
@@ -0,0 +1,40 @@
1
+ [project]
2
+ name = "rbg-ml"
3
+ version = "0.1.0"
4
+ description = "Basic Machine Learning Library"
5
+ readme = "README.md"
6
+ keywords = [
7
+ "machine learning",
8
+ "basic",
9
+ "regression",
10
+ ]
11
+ requires-python = ">=3.12"
12
+ dependencies = [
13
+ "numpy",
14
+ "pandas",
15
+ ]
16
+
17
+ [[project.authors]]
18
+ name = "fragadmsc"
19
+ email = "damasceno.lucas512@gmail.com"
20
+
21
+ [[project.authors]]
22
+ name = "lucca moulin"
23
+
24
+ [project.optional-dependencies]
25
+ test = ["pytest>=9.0"]
26
+ docs = [
27
+ "furo>=2025.12.19",
28
+ "sphinx>=9.1.1",
29
+ ]
30
+
31
+ [tool.uv.build-backend]
32
+ module-name = "rbg"
33
+
34
+ [tool.pytest.ini_options]
35
+ pythonpath = ["src"]
36
+ testpaths = ["test"]
37
+
38
+ [build-system]
39
+ requires = ["uv_build>=0.12.13,<0.13.0"]
40
+ build-backend = "uv_build"
@@ -0,0 +1,33 @@
1
+ [project]
2
+ name = "rbg-ml"
3
+ version = "0.1.0"
4
+ description = "Basic Machine Learning Library"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "fragadmsc", email = "damasceno.lucas512@gmail.com" },
8
+ { name = "lucca moulin"}
9
+ ]
10
+ keywords = ["machine learning", "basic", "regression"]
11
+ requires-python = ">=3.12"
12
+ dependencies = [
13
+ "numpy",
14
+ "pandas",
15
+ ]
16
+
17
+ [tool.uv.build-backend]
18
+ module-name = "rbg"
19
+
20
+ [project.optional-dependencies]
21
+ test = ["pytest>=9.0"]
22
+ docs = [
23
+ "furo>=2025.12.19",
24
+ "sphinx>=9.1.1",
25
+ ]
26
+
27
+ [build-system]
28
+ requires = ["uv_build>=0.12.13,<0.13.0"]
29
+ build-backend = "uv_build"
30
+
31
+ [tool.pytest.ini_options]
32
+ pythonpath = ["src"]
33
+ testpaths = ["test"]
@@ -0,0 +1,178 @@
1
+ import numpy as np
2
+ from rbg.Classification.classifier import Classifier
3
+
4
+ class KNN(Classifier):
5
+ """K-nearest neighbors classifier for categorical labels."""
6
+
7
+ def __init__(self, labels=None, k=3, reference_class = None):
8
+ """Initialize the classifier with class labels and the number of neighbors.
9
+
10
+ Args:
11
+ labels: Unique class labels supported by the classifier.
12
+ k: Number of nearest neighbors used to classify each observation.
13
+ Defaults to 3.
14
+ reference_class: Reference label used to initialize the base
15
+ classifier.
16
+
17
+ Raises:
18
+ ValueError: If the class labels or reference label are invalid,
19
+ as defined by the base classifier.
20
+ """
21
+ Classifier.__init__(self, labels, reference_class)
22
+ self.set_params(k)
23
+
24
+ def set_params(self, k):
25
+ """Set the number of nearest neighbors.
26
+
27
+ Args:
28
+ k: Positive integer specifying the number of neighbors to consider.
29
+
30
+ Returns:
31
+ The classifier instance, allowing method chaining.
32
+
33
+ Raises:
34
+ ValueError: If k is not a positive integer or is a boolean.
35
+ """
36
+ if isinstance(k, bool) == False:
37
+ if isinstance(k, int) and k>0:
38
+ self.k = k
39
+ else:
40
+ raise ValueError("k must be a positive integer.")
41
+ else:
42
+ raise ValueError("k must be a positive integer.")
43
+ return self
44
+
45
+ def get_params(self):
46
+ """Return the current classifier parameters.
47
+
48
+ Returns:
49
+ Dictionary containing k, the number of nearest neighbors.
50
+ """
51
+ return {"k": self.k}
52
+
53
+ def fit(self, X,y):
54
+ """Store the training data after validating their format and contents.
55
+
56
+ Args:
57
+ X: Numerical training feature matrix of shape
58
+ (n_samples, n_features). All values must be finite.
59
+ y: One-dimensional array of class labels of shape (n_samples,).
60
+ All labels must belong to the set declared at initialization.
61
+
62
+ Raises:
63
+ ValueError: If X or y has an invalid dimension, X contains
64
+ non-numerical or non-finite values, y contains unknown labels,
65
+ the numbers of observations do not match, the data are empty,
66
+ or X has no features.
67
+ """
68
+ self._fit_done = False
69
+
70
+ X = np.asarray(X)
71
+ y = np.asarray(y)
72
+
73
+ if X.ndim != 2:
74
+ raise ValueError("X must be two-dimensional.")
75
+ if np.issubdtype(X.dtype, np.number) == False:
76
+ raise ValueError("X must be a numerical array.")
77
+ else:
78
+ if np.isfinite(X).all() == False:
79
+ raise ValueError("X must have only finite values.")
80
+ if y.ndim != 1:
81
+ raise ValueError("y must be one-dimensional.")
82
+ if X.shape[0] != y.shape[0]:
83
+ raise ValueError("The data do not match.")
84
+ if X.shape[0] == 0 or y.shape[0] == 0 or y.size == 0:
85
+ raise ValueError("X and y must not be empty.")
86
+ if X.shape[1] == 0:
87
+ raise ValueError("X must have at least one feature.")
88
+ if self._labels is None:
89
+ self._set_labels(np.unique(y))
90
+ elif not np.isin(y, self._labels).all():
91
+ raise ValueError("y contains unknown class labels.")
92
+
93
+ self._X_train = X
94
+ self._y_train = y
95
+ self._fit_done = True
96
+
97
+ def predict(self, X):
98
+ """Predict class labels using the majority vote of the nearest neighbors.
99
+
100
+ For each observation, calculate the Euclidean distances to the training
101
+ observations, select the k nearest neighbors, and assign the most
102
+ frequent class among their labels.
103
+
104
+ Args:
105
+ X: Numerical feature matrix of shape
106
+ (n_new_samples, n_features). The number of features must match
107
+ the training data, and all values must be finite.
108
+
109
+ Returns:
110
+ Array of predicted class labels of shape (n_new_samples,).
111
+
112
+ Raises:
113
+ ValueError: If the model has not been fitted, X has an invalid
114
+ dimension, contains non-numerical or non-finite values, is
115
+ empty, or has a different number of features from the
116
+ training data.
117
+ """
118
+ if self._fit_done == False:
119
+ raise ValueError("The model must be trained before prediction.")
120
+
121
+ X = np.asarray(X)
122
+
123
+ if X.ndim != 2:
124
+ raise ValueError("X must be two-dimensional.")
125
+ if np.issubdtype(X.dtype, np.number) == False:
126
+ raise ValueError("X must be a numerical array.")
127
+ else:
128
+ if np.isfinite(X).all() == False:
129
+ raise ValueError("X must have only finite values.")
130
+ if X.shape[0] == 0:
131
+ raise ValueError("X must not be empty.")
132
+ if X.shape[1] != self._X_train.shape[1]:
133
+ raise ValueError("X must be the same number of features as the training X.")
134
+
135
+ def min_distance(x, k):
136
+ """Return the indices of the k training observations closest to x.
137
+
138
+ Args:
139
+ x: Feature vector of a single observation.
140
+ k: Number of nearest neighbors to select.
141
+
142
+ Returns:
143
+ Indices of the k training observations with the smallest
144
+ Euclidean distances to x.
145
+ """
146
+ dist = [sum((x[i]-amostra[i])**2 for i in range(len(x)))**(1/2) for amostra in self._X_train]
147
+ indice = np.argsort(dist)[:k]
148
+ return indice
149
+
150
+ def class_neighbors(indice):
151
+ """Retrieve the class labels of the selected neighbors.
152
+
153
+ Args:
154
+ indice: Indices of the selected training observations.
155
+
156
+ Returns:
157
+ Array of class labels corresponding to the selected neighbors.
158
+ """
159
+ neighbors = self._y_train[indice]
160
+ return neighbors
161
+
162
+ prediction = [class_neighbors(min_distance(x, self.k)) for x in X]
163
+
164
+ def final_class(prediction):
165
+ """Determine the most frequent class among the neighbors.
166
+
167
+ Args:
168
+ prediction: Array of class labels assigned to the neighbors.
169
+
170
+ Returns:
171
+ Class label with the highest frequency. Ties are resolved by
172
+ selecting the first class returned by np.unique.
173
+ """
174
+ labels, counts = np.unique(prediction, return_counts=True)
175
+ return labels[np.argmax(counts)]
176
+
177
+ predicted_labels = np.array([final_class(neighbors) for neighbors in prediction])
178
+ return predicted_labels