From c222ea67c562b49a847ca699772dd7033ae467b5 Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Thu, 11 May 2023 14:41:00 -0700 Subject: [PATCH 1/6] Add option to specify the device --- lume_model/torch/model.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index 2db2fe1..1c96934 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -25,6 +25,7 @@ def __init__( output_format: Optional[Dict[str, str]] = {"type": "tensor"}, feature_order: Optional[list] = None, output_order: Optional[list] = None, + device: Optional[str] = "cpu", ) -> None: """Initializes the model, stores inputs/outputs and determines the format in which the model results will be output. @@ -45,6 +46,7 @@ def __init__( order in which they are passed to the model output_order: List[str]: list containing the names of outputs in the order the model produces them + device (Optional[str]): Device on which model evaluation will take place. TODO: make list of Transformer objects into botorch ChainedInputTransform? @@ -61,17 +63,18 @@ def __init__( self.output_variables = output_variables self._model_file = model_file self._output_format = output_format + self.device = device - # make sure all of the transformers are in eval mode + # make sure all of the transformers are in eval mode and on device self._input_transformers = input_transformers - for transformer in self._input_transformers: - transformer.eval() self._output_transformers = output_transformers - for transformer in self._output_transformers: + for transformer in self._input_transformers + self._output_transformers: transformer.eval() + transformer.to(self.device) self._model = torch.load(model_file).double() self._model.eval() + self._model.to(self.device) self._feature_order = feature_order self._output_order = output_order @@ -219,7 +222,7 @@ def _arrange_inputs(self, input_variables: Dict[str, torch.Tensor]) -> torch.Ten """ ) else: - return default_tensor + return default_tensor.to(self.device) def _transform_inputs(self, input_values: torch.Tensor) -> torch.Tensor: """ From b7523563254047351c3bab3f84e00a231dcd7e6b Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Thu, 11 May 2023 16:28:29 -0700 Subject: [PATCH 2/6] Add functionality to update the device retrospectively --- lume_model/torch/model.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index 1c96934..83aa8a3 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -25,7 +25,7 @@ def __init__( output_format: Optional[Dict[str, str]] = {"type": "tensor"}, feature_order: Optional[list] = None, output_order: Optional[list] = None, - device: Optional[str] = "cpu", + device: Optional[Union[torch.device, str]] = "cpu", ) -> None: """Initializes the model, stores inputs/outputs and determines the format in which the model results will be output. @@ -46,7 +46,8 @@ def __init__( order in which they are passed to the model output_order: List[str]: list containing the names of outputs in the order the model produces them - device (Optional[str]): Device on which model evaluation will take place. + device (Optional[Union[torch.device, str]]): Device on which the + model will be evaluated. Defaults to "cpu". TODO: make list of Transformer objects into botorch ChainedInputTransform? @@ -335,3 +336,14 @@ def _update_image_limits( self.output_variables[variable.name].y_max = predicted_output[ self.output_variables[variable.name].y_max_variable ].item() + + def to(self, device: Union[torch.device, str]): + """Updates the device for the model and transformers. + + Args: + device: Device on which the model will be evaluated. + """ + self._model.to(device) + for transformer in self._input_transformers + self._output_transformers: + transformer.to(device) + self.device = device From a10339e7b84f7c019cc1bece5d78494a32d009c0 Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Mon, 15 May 2023 18:42:36 -0700 Subject: [PATCH 3/6] Improve device handling --- lume_model/torch/model.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index 83aa8a3..720c5a4 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -55,16 +55,17 @@ def __init__( super(BaseModel, self).__init__() # Save init + self.device = device self.input_variables = input_variables self.default_values = torch.tensor( [var.default for var in input_variables.values()], dtype=torch.double, requires_grad=True, + device=device ) self.output_variables = output_variables self._model_file = model_file self._output_format = output_format - self.device = device # make sure all of the transformers are in eval mode and on device self._input_transformers = input_transformers @@ -171,17 +172,18 @@ def _prepare_inputs( for var_name, var in input_variables.items(): if isinstance(var, InputVariable): model_vals[var_name] = torch.tensor( - var.value, dtype=torch.double, requires_grad=True + var.value, dtype=torch.double, requires_grad=True, + device=self.device ) self.input_variables[var_name].value = var.value elif isinstance(var, float): model_vals[var_name] = torch.tensor( - var, dtype=torch.double, requires_grad=True + var, dtype=torch.double, requires_grad=True, + device=self.device ) self.input_variables[var_name].value = var elif isinstance(var, torch.Tensor): - var = var.double() - var = var.squeeze() + var = var.double().squeeze().to(self.device) if not var.requires_grad: var.requires_grad = True model_vals[var_name] = var @@ -223,7 +225,7 @@ def _arrange_inputs(self, input_variables: Dict[str, torch.Tensor]) -> torch.Ten """ ) else: - return default_tensor.to(self.device) + return default_tensor def _transform_inputs(self, input_values: torch.Tensor) -> torch.Tensor: """ From f50efdeb77e69f1352c56c032071b03cfb27d204 Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Tue, 16 May 2023 12:26:56 -0700 Subject: [PATCH 4/6] Minor improvements --- lume_model/torch/model.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index 720c5a4..484df23 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -61,7 +61,7 @@ def __init__( [var.default for var in input_variables.values()], dtype=torch.double, requires_grad=True, - device=device + device=self.device ) self.output_variables = output_variables self._model_file = model_file @@ -340,7 +340,7 @@ def _update_image_limits( ].item() def to(self, device: Union[torch.device, str]): - """Updates the device for the model and transformers. + """Updates the device for the model, transformers and default values. Args: device: Device on which the model will be evaluated. @@ -348,4 +348,5 @@ def to(self, device: Union[torch.device, str]): self._model.to(device) for transformer in self._input_transformers + self._output_transformers: transformer.to(device) + self.default_values = self.default_values.to(device) self.device = device From 4bf13ec73b211ca3fc7db8ab111a2acd01ac87e9 Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Wed, 24 May 2023 09:49:22 -0700 Subject: [PATCH 5/6] Simplify device handling in init method --- lume_model/torch/model.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index 484df23..be938ed 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -60,23 +60,23 @@ def __init__( self.default_values = torch.tensor( [var.default for var in input_variables.values()], dtype=torch.double, - requires_grad=True, - device=self.device + requires_grad=True ) self.output_variables = output_variables self._model_file = model_file self._output_format = output_format - # make sure all of the transformers are in eval mode and on device + # make sure all of the transformers are in eval mode self._input_transformers = input_transformers self._output_transformers = output_transformers for transformer in self._input_transformers + self._output_transformers: transformer.eval() - transformer.to(self.device) self._model = torch.load(model_file).double() self._model.eval() - self._model.to(self.device) + + # move model, transformers and default values to device + self.to(self.device) self._feature_order = feature_order self._output_order = output_order From 8bbeeb9f7e3818c780acc18c59bc081cd95a83d5 Mon Sep 17 00:00:00 2001 From: Tobias Boltz Date: Thu, 25 May 2023 09:47:18 -0700 Subject: [PATCH 6/6] Add type check for transformer lists --- lume_model/torch/model.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lume_model/torch/model.py b/lume_model/torch/model.py index be938ed..da25a36 100644 --- a/lume_model/torch/model.py +++ b/lume_model/torch/model.py @@ -66,9 +66,15 @@ def __init__( self._model_file = model_file self._output_format = output_format - # make sure all of the transformers are in eval mode + # make sure transformers are passed as lists + if not isinstance(input_transformers, list) or not isinstance( + output_transformers, list): + raise TypeError( + "In- and output transformers have to be passed as lists.") self._input_transformers = input_transformers self._output_transformers = output_transformers + + # put all transformers in eval mode for transformer in self._input_transformers + self._output_transformers: transformer.eval()