6
6
7
7
import unittest
8
8
9
- from typing import Any , Callable
10
-
11
9
import torch
12
10
from executorch .examples .models import MODEL_NAME_TO_MODEL
13
11
from executorch .examples .models .model_factory import EagerModelFactory
14
12
15
- from executorch .examples .portable .utils import export_to_edge
16
-
17
13
from executorch .extension .pybindings .portable_lib import ( # @manual
18
14
_load_for_executorch_from_buffer ,
19
15
)
20
16
17
+ from ..utils import export_to_edge
18
+
21
19
22
20
class ExportTest (unittest .TestCase ):
23
- def _assert_eager_lowered_same_result (
21
+ def collect_executorch_and_eager_outputs (
24
22
self ,
25
23
eager_model : torch .nn .Module ,
26
24
example_inputs ,
27
- validation_fn : Callable [[Any , Any ], bool ],
28
25
):
29
26
"""
30
- Asserts that the given model has the same result as the eager mode
31
- lowered model, with example_inputs, validated by validation_fn, which
32
- takes the eager mode output and ET output, and returns True if they
33
- match.
27
+ Compares the output of the given eager mode PyTorch model with the output
28
+ of the equivalent executorch model, both provided with example inputs.
29
+ Returns a tuple containing the outputs of the eager mode model and the executorch mode model.
34
30
"""
35
31
eager_model = eager_model .eval ()
36
32
model = torch ._export .capture_pre_autograd_graph (eager_model , example_inputs )
@@ -45,100 +41,107 @@ def _assert_eager_lowered_same_result(
45
41
with torch .no_grad ():
46
42
executorch_output = pte_model .run_method ("forward" , example_inputs )
47
43
48
- self . assertTrue ( validation_fn ( eager_output , executorch_output ) )
44
+ return ( eager_output , executorch_output )
49
45
50
- @staticmethod
51
- def validate_tensor_allclose (eager_output , executorch_output , rtol = 1e-5 , atol = 1e-5 ):
52
- result = torch .allclose (
53
- eager_output ,
54
- executorch_output [0 ],
55
- rtol = rtol ,
56
- atol = atol ,
57
- )
58
- if not result :
59
- print (f"eager output: { eager_output } " )
60
- print (f"executorch output: { executorch_output } " )
61
- return result
46
+ def validate_tensor_allclose (
47
+ self , eager_output , executorch_output , rtol = 1e-5 , atol = 1e-5
48
+ ):
49
+ self .assertTrue (
50
+ isinstance (eager_output , type (executorch_output )),
51
+ f"Outputs are not of the same type: eager type: { type (eager_output )} , executorch type: { type (executorch_output )} " ,
52
+ )
53
+ self .assertTrue (
54
+ len (eager_output ) == len (executorch_output ),
55
+ f"len(eager_output)={ len (eager_output )} , len(executorch_output)={ len (executorch_output )} " ,
56
+ )
57
+ result = True
58
+ for i in range (len (eager_output )):
59
+ result = torch .allclose (
60
+ eager_output [i ],
61
+ executorch_output [i ],
62
+ rtol = rtol ,
63
+ atol = atol ,
64
+ )
65
+ if not result :
66
+ print (f"eager output[{ i } ]: { eager_output [i ]} " )
67
+ print (f"executorch output[{ i } ]: { executorch_output [i ]} " )
68
+ break
69
+ return self .assertTrue (result )
62
70
63
71
def test_mv3_export_to_executorch (self ):
64
72
eager_model , example_inputs , _ = EagerModelFactory .create_model (
65
73
* MODEL_NAME_TO_MODEL ["mv3" ]
66
74
)
67
- eager_model = eager_model .eval ()
68
-
75
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
76
+ eager_model , example_inputs
77
+ )
69
78
# TODO(T166083470): Fix accuracy issue
70
- self ._assert_eager_lowered_same_result (
71
- eager_model ,
72
- example_inputs ,
73
- lambda x , y : self .validate_tensor_allclose (x , y , rtol = 1e-3 , atol = 1e-5 ),
79
+ self .validate_tensor_allclose (
80
+ eager_output , executorch_output [0 ], rtol = 1e-3 , atol = 1e-5
74
81
)
75
82
76
83
def test_mv2_export_to_executorch (self ):
77
84
eager_model , example_inputs , _ = EagerModelFactory .create_model (
78
85
* MODEL_NAME_TO_MODEL ["mv2" ]
79
86
)
80
- eager_model = eager_model .eval ()
81
-
82
- self ._assert_eager_lowered_same_result (
83
- eager_model , example_inputs , self .validate_tensor_allclose
87
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
88
+ eager_model , example_inputs
84
89
)
90
+ self .validate_tensor_allclose (eager_output , executorch_output [0 ])
85
91
86
92
def test_vit_export_to_executorch (self ):
87
93
eager_model , example_inputs , _ = EagerModelFactory .create_model (
88
94
* MODEL_NAME_TO_MODEL ["vit" ]
89
95
)
90
- eager_model = eager_model .eval ()
91
-
92
- self ._assert_eager_lowered_same_result (
93
- eager_model , example_inputs , self .validate_tensor_allclose
96
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
97
+ eager_model , example_inputs
94
98
)
99
+ self .validate_tensor_allclose (eager_output , executorch_output [0 ])
95
100
96
101
def test_w2l_export_to_executorch (self ):
97
102
eager_model , example_inputs , _ = EagerModelFactory .create_model (
98
103
* MODEL_NAME_TO_MODEL ["w2l" ]
99
104
)
100
- eager_model = eager_model .eval ()
101
-
102
- self ._assert_eager_lowered_same_result (
103
- eager_model , example_inputs , self .validate_tensor_allclose
105
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
106
+ eager_model , example_inputs
104
107
)
108
+ self .validate_tensor_allclose (eager_output , executorch_output [0 ])
105
109
106
110
def test_ic3_export_to_executorch (self ):
107
111
eager_model , example_inputs , _ = EagerModelFactory .create_model (
108
112
* MODEL_NAME_TO_MODEL ["ic3" ]
109
113
)
110
- eager_model = eager_model .eval ()
111
-
112
- self ._assert_eager_lowered_same_result (
113
- eager_model , example_inputs , self .validate_tensor_allclose
114
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
115
+ eager_model , example_inputs
116
+ )
117
+ # TODO(T166083470): Fix accuracy issue
118
+ self .validate_tensor_allclose (
119
+ eager_output , executorch_output [0 ], rtol = 1e-3 , atol = 1e-5
114
120
)
115
121
116
122
def test_resnet18_export_to_executorch (self ):
117
123
eager_model , example_inputs , _ = EagerModelFactory .create_model (
118
124
* MODEL_NAME_TO_MODEL ["resnet18" ]
119
125
)
120
- eager_model = eager_model .eval ()
121
-
122
- self ._assert_eager_lowered_same_result (
123
- eager_model , example_inputs , self .validate_tensor_allclose
126
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
127
+ eager_model , example_inputs
124
128
)
129
+ self .validate_tensor_allclose (eager_output , executorch_output [0 ])
125
130
126
131
def test_resnet50_export_to_executorch (self ):
127
132
eager_model , example_inputs , _ = EagerModelFactory .create_model (
128
133
* MODEL_NAME_TO_MODEL ["resnet50" ]
129
134
)
130
- eager_model = eager_model .eval ()
131
-
132
- self ._assert_eager_lowered_same_result (
133
- eager_model , example_inputs , self .validate_tensor_allclose
135
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
136
+ eager_model , example_inputs
134
137
)
138
+ self .validate_tensor_allclose (eager_output , executorch_output [0 ])
135
139
136
140
def test_dl3_export_to_executorch (self ):
137
141
eager_model , example_inputs , _ = EagerModelFactory .create_model (
138
142
* MODEL_NAME_TO_MODEL ["dl3" ]
139
143
)
140
- eager_model = eager_model .eval ()
141
-
142
- self ._assert_eager_lowered_same_result (
143
- eager_model , example_inputs , self .validate_tensor_allclose
144
+ eager_output , executorch_output = self .collect_executorch_and_eager_outputs (
145
+ eager_model , example_inputs
144
146
)
147
+ self .validate_tensor_allclose (list (eager_output .values ()), executorch_output )
0 commit comments