Browse Source

fix the bug about getting const tensor graph

tags/v1.1.0
yelihua 5 years ago
parent
commit
73923dd348
3 changed files with 154 additions and 106 deletions
  1. +10
    -9
      mindinsight/debugger/stream_cache/node_type_identifier.py
  2. +60
    -32
      mindinsight/debugger/stream_cache/tensor.py
  3. +84
    -65
      mindinsight/utils/tensor.py

+ 10
- 9
mindinsight/debugger/stream_cache/node_type_identifier.py View File

@@ -19,19 +19,20 @@ from mindinsight.datavisual.data_transform.graph import NodeTypeEnum
from mindinsight.debugger.common.exceptions.exceptions import DebuggerParamValueError

_ACTIVATIONS = [
'Softmax',
'ELU',
'FastGelu',
'GELU',
'HSigmoid',
'HSwish',
'LeakyReLU',
'LogSigmoid',
'LogSoftmax',
'PReLU',
'ReLU',
'ReLU6',
'Tanh',
'GELU',
'ELU',
'Sigmoid',
'PReLU',
'LeakyReLU',
'HSwish',
'HSigmoid',
'LogSigmoid'
'Softmax',
'Tanh'
]




+ 60
- 32
mindinsight/debugger/stream_cache/tensor.py View File

@@ -55,9 +55,33 @@ class BaseTensor(ABC):
"""If the tensor value is valid."""
return self.value is None

@abstractmethod
def get_tensor_serializable_value_by_shape(self, shape=None):
"""Get tensor value by shape."""
"""
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):
res['value'] = tensor_value.tolist()
else:
res['value'] = tensor_value
res['statistics'] = self.get_tensor_statistics()
return res

@abstractmethod
def get_tensor_value_by_shape(self, shape=None):
"""Abstract method."""

@abstractmethod
def get_tensor_statistics(self):
"""Abstract method."""

def _to_dict(self):
"""Get tensor info in dict format."""
@@ -163,28 +187,6 @@ class OpTensor(BaseTensor):
tensor_value = tensor_value.reshape(self.shape)
return tensor_value

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):
res['value'] = tensor_value.tolist()
elif isinstance(tensor_value, str):
res['value'] = tensor_value
else:
res['value'] = None
res['statistics'] = self.get_tensor_statistics()
return res

def get_tensor_statistics(self):
"""
Get Tensor statistics.
@@ -245,6 +247,8 @@ class OpTensor(BaseTensor):

class ConstTensor(BaseTensor):
"""Tensor data structure for Const Node."""
STRING_TYPE = 'DT_STRING'
BOOL_TYPE = 'DT_BOOL'

def __init__(self, const_proto):
# the type of const_proto is NamedValueProto
@@ -276,8 +280,7 @@ class ConstTensor(BaseTensor):
"""The property of tensor shape."""
return self._value

@staticmethod
def generate_value_from_proto(tensor_proto):
def generate_value_from_proto(self, tensor_proto):
"""
Generate tensor value from proto.

@@ -285,18 +288,43 @@ class ConstTensor(BaseTensor):
tensor_proto (TensorProto): The tensor proto.

Returns:
Union[None, np.ndarray], the value of the tensor.
Union[None, str, np.ndarray], the value of the tensor.
"""
fields = tensor_proto.value.ListFields()
if len(fields) != 2:
log.warning("Unexpected const proto <%s>.\n Please check offline.", tensor_proto)
tensor_value = None
for field_name, field_value in fields:
if field_name != 'dtype':
return field_value
return None
tensor_value = field_value
break
if tensor_value and self.dtype != self.STRING_TYPE:
tensor_value = np.array(tensor_value, dtype=NUMPY_TYPE_MAP.get(self.dtype))
return tensor_value

def get_tensor_serializable_value_by_shape(self, shape=None):
"""Get tensor info with value."""
if shape is not None:
def get_tensor_value_by_shape(self, shape=None):
"""
Get tensor value by shape.

Args:
shape (tuple): The specified shape.

Returns:
Union[None, str, int, float], the value of parsed tensor.
"""
if shape:
log.warning("Invalid shape for const value.")
return self._value

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

+ 84
- 65
mindinsight/utils/tensor.py View File

@@ -23,94 +23,104 @@ from mindinsight.utils.log import utils_logger as logger
F32_MIN, F32_MAX = np.finfo(np.float32).min, np.finfo(np.float32).max
MAX_DIMENSIONS_FOR_TENSOR = 2


class Statistics:
"""Statistics data class.

Args:
max_value (float): max value of tensor data.
min_value (float): min value of tensor data.
avg_value (float): avg value of tensor data.
count (int): total count of tensor data.
nan_count (int): count of NAN.
neg_zero_count (int): count of negative zero.
pos_zero_count (int): count of positive zero.
zero_count (int): count of zero.
neg_inf_count (int): count of negative INF.
pos_inf_count (int): count of positive INF.
stats (dict): Statistic info of tensor data.

- is_bool (bool): If the tensor is bool type.
- max_value (float): Max value of tensor data.
- min_value (float): Min value of tensor data.
- avg_value (float): Avg value of tensor data.
- count (int): Total count of tensor data.
- nan_count (int): Count of NAN.
- neg_zero_count (int): Count of negative zero.
- pos_zero_count (int): Count of positive zero.
- zero_count (int): Count of zero.
- neg_inf_count (int): Count of negative INF.
- pos_inf_count (int): Count of positive INF.
"""

def __init__(self, max_value=0, min_value=0, avg_value=0, count=0,
neg_zero_count=0, pos_zero_count=0, zero_count=0,
nan_count=0, neg_inf_count=0, pos_inf_count=0):
self._max = max_value
self._min = min_value
self._avg = avg_value
self._count = count
self._neg_zero_count = neg_zero_count
self._pos_zero_count = pos_zero_count
self._zero_count = zero_count
self._nan_count = nan_count
self._neg_inf_count = neg_inf_count
self._pos_inf_count = pos_inf_count
def __init__(self, stats):
self._stats = stats

@property
def max(self):
"""Get max value of tensor."""
return self._max
return float(self._stats.get('max_value', 0))

@property
def min(self):
"""Get min value of tensor."""
return self._min
return float(self._stats.get('min_value', 0))

@property
def avg(self):
"""Get avg value of tensor."""
return self._avg
return float(self._stats.get('avg_value', 0))

@property
def count(self):
"""Get total count of tensor."""
return self._count
return int(self._stats.get('count', 0))

@property
def nan_count(self):
"""Get count of NAN."""
return self._nan_count
return int(self._stats.get('nan_count', 0))

@property
def neg_inf_count(self):
"""Get count of negative INF."""
return self._neg_inf_count
return int(self._stats.get('neg_inf_count', 0))

@property
def pos_inf_count(self):
"""Get count of positive INF."""
return self._pos_inf_count
return int(self._stats.get('pos_inf_count', 0))

@property
def neg_zero_count(self):
"""Get count of negative zero."""
return self._neg_zero_count
return int(self._stats.get('neg_zero_count', 0))

@property
def pos_zero_count(self):
"""Get count of positive zero."""
return self._pos_zero_count
return int(self._stats.get('pos_zero_count', 0))

@property
def zero_count(self):
"""Get count of zero."""
return self._zero_count
return int(self._stats.get('zero_count', 0))

@property
def true_count(self):
"""Get count of False."""
return self.pos_zero_count if self.is_bool else 0

@property
def false_count(self):
"""Get count of True."""
return self.zero_count if self.is_bool else 0

@property
def is_bool(self):
"""Whether the tensor is bool type."""
return self._stats.get('is_bool', False)


class TensorComparison:
"""TensorComparison class.

Args:
tolerance (float): tolerance for calculating tensor diff.
stats (float): statistics of tensor diff.
value (numpy.ndarray): tensor diff.
tolerance (float): Tolerance for calculating tensor diff.
stats (float): Statistics of tensor diff.
value (numpy.ndarray): Tensor diff.
"""

def __init__(self, tolerance=0, stats=None, value=None):
self._tolerance = tolerance
self._stats = stats
@@ -136,6 +146,7 @@ class TensorComparison:
"""Get value of tensor diff."""
return self._value


def str_to_slice_or_int(input_str):
"""
Translate param from string to slice or int.
@@ -241,13 +252,13 @@ class TensorUtils:
nan_count, pos_inf_count, neg_inf_count = invalids
if not valid:
logger.warning('There are no valid values in the tensors(size=%d, shape=%s)', total, tensors.shape)
statistics = Statistics(max_value=0,
min_value=0,
avg_value=0,
count=total,
nan_count=nan_count,
neg_inf_count=neg_inf_count,
pos_inf_count=pos_inf_count)
statistics = Statistics({'max_value': 0,
'min_value': 0,
'avg_value': 0,
'count': total,
'nan_count': nan_count,
'neg_inf_count': neg_inf_count,
'pos_inf_count': pos_inf_count})
return statistics

# BUG: max of a masked array with dtype np.float16 returns inf
@@ -268,16 +279,17 @@ class TensorUtils:
pos_zero_count = np.sum(ma_value > 0)
with np.errstate(invalid='ignore'):
zero_count = np.sum(ma_value == 0)
statistics = Statistics(max_value=tensor_max,
min_value=tensor_min,
avg_value=tensor_sum / valid,
count=total,
neg_zero_count=neg_zero_count,
pos_zero_count=pos_zero_count,
zero_count=zero_count,
nan_count=nan_count,
neg_inf_count=neg_inf_count,
pos_inf_count=pos_inf_count)
statistics = Statistics({'is_bool': tensors.dtype == np.bool,
'max_value': tensor_max,
'min_value': tensor_min,
'avg_value': tensor_sum / valid,
'count': total,
'neg_zero_count': neg_zero_count,
'pos_zero_count': pos_zero_count,
'zero_count': zero_count,
'nan_count': nan_count,
'neg_inf_count': neg_inf_count,
'pos_inf_count': pos_inf_count})
return statistics

@staticmethod
@@ -318,18 +330,25 @@ class TensorUtils:
"""
if not overall_stats:
return {}
res = {
"overall_max": float(overall_stats.max),
"overall_min": float(overall_stats.min),
"overall_avg": float(overall_stats.avg),
"overall_count": overall_stats.count,
"overall_nan_count": overall_stats.nan_count,
"overall_neg_inf_count": overall_stats.neg_inf_count,
"overall_pos_inf_count": overall_stats.pos_inf_count,
"overall_zero_count": float(overall_stats.zero_count),
"overall_neg_zero_count": float(overall_stats.neg_zero_count),
"overall_pos_zero_count": float(overall_stats.pos_zero_count)
}
if overall_stats.is_bool:
res = {
'overall_count': overall_stats.count,
'overall_true_count': overall_stats.true_count,
'overall_false_count': overall_stats.false_count
}
else:
res = {
"overall_max": float(overall_stats.max),
"overall_min": float(overall_stats.min),
"overall_avg": float(overall_stats.avg),
"overall_count": overall_stats.count,
"overall_nan_count": overall_stats.nan_count,
"overall_neg_inf_count": overall_stats.neg_inf_count,
"overall_pos_inf_count": overall_stats.pos_inf_count,
"overall_zero_count": float(overall_stats.zero_count),
"overall_neg_zero_count": float(overall_stats.neg_zero_count),
"overall_pos_zero_count": float(overall_stats.pos_zero_count)
}
return res

@staticmethod


Loading…
Cancel
Save