mlextend 0.1.0__py3-none-any.whl
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/__init__.py +51 -0
- mlextend/_experiment.py +70 -0
- mlextend/codes/exp01.txt +110 -0
- mlextend/codes/exp02.txt +89 -0
- mlextend/codes/exp03.txt +110 -0
- mlextend/codes/exp04.txt +104 -0
- mlextend/codes/exp05.txt +67 -0
- mlextend/codes/exp06.txt +63 -0
- mlextend/codes/exp07.txt +98 -0
- mlextend/codes/exp08.txt +82 -0
- mlextend/codes/exp09.txt +87 -0
- mlextend/codes/exp10.txt +134 -0
- mlextend-0.1.0.dist-info/METADATA +107 -0
- mlextend-0.1.0.dist-info/RECORD +16 -0
- mlextend-0.1.0.dist-info/WHEEL +4 -0
- mlextend-0.1.0.dist-info/licenses/LICENSE +21 -0
mlextend/__init__.py
ADDED
|
@@ -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]
|
mlextend/_experiment.py
ADDED
|
@@ -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}>"
|
mlextend/codes/exp01.txt
ADDED
|
@@ -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()
|
mlextend/codes/exp02.txt
ADDED
|
@@ -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()
|
mlextend/codes/exp03.txt
ADDED
|
@@ -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())
|
mlextend/codes/exp04.txt
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Experiment 4: Logistic Regression for Heart Disease Prediction
|
|
2
|
+
# Requirements: pip install pandas matplotlib scikit-learn
|
|
3
|
+
|
|
4
|
+
# Heart Disease Prediction using Logistic Regression
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
|
|
9
|
+
from sklearn.model_selection import train_test_split
|
|
10
|
+
from sklearn.preprocessing import StandardScaler
|
|
11
|
+
from sklearn.linear_model import LogisticRegression
|
|
12
|
+
from sklearn.metrics import (
|
|
13
|
+
accuracy_score, precision_score, recall_score,
|
|
14
|
+
f1_score, roc_auc_score, confusion_matrix,
|
|
15
|
+
ConfusionMatrixDisplay, RocCurveDisplay
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# 1. Load the dataset
|
|
19
|
+
# Replace the file name with the location of your dataset.
|
|
20
|
+
# CHANGE THIS PATH TO YOUR DATASET
|
|
21
|
+
data = pd.read_csv("heart_disease.csv")
|
|
22
|
+
|
|
23
|
+
# 2. Select input features and target variable
|
|
24
|
+
features = [
|
|
25
|
+
"Age",
|
|
26
|
+
"Resting_Blood_Pressure",
|
|
27
|
+
"Cholesterol",
|
|
28
|
+
"Maximum_Heart_Rate",
|
|
29
|
+
"Exercise_Induced_Angina"
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
X = data[features]
|
|
33
|
+
y = data["Heart_Disease"] # 0 = No Heart Disease, 1 = Heart Disease
|
|
34
|
+
|
|
35
|
+
# 3. Split data into training and testing sets
|
|
36
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
37
|
+
X, y,
|
|
38
|
+
test_size=0.20,
|
|
39
|
+
random_state=42,
|
|
40
|
+
stratify=y
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# 4. Standardize numerical features
|
|
44
|
+
scaler = StandardScaler()
|
|
45
|
+
X_train_scaled = scaler.fit_transform(X_train)
|
|
46
|
+
X_test_scaled = scaler.transform(X_test)
|
|
47
|
+
|
|
48
|
+
# 5. Train Logistic Regression model
|
|
49
|
+
model = LogisticRegression(random_state=42)
|
|
50
|
+
model.fit(X_train_scaled, y_train)
|
|
51
|
+
|
|
52
|
+
# 6. Predict class labels and probabilities
|
|
53
|
+
y_pred = model.predict(X_test_scaled)
|
|
54
|
+
y_prob = model.predict_proba(X_test_scaled)[:, 1]
|
|
55
|
+
|
|
56
|
+
# 7. Calculate evaluation metrics
|
|
57
|
+
accuracy = accuracy_score(y_test, y_pred)
|
|
58
|
+
precision = precision_score(y_test, y_pred, zero_division=0)
|
|
59
|
+
recall = recall_score(y_test, y_pred, zero_division=0)
|
|
60
|
+
f1 = f1_score(y_test, y_pred, zero_division=0)
|
|
61
|
+
roc_auc = roc_auc_score(y_test, y_prob)
|
|
62
|
+
|
|
63
|
+
print("Model Performance")
|
|
64
|
+
print("-----------------")
|
|
65
|
+
print("Accuracy :", round(accuracy, 4))
|
|
66
|
+
print("Precision:", round(precision, 4))
|
|
67
|
+
print("Recall :", round(recall, 4))
|
|
68
|
+
print("F1-Score :", round(f1, 4))
|
|
69
|
+
print("ROC-AUC :", round(roc_auc, 4))
|
|
70
|
+
|
|
71
|
+
# 8. Display confusion matrix
|
|
72
|
+
cm = confusion_matrix(y_test, y_pred)
|
|
73
|
+
print("\nConfusion Matrix:\n", cm)
|
|
74
|
+
|
|
75
|
+
ConfusionMatrixDisplay(confusion_matrix=cm).plot()
|
|
76
|
+
plt.title("Confusion Matrix - Heart Disease Prediction")
|
|
77
|
+
plt.show()
|
|
78
|
+
|
|
79
|
+
# 9. Plot ROC curve
|
|
80
|
+
RocCurveDisplay.from_predictions(y_test, y_prob)
|
|
81
|
+
plt.title("ROC Curve - Heart Disease Prediction")
|
|
82
|
+
plt.show()
|
|
83
|
+
|
|
84
|
+
# 10. Predict for a new patient
|
|
85
|
+
new_patient = pd.DataFrame([{
|
|
86
|
+
"Age": 55,
|
|
87
|
+
"Resting_Blood_Pressure": 140,
|
|
88
|
+
"Cholesterol": 240,
|
|
89
|
+
"Maximum_Heart_Rate": 150,
|
|
90
|
+
"Exercise_Induced_Angina": 1
|
|
91
|
+
}])
|
|
92
|
+
|
|
93
|
+
new_patient_scaled = scaler.transform(new_patient)
|
|
94
|
+
prediction = model.predict(new_patient_scaled)[0]
|
|
95
|
+
probability = model.predict_proba(new_patient_scaled)[0, 1]
|
|
96
|
+
|
|
97
|
+
print("\nNew Patient Prediction")
|
|
98
|
+
print("----------------------")
|
|
99
|
+
print("Probability of Heart Disease:", round(probability, 4))
|
|
100
|
+
|
|
101
|
+
if prediction == 1:
|
|
102
|
+
print("Prediction: Heart Disease Present")
|
|
103
|
+
else:
|
|
104
|
+
print("Prediction: No Heart Disease")
|
mlextend/codes/exp05.txt
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Experiment 5: K-Nearest Neighbors (KNN) Classifier for Credit Risk Rating
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
# Import essential libraries
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import seaborn as sns
|
|
9
|
+
from sklearn.model_selection import train_test_split, cross_val_score
|
|
10
|
+
from sklearn.preprocessing import StandardScaler
|
|
11
|
+
from sklearn.neighbors import KNeighborsClassifier
|
|
12
|
+
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, roc_auc_score
|
|
13
|
+
|
|
14
|
+
# 1. Generate Synthetic Dataset for Credit Risk Rating
|
|
15
|
+
np.random.seed(42)
|
|
16
|
+
n_samples = 1000
|
|
17
|
+
|
|
18
|
+
data = {
|
|
19
|
+
'Debt_to_Income_Ratio': np.random.uniform(0.1, 0.8, n_samples),
|
|
20
|
+
'Credit_Score': np.random.randint(300, 850, n_samples),
|
|
21
|
+
'Annual_Income': np.random.uniform(20000, 150000, n_samples),
|
|
22
|
+
'Total_Assets': np.random.uniform(5000, 500000, n_samples)
|
|
23
|
+
}
|
|
24
|
+
df = pd.DataFrame(data)
|
|
25
|
+
|
|
26
|
+
# Generate Multi-class Target Variable: Credit_Risk_Rating (0=Low, 1=Moderate, 2=High)
|
|
27
|
+
risk_score = (df['Debt_to_Income_Ratio'] * 3.0) - (df['Credit_Score'] / 250.0) - (df['Annual_Income'] / 100000.0)
|
|
28
|
+
df['Credit_Risk_Rating'] = pd.qcut(risk_score, q=3, labels=[0, 1, 2]).astype(int)
|
|
29
|
+
|
|
30
|
+
# 2. Train-Test Split and Feature Scaling
|
|
31
|
+
X = df[['Debt_to_Income_Ratio', 'Credit_Score', 'Annual_Income', 'Total_Assets']]
|
|
32
|
+
y = df['Credit_Risk_Rating']
|
|
33
|
+
|
|
34
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42, stratify=y)
|
|
35
|
+
|
|
36
|
+
scaler = StandardScaler()
|
|
37
|
+
X_train_scaled = scaler.fit_transform(X_train)
|
|
38
|
+
X_test_scaled = scaler.transform(X_test)
|
|
39
|
+
|
|
40
|
+
# 3. Hyperparameter Tuning: Finding Optimal K
|
|
41
|
+
k_range = range(1, 26)
|
|
42
|
+
cv_scores = []
|
|
43
|
+
|
|
44
|
+
for k in k_range:
|
|
45
|
+
knn = KNeighborsClassifier(n_neighbors=k, metric='minkowski', p=2)
|
|
46
|
+
scores = cross_val_score(knn, X_train_scaled, y_train, cv=5, scoring='accuracy')
|
|
47
|
+
cv_scores.append(scores.mean())
|
|
48
|
+
|
|
49
|
+
optimal_k = k_range[np.argmax(cv_scores)]
|
|
50
|
+
print(f'Optimal Neighborhood Parameter (K): {optimal_k}')
|
|
51
|
+
|
|
52
|
+
# 4. Train Final KNN Model with Optimal K
|
|
53
|
+
knn_optimal = KNeighborsClassifier(n_neighbors=optimal_k, weights='distance')
|
|
54
|
+
knn_optimal.fit(X_train_scaled, y_train)
|
|
55
|
+
|
|
56
|
+
# 5. Prediction and Evaluation
|
|
57
|
+
y_pred = knn_optimal.predict(X_test_scaled)
|
|
58
|
+
y_probs = knn_optimal.predict_proba(X_test_scaled)
|
|
59
|
+
|
|
60
|
+
print('\n--- Confusion Matrix ---')
|
|
61
|
+
print(confusion_matrix(y_test, y_pred))
|
|
62
|
+
|
|
63
|
+
print('\n--- Classification Report ---')
|
|
64
|
+
print(classification_report(y_test, y_pred, target_names=['Low Risk', 'Moderate Risk', 'High Risk']))
|
|
65
|
+
|
|
66
|
+
auc_score = roc_auc_score(y_test, y_probs, multi_class='ovr')
|
|
67
|
+
print(f'Multi-class ROC-AUC Score (OvR): {auc_score:.4f}')
|
mlextend/codes/exp06.txt
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Experiment 6: Decision Tree Classifier for Multi-Class Credit Risk Assessment
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
# Import required libraries
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import seaborn as sns
|
|
9
|
+
from sklearn.model_selection import train_test_split, cross_val_score
|
|
10
|
+
from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree
|
|
11
|
+
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, roc_auc_score
|
|
12
|
+
|
|
13
|
+
# 1. Generate Synthetic Dataset for Credit Risk Assessment
|
|
14
|
+
np.random.seed(42)
|
|
15
|
+
n_samples = 1000
|
|
16
|
+
|
|
17
|
+
data = {
|
|
18
|
+
'Debt_to_Income_Ratio': np.random.uniform(0.1, 0.8, n_samples),
|
|
19
|
+
'Credit_Score': np.random.randint(300, 850, n_samples),
|
|
20
|
+
'Annual_Income': np.random.uniform(20000, 150000, n_samples),
|
|
21
|
+
'Missed_Payments_Count': np.random.randint(0, 10, n_samples)
|
|
22
|
+
}
|
|
23
|
+
df = pd.DataFrame(data)
|
|
24
|
+
|
|
25
|
+
# Define target: Credit_Risk_Rating (0 = Low Risk, 1 = Moderate Risk, 2 = High Risk)
|
|
26
|
+
risk_index = (df['Debt_to_Income_Ratio'] * 2.5) + (df['Missed_Payments_Count'] * 0.4) - (df['Credit_Score'] / 300.0)
|
|
27
|
+
df['Credit_Risk_Rating'] = pd.qcut(risk_index, q=3, labels=[0, 1, 2]).astype(int)
|
|
28
|
+
|
|
29
|
+
# 2. Train-Test Split (80:20 Stratified Ratio)
|
|
30
|
+
X = df[['Debt_to_Income_Ratio', 'Credit_Score', 'Annual_Income', 'Missed_Payments_Count']]
|
|
31
|
+
y = df['Credit_Risk_Rating']
|
|
32
|
+
|
|
33
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42, stratify=y)
|
|
34
|
+
|
|
35
|
+
# 3. Train Decision Tree Model with Pre-Pruning (Hyperparameter Control)
|
|
36
|
+
dt_model = DecisionTreeClassifier(
|
|
37
|
+
criterion='gini',
|
|
38
|
+
max_depth=4,
|
|
39
|
+
min_samples_split=10,
|
|
40
|
+
min_samples_leaf=5,
|
|
41
|
+
random_state=42
|
|
42
|
+
)
|
|
43
|
+
dt_model.fit(X_train, y_train)
|
|
44
|
+
|
|
45
|
+
# 4. Model Prediction and Performance Evaluation
|
|
46
|
+
y_pred = dt_model.predict(X_test)
|
|
47
|
+
y_probs = dt_model.predict_proba(X_test)
|
|
48
|
+
|
|
49
|
+
print('--- Confusion Matrix ---')
|
|
50
|
+
print(confusion_matrix(y_test, y_pred))
|
|
51
|
+
|
|
52
|
+
print('\n--- Classification Report ---')
|
|
53
|
+
print(classification_report(y_test, y_pred, target_names=['Low Risk', 'Moderate Risk', 'High Risk']))
|
|
54
|
+
|
|
55
|
+
# 5. Feature Importance Analysis
|
|
56
|
+
feature_imp = pd.Series(dt_model.feature_importances_, index=X.columns).sort_values(ascending=False)
|
|
57
|
+
print('\n--- Feature Importances ---')
|
|
58
|
+
print(feature_imp)
|
|
59
|
+
|
|
60
|
+
# 6. Decision Rules Extraction (Text-based)
|
|
61
|
+
tree_rules = export_text(dt_model, feature_names=list(X.columns))
|
|
62
|
+
print('\n--- Decision Tree Rules ---')
|
|
63
|
+
print(tree_rules[:500]) # Print top rule paths
|
mlextend/codes/exp07.txt
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Experiment 7: K-Means Clustering for Customer Profiling
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
# ==========================================
|
|
5
|
+
# STEP 1: Import Libraries & Load Dataset
|
|
6
|
+
# ==========================================
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import seaborn as sns
|
|
11
|
+
|
|
12
|
+
from sklearn.cluster import KMeans
|
|
13
|
+
from sklearn.preprocessing import StandardScaler
|
|
14
|
+
from sklearn.metrics import silhouette_score
|
|
15
|
+
|
|
16
|
+
# Load Dataset
|
|
17
|
+
# CHANGE THIS PATH TO YOUR DATASET (Mall_Customers.csv)
|
|
18
|
+
df = pd.read_csv('Mall_Customers.csv')
|
|
19
|
+
|
|
20
|
+
print("--- Dataset Head ---")
|
|
21
|
+
print(df.head())
|
|
22
|
+
print("\n--- Dataset Info ---")
|
|
23
|
+
print(df.info())
|
|
24
|
+
|
|
25
|
+
# Select relevant numerical features
|
|
26
|
+
X = df[['Annual Income (k$)', 'Spending Score (1-100)']].values
|
|
27
|
+
|
|
28
|
+
# STEP 2: Feature Scaling
|
|
29
|
+
scaler = StandardScaler()
|
|
30
|
+
X_scaled = scaler.fit_transform(X)
|
|
31
|
+
|
|
32
|
+
# STEP 3: Find Optimal K
|
|
33
|
+
wcss = []
|
|
34
|
+
silhouette_scores = []
|
|
35
|
+
K_range = range(2, 11)
|
|
36
|
+
|
|
37
|
+
for k in K_range:
|
|
38
|
+
kmeans = KMeans(n_clusters=k, init='k-means++',
|
|
39
|
+
random_state=42, n_init=10)
|
|
40
|
+
kmeans.fit(X_scaled)
|
|
41
|
+
wcss.append(kmeans.inertia_)
|
|
42
|
+
silhouette_scores.append(
|
|
43
|
+
silhouette_score(X_scaled, kmeans.labels_)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
plt.figure(figsize=(12, 5))
|
|
47
|
+
|
|
48
|
+
plt.subplot(1, 2, 1)
|
|
49
|
+
plt.plot(range(2, 11), wcss, marker='o', color='b')
|
|
50
|
+
plt.title('Elbow Method for Optimal K')
|
|
51
|
+
plt.xlabel('Number of Clusters (K)')
|
|
52
|
+
plt.ylabel('WCSS (Inertia)')
|
|
53
|
+
plt.grid(True)
|
|
54
|
+
|
|
55
|
+
plt.subplot(1, 2, 2)
|
|
56
|
+
plt.plot(range(2, 11), silhouette_scores, marker='s', color='g')
|
|
57
|
+
plt.title('Silhouette Score Analysis')
|
|
58
|
+
plt.xlabel('Number of Clusters (K)')
|
|
59
|
+
plt.ylabel('Silhouette Score')
|
|
60
|
+
plt.grid(True)
|
|
61
|
+
|
|
62
|
+
plt.tight_layout()
|
|
63
|
+
plt.show()
|
|
64
|
+
|
|
65
|
+
# STEP 4: Train K-Means with Optimal K
|
|
66
|
+
optimal_k = 5
|
|
67
|
+
kmeans = KMeans(n_clusters=optimal_k, init='k-means++',
|
|
68
|
+
random_state=42, n_init=10)
|
|
69
|
+
y_kmeans = kmeans.fit_predict(X_scaled)
|
|
70
|
+
df['Cluster'] = y_kmeans
|
|
71
|
+
|
|
72
|
+
# STEP 5: Visualize Customer Profiles
|
|
73
|
+
plt.figure(figsize=(9, 6))
|
|
74
|
+
colors = ['red', 'blue', 'green', 'cyan', 'magenta']
|
|
75
|
+
labels = ['Cluster 1', 'Cluster 2', 'Cluster 3', 'Cluster 4', 'Cluster 5']
|
|
76
|
+
|
|
77
|
+
for i in range(optimal_k):
|
|
78
|
+
plt.scatter(X_scaled[y_kmeans == i, 0],
|
|
79
|
+
X_scaled[y_kmeans == i, 1],
|
|
80
|
+
s=50, c=colors[i], label=labels[i])
|
|
81
|
+
|
|
82
|
+
plt.scatter(kmeans.cluster_centers_[:, 0],
|
|
83
|
+
kmeans.cluster_centers_[:, 1],
|
|
84
|
+
s=200, c='yellow', edgecolors='black',
|
|
85
|
+
marker='*', label='Centroids')
|
|
86
|
+
|
|
87
|
+
plt.title('Customer Segments (K-Means Clustering)')
|
|
88
|
+
plt.xlabel('Annual Income (Scaled)')
|
|
89
|
+
plt.ylabel('Spending Score (Scaled)')
|
|
90
|
+
plt.legend()
|
|
91
|
+
plt.grid(True)
|
|
92
|
+
plt.show()
|
|
93
|
+
|
|
94
|
+
# Display summary metrics per cluster
|
|
95
|
+
profile = df.groupby('Cluster')[
|
|
96
|
+
['Annual Income (k$)', 'Spending Score (1-100)', 'Age']
|
|
97
|
+
].mean()
|
|
98
|
+
print(profile)
|
mlextend/codes/exp08.txt
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Experiment 8: Dimensionality Reduction using Principal Component Analysis (PCA)
|
|
2
|
+
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn
|
|
3
|
+
|
|
4
|
+
# ==========================================
|
|
5
|
+
# STEP 1: Import Libraries & Load Dataset
|
|
6
|
+
# ==========================================
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import seaborn as sns
|
|
11
|
+
from sklearn.datasets import load_breast_cancer
|
|
12
|
+
from sklearn.preprocessing import StandardScaler
|
|
13
|
+
from sklearn.decomposition import PCA
|
|
14
|
+
|
|
15
|
+
# Load High-Dimensional Dataset (Breast Cancer Dataset - 30 features)
|
|
16
|
+
data = load_breast_cancer()
|
|
17
|
+
X = data.data
|
|
18
|
+
y = data.target
|
|
19
|
+
feature_names = data.feature_names
|
|
20
|
+
|
|
21
|
+
df = pd.DataFrame(X, columns=feature_names)
|
|
22
|
+
print("--- Dataset Shape ---")
|
|
23
|
+
print(df.shape)
|
|
24
|
+
print("\n--- Dataset Head ---")
|
|
25
|
+
print(df.head())
|
|
26
|
+
|
|
27
|
+
# ==========================================
|
|
28
|
+
# STEP 2: Feature Standardization
|
|
29
|
+
# ==========================================
|
|
30
|
+
scaler = StandardScaler()
|
|
31
|
+
X_scaled = scaler.fit_transform(X)
|
|
32
|
+
|
|
33
|
+
# ==========================================
|
|
34
|
+
# STEP 3: Full PCA & Scree Plot Analysis
|
|
35
|
+
# ==========================================
|
|
36
|
+
pca_full = PCA()
|
|
37
|
+
pca_full.fit(X_scaled)
|
|
38
|
+
|
|
39
|
+
cum_variance = np.cumsum(pca_full.explained_variance_ratio_)
|
|
40
|
+
|
|
41
|
+
plt.figure(figsize=(12, 5))
|
|
42
|
+
|
|
43
|
+
plt.subplot(1, 2, 1)
|
|
44
|
+
plt.bar(range(1, len(pca_full.explained_variance_ratio_) + 1),
|
|
45
|
+
pca_full.explained_variance_ratio_, alpha=0.6, align='center',
|
|
46
|
+
label='Individual Explained Variance')
|
|
47
|
+
plt.step(range(1, len(cum_variance) + 1), cum_variance, where='mid',
|
|
48
|
+
color='red', label='Cumulative Explained Variance')
|
|
49
|
+
plt.axhline(y=0.90, color='g', linestyle='--', label='90% Variance Threshold')
|
|
50
|
+
plt.title('Scree Plot & Cumulative Explained Variance')
|
|
51
|
+
plt.xlabel('Principal Component Index')
|
|
52
|
+
plt.ylabel('Explained Variance Ratio')
|
|
53
|
+
plt.legend(loc='best')
|
|
54
|
+
plt.grid(True)
|
|
55
|
+
|
|
56
|
+
# ==========================================
|
|
57
|
+
# STEP 4: PCA Reduction to 2 Components
|
|
58
|
+
# ==========================================
|
|
59
|
+
pca_2d = PCA(n_components=2)
|
|
60
|
+
X_pca_2d = pca_2d.fit_transform(X_scaled)
|
|
61
|
+
|
|
62
|
+
print("\n--- Explained Variance Ratio (Top 2 Components) ---")
|
|
63
|
+
print(f"PC1 Variance Ratio: {pca_2d.explained_variance_ratio_[0]:.4f}")
|
|
64
|
+
print(f"PC2 Variance Ratio: {pca_2d.explained_variance_ratio_[1]:.4f}")
|
|
65
|
+
print(f"Total Preserved Variance: {np.sum(pca_2d.explained_variance_ratio_):.4f}")
|
|
66
|
+
|
|
67
|
+
# STEP 5: Visualize Reduced Data Space
|
|
68
|
+
plt.subplot(1, 2, 2)
|
|
69
|
+
scatter = plt.scatter(X_pca_2d[:, 0], X_pca_2d[:, 1], c=y, cmap='coolwarm', alpha=0.8, edgecolors='k')
|
|
70
|
+
plt.title('2D PCA Projection of Dataset')
|
|
71
|
+
plt.xlabel('Principal Component 1')
|
|
72
|
+
plt.ylabel('Principal Component 2')
|
|
73
|
+
plt.legend(handles=scatter.legend_elements()[0], labels=['Malignant', 'Benign'])
|
|
74
|
+
plt.grid(True)
|
|
75
|
+
|
|
76
|
+
plt.tight_layout()
|
|
77
|
+
plt.show()
|
|
78
|
+
|
|
79
|
+
# Display Component Loadings
|
|
80
|
+
df_comp = pd.DataFrame(pca_2d.components_, columns=feature_names, index=['PC1', 'PC2'])
|
|
81
|
+
print("\n--- Component Loadings (Top Features Contribution) ---")
|
|
82
|
+
print(df_comp.iloc[:, :5])
|
mlextend/codes/exp09.txt
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Experiment 9: Apriori Algorithm for Association Rule Mining
|
|
2
|
+
# Requirements: pip install pandas mlxtend
|
|
3
|
+
|
|
4
|
+
# ==========================================
|
|
5
|
+
# STEP 1: Import Libraries & Create Dataset
|
|
6
|
+
# ==========================================
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from mlxtend.preprocessing import TransactionEncoder
|
|
9
|
+
from mlxtend.frequent_patterns import apriori, association_rules
|
|
10
|
+
|
|
11
|
+
transactions = [
|
|
12
|
+
['Milk', 'Bread', 'Butter'],
|
|
13
|
+
['Bread', 'Butter'],
|
|
14
|
+
['Milk', 'Bread'],
|
|
15
|
+
['Milk', 'Bread', 'Butter', 'Eggs'],
|
|
16
|
+
['Bread', 'Eggs'],
|
|
17
|
+
['Milk', 'Bread', 'Eggs'],
|
|
18
|
+
['Milk', 'Butter'],
|
|
19
|
+
['Bread', 'Butter', 'Eggs'],
|
|
20
|
+
['Milk', 'Bread', 'Butter'],
|
|
21
|
+
['Bread', 'Milk']
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Convert transactions into one-hot encoded format
|
|
25
|
+
te = TransactionEncoder()
|
|
26
|
+
te_array = te.fit(transactions).transform(transactions)
|
|
27
|
+
df = pd.DataFrame(te_array, columns=te.columns_)
|
|
28
|
+
|
|
29
|
+
print("--- Transaction Dataset ---")
|
|
30
|
+
print(df.astype(int))
|
|
31
|
+
|
|
32
|
+
# ==========================================
|
|
33
|
+
# STEP 2: Generate Frequent Itemsets
|
|
34
|
+
# ==========================================
|
|
35
|
+
min_support = 0.30
|
|
36
|
+
|
|
37
|
+
frequent_itemsets = apriori(
|
|
38
|
+
df,
|
|
39
|
+
min_support=min_support,
|
|
40
|
+
use_colnames=True
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
frequent_itemsets['itemset_size'] = frequent_itemsets[
|
|
44
|
+
'itemsets'
|
|
45
|
+
].apply(len)
|
|
46
|
+
|
|
47
|
+
print("\n--- Frequent Itemsets ---")
|
|
48
|
+
print(frequent_itemsets.sort_values(
|
|
49
|
+
by=['itemset_size', 'support'],
|
|
50
|
+
ascending=[True, False]
|
|
51
|
+
))
|
|
52
|
+
|
|
53
|
+
# ==========================================
|
|
54
|
+
# STEP 3: Generate Association Rules
|
|
55
|
+
# ==========================================
|
|
56
|
+
min_confidence = 0.60
|
|
57
|
+
|
|
58
|
+
rules = association_rules(
|
|
59
|
+
frequent_itemsets,
|
|
60
|
+
metric="confidence",
|
|
61
|
+
min_threshold=min_confidence
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
rules = rules.sort_values(
|
|
65
|
+
by=['lift', 'confidence'],
|
|
66
|
+
ascending=False
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
print("\n--- Association Rules ---")
|
|
70
|
+
print(rules[
|
|
71
|
+
['antecedents', 'consequents',
|
|
72
|
+
'support', 'confidence', 'lift']
|
|
73
|
+
])
|
|
74
|
+
|
|
75
|
+
# ==========================================
|
|
76
|
+
# STEP 4: Display Strong Rules
|
|
77
|
+
# ==========================================
|
|
78
|
+
strong_rules = rules[
|
|
79
|
+
(rules['confidence'] >= min_confidence) &
|
|
80
|
+
(rules['lift'] > 1)
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
print("\n--- Strong Positive Association Rules ---")
|
|
84
|
+
print(strong_rules[
|
|
85
|
+
['antecedents', 'consequents',
|
|
86
|
+
'support', 'confidence', 'lift']
|
|
87
|
+
])
|
mlextend/codes/exp10.txt
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Experiment 10: Q-Learning Algorithm for Grid World Environment
|
|
2
|
+
# Requirements: pip install numpy pandas
|
|
3
|
+
|
|
4
|
+
# ==========================================
|
|
5
|
+
# STEP 1: Import Libraries & Environment Setup
|
|
6
|
+
# ==========================================
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
# Define Grid Dimensions
|
|
11
|
+
GRID_ROWS = 4
|
|
12
|
+
GRID_COLS = 4
|
|
13
|
+
|
|
14
|
+
# Special States & Rewards
|
|
15
|
+
START = (3, 0)
|
|
16
|
+
GOAL = (0, 3)
|
|
17
|
+
WALL = (1, 1)
|
|
18
|
+
|
|
19
|
+
REWARD_GOAL = 10.0
|
|
20
|
+
REWARD_WALL = -1.0
|
|
21
|
+
REWARD_DEFAULT = 0.0
|
|
22
|
+
|
|
23
|
+
# Hyperparameters
|
|
24
|
+
ALPHA = 0.5 # Learning rate
|
|
25
|
+
GAMMA = 0.9 # Discount factor
|
|
26
|
+
EPISODES = 2000
|
|
27
|
+
|
|
28
|
+
# Actions: 0: Up, 1: Down, 2: Left, 3: Right
|
|
29
|
+
ACTIONS = ['Up', 'Down', 'Left', 'Right']
|
|
30
|
+
ACTION_MOVES = {
|
|
31
|
+
'Up': (-1, 0),
|
|
32
|
+
'Down': (1, 0),
|
|
33
|
+
'Left': (0, -1),
|
|
34
|
+
'Right': (0, 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# ==========================================
|
|
38
|
+
# STEP 2: Environment Step Function
|
|
39
|
+
# ==========================================
|
|
40
|
+
def step(state, action_idx):
|
|
41
|
+
if state == GOAL:
|
|
42
|
+
return state, 0, True
|
|
43
|
+
|
|
44
|
+
action_name = ACTIONS[action_idx]
|
|
45
|
+
dr, dc = ACTION_MOVES[action_name]
|
|
46
|
+
next_r = state[0] + dr
|
|
47
|
+
next_c = state[1] + dc
|
|
48
|
+
|
|
49
|
+
# Check boundary collision
|
|
50
|
+
if next_r < 0 or next_r >= GRID_ROWS or next_c < 0 or next_c >= GRID_COLS:
|
|
51
|
+
next_state = state
|
|
52
|
+
else:
|
|
53
|
+
next_state = (next_r, next_c)
|
|
54
|
+
|
|
55
|
+
# Determine reward and terminal condition
|
|
56
|
+
if next_state == WALL:
|
|
57
|
+
# Wall penalty; agent hits wall
|
|
58
|
+
reward = REWARD_WALL
|
|
59
|
+
is_terminal = False
|
|
60
|
+
elif next_state == GOAL:
|
|
61
|
+
reward = REWARD_GOAL
|
|
62
|
+
is_terminal = True
|
|
63
|
+
else:
|
|
64
|
+
reward = REWARD_DEFAULT
|
|
65
|
+
is_terminal = False
|
|
66
|
+
|
|
67
|
+
return next_state, reward, is_terminal
|
|
68
|
+
|
|
69
|
+
# ==========================================
|
|
70
|
+
# STEP 3: Q-Learning Algorithm Implementation
|
|
71
|
+
# ==========================================
|
|
72
|
+
def run_q_learning():
|
|
73
|
+
# Initialize Q-table with zeros: shape (4, 4, 4)
|
|
74
|
+
q_table = np.zeros((GRID_ROWS, GRID_COLS, len(ACTIONS)))
|
|
75
|
+
|
|
76
|
+
for episode in range(EPISODES):
|
|
77
|
+
state = START
|
|
78
|
+
is_terminal = False
|
|
79
|
+
|
|
80
|
+
while not is_terminal:
|
|
81
|
+
# Epsilon-greedy action selection
|
|
82
|
+
epsilon = max(0.1, 1.0 - episode / 1000)
|
|
83
|
+
if np.random.rand() < epsilon:
|
|
84
|
+
action_idx = np.random.choice(len(ACTIONS))
|
|
85
|
+
else:
|
|
86
|
+
action_idx = np.argmax(q_table[state[0], state[1]])
|
|
87
|
+
|
|
88
|
+
next_state, reward, is_terminal = step(state, action_idx)
|
|
89
|
+
|
|
90
|
+
# Target Q-value calculation
|
|
91
|
+
if is_terminal:
|
|
92
|
+
max_next_q = 0.0
|
|
93
|
+
else:
|
|
94
|
+
max_next_q = np.max(q_table[next_state[0], next_state[1]])
|
|
95
|
+
|
|
96
|
+
td_target = reward + GAMMA * max_next_q
|
|
97
|
+
td_error = td_target - q_table[state[0], state[1], action_idx]
|
|
98
|
+
|
|
99
|
+
# Q-value update rule
|
|
100
|
+
q_table[state[0], state[1], action_idx] += ALPHA * td_error
|
|
101
|
+
|
|
102
|
+
state = next_state
|
|
103
|
+
|
|
104
|
+
return q_table
|
|
105
|
+
|
|
106
|
+
# Run training
|
|
107
|
+
q_table = run_q_learning()
|
|
108
|
+
|
|
109
|
+
# ==========================================
|
|
110
|
+
# STEP 4: Formatted Q-Table Display
|
|
111
|
+
# ==========================================
|
|
112
|
+
rows = []
|
|
113
|
+
for r in range(GRID_ROWS):
|
|
114
|
+
for c in range(GRID_COLS):
|
|
115
|
+
state = (r, c)
|
|
116
|
+
if state == GOAL:
|
|
117
|
+
rows.append({"State (r,c)": f"({r},{c}) [Goal]", "Up": "-", "Down": "-", "Left": "-", "Right": "-", "Optimal Action": "Terminal"})
|
|
118
|
+
elif state == WALL:
|
|
119
|
+
rows.append({"State (r,c)": f"({r},{c}) [Wall]", "Up": "-", "Down": "-", "Left": "-", "Right": "-", "Optimal Action": "Obstacle"})
|
|
120
|
+
else:
|
|
121
|
+
q_vals = q_table[r, c]
|
|
122
|
+
best_a = ACTIONS[np.argmax(q_vals)]
|
|
123
|
+
rows.append({
|
|
124
|
+
"State (r,c)": f"({r},{c})",
|
|
125
|
+
"Up": f"{q_vals[0]:.4f}",
|
|
126
|
+
"Down": f"{q_vals[1]:.4f}",
|
|
127
|
+
"Left": f"{q_vals[2]:.4f}",
|
|
128
|
+
"Right": f"{q_vals[3]:.4f}",
|
|
129
|
+
"Optimal Action": best_a
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
df_qtable = pd.DataFrame(rows)
|
|
133
|
+
print("--- CONVERGED Q-TABLE ---")
|
|
134
|
+
print(df_qtable.to_string(index=False))
|
|
@@ -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
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
mlextend/__init__.py,sha256=sCfVf8NtVXKc2Ym-XJJV9qzEgrvcheQIZBaUyy_zEe8,1663
|
|
2
|
+
mlextend/_experiment.py,sha256=Q1Y3wlBpxSE1NE4uBpoCSNjBZJgJ1kuJ8rvXKfK7SUE,2464
|
|
3
|
+
mlextend/codes/exp01.txt,sha256=I6INK3Mql-bOvsrsG9MMm6wPG5JtYss3EutEifbtj0A,3845
|
|
4
|
+
mlextend/codes/exp02.txt,sha256=tf1jDOTVxcQA16xJEry9LWUyjKU7DMZwdIU_zK_BQ5o,3187
|
|
5
|
+
mlextend/codes/exp03.txt,sha256=uAItQ9NIo1Aq6I2rCOSEdARDF1oCmEpcupUjghz1H8A,3700
|
|
6
|
+
mlextend/codes/exp04.txt,sha256=iEYZU-zlip7ysx0VfRJa-zG6prydAg5IJKSOGIhgmrw,3050
|
|
7
|
+
mlextend/codes/exp05.txt,sha256=a43OqILiMQrFc5h0aRFpu_vECPuFg6PiIQ9x9TDoB5g,2612
|
|
8
|
+
mlextend/codes/exp06.txt,sha256=1_didZMLmHsOG2Jx568gzQhXa3x3TQnmR_CULDR1pBM,2450
|
|
9
|
+
mlextend/codes/exp07.txt,sha256=P3wFIkflfum8t-QJTlKVRkYCBr_VQB3xC0yVnAcuL2U,2780
|
|
10
|
+
mlextend/codes/exp08.txt,sha256=hL3pb7i3b1WNDarl3aYmdHDC81Qp2focmYNMYHyDf1Q,2964
|
|
11
|
+
mlextend/codes/exp09.txt,sha256=kjRRITb9AeRFTGpv1kIkXR3x5g_qOAH0uKqt0Eozyl8,2228
|
|
12
|
+
mlextend/codes/exp10.txt,sha256=vdldFThC7h55ZOOCiB-OLrQHnKPP-jhz_LlB50IrSTM,3989
|
|
13
|
+
mlextend-0.1.0.dist-info/METADATA,sha256=bVRUjhngoorfJ5kO0xtucZLDNFmX-HQrwBeDtGgLi-A,3868
|
|
14
|
+
mlextend-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
15
|
+
mlextend-0.1.0.dist-info/licenses/LICENSE,sha256=eliHYRuSwg2O43tpLudXWMp93YF3SbH_NKQcKNm8w14,1082
|
|
16
|
+
mlextend-0.1.0.dist-info/RECORD,,
|
|
@@ -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.
|