-
Notifications
You must be signed in to change notification settings - Fork 0
/
validation.py
172 lines (137 loc) · 5.71 KB
/
validation.py
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
"""
Validation Module
Cross-Validation Techniques for Performance Evaluation of Big Data Workloads
This module implements various cross-validation techniques to evaluate the performance of predictive models for big data workloads, particularly in Apache Spark environments.
Author: Mariano Garralda-Barrio, Carlos Eiras-Franco, Verónica Bolón-Canedo
License: MIT License (see LICENSE file for details)
Date: 2024
Usage:
- Import the `CrossValidation` class and use the `leave_one_out` or `leave_one_group_out` methods to perform cross-validation.
- See the documentation or README for more details on how to use this module.
Example:
validation = CrossValidation(
w=garralda_workload_descriptors,
w_groups=worload_groups,
cs=configuration_settings
t=execution_times,
k_min=k_min,
k_max=k_max
eebc_weight=0.5
)
loocv_eval = validation.leave_one_out()
logocv_eval = validation.leave_one_group_out()
print(f"{loocv_eval}")
print(f"{logocv_eval}")
ame = EvaluationMetrics.AME(
loocv_eval.HME(),
logocv_eval.HME()
)
print(f"AME: {ame:.2f}")
"""
import warnings
import numpy as np
from sklearn.model_selection import LeaveOneGroupOut, LeaveOneOut
from performance.domain.model.garralda_perf_model import GarraldaPerformanceModel
from evaluation import EvaluationMetrics
class CrossValidation:
""" Cross validation techniques """
def __init__(
self,
w: np.ndarray,
w_groups: np.ndarray,
cs: np.ndarray,
t: np.ndarray,
k_min: int,
k_max: int,
eebc_weight: float
) -> None:
""" Initialize the cross validation attributes
Args:
w (np.ndarray): Garralda workload descriptor.
w_groups (np.ndarray): Unique groups of workloads.
cs (np.ndarray): Configuration settings.
t (np.ndarray): Execution times (target).
k_min (int): Minimum value in range K.
k_max (int): Maximum value in range K.
eebc_weight (float): Weight to use on EEBC. Default is 0.5.
"""
self.w = w
self.w_groups = w_groups
self.cs = cs
self.t = t
self.k_min = k_min
self.k_max = k_max
self.eebc_weight = eebc_weight
self.perf_model = GarraldaPerformanceModel()
def leave_one_out(self) -> EvaluationMetrics:
"""
Leave-one-out cross-validation
:return: EvaluationMetrics
"""
y_pred = []
y_true = []
loocv = LeaveOneOut()
# Split the data into training and test sets for each fold leaving one sample out
for train_index, test_index in loocv.split(X=self.w):
w_train, w_test = self.w[train_index], self.w[test_index]
cs_train, cs_test = self.cs[train_index], self.cs[test_index]
t_train, t_test = self.t[train_index], self.t[test_index]
try:
# Lazy training and prediction
prediction = self.perf_model.fit_predict(
workload_descriptors=w_train,
configuration_settings=cs_train,
execution_times=t_train,
workload_ref=w_test,
new_configuration_settings=cs_test,
k_min=self.k_min,
k_max=self.k_max,
eebc_weight=self.eebc_weight
)
y_pred.append(prediction)
y_true.append(t_test)
except Exception as e:
warnings.warn(f"leave_one_group_out: {e}", UserWarning)
evaluation_metrics = EvaluationMetrics(y_true, y_pred)
return evaluation_metrics
def leave_one_group_out(self) -> EvaluationMetrics:
"""
Leave-one-group-out cross-validation
:return: EvaluationMetrics
"""
evaluation_metrics = []
logocv = LeaveOneGroupOut()
# Split the data into training and test sets for each fold leaving one workload group out
for train_index, test_index in logocv.split(X=self.w, groups=self.w_groups):
y_pred = []
y_true = []
w_train, w_test = self.w[train_index], self.w[test_index]
cs_train, cs_test = self.cs[train_index], self.cs[test_index]
t_train, t_test = self.t[train_index], self.t[test_index]
# For each sample (workload_ref) in test_data (workload group) a lazy model is trained to predict the execution time
for i in range(len(w_test)):
w_test_i = w_test[i] # workload_ref
cs_test_i = cs_test[i]
t_test_i = t_test[i]
try:
prediction = self.perf_model.fit_predict(
workload_descriptors=w_train,
configuration_settings=cs_train,
execution_times=t_train,
workload_ref=w_test_i,
new_configuration_settings=cs_test_i,
k_min=self.k_min,
k_max=self.k_max,
eebc_weight=self.eebc_weight
)
y_pred.append(prediction[0])
y_true.append(t_test_i)
except Exception as e:
warnings.warn(f"leave_one_group_out: {e}", UserWarning)
# Calculate metrics for this fold and save them for later averaging
evaluation_metrics.append(
EvaluationMetrics(y_true, y_pred)
)
# Average the metrics across all folds
final_metrics = EvaluationMetrics.average_metrics(evaluation_metrics)
return final_metrics