Call new fit method

master
Alinson S. Xavier 5 years ago
parent cb62345acf
commit 9d404f29a7
No known key found for this signature in database
GPG Key ID: DCA0DAD4D2F58624

@ -25,44 +25,7 @@ class Component(EnforceOverrides):
strategy. strategy.
""" """
def before_solve_lp_old( def after_solve_lp(
self,
solver: "LearningSolver",
instance: Instance,
model: Any,
stats: LearningSolveStats,
features: Features,
training_data: TrainingSample,
) -> None:
"""
Method called by LearningSolver before the root LP relaxation is solved.
Parameters
----------
solver: LearningSolver
The solver calling this method.
instance: Instance
The instance being solved.
model
The concrete optimization model being solved.
stats: LearningSolveStats
A dictionary containing statistics about the solution process, such as
number of nodes explored and running time. Components are free to add
their own statistics here. For example, PrimalSolutionComponent adds
statistics regarding the number of predicted variables. All statistics in
this dictionary are exported to the benchmark CSV file.
features: miplearn.features.Features
Features describing the model.
training_data: TrainingSample
A dictionary containing data that may be useful for training machine
learning models and accelerating the solution process. Components are
free to add their own training data here. For example,
PrimalSolutionComponent adds the current primal solution. The data must
be pickable.
"""
return
def before_solve_lp(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -71,26 +34,8 @@ class Component(EnforceOverrides):
sample: Sample, sample: Sample,
) -> None: ) -> None:
""" """
Method called by LearningSolver before the root LP relaxation is solved. Method called by LearningSolver after the root LP relaxation is solved.
See before_solve_lp for a description of the parameters.
Parameters
----------
solver: LearningSolver
The solver calling this method.
instance: Instance
The instance being solved.
model
The concrete optimization model being solved.
stats: LearningSolveStats
A dictionary containing statistics about the solution process, such as
number of nodes explored and running time. Components are free to add
their own statistics here. For example, PrimalSolutionComponent adds
statistics regarding the number of predicted variables. All statistics in
this dictionary are exported to the benchmark CSV file.
sample: miplearn.features.Sample
An object containing data that may be useful for training machine
learning models and accelerating the solution process. Components are
free to add their own training data here.
""" """
return return
@ -109,7 +54,7 @@ class Component(EnforceOverrides):
""" """
return return
def after_solve_lp( def after_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -118,12 +63,12 @@ class Component(EnforceOverrides):
sample: Sample, sample: Sample,
) -> None: ) -> None:
""" """
Method called by LearningSolver after the root LP relaxation is solved. Method called by LearningSolver after the MIP is solved.
See before_solve_lp for a description of the parameters. See before_solve_lp for a description of the parameters.
""" """
return return
def before_solve_mip_old( def after_solve_mip_old(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -133,12 +78,12 @@ class Component(EnforceOverrides):
training_data: TrainingSample, training_data: TrainingSample,
) -> None: ) -> None:
""" """
Method called by LearningSolver before the MIP is solved. Method called by LearningSolver after the MIP is solved.
See before_solve_lp for a description of the parameters. See before_solve_lp for a description of the parameters.
""" """
return return
def before_solve_mip( def before_solve_lp(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -147,12 +92,30 @@ class Component(EnforceOverrides):
sample: Sample, sample: Sample,
) -> None: ) -> None:
""" """
Method called by LearningSolver before the MIP is solved. Method called by LearningSolver before the root LP relaxation is solved.
See before_solve_lp for a description of the parameters.
Parameters
----------
solver: LearningSolver
The solver calling this method.
instance: Instance
The instance being solved.
model
The concrete optimization model being solved.
stats: LearningSolveStats
A dictionary containing statistics about the solution process, such as
number of nodes explored and running time. Components are free to add
their own statistics here. For example, PrimalSolutionComponent adds
statistics regarding the number of predicted variables. All statistics in
this dictionary are exported to the benchmark CSV file.
sample: miplearn.features.Sample
An object containing data that may be useful for training machine
learning models and accelerating the solution process. Components are
free to add their own training data here.
""" """
return return
def after_solve_mip_old( def before_solve_lp_old(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -162,12 +125,34 @@ class Component(EnforceOverrides):
training_data: TrainingSample, training_data: TrainingSample,
) -> None: ) -> None:
""" """
Method called by LearningSolver after the MIP is solved. Method called by LearningSolver before the root LP relaxation is solved.
See before_solve_lp for a description of the parameters.
Parameters
----------
solver: LearningSolver
The solver calling this method.
instance: Instance
The instance being solved.
model
The concrete optimization model being solved.
stats: LearningSolveStats
A dictionary containing statistics about the solution process, such as
number of nodes explored and running time. Components are free to add
their own statistics here. For example, PrimalSolutionComponent adds
statistics regarding the number of predicted variables. All statistics in
this dictionary are exported to the benchmark CSV file.
features: miplearn.features.Features
Features describing the model.
training_data: TrainingSample
A dictionary containing data that may be useful for training machine
learning models and accelerating the solution process. Components are
free to add their own training data here. For example,
PrimalSolutionComponent adds the current primal solution. The data must
be pickable.
""" """
return return
def after_solve_mip( def before_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -176,56 +161,44 @@ class Component(EnforceOverrides):
sample: Sample, sample: Sample,
) -> None: ) -> None:
""" """
Method called by LearningSolver after the MIP is solved. Method called by LearningSolver before the MIP is solved.
See before_solve_lp for a description of the parameters. See before_solve_lp for a description of the parameters.
""" """
return return
def sample_xy_old( def before_solve_mip_old(
self, self,
solver: "LearningSolver",
instance: Instance, instance: Instance,
sample: TrainingSample, model: Any,
) -> Tuple[Dict, Dict]: stats: LearningSolveStats,
""" features: Features,
Returns a pair of x and y dictionaries containing, respectively, the matrices training_data: TrainingSample,
of ML features and the labels for the sample. If the training sample does not ) -> None:
include label information, returns (x, {}).
"""
pass
def sample_xy(
self,
instance: Optional[Instance],
sample: Sample,
) -> Tuple[Dict, Dict]:
""" """
Returns a pair of x and y dictionaries containing, respectively, the matrices Method called by LearningSolver before the MIP is solved.
of ML features and the labels for the sample. If the training sample does not See before_solve_lp for a description of the parameters.
include label information, returns (x, {}).
""" """
pass return
def xy_instances_old( def evaluate_old(self, instances: List[Instance]) -> List:
self, ev = []
instances: List[Instance],
) -> Tuple[Dict, Dict]:
x_combined: Dict = {}
y_combined: Dict = {}
for instance in instances: for instance in instances:
instance.load() instance.load()
for sample in instance.training_data: for sample in instance.training_data:
xy = self.sample_xy_old(instance, sample) ev += [self.sample_evaluate_old(instance, sample)]
if xy is None:
continue
x_sample, y_sample = xy
for cat in x_sample.keys():
if cat not in x_combined:
x_combined[cat] = []
y_combined[cat] = []
x_combined[cat] += x_sample[cat]
y_combined[cat] += y_sample[cat]
instance.free() instance.free()
return x_combined, y_combined return ev
def fit(
self,
training_instances: List[Instance],
) -> None:
x, y = self.xy_instances(training_instances)
for cat in x.keys():
x[cat] = np.array(x[cat])
y[cat] = np.array(y[cat])
self.fit_xy(x, y)
def fit_old( def fit_old(
self, self,
@ -286,6 +259,37 @@ class Component(EnforceOverrides):
) -> None: ) -> None:
return return
def sample_evaluate_old(
self,
instance: Instance,
sample: TrainingSample,
) -> Dict[Hashable, Dict[str, float]]:
return {}
def sample_xy(
self,
instance: Optional[Instance],
sample: Sample,
) -> Tuple[Dict, Dict]:
"""
Returns a pair of x and y dictionaries containing, respectively, the matrices
of ML features and the labels for the sample. If the training sample does not
include label information, returns (x, {}).
"""
pass
def sample_xy_old(
self,
instance: Instance,
sample: TrainingSample,
) -> Tuple[Dict, Dict]:
"""
Returns a pair of x and y dictionaries containing, respectively, the matrices
of ML features and the labels for the sample. If the training sample does not
include label information, returns (x, {}).
"""
pass
def user_cut_cb( def user_cut_cb(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
@ -294,18 +298,43 @@ class Component(EnforceOverrides):
) -> None: ) -> None:
return return
def evaluate_old(self, instances: List[Instance]) -> List: def xy_instances(
ev = [] self,
instances: List[Instance],
) -> Tuple[Dict, Dict]:
x_combined: Dict = {}
y_combined: Dict = {}
for instance in instances: for instance in instances:
instance.load() instance.load()
for sample in instance.training_data: for sample in instance.samples:
ev += [self.sample_evaluate_old(instance, sample)] x_sample, y_sample = self.sample_xy(instance, sample)
for cat in x_sample.keys():
if cat not in x_combined:
x_combined[cat] = []
y_combined[cat] = []
x_combined[cat] += x_sample[cat]
y_combined[cat] += y_sample[cat]
instance.free() instance.free()
return ev return x_combined, y_combined
def sample_evaluate_old( def xy_instances_old(
self, self,
instance: Instance, instances: List[Instance],
sample: TrainingSample, ) -> Tuple[Dict, Dict]:
) -> Dict[Hashable, Dict[str, float]]: x_combined: Dict = {}
return {} y_combined: Dict = {}
for instance in instances:
instance.load()
for sample in instance.training_data:
xy = self.sample_xy_old(instance, sample)
if xy is None:
continue
x_sample, y_sample = xy
for cat in x_sample.keys():
if cat not in x_combined:
x_combined[cat] = []
y_combined[cat] = []
x_combined[cat] += x_sample[cat]
y_combined[cat] += y_sample[cat]
instance.free()
return x_combined, y_combined

@ -154,3 +154,10 @@ class ObjectiveValueComponent(Component):
if sample.lower_bound is not None: if sample.lower_bound is not None:
result["Lower bound"] = compare(pred["Lower bound"], sample.lower_bound) result["Lower bound"] = compare(pred["Lower bound"], sample.lower_bound)
return result return result
@overrides
def fit(
self,
training_instances: List[Instance],
) -> None:
return

@ -279,3 +279,10 @@ class PrimalSolutionComponent(Component):
thr.fit(clf, x[category], y[category]) thr.fit(clf, x[category], y[category])
self.classifiers[category] = clf self.classifiers[category] = clf
self.thresholds[category] = thr self.thresholds[category] = thr
@overrides
def fit(
self,
training_instances: List[Instance],
) -> None:
return

@ -40,6 +40,7 @@ class InstanceFeatures:
features: List[float] = [] features: List[float] = []
if self.user_features is not None: if self.user_features is not None:
features.extend(self.user_features) features.extend(self.user_features)
_clip(features)
return features return features
@ -85,6 +86,7 @@ class Variable:
for attr in ["user_features", "alvarez_2017"]: for attr in ["user_features", "alvarez_2017"]:
if getattr(self, attr) is not None: if getattr(self, attr) is not None:
features.extend(getattr(self, attr)) features.extend(getattr(self, attr))
_clip(features)
return features return features
@ -120,6 +122,7 @@ class Constraint:
features.append(np.max(self.lhs.values())) features.append(np.max(self.lhs.values()))
features.append(np.average(self.lhs.values())) features.append(np.average(self.lhs.values()))
features.append(np.min(self.lhs.values())) features.append(np.min(self.lhs.values()))
_clip(features)
return features return features
@ -313,3 +316,9 @@ class FeaturesExtractor:
for v in f: for v in f:
assert isfinite(v), f"non-finite elements detected: {f}" assert isfinite(v), f"non-finite elements detected: {f}"
var.alvarez_2017 = f var.alvarez_2017 = f
def _clip(v: List[float]) -> None:
for (i, vi) in enumerate(v):
if not isfinite(vi):
v[i] = max(min(vi, 1e20), -1e20)

@ -415,6 +415,7 @@ class LearningSolver:
return return
for component in self.components.values(): for component in self.components.values():
logger.info(f"Fitting {component.__class__.__name__}...") logger.info(f"Fitting {component.__class__.__name__}...")
component.fit(training_instances)
component.fit_old(training_instances) component.fit_old(training_instances)
def _add_component(self, component: Component) -> None: def _add_component(self, component: Component) -> None:

Loading…
Cancel
Save