Skip to content
This repository was archived by the owner on Jan 3, 2023. It is now read-only.

Commit 0f0c367

Browse files
yeonsilyavijit-nervana
authored andcommitted
Yeonsily/l2l test (#280)
* Modify the model test script - Change input numbers between 0-255 - Load both pb and pbtxt type graph - Set back_end as parameter - Save test result and tensor array to .npy file
1 parent 4dd7a89 commit 0f0c367

File tree

4 files changed

+91
-33
lines changed

4 files changed

+91
-33
lines changed

diagnostics/model_test/README.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
# Compare model output between Tensorflow and NGraph
1+
# Compare model output between two different backends
22

3-
### This model_test tool will run the model inference seperately on TF and NGraph, and the desired output from TF and NGraph should match given the same inputs. It can be used as a debugging tool, and also a verification that NGraph produces the same output as Tensorflow.
3+
### This model_test tool will run the model inference seperately on two specified backends(e.g.Tensorflow and nGraph) in json file and the desired outputs from each backend should match given the same inputs. It can be used as a debugging tool for layer by layer comparison, and also a verification that nGraph produces the same output as Tensorflow.
44

55
# Required files to use the tool:
66
* A json file: Provide model specific parameters. Look at the example ```mnist_cnn.json```. You can start with the ```template.json``` and modify it to match your model
7-
* A tensorflow frozen graph: A model frozen graph(.pb file) with trained weights and model architecture
7+
* A tensorflow model file: Either .pb or .pbtxt file
88

9-
## To prepare the required json file:"
9+
## To prepare the required json file:
10+
* Specify the ```reference_backend``` and ```testing_backend```. For tensolrflow on CPU, use 'CPU' and for nGraph, use 'NGRAPH_[desired backend name]' (e.g. Use 'NGAPH_CPU' for nGraph on CPU)
1011
* You will need the names of the input/output tensors of the model. Currently we are supporting
11-
multiple input tensors and one output tensor. Put the input tensor names as a list in the ```input_tensor_name``` field of the json file, and the output tensor name as a string in the ```output_tensor_name``` field of the json file
12+
multiple input tensors and output tensors. Put the input tensor names as a list in the ```input_tensor_name``` field of the json file, and the output tensor name as a list in the ```output_tensor_name``` field of the json file. If no outputs are specified in the ```output_tensor_name```, then it will compare all output tensors
1213
* You will need the input dimensions for all the input tensors provided. Put the dimensions information as a list in the ```input_dimension``` field of the json file, and the corresponding order of ```input_tensor_name``` list should match the ```input_dimension``` list. Therfore, the length of ```input_tensor_name``` list should match the length of ```input_dimension``` list
13-
* Specify the the location of the frozen graph in the ```frozen_graph_location``` of the json file
14+
* Specify the the location of the graph file in the ```graph_location``` of the json file
1415
* Specify the ```batch_size``` field in the json file to the desired batch size for inference
1516
* Specify the tolerance between the TF and NGraph outputs at ```l1_norm_threshold```, ```l2_norm_threshold``` and ```inf_norm_threshold``` in the json file
17+
* Specify the ```random_val_range``` used to generate the input within 0 to random_val_range
1618

1719
# To run the model test tool:
1820
python verify_model.py --json_file="/path/to/your/json/file"
1921

2022
# Result Metrics
21-
### The model_test tool will run the model inference and compare the outputs from TF and NGraph in terms of L1, L2 and Inf norm. If the corresponding norm is smaller than the matching tolerance specified in the json file, then the test passes. Otherwise, the test failes. In the situation of test failure, feel free to report the problem at the ngraph-tf github issue section.
23+
### The model_test tool will run the model inference and compare the outputs in terms of L1, L2 and Inf norm. If the corresponding norm is smaller than the matching tolerance specified in the json file, then the test passes. Otherwise, the test failes. Each output tensors will be saved as .npy file in a folder named as '[reference_backend_name]-[testing_backend_name]'(e.g. CPU-NGRAPH_CPU). In the situation of test failure, feel free to report the problem at the ngraph-tf github issue section.

diagnostics/model_test/mnist_cnn.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
{
22
"model_name": "mnist_cnn",
3-
"frozen_graph_location": "/nfs/site/home/mingshan/frozen_graphs/frozen_mnist.pb",
3+
"reference_backend": "CPU",
4+
"testing_backend": "NGRAPH_CPU",
5+
"graph_location": "/nfs/site/home/mingshan/frozen_graphs/frozen_mnist.pb",
46
"input_tensor_name": ["import/Placeholder:0"],
57
"output_tensor_name": ["import/Placeholder:0", "import/fc2/yconv:0"],
8+
"random_val_range": 255,
69
"l1_norm_threshold": 0.01,
710
"l2_norm_threshold": 0.01,
811
"inf_norm_threshold": 0.01,

diagnostics/model_test/template.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
{
22
"model_name": "name_of_your_model",
3+
"reference_backend": "your_reference_backend",
4+
"testing_backend": "your_testing_backend",
35
"frozen_graph_location": "/path/to/the/frozen_graph.pb",
46
"input_tensor_name": ["input_tesor_1","input_tensor_2"],
5-
"output_tensor_name":"output_tensor_name",
7+
"output_tensor_name":["output_tensor_name1","output_tensor_name_2"],
8+
"random_val_range": 255,
69
"l1_norm_threshold": 0.01,
710
"l2_norm_threshold": 0.01,
811
"inf_norm_threshold": 0.01,

diagnostics/model_test/verify_model.py

+74-24
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,37 @@
1818
import argparse
1919
import numpy as np
2020
import ngraph
21+
from google.protobuf import text_format
2122
import json
2223
import os
2324

2425

26+
def createFolder(directory):
27+
try:
28+
if not os.path.exists(directory):
29+
os.makedirs(directory)
30+
except OSError:
31+
print('Error: Creating directory. ' + directory)
32+
33+
34+
def set_os_env(select_device):
35+
if select_device == 'CPU':
36+
# run on TF only
37+
ngraph.disable()
38+
else:
39+
if not ngraph.is_enabled():
40+
ngraph.enable()
41+
42+
assert select_device[:
43+
7] == "NGRAPH_", "Expecting device name to start with NGRAPH_"
44+
back_end = select_device.split("NGRAPH_")
45+
os.environ['NGRAPH_TF_BACKEND'] = back_end[1]
46+
47+
2548
def calculate_output(param_dict, select_device, input_example):
26-
"""Calculate the output of the imported frozen graph given the input.
49+
"""Calculate the output of the imported graph given the input.
2750
28-
Load the graph def from frozen_graph_file on selected device, then get the tensors based on the input and output name from the graph,
51+
Load the graph def from graph file on selected device, then get the tensors based on the input and output name from the graph,
2952
then feed the input_example to the graph and retrieves the output vector.
3053
3154
Args:
@@ -36,23 +59,22 @@ def calculate_output(param_dict, select_device, input_example):
3659
Returns:
3760
The output vector obtained from running the input_example through the graph.
3861
"""
39-
frozen_graph_filename = param_dict["frozen_graph_location"]
62+
graph_filename = param_dict["graph_location"]
4063
output_tensor_name = param_dict["output_tensor_name"]
4164

42-
if not tf.gfile.Exists(frozen_graph_filename):
43-
raise Exception("Input graph file '" + frozen_graph_filename +
65+
if not tf.gfile.Exists(graph_filename):
66+
raise Exception("Input graph file '" + graph_filename +
4467
"' does not exist!")
4568

46-
with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
47-
graph_def = tf.GraphDef()
48-
graph_def.ParseFromString(f.read())
49-
50-
if select_device == 'CPU':
51-
ngraph.disable()
69+
graph_def = tf.GraphDef()
70+
if graph_filename.endswith("pbtxt"):
71+
with open(graph_filename, "r") as f:
72+
text_format.Merge(f.read(), graph_def)
5273
else:
53-
# run on NGRAPH
54-
if not ngraph.is_enabled():
55-
ngraph.enable()
74+
with open(graph_filename, "rb") as f:
75+
graph_def.ParseFromString(f.read())
76+
77+
set_os_env(select_device)
5678

5779
with tf.Graph().as_default() as graph:
5880
tf.import_graph_def(graph_def)
@@ -111,8 +133,12 @@ def calculate_norm(ngraph_output, tf_output, desired_norm):
111133
if desired_norm not in [1, 2, np.inf]:
112134
raise Exception('Only L2, L2, and inf norms are supported')
113135

114-
return np.linalg.norm((ngraph_output_flatten - tf_output_flatten),
115-
desired_norm)
136+
n = np.linalg.norm((ngraph_output_flatten - tf_output_flatten),
137+
desired_norm)
138+
if desired_norm is np.inf:
139+
return n
140+
else:
141+
return n / len(ngraph_output_flatten)
116142

117143

118144
def parse_json():
@@ -139,6 +165,23 @@ def parse_json():
139165

140166
parameters = parse_json()
141167

168+
# Get reference/testing backend to compare
169+
device1 = parameters["reference_backend"]
170+
device2 = parameters["testing_backend"]
171+
172+
# Get L1/L2/Inf threshold value
173+
l1_norm_threshold = parameters["l1_norm_threshold"]
174+
l2_norm_threshold = parameters["l2_norm_threshold"]
175+
inf_norm_threshold = parameters["inf_norm_threshold"]
176+
177+
# Create a folder to save output tensor arrays
178+
output_folder = device1 + "-" + device2
179+
createFolder(output_folder)
180+
os.chdir(output_folder)
181+
print("Model name: " + parameters["model_name"])
182+
print("L1/L2/Inf norm configuration: {}, {}, {}".format(
183+
l1_norm_threshold, l2_norm_threshold, inf_norm_threshold))
184+
142185
# Generate random input based on input_dimension
143186
np.random.seed(100)
144187
input_dimension = parameters["input_dimension"]
@@ -149,26 +192,33 @@ def parse_json():
149192
input_tensor_name
150193
), "input_tensor_name dimension should match input_dimension in json file"
151194

195+
# Get random value range
196+
rand_val_range = parameters["random_val_range"]
197+
152198
# Matches the input tensors name with its required dimensions
153199
input_tensor_dim_map = {}
154200
for (dim, name) in zip(input_dimension, input_tensor_name):
155-
random_input = np.random.random_sample([bs] + dim)
201+
random_input = np.random.randint(
202+
rand_val_range, size=[bs] + dim).astype('float32')
156203
input_tensor_dim_map[name] = random_input
157204

158-
# Run the model on tensorflow
205+
# Run the model on reference backend
159206
result_tf_graph_arrs, out_tensor_names_cpu = calculate_output(
160-
parameters, "CPU", input_tensor_dim_map)
161-
# Run the model on ngraph
207+
parameters, device1, input_tensor_dim_map)
208+
# Run the model on testing backend
162209
result_ngraph_arrs, out_tensor_names_ngraph = calculate_output(
163-
parameters, "NGRAPH", input_tensor_dim_map)
210+
parameters, device2, input_tensor_dim_map)
164211

165212
assert all(
166213
[i == j for i, j in zip(out_tensor_names_cpu, out_tensor_names_ngraph)])
167-
l1_norm_threshold = parameters["l1_norm_threshold"]
168-
l2_norm_threshold = parameters["l2_norm_threshold"]
169-
inf_norm_threshold = parameters["inf_norm_threshold"]
170214
for tname, result_ngraph, result_tf_graph in zip(
171215
out_tensor_names_cpu, result_ngraph_arrs, result_tf_graph_arrs):
216+
new_out_layer = tname.replace("/", "_")
217+
nparray_tf = np.array(result_tf_graph)
218+
nparray_ngraph = np.array(result_ngraph)
219+
np.save(device1 + "-" + new_out_layer + ".npy", nparray_tf)
220+
np.save(device2 + "-" + new_out_layer + ".npy", nparray_ngraph)
221+
172222
l1_norm = calculate_norm(result_ngraph, result_tf_graph, 1)
173223
l2_norm = calculate_norm(result_ngraph, result_tf_graph, 2)
174224
inf_norm = calculate_norm(result_ngraph, result_tf_graph, np.inf)

0 commit comments

Comments
 (0)