11"""Load and run pretrained ResNet-18 from TorchVision."""
22
3+ import os
4+ from math import isclose
5+
36import numpy as np
47import torch
58import torchvision
69from PIL import Image
710
811
9- # Initialize everything
1012def initialize (precision : torch .dtype ) -> torch .nn .Module :
1113 """
1214 Download pre-trained ResNet-18 model and prepare for inference.
1315
16+ NOTE: These steps duplicate the process for loading pre-trained models in the pt2ts
17+ script and are provided here for testing.
18+
1419 Parameters
1520 ----------
1621 precision: torch.dtype
@@ -36,78 +41,21 @@ def initialize(precision: torch.dtype) -> torch.nn.Module:
3641 return model
3742
3843
39- def run_model (model : torch .nn .Module , precision : type ) -> None :
40- """
41- Run the pre-trained ResNet-18 with an example image of a dog.
42-
43- Parameters
44- ----------
45- model: torch.nn.Module
46- Pretrained model to run.
47- precision: type
48- NumPy data type to save input tensor.
49- """
50- # Transform image into the form expected by the pre-trained model, using the mean
51- # and standard deviation from the ImageNet dataset
52- # See: https://pytorch.org/vision/0.8/models.html
53- image_filename = "data/dog.jpg"
54- input_image = Image .open (image_filename )
55- preprocess = torchvision .transforms .Compose (
56- [
57- torchvision .transforms .Resize (256 ),
58- torchvision .transforms .CenterCrop (224 ),
59- torchvision .transforms .ToTensor (),
60- torchvision .transforms .Normalize (
61- mean = [0.485 , 0.456 , 0.406 ], std = [0.229 , 0.224 , 0.225 ]
62- ),
63- ]
64- )
65- input_tensor = preprocess (input_image )
66- input_batch = input_tensor .unsqueeze (0 )
67-
68- print ("Saving input batch..." , end = "" )
69- # Transpose input before saving so order consistent with Fortran
70- np_input = np .array (input_batch .numpy ().transpose ().flatten (), dtype = precision ) # type: np.typing.NDArray
71-
72- # Save data as binary
73- np_input .tofile ("data/image_tensor.dat" )
74-
75- # Load saved data to check it was saved correctly
76- np_data = np .fromfile ("data/image_tensor.dat" , dtype = precision ) # type: np.typing.NDArray
77-
78- # Reshape to original tensor shape
79- tensor_shape = np .array (input_batch .numpy ()).transpose ().shape
80- np_data = np_data .reshape (tensor_shape )
81- np_data = np_data .transpose ()
82- if not np .array_equal (np_data , input_batch .numpy ()):
83- result_error = (
84- "Image read from saved file (data/image_tensor.dat) does not match"
85- "processed data read from data/dog.jpg expected value."
86- )
87- raise ValueError (result_error )
88- print ("done." )
89-
90- print ("Running ResNet-18 model for input..." , end = "" )
91- with torch .inference_mode ():
92- output = model (input_batch )
93- print ("done." )
94-
95- print_top_results (output )
96-
97-
98- def print_top_results (output : torch .Tensor ) -> None :
44+ def print_top_results (output : torch .Tensor , data_dir : str ) -> None :
9945 """Print top 5 results.
10046
10147 Parameters
10248 ----------
10349 output: torch.Tensor
10450 Output from ResNet-18.
51+ data_dir : str
52+ Path to data directory
10553 """
10654 # Run a softmax to get probabilities
10755 probabilities = torch .nn .functional .softmax (output [0 ], dim = 0 )
10856
10957 # Read ImageNet labels from text file
110- cats_filename = "data/ categories.txt"
58+ cats_filename = os . path . join ( data_dir , " categories.txt")
11159 categories = np .genfromtxt (cats_filename , dtype = str , delimiter = "\n " )
11260
11361 # Show top categories per image
@@ -128,15 +76,53 @@ def print_top_results(output: torch.Tensor) -> None:
12876 ]
12977 if not np .allclose (top5_prob , expected_prob , rtol = 1e-5 ):
13078 result_error = (
131- f"Predicted top 5 probabilities:\n { top5_prob } \n do not match the"
132- "expected values:\n {expected_prob}"
79+ f"Predicted top 5 probabilities:\n { top5_prob } \n do not match the expected"
80+ f" values:\n { expected_prob } "
81+ )
82+ raise ValueError (result_error )
83+
84+
85+ def check_results (output : torch .Tensor ) -> None :
86+ """
87+ Compare top model output to expected result.
88+
89+ Parameters
90+ ----------
91+ output: torch.Tensor
92+ Output from ResNet-18.
93+ """
94+ # Run a softmax to get probabilities
95+ predicted_prob = torch .max (torch .nn .functional .softmax (output [0 ], dim = 0 ))
96+ expected_prob = 0.8846225142478943
97+ if not isclose (predicted_prob , expected_prob , abs_tol = 1e-5 ):
98+ result_error = (
99+ f"Predicted probability: { predicted_prob } does not match the expected"
100+ f" value: { expected_prob } ."
133101 )
134102 raise ValueError (result_error )
135103
136104
137105if __name__ == "__main__" :
138- np_precision = np . float32
106+ import argparse
139107
108+ # Parse user input
109+ parser = argparse .ArgumentParser (
110+ formatter_class = argparse .ArgumentDefaultsHelpFormatter ,
111+ )
112+ parser .add_argument (
113+ "--device_type" ,
114+ help = "Device type to run the inference on" ,
115+ type = str ,
116+ choices = ["cpu" , "cuda" , "hip" , "xpu" , "mps" ],
117+ default = "cpu" ,
118+ )
119+ parsed_args = parser .parse_args ()
120+ parsed_args = parser .parse_args ()
121+ device_type = parsed_args .device_type
122+ data_dir = os .path .join (os .path .dirname (__file__ ), "data" )
123+
124+ # Specify working precision
125+ np_precision = np .float32
140126 if np_precision == np .float32 :
141127 torch_precision = torch .float32
142128 elif np_precision == np .float64 :
@@ -145,5 +131,58 @@ def print_top_results(output: torch.Tensor) -> None:
145131 precision_mismatch = "`np_precision` must be type `np.float32` or `np.float64`"
146132 raise ValueError (precision_mismatch )
147133
148- rn_model = initialize (torch_precision )
149- run_model (rn_model , np_precision )
134+ # Initialize model on the specified device
135+ model = initialize (torch_precision ).to (device_type )
136+
137+ # Transform image into the form expected by the pre-trained model, using the mean
138+ # and standard deviation from the ImageNet dataset
139+ # See: https://pytorch.org/vision/0.8/models.html
140+ image_filename = os .path .join (data_dir , "dog.jpg" )
141+ input_image = Image .open (image_filename )
142+ preprocess = torchvision .transforms .Compose (
143+ [
144+ torchvision .transforms .Resize (256 ),
145+ torchvision .transforms .CenterCrop (224 ),
146+ torchvision .transforms .ToTensor (),
147+ torchvision .transforms .Normalize (
148+ mean = [0.485 , 0.456 , 0.406 ], std = [0.229 , 0.224 , 0.225 ]
149+ ),
150+ ]
151+ )
152+ input_tensor = preprocess (input_image )
153+ input_batch = input_tensor .unsqueeze (0 )
154+
155+ print ("Saving input batch..." , end = "" )
156+ # Transpose input before saving so order consistent with Fortran
157+ np_input = np .array (input_batch .numpy ().transpose ().flatten (), dtype = np_precision ) # type: np.typing.NDArray
158+
159+ # Save data as binary
160+ tensor_filename = os .path .join (data_dir , "image_tensor.dat" )
161+ np_input .tofile (tensor_filename )
162+
163+ # Load saved data to check it was saved correctly
164+ np_data = np .fromfile (tensor_filename , dtype = np_precision ) # type: np.typing.NDArray
165+
166+ # Reshape to original tensor shape
167+ tensor_shape = np .array (input_batch .numpy ()).transpose ().shape
168+ np_data = np_data .reshape (tensor_shape )
169+ np_data = np_data .transpose ()
170+ if not np .array_equal (np_data , input_batch .numpy ()):
171+ result_error = (
172+ f"Image read from saved file ({ tensor_filename } ) does not match processed"
173+ f" data read from { data_dir } /dog.jpg expected value."
174+ )
175+ raise ValueError (result_error )
176+ print ("done." )
177+
178+ # Save the input tensor in PyTorch format
179+ input_batch = input_batch .to (device_type )
180+ torch .save (input_batch , f"pytorch_resnet18_input_tensor_{ device_type } .pt" )
181+
182+ # Run the model
183+ print ("Running ResNet-18 model for input..." , end = "" )
184+ with torch .inference_mode ():
185+ output = model (input_batch )
186+ print ("done." )
187+ print_top_results (output , data_dir )
188+ check_results (output )
0 commit comments