def _get_comparison_statistics(curr_tensor, prev_tensor): """Get comparison statistics.""" stats_info = {} diff_tensor_stats = curr_tensor.tensor_comparison.stats curr_tensor_stats = TensorUtils.get_statistics_from_tensor(curr_tensor.value) prev_tensor_stats = TensorUtils.get_statistics_from_tensor(prev_tensor.value) stats_info['curr_step_statistics'] = TensorUtils.get_overall_statistic_dict(overall_stats=curr_tensor_stats) stats_info['prev_step_statistics'] = TensorUtils.get_overall_statistic_dict(overall_stats=prev_tensor_stats) stats_info['statistics'] = TensorUtils.get_overall_statistic_dict(overall_stats=diff_tensor_stats) return stats_info
def test_get_tensor_histogram_success(self): """Get tensor histogram success.""" test_tag_name = self._complete_tag_name processor = TensorProcessor(self._mock_data_manager) results = processor.get_tensors([self._train_id], [test_tag_name], None, None, detail='histogram') recv_metadata = results.get('tensors')[0].get("values") for recv_values, expected_values in zip(recv_metadata, self._tensors): assert recv_values.get('wall_time') == expected_values.get( 'wall_time') assert recv_values.get('step') == expected_values.get('step') expected_data = expected_values.get('value').get("float_data") expected_statistic = TensorUtils.get_statistics_from_tensor( expected_data) expected_buckets = calc_original_buckets(expected_data, expected_statistic) recv_buckets = recv_values.get('value').get("histogram_buckets") for recv_bucket, expected_bucket in zip(recv_buckets, expected_buckets): assert recv_bucket[0] - expected_bucket.left < 1e-6 assert recv_bucket[1] - expected_bucket.width < 1e-6 assert recv_bucket[2] - expected_bucket.count <= 1
def test_get_tensor_stats_success(self): """Get tensor stats success.""" test_tag_name = self._complete_tag_name processor = TensorProcessor(self._mock_data_manager) results = processor.get_tensors([self._train_id], [test_tag_name], None, None, detail='stats') recv_metadata = results.get('tensors')[0].get("values") for recv_values, expected_values in zip(recv_metadata, self._tensors): assert recv_values.get('wall_time') == expected_values.get( 'wall_time') assert recv_values.get('step') == expected_values.get('step') expected_data = expected_values.get('value').get("float_data") expected_statistic_instance = TensorUtils.get_statistics_from_tensor( expected_data) expected_statistic = TensorUtils.get_statistics_dict( stats=expected_statistic_instance, overall_stats=expected_statistic_instance) recv_statistic = recv_values.get('value').get("statistics") assert recv_statistic.get("max") - expected_statistic.get( "max") < 1e-6 assert recv_statistic.get("min") - expected_statistic.get( "min") < 1e-6 assert recv_statistic.get("avg") - expected_statistic.get( "avg") < 1e-6 assert recv_statistic.get("count") - expected_statistic.get( "count") < 1e-6
def get_tensors_diff(self, tensor_name, shape, tolerance=0): """ Get tensor comparisons data for given name, detail, shape and tolerance. Args: tensor_name (str): The name of tensor for cache. shape (tuple): Specify concrete dimensions of shape. tolerance (str): Specify tolerance of difference between current step tensor and previous step tensor. Default value is 0. Its is a percentage. The boundary value is equal to max(abs(min),abs(max)) * tolerance. The function of min and max is being used to calculate the min value and max value of the result of the current step tensor subtract the previous step tensor. If the absolute value of result is less than or equal to boundary value, the result will set to be zero. Raises: DebuggerParamValueError, If get current step node and previous step node failed or the type of tensor value is not numpy.ndarray." Returns: dict, the retrieved data. """ curr_tensor = self.get_valid_tensor_by_name(tensor_name) prev_tensor = self.get_valid_tensor_by_name(tensor_name, prev=True) if not (curr_tensor and prev_tensor): log.error("Get current step and previous step for this tensor name %s failed.", tensor_name) raise DebuggerParamValueError(f"Get current step and previous step for this tensor name " f"{tensor_name} failed.") curr_tensor_slice = curr_tensor.get_tensor_value_by_shape(shape) prev_tensor_slice = prev_tensor.get_tensor_value_by_shape(shape) # get tensor comparison basic info tensor_info = curr_tensor.get_basic_info() tensor_info.pop('has_prev_step') tensor_info.pop('value') # calculate tensor comparision object tensor_comparison = curr_tensor.tensor_comparison if not tensor_comparison or tensor_comparison.tolerance != tolerance: if curr_tensor.value.shape != prev_tensor.value.shape: raise DebuggerParamValueError("The shape of these two step tensors is not the same.") tensor_diff = TensorUtils.calc_diff_between_two_tensor(curr_tensor.value, prev_tensor.value, tolerance) stats = TensorUtils.get_statistics_from_tensor(tensor_diff) tensor_comparison = TensorComparison(tolerance, stats, tensor_diff) curr_tensor.update_tensor_comparisons(tensor_comparison) # calculate diff value # the type of curr_tensor_slice is one of np.ndarray or str if isinstance(curr_tensor_slice, np.ndarray) and isinstance(prev_tensor_slice, np.ndarray): if not shape: tensor_diff_slice = tensor_comparison.value else: tensor_diff_slice = tensor_comparison.value[shape] result = np.stack([prev_tensor_slice, curr_tensor_slice, tensor_diff_slice], axis=-1) tensor_info['diff'] = result.tolist() elif isinstance(curr_tensor_slice, str): tensor_info['diff'] = curr_tensor_slice # add comparision statistics tensor_info.update(self._get_comparison_statistics(curr_tensor, prev_tensor)) reply = {'tensor_value': tensor_info} return reply
def test_get_statistics_from_tensor(self): """Tests get statistics from tensor.""" ndarray = np.array( [1, 2, 3, 4, 5, float('-INF'), float('INF'), float('NAN')]).reshape([2, 2, 2]) statistics = TensorUtils.get_statistics_from_tensor(ndarray) assert (statistics.max, statistics.min, statistics.avg, statistics.count, statistics.nan_count, statistics.neg_inf_count, statistics.pos_inf_count) == \ (5, 1, 3, 8, 1, 1, 1)
def get_tensor_statistics(self): """ Get Tensor statistics. Returns: dict, overall statistics. """ if self.empty or self.dtype == self._STRING_TYPE: return {} stats = TensorUtils.get_statistics_from_tensor(self.value) statistics = TensorUtils.get_overall_statistic_dict(stats) return statistics
def __init__(self, tensor_message): # Original dims can not be pickled to transfer to other process, so tuple is used. self._dims = tuple(tensor_message.dims) self._data_type = tensor_message.data_type self._np_array = self.get_ndarray(tensor_message.float_data) self._stats = TensorUtils.get_statistics_from_tensor(self._np_array) original_buckets = calc_original_buckets(self._np_array, self._stats) self._count = sum(bucket.count for bucket in original_buckets) self._max = self._stats.max self._min = self._stats.min self._histogram = Histogram(tuple(original_buckets), self._max, self._min, self._count)
def get_tensor_statistics(self): """ Get Tensor statistics. Returns: dict, overall statistics. """ if self.empty: return {} if not self.stats: self.stats = TensorUtils.get_statistics_from_tensor(self.value) statistics = TensorUtils.get_overall_statistic_dict(self.stats) return statistics
def test_calc_original_buckets(self): """Tests calculate original buckets.""" ndarray = np.array( [1, 2, 3, 4, 5, float('-INF'), float('INF'), float('NAN')]).reshape([2, 2, 2]) statistics = TensorUtils.get_statistics_from_tensor(ndarray) buckets = tensor.calc_original_buckets(ndarray, statistics) assert (buckets[0].left, buckets[0].width, buckets[0].count) == (1, 2, 2) assert (buckets[1].left, buckets[1].width, buckets[1].count) == (3, 2, 3)
def get_tensors_diff(self, tensor_name, shape, tolerance=0): """ Get tensor comparisons data for given name, detail, shape and tolerance. Args: tensor_name (str): The name of tensor for cache. shape (tuple): Specify concrete dimensions of shape. tolerance (str): Specify tolerance of difference between current step tensor and previous step tensor. Default value is 0. Its is a percentage. The boundary value is equal to max(abs(min),abs(max)) * tolerance. The function of min and max is being used to calculate the min value and max value of the result of the current step tensor subtract the previous step tensor. If the absolute value of result is less than or equal to boundary value, the result will set to be zero. Raises: DebuggerParamValueError, If get current step node and previous step node failed. Returns: dict, the retrieved data. """ curr_tensor = self.get_tensor_value_by_name(tensor_name) prev_tensor = self.get_tensor_value_by_name(tensor_name, prev=True) if not (curr_tensor and prev_tensor): log.error( "Get current step and previous step for this tensor name %s failed.", tensor_name) raise DebuggerParamValueError( f"Get current step and previous step for this tensor name " f"{tensor_name} failed.") curr_tensor_slice = curr_tensor.get_tensor_value_by_shape(shape) prev_tensor_slice = prev_tensor.get_tensor_value_by_shape(shape) tensor_info = curr_tensor.get_basic_info() if isinstance(tensor_info, dict): del tensor_info['has_prev_step'] del tensor_info['value'] # the type of curr_tensor_slice is one of None, np.ndarray or str if isinstance(curr_tensor_slice, np.ndarray) and isinstance( prev_tensor_slice, np.ndarray): diff_tensor = TensorUtils.calc_diff_between_two_tensor( curr_tensor_slice, prev_tensor_slice, tolerance) result = np.stack( [prev_tensor_slice, curr_tensor_slice, diff_tensor], axis=-1) tensor_info['diff'] = result.tolist() stats = TensorUtils.get_statistics_from_tensor(diff_tensor) tensor_info['statistics'] = TensorUtils.get_statistics_dict(stats) elif isinstance(curr_tensor_slice, str): tensor_info['diff'] = curr_tensor_slice reply = {'tensor_value': tensor_info} return reply
def get_tensor_serializable_value_by_shape(self, shape=None): """ Get tensor value info by shape. Args: shape (tuple): The specified range of tensor value. Returns: dict, the specified tensor value and value statistics. """ tensor_value = self.get_tensor_value_by_shape(shape) res = {} # the type of tensor_value is one of None, np.ndarray or str if isinstance(tensor_value, np.ndarray): statistics = TensorUtils.get_statistics_from_tensor(tensor_value) res['statistics'] = TensorUtils.get_statistics_dict(statistics) res['value'] = tensor_value.tolist() elif isinstance(tensor_value, str): res['value'] = tensor_value return res
def _get_tensors_data(self, step, dims, tensors): """ Builds a JSON-serializable object with information about tensor dims data. Args: step (int): Specify step of tensor. dims (str): Specify dims of tensor. tensors (list): The list of _Tensor data. Returns: dict, a dict including the `wall_time`, `step`, and `value' for each tensor. { "wall_time": 0, "step": 0, "value": { "dims": [1], "data_type": "DT_FLOAT32", "data": [[0.1]] "statistics": { "max": 0, "min": 0, "avg": 0, "count": 1, "nan_count": 0, "neg_inf_count": 0, "pos_inf_count": 0 } } } Raises: ResponseDataExceedMaxValueError, If the size of response data exceed max value. StepTensorDataNotInCacheError, If query step is not in cache. """ values = [] step_in_cache = False dims = TensorUtils.convert_array_from_str_dims(dims, limit=2) for tensor in tensors: # This value is an instance of TensorContainer value = tensor.value if step != tensor.step: continue step_in_cache = True res_data = TensorUtils.get_specific_dims_data( value.ndarray, dims, list(value.dims)) flatten_data = res_data.flatten().tolist() if len(flatten_data) > MAX_TENSOR_RESPONSE_DATA_SIZE: raise ResponseDataExceedMaxValueError( "the size of response data: {} exceed max value: {}.". format(len(flatten_data), MAX_TENSOR_RESPONSE_DATA_SIZE)) def transfer(array): if not isinstance(array, np.ndarray): # The list is used here so that len function can be used # when the value of array is `NAN`、`-INF` or `INF`. array = [array] transfer_data = [None] * len(array) for index, data in enumerate(array): if isinstance(data, np.ndarray): transfer_data[index] = transfer(data) else: if np.isnan(data): transfer_data[index] = 'NAN' elif np.isneginf(data): transfer_data[index] = '-INF' elif np.isposinf(data): transfer_data[index] = 'INF' else: transfer_data[index] = float(data) return transfer_data stats = TensorUtils.get_statistics_from_tensor(res_data) if stats.nan_count + stats.neg_inf_count + stats.pos_inf_count > 0: tensor_data = transfer(res_data) else: tensor_data = res_data.tolist() values.append({ "wall_time": tensor.wall_time, "step": tensor.step, "value": { "dims": value.dims, "data_type": anf_ir_pb2.DataType.Name(value.data_type), "data": tensor_data, "statistics": TensorUtils.get_statistics_dict(stats) } }) break if not step_in_cache: raise StepTensorDataNotInCacheError( "this step: {} data may has been dropped.".format(step)) return values