Browse Source

[ENH] support multiclass logits in EnsemblePruningReuser

tags/v0.3.2
Gene 2 years ago
parent
commit
b9cec567b6
2 changed files with 28 additions and 17 deletions
  1. +19
    -12
      learnware/learnware/reuse.py
  2. +9
    -5
      tests/test_workflow/test_workflow.py

+ 19
- 12
learnware/learnware/reuse.py View File

@@ -643,6 +643,21 @@ class EnsemblePruningReuser(BaseReuser):

return res["Vars"][bst_pop]

def _get_predict(self, X, selected_idxes):
preds = []
for idx in selected_idxes:
pred_y = self.learnware_list[idx].predict(X)
if len(pred_y.shape) == 1:
pred_y = pred_y.reshape(-1, 1)
elif len(pred_y.shape) == 2:
if pred_y.shape[1] > 1:
pred_y = pred_y.argmax(axis=1).reshape(-1, 1)
else:
raise ValueError("Model output must be a 1D or 2D vector")
preds.append(pred_y)
return np.concatenate(preds, axis=1)
def fit(self, val_X: np.ndarray, val_y: np.ndarray, maxgen: int = 500):
"""Ensemble pruning based on the validation set

@@ -656,11 +671,7 @@ class EnsemblePruningReuser(BaseReuser):
The maximum number of iteration rounds in ensemble pruning algorithms.
"""
# Get the prediction of each learnware on the validation set
v_predict = []
for idx in range(len(self.learnware_list)):
pred_y = self.learnware_list[idx].predict(val_X).reshape(-1, 1)
v_predict.append(pred_y)
v_predict = np.concatenate(v_predict, axis=1)
v_predict = self._get_predict(val_X, list(range(len(self.learnware_list))))
v_true = val_y.reshape(-1, 1)

# Run ensemble pruning algorithm
@@ -686,13 +697,9 @@ class EnsemblePruningReuser(BaseReuser):
np.ndarray
Prediction given by ensemble method
"""
preds = []
for idx in self.selected_idxes:
pred_y = self.learnware_list[idx].predict(user_data).reshape(-1, 1)
preds.append(pred_y)
preds = self._get_predict(user_data, self.selected_idxes)

if self.mode == "regression":
return np.concatenate(preds, axis=1).mean(axis=1)
elif self.option == "binary" or self.option == "multiclass":
preds = np.concatenate(preds, axis=1)
return preds.mean(axis=1)
elif self.mode == "binary" or self.mode == "multiclass":
return np.apply_along_axis(lambda x: np.bincount(x).argmax(), axis=1, arr=preds)

+ 9
- 5
tests/test_workflow/test_workflow.py View File

@@ -12,7 +12,7 @@ from shutil import copyfile, rmtree

import learnware
from learnware.market import EasyMarket, BaseUserInfo
from learnware.learnware import JobSelectorReuser, AveragingReuser
from learnware.learnware import JobSelectorReuser, AveragingReuser, EnsemblePruningReuser
import learnware.specification as specification

curr_root = os.path.dirname(os.path.abspath(__file__))
@@ -172,15 +172,13 @@ class TestAllWorkflow(unittest.TestCase):
print("Total Item:", len(easy_market))

X, y = load_digits(return_X_y=True)
_, data_X, _, data_y = train_test_split(X, y, test_size=0.3, shuffle=True)
train_X, data_X, train_y, data_y = train_test_split(X, y, test_size=0.3, shuffle=True)

stat_spec = specification.utils.generate_rkme_spec(X=data_X, gamma=0.1, cuda_idx=0)
user_info = BaseUserInfo(semantic_spec=user_semantic, stat_info={"RKMEStatSpecification": stat_spec})

_, _, _, mixture_learnware_list = easy_market.search_learnware(user_info)

# print("Mixture Learnware:", mixture_learnware_list)

# Based on user information, the learnware market returns a list of learnwares (learnware_list)
# Use jobselector reuser to reuse the searched learnwares to make prediction
reuse_job_selector = JobSelectorReuser(learnware_list=mixture_learnware_list)
@@ -189,9 +187,15 @@ class TestAllWorkflow(unittest.TestCase):
# Use averaging ensemble reuser to reuse the searched learnwares to make prediction
reuse_ensemble = AveragingReuser(learnware_list=mixture_learnware_list, mode="vote")
ensemble_predict_y = reuse_ensemble.predict(user_data=data_X)
# Use ensemble pruning reuser to reuse the searched learnwares to make prediction
reuse_ensemble = EnsemblePruningReuser(learnware_list=mixture_learnware_list, mode="multiclass")
reuse_ensemble.fit(train_X[-200:], train_y[-200:])
ensemble_pruning_predict_y = reuse_ensemble.predict(user_data=data_X)

print("Job Selector Acc:", np.sum(np.argmax(job_selector_predict_y, axis=1) == data_y) / len(data_y))
print("Averaging Selector Acc:", np.sum(np.argmax(ensemble_predict_y, axis=1) == data_y) / len(data_y))
print("Averaging Reuser Acc:", np.sum(np.argmax(ensemble_predict_y, axis=1) == data_y) / len(data_y))
print("Ensemble Pruning Reuser Acc:", np.sum(ensemble_pruning_predict_y == data_y) / len(data_y))


def suite():


Loading…
Cancel
Save