From e93af79c72f588ae8571942a1896391fca994f41 Mon Sep 17 00:00:00 2001 From: StuPidMRE1107 Date: Mon, 8 May 2023 23:28:36 +0800 Subject: [PATCH] add output compare tool --- troubleshooter/README.md | 47 +++ troubleshooter/docs/images/outputcompare.png | Bin 0 -> 127942 bytes .../tests/diff_handler/test_netdifffinder.py | 72 +++++ .../troubleshooter/common/format_msg.py | 69 +++-- troubleshooter/troubleshooter/common/util.py | 43 +++ .../troubleshooter/migrator/diff_handler.py | 288 ++++++++++++------ .../diff_handler/results/compare_result.csv | 6 + 7 files changed, 419 insertions(+), 106 deletions(-) create mode 100644 troubleshooter/docs/images/outputcompare.png create mode 100644 troubleshooter/tests/diff_handler/test_netdifffinder.py create mode 100644 troubleshooter/troubleshooter/tests/diff_handler/results/compare_result.csv diff --git a/troubleshooter/README.md b/troubleshooter/README.md index a14a4ba..b3ff18f 100644 --- a/troubleshooter/README.md +++ b/troubleshooter/README.md @@ -25,6 +25,7 @@ pip install troubleshooter * 应用场景1:pth到ckpt权重转换 * 应用场景2:将转换后的ckpt与MindSpore网络生成的ckpt进行对比 * 应用场景3:比较两组tensor值(npy文件)是否相等 +* 应用场景4:比较pytorch和mindspore的网络输出是否相等 ## 其他调试功能 * 应用场景1:tracking在指定epoch/step停止跟踪(使用model.train训练) @@ -553,6 +554,52 @@ x = self.sqrt(y) 出现 nan, 给出“User Warning 'nan' is detected”报错。 # 将调整后的名称传入比较接口 dif.compare_npy_dir(name_map_list=name_list) +### 应用场景:比较mindspore和pytorch网络输出是否一致 + +在进行网络迁移时,由于大多数网络是使用pytorch搭建的,在迁移到mindspore过程中,我们需要比较mindspore和pytorch网络输出结果是否一致。此功能实现对比mindspore和pytorch的输出结果。 + +#### 接口参数 + +| 参数 | 类型 | 说明 | +| ------------ | ------------------------- | ------------------------------------------------------------ | +| ms_net | mindspore.nn.Cell | mindspore模型实例 | +| pt_net | torch.nn.Module | torch模型实例 | +| input_data | Union(list[Iterable[np.array]], list[Iterable[str]]) | 模型的输入。支持多输入,每个输入使用一个list。当list中为array时,将会依序使用其中的array作为模型的输入,每个array形状与模型输入形状相同,以图像分类任务为例,输入形状为[batch_size, num_channel, w, h];当为str时,将会加载相应位置的npy文件作为模型输入。 对于单输入情况,用户需要传入[[input1, input2, ...]] 或者 [['input1.npy', 'input2.npy', ...]];对于多输入,用户应当传入[[input1_1, input1_2, ...], [input2_1, input2_2, ...]]或者[['input1_1.npy', 'input1_2.npy', ...], ['input2_1.npy', 'input2_2.npy', ...]]| +| out_path | str | 结果保存的文件夹,例如,'troubleshooter/results' | +| print_result | bool | 是否打印输出结果,以及中间过程 | + +#### 如何使用 + +可以参考troubleshooter/tests/diff_handler/test_netdifffinder.py中的使用方法,或者下面的使用方法: + +```python +# 构造输入,这里假设测试用例有两个,分别为input1,input2; +input1 = [np.random.randn(1, 12).astype(np.float32), np.random.randn(1, 13).astype(np.float32)] +input2 = [np.random.randn(1, 12).astype(np.float32), np.random.randn(1, 13).astype(np.float32)] +# 实例化mindspore模型以及torch模型 +ms_net = MSNet() +pt_net = TorchNet() +diff_finder = NetDifferenceFinder( + ms_net=ms_net, + pt_net=pt_net, + inputs=[input1, input2], + out_path='troubleshooter/tests/diff_handler/results', + print_result=False, +) +diff_finder.start_compare() +``` + +#### 结果展示 + +命令: + +```python +python troubleshooter/tests/diff_handler/test_netdifffinder.py +``` + +输出结果: + +![网络输出对比结果展示](docs/images/outputcompare.png) ## 其他调试功能: ### 应用场景1:tracking在指定epoch/step停止跟踪(使用model.train训练) diff --git a/troubleshooter/docs/images/outputcompare.png b/troubleshooter/docs/images/outputcompare.png new file mode 100644 index 0000000000000000000000000000000000000000..813ea838fb0edb4ac6453af8bda3dd504246d3a3 GIT binary patch literal 127942 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 None: + super().__init__() + self.net1 = t_nn.Linear(12, 21) + self.net2 = t_nn.Linear(13, 22) + + def forward(self, x, y): + return {'a': self.net1(x), 'b': self.net2(y)} + + +class MSNet(m_nn.Cell): + def __init__(self, n=0) -> None: + super().__init__() + self.net1 = m_nn.Dense(12, 21) + self.net2 = m_nn.Dense(13, 22) + self.n = n + + def construct(self, x, y): + if self.n: + print(self.n) + return self.net1(x), self.net2(y) + + +def test_model(capsys): + input1 = (np.random.randn(1, 12).astype(np.float32), + np.random.randn(1, 13).astype(np.float32)) + input2 = (np.random.randn(1, 12).astype(np.float32), + np.random.randn(1, 13).astype(np.float32)) + ms_net = MSNet() + pt_net = TorchNet() + diff_finder = NetDifferenceFinder( + ms_net=ms_net, + pt_net=pt_net, + inputs=[input1, input2], + out_path='troubleshooter/tests/diff_handler/results', + print_result=False, + ) + diff_finder.start_compare() + out, err = capsys.readouterr() + info_pattern = r".*In test case \d+, the .*? net inference completed cost .*? seconds\..*" + assert re.match(info_pattern, out) is not None + assert err == '' + + +def test_dict(capsys): + input1 = {'a': np.random.randn(1, 12).astype( + np.float32), 'b': np.random.randn(1, 13).astype(np.float32)} + input2 = {'a': np.random.randn(1, 12).astype( + np.float32), 'b': np.random.randn(1, 13).astype(np.float32)} + ms_net = MSNet() + pt_net = TorchNet() + diff_finder = NetDifferenceFinder( + ms_net=ms_net, + pt_net=pt_net, + inputs=[input1, input2], + out_path='troubleshooter/tests/diff_handler/results', + print_result=False, + ) + diff_finder.start_compare() + out, err = capsys.readouterr() + info_pattern = r".*In test case \d+, the .*? net inference completed cost .*? seconds\..*" + assert re.match(info_pattern, out) is not None + assert err == '' diff --git a/troubleshooter/troubleshooter/common/format_msg.py b/troubleshooter/troubleshooter/common/format_msg.py index 261d7b0..ab118d2 100644 --- a/troubleshooter/troubleshooter/common/format_msg.py +++ b/troubleshooter/troubleshooter/common/format_msg.py @@ -48,7 +48,8 @@ def _add_row(x, item, message, width=TABLE_WIDTH, break_long_words=False, break_ if message is None: return item_cn = _item_to_cn.get(item) - format_message = _format_str_length(message) if os.linesep in message else message + format_message = _format_str_length( + message) if os.linesep in message else message x.add_row([item_cn, fill(format_message, width=width, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens)]) @@ -56,10 +57,11 @@ def _add_row(x, item, message, width=TABLE_WIDTH, break_long_words=False, break_ def print_weight_compare_result(result_list, print_type=1): x = PrettyTable() x.title = 'The list of comparison results' - x.field_names = ["Parameter name of input ckpt", "Parameter name of converted ckpt", "Whether shape are equal", "Parameter shape of input ckpt", "Parameter shape of converted ckpt"] + x.field_names = ["Parameter name of input ckpt", "Parameter name of converted ckpt", "Whether shape are equal", + "Parameter shape of input ckpt", "Parameter shape of converted ckpt"] for result in result_list: if print_type == 1: - x.add_row([result[0],result[1],result[2],result[3],result[4]]) + x.add_row([result[0], result[1], result[2], result[3], result[4]]) elif result[2] is not True: x.add_row([result[0], result[1], result[2], result[3], result[4]]) print(x.get_string()) @@ -69,19 +71,33 @@ def print_convert_result(result_list): x = PrettyTable() x.title = 'The list of conversion result' x.field_names = ["Parameter name of pth", "Parameter name of converted ckpt", "Whether the name is converted", - "Whether the weight value is converted","Parameter shape of pth","Parameter shape of ckpt"] + "Whether the weight value is converted", "Parameter shape of pth", "Parameter shape of ckpt"] for result in result_list: - x.add_row([result[0],result[1],result[2],result[3],result[4],result[5]]) + x.add_row([result[0], result[1], result[2], + result[3], result[4], result[5]]) print(x.get_string()) + def print_diff_result(result_list): x = PrettyTable() x.title = 'The list of comparison results' - x.field_names = ["orig array name", "target array name", "Results of comparison", "(mean,max,min)"] + x.field_names = ["orig array name", "target array name", + "Results of comparison", "(mean,max,min)"] for result in result_list: - x.add_row([result[0],result[1],result[2],result[3]]) + x.add_row([result[0], result[1], result[2], result[3]]) print(x.get_string()) + +def print_net_infer_diff_result(result_list): + x = PrettyTable() + x.title = 'The list of comparison results' + x.field_names = ["Pytorch data", "MindSpore data", + "Results of comparison", "cosine similarity", "(mean, max, min)"] + for result in result_list: + x.add_row([result[0], result[1], result[2], result[3], result[4]]) + print(x.get_string()) + + def print_result(expert_experience, write_file_path): """ print MindSpore FAR @@ -94,19 +110,25 @@ def print_result(expert_experience, write_file_path): mindspore_version = expert_experience.get("mindspore_version") mindspore_mode = expert_experience.get("mindspore_mode") mindspore_device = expert_experience.get("Device Type") - x.add_row([item_desc.get("ms_version"), fill(mindspore_version, width=TABLE_WIDTH)]) - x.add_row([item_desc.get("ms_mode"), fill(mindspore_mode, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("ms_version"), fill( + mindspore_version, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("ms_mode"), fill( + mindspore_mode, width=TABLE_WIDTH)]) if mindspore_device: - x.add_row([item_desc.get("ms_device"), fill(mindspore_device, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("ms_device"), fill( + mindspore_device, width=TABLE_WIDTH)]) ms_status = expert_experience.get("ms_status") code_line = expert_experience.get("code_line") sink_mode = expert_experience.get("Sink Mode") if ms_status: - x.add_row([item_desc.get("ms_status"), fill(ms_status, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("ms_status"), + fill(ms_status, width=TABLE_WIDTH)]) if code_line: - x.add_row([item_desc.get("code_line"), fill(code_line, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("code_line"), + fill(code_line, width=TABLE_WIDTH)]) if sink_mode: - x.add_row([item_desc.get("sink_mode"), fill(sink_mode, width=TABLE_WIDTH)]) + x.add_row([item_desc.get("sink_mode"), + fill(sink_mode, width=TABLE_WIDTH)]) # 可能原因 fault_cause = expert_experience.get('Fault Cause') @@ -131,7 +153,8 @@ def print_result(expert_experience, write_file_path): if write_file_path: case_id = expert_experience.get("ID") _add_row(x, "case_id", case_id) - file = os.path.join(write_file_path, "mindspore_failure_analysis_report.log") + file = os.path.join( + write_file_path, "mindspore_failure_analysis_report.log") with open(file, "w") as f: f.write(x.get_string() + os.linesep) print(x.get_string()) @@ -243,7 +266,8 @@ def _format_case_str(content, mindspore_version): # no mindspore link, return if match: link_version = line[match.start():match.end()] - line = _replace_link_version(line, link_version, mindspore_version) + line = _replace_link_version( + line, link_version, mindspore_version) result += line + os.linesep else: # link version same with mindspore version, no replace return content @@ -271,8 +295,10 @@ def _filter_stack(stack): def print_clear_exception(exc_type, exc_value, exc_traceback_obj): if exc_traceback_obj: - _print_msg("[TroubleShooter-Clear Stack] Python Traceback (most recent call last):", "NULL", False) - org_err_stack = traceback.format_exception(exc_type, exc_value, exc_traceback_obj) + _print_msg( + "[TroubleShooter-Clear Stack] Python Traceback (most recent call last):", "NULL", False) + org_err_stack = traceback.format_exception( + exc_type, exc_value, exc_traceback_obj) for stack in org_err_stack: if _filter_stack(stack): print(stack.rstrip(os.linesep)) @@ -293,9 +319,11 @@ def print_format_exception(exc_type, exc_value, exc_traceback_obj): _print_msg("Error Message:", msg_dict.get("err_msg")) if msg_dict.get("construct_stack_msg"): - _print_msg("The Traceback of Net Construct Code:", msg_dict.get("construct_stack_msg")) + _print_msg("The Traceback of Net Construct Code:", + msg_dict.get("construct_stack_msg")) else: - _print_msg("The Traceback of Net Construct Code:", msg_dict.get("construct_stack_in_file_msg")) + _print_msg("The Traceback of Net Construct Code:", + msg_dict.get("construct_stack_in_file_msg")) _print_msg("C++ Function:", msg_dict.get("cpp_fun_msg")) _print_msg("Inner Message:", msg_dict.get("abstract_inner_msg")) @@ -304,7 +332,8 @@ def format_error_message(error_message): """ format error message, from string to dict """ - msg_list = error_message.split('----------------------------------------------------') + msg_list = error_message.split( + '----------------------------------------------------') format_msg_dict = {} current_key = None for msg in msg_list: diff --git a/troubleshooter/troubleshooter/common/util.py b/troubleshooter/troubleshooter/common/util.py index 2a1a87b..0a91540 100644 --- a/troubleshooter/troubleshooter/common/util.py +++ b/troubleshooter/troubleshooter/common/util.py @@ -191,3 +191,46 @@ class SaveNet(nn.Cell): return save = SaveNet() + + +def cal_cosine_sim(a, b): + a, b = a.flatten(), b.flatten() + sim = 0. + num = np.dot(a, b) + denom = np.linalg.norm(a) * np.linalg.norm(b) + if not denom == 0.: + sim = 0.5 + 0.5 * (num / denom) + return sim + + +def cal_similarity(ms_data, th_data, index, **kwargs): + result_list = [] + rtol = kwargs.get('rtol', 1e-05) + atol = kwargs.get('atol', 1e-08) + equal_nan = kwargs.get('equal_nan', False) + if ms_data.shape == th_data.shape: + result = np.allclose(ms_data, th_data, rtol=rtol, + atol=atol, equal_nan=equal_nan) + + if not result: + value_diff = np.abs(ms_data - th_data) + value_mean = value_diff.mean() + value_max = value_diff.max() + value_min = value_diff.min() + cosine_sim = cal_cosine_sim(ms_data, th_data) + diff_detail = value_mean, value_max, value_min + else: + diff_detail = () + else: + result = False + diff_detail = ("Shape is inconsistent", ms_data.shape, th_data.shape) + + result_list = ['mindspore output {}'.format( + index), 'torch output {}'.format(index), result, cosine_sim, diff_detail] + return result_list + + +def save_numpy_data(file_path, data): + if not os.path.exists(os.path.dirname(file_path)): + os.makedirs(os.path.dirname(file_path)) + np.save(file_path, data) diff --git a/troubleshooter/troubleshooter/migrator/diff_handler.py b/troubleshooter/troubleshooter/migrator/diff_handler.py index a0864f3..df970ff 100644 --- a/troubleshooter/troubleshooter/migrator/diff_handler.py +++ b/troubleshooter/troubleshooter/migrator/diff_handler.py @@ -14,16 +14,23 @@ # ============================================================================ """compare tools""" import os +import csv +import time +from pprint import pprint import torch import numpy as np -from collections import OrderedDict -from pprint import pprint from troubleshooter import log as logger -from troubleshooter.common.util import validate_and_normalize_path, find_file, make_directory +from troubleshooter.common.util import validate_and_normalize_path, find_file, make_directory, \ + cal_similarity, cal_cosine_sim, save_numpy_data from troubleshooter.migrator.mapping_relation.weight_mapping_lib import weight_name_map, weight_value_map -from troubleshooter.common.format_msg import print_diff_result, print_weight_compare_result, print_convert_result +from troubleshooter.common.format_msg import print_diff_result, print_weight_compare_result, \ + print_convert_result, print_net_infer_diff_result FRAMEWORK_TYPE = "ms" +MS_OUTPUT_PATH = "data/output/MindSpore" +PT_OUTPUT_PATH = "data/output/PyTorch" +RESULT_COLUMNS = ["Pytorch data", "MindSpore data", + "Results of comparison", "cosine similarity", "(mean, max, min)"] try: import mindspore as ms @@ -35,6 +42,7 @@ except ModuleNotFoundError as e: else: raise e + class TensorRecorder: def __init__(self): self.summary_record = None @@ -45,7 +53,8 @@ class TensorRecorder: record_mode = ms.get_context("mode") if record_mode == 0: - self.summary_record = ms.SummaryRecord(record_path, export_options={'tensor_format': 'npy'}) + self.summary_record = ms.SummaryRecord( + record_path, export_options={'tensor_format': 'npy'}) def record(self): if not self.summary_record: @@ -63,7 +72,7 @@ class TensorRecorder: normal_dir = validate_and_normalize_path(record_dir) make_directory(normal_dir) - if framework=="ms": + if framework == "ms": if record_mode is None: record_mode = ms.get_context("mode") if record_mode == 0: @@ -86,11 +95,13 @@ class TensorRecorder: return save_op + class DifferenceFinder: def __init__(self, orig_dir, target_dir): self.orig_dir = orig_dir self.target_dir = target_dir + def get_filename_map_list(self): name_map_list = [] orig_name_list = find_file(self.orig_dir) @@ -99,8 +110,8 @@ class DifferenceFinder: none_flag = False if not (orig_name_list and target_name_list): - logger.user_error("The comparison file is not found in the directory. " - "Please check whether the directory is correct") + logger.user_error("The comparison file is not found in the directory. Please \ + check whether the directory is correct") exit(1) for name in orig_name_list: @@ -123,7 +134,6 @@ class DifferenceFinder: print("filename mapping list:" + str(name_map_list)) return name_map_list - def compare_npy_dir(self, name_map_list=None, **kwargs): """ """ @@ -144,7 +154,8 @@ class DifferenceFinder: if orig_name is None or target_name is None: result = False diff_detail = () - result_list.append((orig_name, target_name, result, diff_detail)) + result_list.append( + (orig_name, target_name, result, diff_detail)) continue orig_file = os.path.join(normal_orig_dir, orig_name) @@ -156,61 +167,40 @@ class DifferenceFinder: orig_value = np.load(orig_file) target_value = np.load(target_file) if orig_value.shape == target_value.shape: - result = np.allclose(orig_value, target_value, rtol=rtol, atol=atol, equal_nan=equal_nan) + result = np.allclose( + orig_value, target_value, rtol=rtol, atol=atol, equal_nan=equal_nan) if not result: value_diff = np.abs(orig_value - target_value) value_mean = value_diff.mean() value_max = value_diff.max() value_min = value_diff.min() + cosine_sim = cal_cosine_sim(orig_value, target_value) diff_detail = value_mean, value_max, value_min else: diff_detail = () + cosine_sim = cal_cosine_sim(orig_value, target_value) else: result = False - diff_detail = ("Shape is inconsistent", orig_value.shape, target_value.shape) + diff_detail = ("Shape is inconsistent", + orig_value.shape, target_value.shape) - result_list.append((orig_name, target_name, result, diff_detail)) + result_list.append( + (orig_name, target_name, result, cosine_sim, diff_detail)) logger.user_attention("The compare directory information:\n The orig dir: %s \n The target dir: %s", self.orig_dir, self.target_dir) print_diff_result(result_list) + class WeightMigrator: - def __init__(self, pt_model=None, pth_file_path=None, pth_para_dict=None, ckpt_save_path=None): + def __init__(self, pt_model=None, pth_file_path=None, ckpt_save_path=None): self.weight_map = weight_name_map self.ckpt_path = ckpt_save_path self.pt_model = pt_model - self.pt_para_dict = self._get_para_dict(pth_file_path, pth_para_dict) + self.pt_para_dict = torch.load(pth_file_path, map_location='cpu') self.print_params_list = [] - - def _get_para_dict(self, pth_file_path, pth_para_dict): - if pth_para_dict: - return pth_para_dict - - pt_para_dict = {} - pt_object = torch.load(pth_file_path, map_location='cpu') - if isinstance(pt_object, OrderedDict): - pt_para_dict = pt_object - elif isinstance(pt_object, torch.nn.Module): - pt_para_dict = pt_object.state_dict() - else: - raise ValueError("PTH file parsing failed, possible reasons: " - "1) If using a custom method to save parameter files, please load and set " - "the 'pth_para_dict' parameter yourself to use the conversion tool." - "2) If the input is an optimizer parameter, this tool does not support " - "the conversion of optimizer parameters.") - - values = list(pt_para_dict.values()) - if values and not isinstance(values[0], torch.Tensor): - raise ValueError("PTH file parsing failed, possible reasons: " - "1) If using a custom method to save parameter files, please load and set " - "the 'pth_para_dict' parameter yourself to use the conversion tool." - "2) If the input is an optimizer parameter, this tool does not support " - "the conversion of optimizer parameters.") - return pt_para_dict - def _get_object(self, name): object_res = None index = name.rfind(".") @@ -222,7 +212,6 @@ class WeightMigrator: object_res = getattr(imp_module, class_name) return object_res - def _get_trans_map(self, weight_name, module, weight_map, igone_name=False): res_weight_map = {} for api_name in weight_map: @@ -240,42 +229,22 @@ class WeightMigrator: return res_weight_map - - def _custorm_weight_name_prefix(self, weight_name_map, prefix=None): - if prefix: - custorm_name_map = {} - for key, value in weight_name_map.items(): - # print(key, ":", prefix + '.' + value) - custorm_name_map[key] = str(prefix) + '.' + str(value) - return custorm_name_map - else: - return weight_name_map - - - def get_weight_map(self, print_map=False, full_name_map=False): + def get_weight_map(self, print_map=False): res_weight_name_map = {} res_weight_value_map = {} - full_weight_name_map = {} - for name, module in self.pt_model.named_modules(): tmp_name_map = self._get_trans_map(name, module, weight_name_map) if tmp_name_map: res_weight_name_map.update(tmp_name_map) - tmp_value_map = self._get_trans_map(name, module, weight_value_map, igone_name=True) + tmp_value_map = self._get_trans_map( + name, module, weight_value_map, igone_name=True) if tmp_value_map: res_weight_value_map.update(tmp_value_map) - if full_name_map: - for key, value in self.pt_para_dict.items(): - full_weight_name_map[key]=key - full_weight_name_map.update(res_weight_name_map) - res_weight_name_map = full_weight_name_map - if print_map: pprint(res_weight_name_map) pprint(res_weight_value_map) return res_weight_name_map, res_weight_value_map - def _get_name_and_value(self, pth_param_name, name_map, value_map): new_name = pth_param_name parameter = self.pt_para_dict[pth_param_name] @@ -294,45 +263,38 @@ class WeightMigrator: def_get_value = self._get_object(fun) ms_tensor = def_get_value(ms_tensor) - self.print_params_list.append((pth_param_name, new_name, bool(ms_para_item), bool(fun) , parameter.size(), + self.print_params_list.append((pth_param_name, new_name, bool(ms_para_item), bool(fun), parameter.size(), ms_tensor.shape)) return new_name, ms_tensor - - def convert(self, weight_name_map=None, weight_value_map=None ,weight_name_prefix=None, print_conv_info=True): - - if weight_name_prefix: - name_map, value_map = self.get_weight_map(full_name_map=True) - name_map = self._custorm_weight_name_prefix(name_map, weight_name_prefix) - else: - name_map, value_map = self.get_weight_map() - + def convert(self, weight_name_map=None, weight_value_map=None, print_conv_info=True): + name_map, value_map = self.get_weight_map() if weight_name_map is not None: - name_map = weight_name_map + name_map = weight_name_map if weight_value_map is not None: - value_map = weight_value_map + value_map = weight_value_map new_params_list = [] for pth_param_name in self.pt_para_dict: # get ckpt name and value - new_name, ms_tensor = self._get_name_and_value(pth_param_name,name_map,value_map) + new_name, ms_tensor = self._get_name_and_value( + pth_param_name, name_map, value_map) # add name and value to list new_params_list.append({"name": new_name, "data": ms_tensor}) if new_params_list: - ms.save_checkpoint(new_params_list , self.ckpt_path) + ms.save_checkpoint(new_params_list, self.ckpt_path) else: logger.user_warning("There are no parameters to be converted. Parameter conversion failed. " "Please check whether the configuration is correct") if print_conv_info: - print_convert_result(self.print_params_list) + print_convert_result(self.print_params_list) logger.user_attention("The PTH has been converted to the checkpoint of MindSpore. " "Please check whether the conversion result is correct. " - "The saved path is: %s",self.ckpt_path) - + "The saved path is: %s", self.ckpt_path) def compare_ckpt(self, ckpt_path=None, converted_ckpt_path=None, print_result=1): name_map_list = [] @@ -345,12 +307,166 @@ class WeightMigrator: ms_para_after_conv = ckpt_after_conv_dict.get(ms_para_name) if ms_para_after_conv is not None: - name_map_list.append((ms_para_name, ms_para_name, (ms_para.shape == ms_para_after_conv.shape), - ms_para.shape, ms_para_after_conv.shape)) + name_map_list.append((ms_para_name, ms_para_name, (ms_para.shape == + ms_para_after_conv.shape), ms_para.shape, ms_para_after_conv.shape)) ckpt_after_conv_dict.pop(ms_para_name) else: - name_map_list.append((ms_para_name, None, None, ms_para.shape, None)) + name_map_list.append( + (ms_para_name, None, None, ms_para.shape, None)) for name, ms_para in ckpt_after_conv_dict.items(): name_map_list.append((None, name, None, None, ms_para.shape)) print_weight_compare_result(name_map_list, print_type=print_result) + + +class NetDifferenceFinder: + + def __init__(self, ms_net, pt_net, inputs, + out_path, print_result): + self.ms_net = ms_net + self.pt_net = pt_net + self.inputs = inputs + self.out_path = out_path + self.print_result = print_result + + def start_compare(self): + compare_results = [] + for idx, input in enumerate(self.inputs): + input_data = self.get_input_data(input) + result_ms, result_pt = self.infer_net( + input_data, self.ms_net, self.pt_net, idx) + self.check_output(result_ms, result_pt) + if idx != 0: + compare_results.append(['', '', '', '', '']) + compare_results.extend( + self.compare_results(result_ms, result_pt, idx)) + self.save_results(compare_results) + print_net_infer_diff_result(compare_results) + + def get_input_data(self, input): + input_data = [] + if isinstance(input, dict): + input_data = list(input.values()) + else: + for data in input: + if isinstance(data, str): + input_data.append(np.load(data)) + elif isinstance(data, np.ndarray): + input_data.append(data) + else: + logger.user_error( + 'Unknow input data type {}'.format(type(data))) + exit(1) + return input_data + + def infer_net(self, input_data, ms_net, pt_net, idx): + if self.print_result: + print( + "\n=================================Start inference net=================================") + start_pt = time.time() + result_pt = self.run_pt_net(pt_net, input_data) + end_pt = time.time() + print(f"In test case {idx}, the PyTorch net inference completed cost %.5f seconds." % ( + end_pt - start_pt)) + start_ms = time.time() + result_ms = self.run_ms_net(ms_net, input_data) + end_ms = time.time() + print(f"In test case {idx}, the MindSpore net inference completed cost %.5f seconds." % ( + end_ms - start_ms)) + if isinstance(result_ms, tuple): + result_ms = {f"result_{idx}": result for idx, + result in enumerate(result_ms)} + if isinstance(result_pt, tuple): + result_pt = {f"result_{idx}": result for idx, + result in enumerate(result_pt)} + return result_ms, result_pt + + def run_pt_net(self, pt_net, input_data_list): + data_list = [] + for data in input_data_list: + data_list.append(torch.tensor(data)) + pt_results = pt_net(*data_list) + return pt_results + + def run_ms_net(self, ms_net, input_data_list): + data_list = [] + for data in input_data_list: + data_list.append(ms.Tensor(data)) + ms_results = ms_net(*data_list) + return ms_results + + def check_output(self, result_ms, result_pt): + ms_result_num = len(result_ms) + if self.print_result: + print("The MindSpore net inference have %s result." % ms_result_num) + pt_result_num = len(result_pt) + if self.print_result: + print("The PyTorch net inference have %s result." % pt_result_num) + assert ms_result_num == pt_result_num, "output results are in different counts!" + + def compare_results(self, result_ms, result_pt, idx): + index = 0 + compare_result = [] + for (k_pt, k_ms) in zip(result_pt, result_ms): + result_pt_ = result_pt[k_pt].detach().numpy() + result_ms_ = result_ms[k_ms].asnumpy() + self.check_out_data_shape(index, result_ms_, result_pt_) + self.save_out_data(index, k_ms, k_pt, result_ms_, result_pt_) + result_pt_ = result_pt_.reshape(1, -1) + result_ms_ = result_ms_.reshape(1, -1) + result = self.compare_data(result_ms_, result_pt_, index) + result[0], result[1] = f"test{idx}-{k_ms}", f"test{idx}-{k_pt}" + result[3] = "%.5f" % float(result[3]) + min_max = ['%.5f' % r for r in result[4]] + result[4] = min_max + compare_result.append(result) + index += 1 + return compare_result + + def check_out_data_shape(self, index, result_ms, result_pt): + if self.print_result: + print( + "\n=========================Start Check Out Data %s ===========================" % index) + pt_out_shape = result_pt.shape + ms_out_shape = result_pt.shape + assert pt_out_shape == ms_out_shape, "output results are in different shapes!" + if self.print_result: + print("shape of result_pt: %s" % str(pt_out_shape)) + print("shape of result_ms: %s" % str(ms_out_shape)) + print("-result_pt-: \n", result_pt) + print("-result_ms-: \n", result_ms) + + def save_out_data(self, index, k_ms, k_pt, result_ms, result_pt): + if self.print_result: + print( + "\n================= ======Start Save Out Data %s =========================" % index) + result_file = "%s.npy" % k_ms + ms_out_path = os.path.join(self.out_path, MS_OUTPUT_PATH, result_file) + save_numpy_data(ms_out_path, result_ms) + if self.print_result: + print("Saved MindSpore output data at: %s" % ms_out_path) + + result_file = "%s.npy" % k_pt + pt_out_path = os.path.join(self.out_path, PT_OUTPUT_PATH, result_file) + save_numpy_data(pt_out_path, result_pt) + if self.print_result: + print("Saved PyTorch output data at: %s" % pt_out_path) + + def compare_data(self, result_ms, result_pt, index): + if self.print_result: + print( + "\n=========================Start Compare Out Data %s ===========================" % index) + sim_result = cal_similarity(result_ms, result_pt, index) + return sim_result + + def save_results(self, compare_results): + if self.print_result: + logger.info( + "=================================Start save result=================================") + result_path = os.path.join(self.out_path, "compare_result.csv") + with open(result_path, "w", encoding='utf-8') as csvfile: + writer = csv.writer(csvfile) + writer.writerow(RESULT_COLUMNS) + writer.writerows(compare_results) + logger.info( + "The comparison result have been written to %s" % result_path) diff --git a/troubleshooter/troubleshooter/tests/diff_handler/results/compare_result.csv b/troubleshooter/troubleshooter/tests/diff_handler/results/compare_result.csv new file mode 100644 index 0000000..963f094 --- /dev/null +++ b/troubleshooter/troubleshooter/tests/diff_handler/results/compare_result.csv @@ -0,0 +1,6 @@ +Pytorch data,MindSpore data,Results of comparison,cosine similarity,"(mean, max, min)" +test0-result_0,test0-a,False,0.46132,"['0.44795', '1.04435', '0.06219']" +test0-result_1,test0-b,False,0.44855,"['0.36956', '1.00635', '0.00237']" +,,,, +test1-result_0,test1-a,False,0.40539,"['0.70020', '1.53871', '0.02968']" +test1-result_1,test1-b,False,0.51905,"['0.59969', '1.36461', '0.02182']" -- Gitee