DropRedundant: Update for new classifier interface

master
Alinson S. Xavier 5 years ago
parent d3c5371fa5
commit 8153dfc825

@ -45,6 +45,10 @@ class DropRedundantInequalitiesStep(Component):
self.violation_tolerance = violation_tolerance self.violation_tolerance = violation_tolerance
self.max_iterations = max_iterations self.max_iterations = max_iterations
self.current_iteration = 0 self.current_iteration = 0
self.total_dropped = 0
self.total_restored = 0
self.total_kept = 0
self.total_iterations = 0
def before_solve(self, solver, instance, _): def before_solve(self, solver, instance, _):
self.current_iteration = 0 self.current_iteration = 0
@ -62,7 +66,7 @@ class DropRedundantInequalitiesStep(Component):
self.total_iterations = 0 self.total_iterations = 0
for category in y.keys(): for category in y.keys():
for i in range(len(y[category])): for i in range(len(y[category])):
if y[category][i][0] == 1: if y[category][i][1] == 1:
cid = constraints[category][i] cid = constraints[category][i]
c = LazyConstraint( c = LazyConstraint(
cid=cid, cid=cid,
@ -101,7 +105,7 @@ class DropRedundantInequalitiesStep(Component):
for category in tqdm(x.keys(), desc="Fit (rlx:drop_ineq)"): for category in tqdm(x.keys(), desc="Fit (rlx:drop_ineq)"):
if category not in self.classifiers: if category not in self.classifiers:
self.classifiers[category] = deepcopy(self.classifier_prototype) self.classifiers[category] = deepcopy(self.classifier_prototype)
self.classifiers[category].fit(x[category], y[category]) self.classifiers[category].fit(x[category], np.array(y[category]))
@staticmethod @staticmethod
def _x_test(instance, constraint_ids): def _x_test(instance, constraint_ids):
@ -160,9 +164,9 @@ class DropRedundantInequalitiesStep(Component):
if category not in y: if category not in y:
y[category] = [] y[category] = []
if slack > self.slack_tolerance: if slack > self.slack_tolerance:
y[category] += [[1]] y[category] += [[False, True]]
else: else:
y[category] += [[0]] y[category] += [[True, False]]
return y return y
def predict(self, x): def predict(self, x):
@ -175,9 +179,9 @@ class DropRedundantInequalitiesStep(Component):
proba = self.classifiers[category].predict_proba(x_cat) proba = self.classifiers[category].predict_proba(x_cat)
for i in range(len(proba)): for i in range(len(proba)):
if proba[i][1] >= self.threshold: if proba[i][1] >= self.threshold:
y[category] += [[1]] y[category] += [[False, True]]
else: else:
y[category] += [[0]] y[category] += [[True, False]]
return y return y
def evaluate(self, instance): def evaluate(self, instance):
@ -187,13 +191,13 @@ class DropRedundantInequalitiesStep(Component):
tp, tn, fp, fn = 0, 0, 0, 0 tp, tn, fp, fn = 0, 0, 0, 0
for category in y_true.keys(): for category in y_true.keys():
for i in range(len(y_true[category])): for i in range(len(y_true[category])):
if y_pred[category][i][0] == 1: if y_pred[category][i][1] == 1:
if y_true[category][i][0] == 1: if y_true[category][i][1] == 1:
tp += 1 tp += 1
else: else:
fp += 1 fp += 1
else: else:
if y_true[category][i][0] == 1: if y_true[category][i][1] == 1:
fn += 1 fn += 1
else: else:
tn += 1 tn += 1

@ -6,11 +6,13 @@ from unittest.mock import Mock, call
import numpy as np import numpy as np
from miplearn import RelaxIntegralityStep, BasePyomoSolver
from miplearn.classifiers import Classifier from miplearn.classifiers import Classifier
from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep
from miplearn.instance import Instance from miplearn.instance import Instance
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
from tests.solvers import _get_knapsack_instance
def _setup(): def _setup():
@ -268,8 +270,20 @@ def test_x_y_fit_predict_evaluate():
), ),
} }
expected_y = { expected_y = {
"type-a": np.array([[0], [0], [1]]), "type-a": np.array(
"type-b": np.array([[1], [0], [0]]), [
[True, False],
[True, False],
[False, True],
]
),
"type-b": np.array(
[
[False, True],
[True, False],
[True, False],
]
),
} }
# Should build X and Y matrices correctly # Should build X and Y matrices correctly
@ -287,7 +301,15 @@ def test_x_y_fit_predict_evaluate():
np.testing.assert_array_equal(actual_x, expected_x[category]) np.testing.assert_array_equal(actual_x, expected_x[category])
np.testing.assert_array_equal(actual_y, expected_y[category]) np.testing.assert_array_equal(actual_y, expected_y[category])
assert component.predict(expected_x) == {"type-a": [[1]], "type-b": [[0], [1]]} assert component.predict(expected_x) == {
"type-a": [
[False, True],
],
"type-b": [
[True, False],
[False, True],
],
}
ev = component.evaluate(instances[1]) ev = component.evaluate(instances[1])
assert ev["True positive"] == 1 assert ev["True positive"] == 1
@ -350,8 +372,20 @@ def test_x_multiple_solves():
} }
expected_y = { expected_y = {
"type-a": np.array([[1], [0], [0], [1]]), "type-a": np.array(
"type-b": np.array([[1], [0]]), [
[False, True],
[True, False],
[True, False],
[False, True],
]
),
"type-b": np.array(
[
[False, True],
[True, False],
]
),
} }
# Should build X and Y matrices correctly # Should build X and Y matrices correctly
@ -362,3 +396,17 @@ def test_x_multiple_solves():
for category in ["type-a", "type-b"]: for category in ["type-a", "type-b"]:
np.testing.assert_array_equal(actual_x[category], expected_x[category]) np.testing.assert_array_equal(actual_x[category], expected_x[category])
np.testing.assert_array_equal(actual_y[category], expected_y[category]) np.testing.assert_array_equal(actual_y[category], expected_y[category])
def test_usage():
solver = LearningSolver(
components=[
RelaxIntegralityStep(),
DropRedundantInequalitiesStep(),
]
)
instance = _get_knapsack_instance(BasePyomoSolver)
# The following should not crash
solver.solve(instance)
solver.fit([instance])
solver.solve(instance)

Loading…
Cancel
Save