mlextend 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.
- mlextend-0.1.0/LICENSE +21 -0
- mlextend-0.1.0/PKG-INFO +107 -0
- mlextend-0.1.0/README.md +92 -0
- mlextend-0.1.0/pyproject.toml +30 -0
- mlextend-0.1.0/src/mlextend/__init__.py +51 -0
- mlextend-0.1.0/src/mlextend/_experiment.py +70 -0
- mlextend-0.1.0/src/mlextend/codes/exp01.txt +110 -0
- mlextend-0.1.0/src/mlextend/codes/exp02.txt +89 -0
- mlextend-0.1.0/src/mlextend/codes/exp03.txt +110 -0
- mlextend-0.1.0/src/mlextend/codes/exp04.txt +104 -0
- mlextend-0.1.0/src/mlextend/codes/exp05.txt +67 -0
- mlextend-0.1.0/src/mlextend/codes/exp06.txt +63 -0
- mlextend-0.1.0/src/mlextend/codes/exp07.txt +98 -0
- mlextend-0.1.0/src/mlextend/codes/exp08.txt +82 -0
- mlextend-0.1.0/src/mlextend/codes/exp09.txt +87 -0
- mlextend-0.1.0/src/mlextend/codes/exp10.txt +134 -0
- mlextend-0.1.0/tests/test_mlextend.py +98 -0
mlextend-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The mlextend contributors
|
|
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.
|
mlextend-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mlextend
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ready-to-copy source code of 10 machine learning practicals (EDA, regression, KNN, decision tree, K-Means, PCA, Apriori, Q-Learning).
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: education,lab,machine learning,practicals,scikit-learn,source code
|
|
8
|
+
Classifier: Intended Audience :: Education
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Topic :: Education
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# mlextend
|
|
17
|
+
|
|
18
|
+
Ready-to-copy source code for 10 machine learning practicals.
|
|
19
|
+
|
|
20
|
+
`mlextend` does **not** run anything. Each experiment only gives you its complete
|
|
21
|
+
Python code as plain text. Copy it into Jupyter Notebook, VS Code or any other
|
|
22
|
+
Python environment and run it there.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install mlextend
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The package itself has no dependencies. Each practical lists the libraries it needs
|
|
31
|
+
in its first comment lines, for example:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install numpy pandas matplotlib seaborn scikit-learn statsmodels mlxtend
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import mlextend
|
|
41
|
+
|
|
42
|
+
mlextend.list_experiments() # list all experiments
|
|
43
|
+
|
|
44
|
+
mlextend.exp1.print() # print the complete code of Experiment 1
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Or import single experiments:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from mlextend import exp3, exp7
|
|
51
|
+
|
|
52
|
+
exp3.print()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Call | What it does |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `exp1.print()` | Prints the complete code as plain text, ready to copy |
|
|
58
|
+
| `exp1.code` | Returns the complete code as a Python string |
|
|
59
|
+
| `exp1.show()` | Shows syntax-highlighted code in Jupyter (plain text elsewhere) |
|
|
60
|
+
| `exp1.save("exp1.py")` | Saves the code to a `.py` file (default name: `exp1.py`) |
|
|
61
|
+
|
|
62
|
+
`save()` will not replace an existing file unless you pass `overwrite=True`:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
mlextend.exp1.save("exp1.py", overwrite=True)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
None of these calls execute, import or compile the practical code.
|
|
69
|
+
|
|
70
|
+
## Using your own dataset
|
|
71
|
+
|
|
72
|
+
Where a practical reads a file, the line just above it is marked:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# CHANGE THIS PATH TO YOUR DATASET
|
|
76
|
+
data = pd.read_csv("heart_disease.csv")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Replace the file name with the path to your own CSV, and make sure the column names
|
|
80
|
+
match the ones used in the code. No datasets are bundled with this package.
|
|
81
|
+
|
|
82
|
+
| Experiment | File needed | Required columns |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| exp4 | `heart_disease.csv` | `Age, Resting_Blood_Pressure, Cholesterol, Maximum_Heart_Rate, Exercise_Induced_Angina, Heart_Disease` |
|
|
85
|
+
| exp7 | `Mall_Customers.csv` | `Age, Annual Income (k$), Spending Score (1-100)` |
|
|
86
|
+
|
|
87
|
+
All other experiments generate their own data or use a dataset built into scikit-learn.
|
|
88
|
+
exp1 and exp2 also show where to plug in your own CSV.
|
|
89
|
+
|
|
90
|
+
## Experiments
|
|
91
|
+
|
|
92
|
+
| Name | Topic | Libraries |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `exp1` | Data Pre-processing and Exploratory Data Analysis (EDA) | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
95
|
+
| `exp2` | Simple Linear Regression | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
96
|
+
| `exp3` | Multiple Linear Regression (House Price Prediction) | numpy, pandas, matplotlib, seaborn, scikit-learn, statsmodels |
|
|
97
|
+
| `exp4` | Logistic Regression for Heart Disease Prediction | pandas, matplotlib, scikit-learn |
|
|
98
|
+
| `exp5` | K-Nearest Neighbors (KNN) Classifier for Credit Risk Rating | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
99
|
+
| `exp6` | Decision Tree Classifier for Multi-Class Credit Risk Assessment | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
100
|
+
| `exp7` | K-Means Clustering for Customer Profiling | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
101
|
+
| `exp8` | Dimensionality Reduction using PCA | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
102
|
+
| `exp9` | Apriori Algorithm for Association Rule Mining | pandas, mlxtend |
|
|
103
|
+
| `exp10` | Q-Learning Algorithm for Grid World Environment | numpy, pandas |
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
mlextend-0.1.0/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# mlextend
|
|
2
|
+
|
|
3
|
+
Ready-to-copy source code for 10 machine learning practicals.
|
|
4
|
+
|
|
5
|
+
`mlextend` does **not** run anything. Each experiment only gives you its complete
|
|
6
|
+
Python code as plain text. Copy it into Jupyter Notebook, VS Code or any other
|
|
7
|
+
Python environment and run it there.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install mlextend
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The package itself has no dependencies. Each practical lists the libraries it needs
|
|
16
|
+
in its first comment lines, for example:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install numpy pandas matplotlib seaborn scikit-learn statsmodels mlxtend
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import mlextend
|
|
26
|
+
|
|
27
|
+
mlextend.list_experiments() # list all experiments
|
|
28
|
+
|
|
29
|
+
mlextend.exp1.print() # print the complete code of Experiment 1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or import single experiments:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from mlextend import exp3, exp7
|
|
36
|
+
|
|
37
|
+
exp3.print()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Call | What it does |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `exp1.print()` | Prints the complete code as plain text, ready to copy |
|
|
43
|
+
| `exp1.code` | Returns the complete code as a Python string |
|
|
44
|
+
| `exp1.show()` | Shows syntax-highlighted code in Jupyter (plain text elsewhere) |
|
|
45
|
+
| `exp1.save("exp1.py")` | Saves the code to a `.py` file (default name: `exp1.py`) |
|
|
46
|
+
|
|
47
|
+
`save()` will not replace an existing file unless you pass `overwrite=True`:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
mlextend.exp1.save("exp1.py", overwrite=True)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
None of these calls execute, import or compile the practical code.
|
|
54
|
+
|
|
55
|
+
## Using your own dataset
|
|
56
|
+
|
|
57
|
+
Where a practical reads a file, the line just above it is marked:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# CHANGE THIS PATH TO YOUR DATASET
|
|
61
|
+
data = pd.read_csv("heart_disease.csv")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Replace the file name with the path to your own CSV, and make sure the column names
|
|
65
|
+
match the ones used in the code. No datasets are bundled with this package.
|
|
66
|
+
|
|
67
|
+
| Experiment | File needed | Required columns |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| exp4 | `heart_disease.csv` | `Age, Resting_Blood_Pressure, Cholesterol, Maximum_Heart_Rate, Exercise_Induced_Angina, Heart_Disease` |
|
|
70
|
+
| exp7 | `Mall_Customers.csv` | `Age, Annual Income (k$), Spending Score (1-100)` |
|
|
71
|
+
|
|
72
|
+
All other experiments generate their own data or use a dataset built into scikit-learn.
|
|
73
|
+
exp1 and exp2 also show where to plug in your own CSV.
|
|
74
|
+
|
|
75
|
+
## Experiments
|
|
76
|
+
|
|
77
|
+
| Name | Topic | Libraries |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `exp1` | Data Pre-processing and Exploratory Data Analysis (EDA) | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
80
|
+
| `exp2` | Simple Linear Regression | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
81
|
+
| `exp3` | Multiple Linear Regression (House Price Prediction) | numpy, pandas, matplotlib, seaborn, scikit-learn, statsmodels |
|
|
82
|
+
| `exp4` | Logistic Regression for Heart Disease Prediction | pandas, matplotlib, scikit-learn |
|
|
83
|
+
| `exp5` | K-Nearest Neighbors (KNN) Classifier for Credit Risk Rating | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
84
|
+
| `exp6` | Decision Tree Classifier for Multi-Class Credit Risk Assessment | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
85
|
+
| `exp7` | K-Means Clustering for Customer Profiling | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
86
|
+
| `exp8` | Dimensionality Reduction using PCA | numpy, pandas, matplotlib, seaborn, scikit-learn |
|
|
87
|
+
| `exp9` | Apriori Algorithm for Association Rule Mining | pandas, mlxtend |
|
|
88
|
+
| `exp10` | Q-Learning Algorithm for Grid World Environment | numpy, pandas |
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.24"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mlextend"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Ready-to-copy source code of 10 machine learning practicals (EDA, regression, KNN, decision tree, K-Means, PCA, Apriori, Q-Learning)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
dependencies = []
|
|
14
|
+
keywords = ["machine learning", "practicals", "lab", "education", "scikit-learn", "source code"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Intended Audience :: Education",
|
|
19
|
+
"Topic :: Education",
|
|
20
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[tool.hatch.build.targets.wheel]
|
|
24
|
+
packages = ["src/mlextend"]
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.sdist]
|
|
27
|
+
include = ["src/mlextend", "tests", "README.md", "LICENSE", "pyproject.toml"]
|
|
28
|
+
|
|
29
|
+
[tool.pytest.ini_options]
|
|
30
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""mlextend - ready-to-copy source code of 10 machine learning practicals.
|
|
2
|
+
|
|
3
|
+
import mlextend
|
|
4
|
+
mlextend.list_experiments()
|
|
5
|
+
mlextend.exp1.print() # print the full code
|
|
6
|
+
mlextend.exp1.code # the code as a string
|
|
7
|
+
mlextend.exp1.show() # syntax-highlighted in Jupyter
|
|
8
|
+
mlextend.exp1.save() # write exp1.py
|
|
9
|
+
|
|
10
|
+
Retrieving code never executes it.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from ._experiment import Experiment
|
|
14
|
+
|
|
15
|
+
__version__ = "0.1.0"
|
|
16
|
+
|
|
17
|
+
_TITLES = {
|
|
18
|
+
1: "Data Pre-processing and Exploratory Data Analysis (EDA)",
|
|
19
|
+
2: "Simple Linear Regression",
|
|
20
|
+
3: "Multiple Linear Regression (House Price Prediction)",
|
|
21
|
+
4: "Logistic Regression for Heart Disease Prediction",
|
|
22
|
+
5: "K-Nearest Neighbors (KNN) Classifier for Credit Risk Rating",
|
|
23
|
+
6: "Decision Tree Classifier for Multi-Class Credit Risk Assessment",
|
|
24
|
+
7: "K-Means Clustering for Customer Profiling",
|
|
25
|
+
8: "Dimensionality Reduction using PCA",
|
|
26
|
+
9: "Apriori Algorithm for Association Rule Mining",
|
|
27
|
+
10: "Q-Learning Algorithm for Grid World Environment",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
EXPERIMENTS = {f"exp{n}": Experiment(n, t) for n, t in _TITLES.items()}
|
|
31
|
+
|
|
32
|
+
exp1 = EXPERIMENTS["exp1"]
|
|
33
|
+
exp2 = EXPERIMENTS["exp2"]
|
|
34
|
+
exp3 = EXPERIMENTS["exp3"]
|
|
35
|
+
exp4 = EXPERIMENTS["exp4"]
|
|
36
|
+
exp5 = EXPERIMENTS["exp5"]
|
|
37
|
+
exp6 = EXPERIMENTS["exp6"]
|
|
38
|
+
exp7 = EXPERIMENTS["exp7"]
|
|
39
|
+
exp8 = EXPERIMENTS["exp8"]
|
|
40
|
+
exp9 = EXPERIMENTS["exp9"]
|
|
41
|
+
exp10 = EXPERIMENTS["exp10"]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def list_experiments():
|
|
45
|
+
"""Print all available experiments and return their names."""
|
|
46
|
+
for name, exp in EXPERIMENTS.items():
|
|
47
|
+
print(f"{name:<6} {exp.title}")
|
|
48
|
+
return list(EXPERIMENTS)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__all__ = ["Experiment", "EXPERIMENTS", "list_experiments", *EXPERIMENTS]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""The Experiment class: read-only access to a practical's source code.
|
|
2
|
+
|
|
3
|
+
Nothing in this module ever executes, imports or compiles the practical code.
|
|
4
|
+
The code is stored as plain text files inside the package and only read.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import builtins
|
|
10
|
+
import os
|
|
11
|
+
from importlib.resources import files
|
|
12
|
+
|
|
13
|
+
_CODES = "codes"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Experiment:
|
|
17
|
+
"""One practical. Use ``.print()``, ``.code``, ``.show()`` and ``.save()``."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, number: int, title: str) -> None:
|
|
20
|
+
self.number = number
|
|
21
|
+
self.name = f"exp{number}"
|
|
22
|
+
self.title = title
|
|
23
|
+
self._resource = f"exp{number:02d}.txt"
|
|
24
|
+
self._code: str | None = None
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def code(self) -> str:
|
|
28
|
+
"""The complete source code of the practical, as a string."""
|
|
29
|
+
if self._code is None:
|
|
30
|
+
path = files(__package__).joinpath(_CODES).joinpath(self._resource)
|
|
31
|
+
self._code = path.read_text(encoding="utf-8")
|
|
32
|
+
return self._code
|
|
33
|
+
|
|
34
|
+
def print(self) -> None:
|
|
35
|
+
"""Print the complete source code as plain text, ready to copy."""
|
|
36
|
+
builtins.print(self.code, end="")
|
|
37
|
+
|
|
38
|
+
def show(self) -> None:
|
|
39
|
+
"""Display the code in a readable format.
|
|
40
|
+
|
|
41
|
+
In Jupyter / IPython the code is rendered with syntax highlighting;
|
|
42
|
+
anywhere else it is printed as plain text.
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
from IPython import get_ipython
|
|
46
|
+
from IPython.display import Markdown, display
|
|
47
|
+
|
|
48
|
+
shell = get_ipython()
|
|
49
|
+
if shell is not None and shell.__class__.__name__ == "ZMQInteractiveShell":
|
|
50
|
+
display(Markdown(f"```python\n{self.code}```"))
|
|
51
|
+
return
|
|
52
|
+
except ImportError:
|
|
53
|
+
pass
|
|
54
|
+
self.print()
|
|
55
|
+
|
|
56
|
+
def save(self, path: str | os.PathLike | None = None, overwrite: bool = False) -> str:
|
|
57
|
+
"""Save the code to a ``.py`` file and return its path.
|
|
58
|
+
|
|
59
|
+
Defaults to ``exp<N>.py`` in the current directory. An existing file is
|
|
60
|
+
not replaced unless ``overwrite=True``.
|
|
61
|
+
"""
|
|
62
|
+
path = os.fspath(path) if path is not None else f"{self.name}.py"
|
|
63
|
+
if os.path.exists(path) and not overwrite:
|
|
64
|
+
raise FileExistsError(f"{path} already exists; pass overwrite=True to replace it")
|
|
65
|
+
with open(path, "w", encoding="utf-8", newline="\n") as fh:
|
|
66
|
+
fh.write(self.code)
|
|
67
|
+
return path
|
|
68
|
+
|
|
69
|
+
def __repr__(self) -> str:
|
|
70
|
+
return f"<{self.name}: {self.title}>"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Experiment 1: Data Pre-processing and Exploratory Data Analysis (EDA)
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import seaborn as sns
|
|
8
|
+
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
|
|
9
|
+
|
|
10
|
+
# ==========================================
|
|
11
|
+
# STEP 1: Loading the Dataset
|
|
12
|
+
# ==========================================
|
|
13
|
+
# Raw retail customer dataset (from the problem statement).
|
|
14
|
+
# To use your own data instead, uncomment the next line:
|
|
15
|
+
# CHANGE THIS PATH TO YOUR DATASET
|
|
16
|
+
# df = pd.read_csv("your_dataset.csv")
|
|
17
|
+
df = pd.DataFrame({
|
|
18
|
+
'CustomerID': [101, 102, 103, 104, 105, 106, 107],
|
|
19
|
+
'Age': [23, 45, np.nan, 31, 22, 54, 38],
|
|
20
|
+
'Annual_Income_k': [50, 85, 62, np.nan, 45, 120, 350],
|
|
21
|
+
'City': ['New York', 'Paris', 'New York', 'London', np.nan, 'London', 'Paris']
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
print("--- Raw Dataset ---")
|
|
25
|
+
print(df)
|
|
26
|
+
|
|
27
|
+
# ==========================================
|
|
28
|
+
# STEP 2: Data Inspection & Handling Missing Values
|
|
29
|
+
# ==========================================
|
|
30
|
+
print("\n--- Dataset Info ---")
|
|
31
|
+
df.info()
|
|
32
|
+
|
|
33
|
+
print("\n--- Missing Values per Column ---")
|
|
34
|
+
print(df.isnull().sum())
|
|
35
|
+
|
|
36
|
+
# Numerical columns -> Median imputation (robust to outliers)
|
|
37
|
+
for col in ['Age', 'Annual_Income_k']:
|
|
38
|
+
df[col] = df[col].fillna(df[col].median())
|
|
39
|
+
|
|
40
|
+
# Categorical column -> Mode imputation
|
|
41
|
+
df['City'] = df['City'].fillna(df['City'].mode()[0])
|
|
42
|
+
|
|
43
|
+
print("\n--- Dataset after Imputation ---")
|
|
44
|
+
print(df)
|
|
45
|
+
|
|
46
|
+
# ==========================================
|
|
47
|
+
# STEP 3: Outlier Detection & Treatment (IQR Capping)
|
|
48
|
+
# ==========================================
|
|
49
|
+
Q1 = df['Annual_Income_k'].quantile(0.25)
|
|
50
|
+
Q3 = df['Annual_Income_k'].quantile(0.75)
|
|
51
|
+
IQR = Q3 - Q1
|
|
52
|
+
lower_bound = Q1 - 1.5 * IQR
|
|
53
|
+
upper_bound = Q3 + 1.5 * IQR
|
|
54
|
+
|
|
55
|
+
print(f"\nIQR Bounds for Annual_Income_k: [{lower_bound:.2f}, {upper_bound:.2f}]")
|
|
56
|
+
outliers = df[(df['Annual_Income_k'] < lower_bound) | (df['Annual_Income_k'] > upper_bound)]
|
|
57
|
+
print("Detected Outliers:")
|
|
58
|
+
print(outliers)
|
|
59
|
+
|
|
60
|
+
# Boxplot before capping
|
|
61
|
+
plt.figure(figsize=(6, 4))
|
|
62
|
+
sns.boxplot(x=df['Annual_Income_k'])
|
|
63
|
+
plt.title('Annual Income (Before Outlier Capping)')
|
|
64
|
+
plt.show()
|
|
65
|
+
|
|
66
|
+
# Cap values outside the IQR bounds
|
|
67
|
+
df['Annual_Income_k'] = df['Annual_Income_k'].clip(lower=lower_bound, upper=upper_bound)
|
|
68
|
+
|
|
69
|
+
print("\n--- Dataset after Outlier Capping ---")
|
|
70
|
+
print(df)
|
|
71
|
+
|
|
72
|
+
# ==========================================
|
|
73
|
+
# STEP 4: Categorical Encoding & Feature Scaling
|
|
74
|
+
# ==========================================
|
|
75
|
+
# Encode City names into integer identifiers
|
|
76
|
+
le = LabelEncoder()
|
|
77
|
+
df['City_Encoded'] = le.fit_transform(df['City'])
|
|
78
|
+
print("\nCity Encoding:", dict(zip(le.classes_, le.transform(le.classes_))))
|
|
79
|
+
|
|
80
|
+
# Normalize Age and Income to the range [0, 1]
|
|
81
|
+
scaler = MinMaxScaler()
|
|
82
|
+
df[['Age_Scaled', 'Income_Scaled']] = scaler.fit_transform(df[['Age', 'Annual_Income_k']])
|
|
83
|
+
|
|
84
|
+
print("\n--- Final Pre-processed Dataset ---")
|
|
85
|
+
print(df)
|
|
86
|
+
|
|
87
|
+
# ==========================================
|
|
88
|
+
# STEP 5: Exploratory Data Analysis (EDA) - Heatmaps & Histograms
|
|
89
|
+
# ==========================================
|
|
90
|
+
# Histograms: distribution of Age and Income
|
|
91
|
+
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
|
|
92
|
+
sns.histplot(df['Age'], bins=5, kde=True, ax=axes[0], color='skyblue')
|
|
93
|
+
axes[0].set_title('Age Distribution')
|
|
94
|
+
sns.histplot(df['Annual_Income_k'], bins=5, kde=True, ax=axes[1], color='salmon')
|
|
95
|
+
axes[1].set_title('Annual Income Distribution (k)')
|
|
96
|
+
plt.tight_layout()
|
|
97
|
+
plt.show()
|
|
98
|
+
|
|
99
|
+
# Scatter plot: demographic clusters by City
|
|
100
|
+
plt.figure(figsize=(6, 4))
|
|
101
|
+
sns.scatterplot(data=df, x='Age', y='Annual_Income_k', hue='City', s=100)
|
|
102
|
+
plt.title('Age vs Annual Income by City')
|
|
103
|
+
plt.show()
|
|
104
|
+
|
|
105
|
+
# Correlation heatmap
|
|
106
|
+
numeric_cols = ['Age', 'Annual_Income_k', 'City_Encoded']
|
|
107
|
+
plt.figure(figsize=(6, 5))
|
|
108
|
+
sns.heatmap(df[numeric_cols].corr(), annot=True, cmap='coolwarm', fmt='.2f')
|
|
109
|
+
plt.title('Feature Correlation Heatmap')
|
|
110
|
+
plt.show()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Experiment 2: Simple Linear Regression
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import seaborn as sns
|
|
8
|
+
from sklearn.model_selection import train_test_split
|
|
9
|
+
from sklearn.linear_model import LinearRegression
|
|
10
|
+
from sklearn.metrics import mean_squared_error, r2_score
|
|
11
|
+
|
|
12
|
+
# ==========================================
|
|
13
|
+
# STEP 1: Generate the Data
|
|
14
|
+
# ==========================================
|
|
15
|
+
# Synthetic data: Years of Experience vs Salary, with random noise.
|
|
16
|
+
np.random.seed(42)
|
|
17
|
+
n_samples = 100
|
|
18
|
+
|
|
19
|
+
experience = np.random.uniform(0, 15, n_samples)
|
|
20
|
+
noise = np.random.normal(0, 5000, n_samples)
|
|
21
|
+
salary = 30000 + 4500 * experience + noise
|
|
22
|
+
|
|
23
|
+
data = pd.DataFrame({'YearsExperience': experience, 'Salary': salary})
|
|
24
|
+
data.to_csv('simple_linear_regression_data.csv', index=False)
|
|
25
|
+
|
|
26
|
+
# Load the saved CSV
|
|
27
|
+
# CHANGE THIS PATH TO YOUR DATASET (and the column names below)
|
|
28
|
+
df = pd.read_csv('simple_linear_regression_data.csv')
|
|
29
|
+
print("--- Dataset Head ---")
|
|
30
|
+
print(df.head())
|
|
31
|
+
|
|
32
|
+
X = df[['YearsExperience']] # Feature matrix (2D)
|
|
33
|
+
y = df['Salary'] # Target vector
|
|
34
|
+
|
|
35
|
+
# ==========================================
|
|
36
|
+
# STEP 2: Splitting Data into Training and Testing Sets (80/20)
|
|
37
|
+
# ==========================================
|
|
38
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
39
|
+
X, y, test_size=0.2, random_state=42
|
|
40
|
+
)
|
|
41
|
+
print(f"\nTraining Set Shape: {X_train.shape}")
|
|
42
|
+
print(f"Testing Set Shape: {X_test.shape}")
|
|
43
|
+
|
|
44
|
+
# ==========================================
|
|
45
|
+
# STEP 3: Training the Simple Linear Regression Model
|
|
46
|
+
# ==========================================
|
|
47
|
+
model = LinearRegression()
|
|
48
|
+
model.fit(X_train, y_train)
|
|
49
|
+
|
|
50
|
+
print(f"\nIntercept (beta_0): {model.intercept_:.2f}")
|
|
51
|
+
print(f"Slope (beta_1): {model.coef_[0]:.2f}")
|
|
52
|
+
|
|
53
|
+
# ==========================================
|
|
54
|
+
# STEP 4: Making Predictions & Model Evaluation
|
|
55
|
+
# ==========================================
|
|
56
|
+
y_pred = model.predict(X_test)
|
|
57
|
+
|
|
58
|
+
mse = mean_squared_error(y_test, y_pred)
|
|
59
|
+
rmse = np.sqrt(mse)
|
|
60
|
+
r2 = r2_score(y_test, y_pred)
|
|
61
|
+
|
|
62
|
+
print("\n--- MODEL PERFORMANCE METRICS ---")
|
|
63
|
+
print(f"Mean Squared Error (MSE) : {mse:.2f}")
|
|
64
|
+
print(f"Root Mean Squared Error (RMSE) : {rmse:.2f}")
|
|
65
|
+
print(f"R^2 Score : {r2:.4f}")
|
|
66
|
+
|
|
67
|
+
# ==========================================
|
|
68
|
+
# STEP 5: Visualizing Results
|
|
69
|
+
# ==========================================
|
|
70
|
+
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
|
71
|
+
|
|
72
|
+
# Training set
|
|
73
|
+
sns.scatterplot(x=X_train['YearsExperience'], y=y_train, ax=axes[0], color='blue', label='Actual')
|
|
74
|
+
axes[0].plot(X_train['YearsExperience'], model.predict(X_train), color='red', label='Regression Line')
|
|
75
|
+
axes[0].set_title('Training Set: Salary vs Experience')
|
|
76
|
+
axes[0].set_xlabel('Years of Experience')
|
|
77
|
+
axes[0].set_ylabel('Salary')
|
|
78
|
+
axes[0].legend()
|
|
79
|
+
|
|
80
|
+
# Testing set
|
|
81
|
+
sns.scatterplot(x=X_test['YearsExperience'], y=y_test, ax=axes[1], color='green', label='Actual')
|
|
82
|
+
axes[1].plot(X_train['YearsExperience'], model.predict(X_train), color='red', label='Regression Line')
|
|
83
|
+
axes[1].set_title('Testing Set: Salary vs Experience')
|
|
84
|
+
axes[1].set_xlabel('Years of Experience')
|
|
85
|
+
axes[1].set_ylabel('Salary')
|
|
86
|
+
axes[1].legend()
|
|
87
|
+
|
|
88
|
+
plt.tight_layout()
|
|
89
|
+
plt.show()
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Experiment 3: Multiple Linear Regression (House Price Prediction)
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn statsmodels
|
|
3
|
+
|
|
4
|
+
# Step 1: Environment Setup & Synthetic Data Generation
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import seaborn as sns
|
|
9
|
+
|
|
10
|
+
from sklearn.model_selection import train_test_split
|
|
11
|
+
from sklearn.linear_model import LinearRegression
|
|
12
|
+
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
|
|
13
|
+
from statsmodels.stats.outliers_influence import variance_inflation_factor
|
|
14
|
+
import statsmodels.api as sm
|
|
15
|
+
|
|
16
|
+
# Set random seed for reproducibility
|
|
17
|
+
np.random.seed(42)
|
|
18
|
+
n_samples = 500
|
|
19
|
+
|
|
20
|
+
# Generate synthetic features
|
|
21
|
+
sqft = np.random.normal(2100, 500, n_samples).clip(800, 4500)
|
|
22
|
+
bedrooms = np.random.choice([1, 2, 3, 4, 5], size=n_samples, p=[0.1, 0.25, 0.4, 0.2, 0.05])
|
|
23
|
+
dist_transit = np.random.exponential(scale=4.0, size=n_samples).clip(0.5, 20.0)
|
|
24
|
+
age = np.random.uniform(1, 40, n_samples)
|
|
25
|
+
school_rating = np.random.uniform(3.0, 9.8, n_samples)
|
|
26
|
+
|
|
27
|
+
# True linear relationship + Gaussian noise
|
|
28
|
+
noise = np.random.normal(0, 25000, n_samples)
|
|
29
|
+
price = (150 * sqft) + (12000 * bedrooms) - (8500 * dist_transit) - (1500 * age) + (9000 * school_rating) + 50000 + noise
|
|
30
|
+
|
|
31
|
+
# Construct DataFrame
|
|
32
|
+
df = pd.DataFrame({
|
|
33
|
+
'Square_Footage': sqft,
|
|
34
|
+
'Number_of_Bedrooms': bedrooms,
|
|
35
|
+
'Distance_to_Transit_km': dist_transit,
|
|
36
|
+
'Age_of_Property': age,
|
|
37
|
+
'School_Rating': school_rating,
|
|
38
|
+
'House_Price': price
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
print("Dataset Head:")
|
|
42
|
+
print(df.head())
|
|
43
|
+
|
|
44
|
+
# Step 2: Train-Test Split (80:20)
|
|
45
|
+
# Define Independent Features (X) and Target Variable (Y)
|
|
46
|
+
X = df[['Square_Footage', 'Number_of_Bedrooms', 'Distance_to_Transit_km', 'Age_of_Property', 'School_Rating']]
|
|
47
|
+
Y = df['House_Price']
|
|
48
|
+
|
|
49
|
+
# Split data into 80% training and 20% testing sets
|
|
50
|
+
X_train, X_test, Y_train, Y_test = train_test_split(
|
|
51
|
+
X, Y, test_size=0.20, random_state=42
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
print(f"Training Set Shape: {X_train.shape}")
|
|
55
|
+
print(f"Testing Set Shape: {X_test.shape}")
|
|
56
|
+
|
|
57
|
+
# Step 3: Model Fitting & Parameter Estimation
|
|
58
|
+
# Instantiate and fit Linear Regression model
|
|
59
|
+
model = LinearRegression()
|
|
60
|
+
model.fit(X_train, Y_train)
|
|
61
|
+
|
|
62
|
+
# Extract intercept and slope coefficients
|
|
63
|
+
intercept = model.intercept_
|
|
64
|
+
coefficients = pd.DataFrame({
|
|
65
|
+
'Feature': X.columns,
|
|
66
|
+
'Coefficient (Beta)': model.coef_
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
print(f"Intercept (Beta_0): ${intercept:,.2f}\n")
|
|
70
|
+
print("Learned Feature Coefficients:")
|
|
71
|
+
print(coefficients.to_string(index=False))
|
|
72
|
+
|
|
73
|
+
# Step 4: Predictions & Quantitative Performance Evaluation
|
|
74
|
+
# Model Predictions on Test Data
|
|
75
|
+
Y_pred = model.predict(X_test)
|
|
76
|
+
|
|
77
|
+
# Calculate Evaluation Metrics
|
|
78
|
+
mae = mean_absolute_error(Y_test, Y_pred)
|
|
79
|
+
mse = mean_squared_error(Y_test, Y_pred)
|
|
80
|
+
rmse = np.sqrt(mse)
|
|
81
|
+
r2 = r2_score(Y_test, Y_pred)
|
|
82
|
+
|
|
83
|
+
# Adjusted R-Squared
|
|
84
|
+
n = len(Y_test)
|
|
85
|
+
p = X_test.shape[1]
|
|
86
|
+
adj_r2 = 1 - (1 - r2) * (n - 1) / (n - p - 1)
|
|
87
|
+
|
|
88
|
+
print("--- MODEL PERFORMANCE METRICS ---")
|
|
89
|
+
print(f"Mean Absolute Error (MAE) : ${mae:,.2f}")
|
|
90
|
+
print(f"Mean Squared Error (MSE) : ${mse:,.2f}")
|
|
91
|
+
print(f"Root Mean Squared Error (RMSE) : ${rmse:,.2f}")
|
|
92
|
+
print(f"R-squared Score (R²) : {r2:.4f}")
|
|
93
|
+
print(f"Adjusted R-squared Score : {adj_r2:.4f}")
|
|
94
|
+
|
|
95
|
+
# Step 5: Residual Diagnostics & VIF Check
|
|
96
|
+
# Calculate Residuals
|
|
97
|
+
residuals = Y_test - Y_pred
|
|
98
|
+
|
|
99
|
+
# Calculate Variance Inflation Factor (VIF) for Multicollinearity
|
|
100
|
+
vif_data = pd.DataFrame()
|
|
101
|
+
vif_data["Feature"] = X.columns
|
|
102
|
+
vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
|
|
103
|
+
|
|
104
|
+
print("--- VARIANCE INFLATION FACTOR (VIF) ---")
|
|
105
|
+
print(vif_data.to_string(index=False))
|
|
106
|
+
|
|
107
|
+
# Statsmodels OLS detailed summary
|
|
108
|
+
X_train_sm = sm.add_constant(X_train)
|
|
109
|
+
ols_model = sm.OLS(Y_train, X_train_sm).fit()
|
|
110
|
+
print(ols_model.summary())
|