-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreprocessing,basicmlmodel
More file actions
132 lines (110 loc) · 5.25 KB
/
Copy pathpreprocessing,basicmlmodel
File metadata and controls
132 lines (110 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# --- Classification Models ---
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
# --- Regression Model ---
from sklearn.linear_model import LinearRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np
# Load the enriched dataset containing the A* Agent features
df = pd.read_csv('epl_with_agent_features.csv')
# --- 1. Target Encoding ---
# The target variable is 'FullTimeResult' (H, D, A). LabelEncoder maps these to 0, 1, 2.
le = LabelEncoder()
df['Target'] = le.fit_transform(df['FullTimeResult'])
# --- 2. Feature Selection ---
numerical_features = ['HomeShots', 'AwayShots', 'HomeShotsOnTarget', 'AwayShotsOnTarget',
'HomeCorners', 'AwayCorners', 'HomeFouls', 'AwayFouls',
'HomeYellowCards', 'AwayYellowCards', 'HomeRedCards', 'AwayRedCards',
# Agent Features (Optimal Form Score)
'Home_Optimal_Form_Score', 'Away_Optimal_Form_Score', 'Optimal_Form_Differential']
categorical_features = ['HomeTeam', 'AwayTeam']
X = df[numerical_features + categorical_features]
y = df['Target']
# --- 3. Time-Series Train-Test Split (80/20 split) ---
# CRITICAL: Splitting chronologically to prevent data leakage.
split_point = int(0.8 * len(X))
X_train, X_test = X.iloc[:split_point], X.iloc[split_point:]
y_train, y_test = y.iloc[:split_point], y.iloc[split_point:]
# --- 4. Preprocessing Pipeline Definition ---
# Defines the transformation steps (scaling and encoding) applied to features.
preprocessor = ColumnTransformer(
transformers=[
# Apply standardization to numerical columns (e.g., Shots, Form Scores)
('num', StandardScaler(), numerical_features),
# Apply one-hot encoding to team names (HomeTeam, AwayTeam)
('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
],
remainder='passthrough'
)
# --- 5. Baseline Model Training and Evaluation ---
class LinearRegressionClassifier(BaseEstimator, TransformerMixin):
"""
Adapter class to use the Regression model (Linear Regression) for a classification task.
Required by the project specification.
"""
def __init__(self, **kwargs):
self.model = LinearRegression(**kwargs)
def fit(self, X, y):
self.model.fit(X, y)
return self
def predict(self, X):
y_pred = self.model.predict(X)
# Clip and round to force prediction into the 0, 1, 2 class labels
return np.clip(np.round(y_pred), 0, 2).astype(int)
def train_and_evaluate_model(model, name, X_train, y_train, X_test, y_test, preprocessor):
"""Utility function to train a model within the pipeline and calculate all required metrics."""
# Full pipeline includes preprocessing and the classifier
pipeline = Pipeline(steps=[('preprocessor', preprocessor), ('classifier', model)])
print(f"\n--- Training {name} ---")
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
# Calculate performance metrics (Macro averaging used for multi-class H/D/A)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred, average='macro', zero_division=0)
recall = recall_score(y_test, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_test, y_pred, average='macro', zero_division=0)
roc_auc = 'N/A'
try:
# ROC-AUC uses probabilities (predict_proba)
y_proba = pipeline.predict_proba(X_test)
roc_auc = roc_auc_score(y_test, y_proba, multi_class='ovr', average='macro')
except AttributeError:
pass
metrics = {
'Model': name,
'Accuracy': f"{accuracy:.4f}",
'Precision (Macro)': f"{precision:.4f}",
'Recall (Macro)': f"{recall:.4f}",
'F1-Score (Macro)': f"{f1:.4f}",
'ROC-AUC (Macro, OVR)': roc_auc if isinstance(roc_auc, str) else f"{roc_auc:.4f}"
}
return metrics
results = []
# --- 1. Logistic Regression (Linear Classification Baseline) ---
results.append(train_and_evaluate_model(
model=LogisticRegression(max_iter=1000, random_state=42),
name="Logistic Regression",
X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test, preprocessor=preprocessor)
)
# --- 2. Random Forest Classifier (Non-linear Ensemble Baseline) ---
results.append(train_and_evaluate_model(
model=RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1),
name="Random Forest",
X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test, preprocessor=preprocessor)
)
# --- 3. Adapted Linear Regression (Regression Model Baseline) ---
results.append(train_and_evaluate_model(
model=LinearRegressionClassifier(),
name="Adapted Linear Regression",
X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test, preprocessor=preprocessor)
)
results_df = pd.DataFrame(results)
print("\n\n--- Baseline Model Performance Metrics ---")
print(results_df)
results_df.to_csv('baseline_model_metrics.csv', index=False)