Ejemplo n.º 1
0
    def type_inference(self):
        x_type = self.x.dtype
        x_shape = list(self.x.shape)
        y_shape = list(self.y.shape)
        x_rank = len(x_shape)

        if x_rank == 1 and self.transpose_x.val:
            msg = "Op {} (matmul): x is rank 1, but transpose_x is True, which is not allowed."
            raise ValueError(msg.format(self.name))

        if self.transpose_x.val:
            x_shape = list(x_shape)
            x_shape[-1], x_shape[-2] = x_shape[-2], x_shape[-1]
            x_shape = tuple(x_shape)
        if self.transpose_y.val:
            y_shape = list(y_shape)
            y_shape[-1], y_shape[-2] = y_shape[-2], y_shape[-1]
            y_shape = tuple(y_shape)
        if not (x_shape[-1] == y_shape[-2] or is_symbolic(x_shape[-1])
                or is_symbolic(y_shape[-2])):
            msg = "Op {} (matmul): x {}, y {} are not broadcastable"
            raise ValueError(msg.format(self.name, self.x.shape, self.y.shape))

        if x_rank == 1:
            # promote shape of x to rank 2
            x_shape = list((1, ) + tuple(x_shape))
        ret_shape = list(broadcast_shapes(x_shape[:-2], y_shape[:-2]))
        ret_shape += [x_shape[-2], y_shape[-1]]
        if x_rank == 1:
            # remove the first dimension of the returned shape
            return types.tensor(x_type, tuple(ret_shape[1:]))
        else:
            return types.tensor(x_type, tuple(ret_shape))
Ejemplo n.º 2
0
    def __init__(self, shape, default=None):
        """
        The basic shape class to be set in InputType.

        Attribute:

        shape: list of (int), symbolic values, RangeDim object
            The valid shape of the input
        default: tuple of int or None
            The default shape that is used for initiating the model, and set in
            the metadata of the model file.
            If None, then `shape` would be used.
        """
        from coremltools.converters.mil.mil import get_new_symbol

        if not isinstance(shape, (list, tuple)):
            msg = "Shape should be list or tuple, got type {} instead"
            raise ValueError(msg.format(type(shape)))
        self.symbolic_shape = []
        shape = list(shape)
        for idx, s in enumerate(shape):
            if s is None or s == -1:
                msg = 'Dimension cannot be None or -1. Use ' +\
                        'ct.RangeDim for runtime determined dimension. ' +\
                        'Dim {}: {} ' +\
                        'See https://coremltools.readme.io/docs/flexible-inputs'
                raise ValueError(msg.format(idx, s))
            if isinstance(s, RangeDim):
                sym = s.symbol
                self.symbolic_shape.append(sym)
            elif isinstance(s,
                            (np.generic, six.integer_types)) or is_symbolic(s):
                self.symbolic_shape.append(s)
            else:
                raise ValueError(
                    "Unknown type {} to build symbolic shape.".format(type(s)))

        self.shape = tuple(shape)
        if default is not None:
            if not isinstance(default, (list, tuple)):
                raise ValueError(
                    "Default shape should be list or tuple, got type {} instead"
                    .format(type(default)))
            for idx, s in enumerate(default):
                if not isinstance(
                        s,
                    (np.generic, six.integer_types)) and not is_symbolic(s):
                    raise ValueError(
                        "Default shape invalid, got error at index {} which is {}"
                        .format(idx, s))
        else:
            default = []
            for idx, s in enumerate(self.shape):
                if isinstance(s, RangeDim):
                    default.append(s.default)
                elif s is None or s == -1:
                    default.append(self.symbolic_shape[idx])
                else:
                    default.append(s)
        self.default = tuple(default)
Ejemplo n.º 3
0
    def get_cast_value(input_var, dtype_val):
        type_map = {
            "int32": np.int32,
            "int64": np.int64,
            "fp16": np.float16,
            "fp32": np.float32,
            "fp64": np.float64,
            "bool": np.bool,
        }

        if dtype_val not in type_map.keys():
            raise NotImplementedError(
                "Parameter dtype of the cast operation can be one of the {}. "
                "Provided {}".format(type_map.keys(), dtype_val))

        if input_var.val is None:
            if input_var.sym_val is not None and not is_symbolic(
                    input_var.sym_val) and len(input_var.sym_val.shape) == 1:
                result = [
                    np.array(val).astype(dtype=type_map[dtype_val]).item()
                    if not is_symbolic(val) else val
                    for val in input_var.sym_val
                ]
                return np.array(result)
            return None

        if not types.is_tensor(input_var.sym_type):
            return input_var.val.astype(dtype=type_map[dtype_val])
        else:
            return np.array(input_var.val).astype(dtype=type_map[dtype_val])
Ejemplo n.º 4
0
    def type_inference(self):
        if self.x.rank != 4:
            raise ValueError(
                'input "x" to the "resample" op must be a rank 4 tensor. '
                "Got rank {} tensor of shape {}".format(
                    self.x.rank, self.x.shape))
        if self.coordinates.rank != 4:
            raise ValueError(
                'input "coordinates" to the "resample" op must be a rank 4 tensor. '
                "Got rank {} tensor of shape {}".format(
                    self.coordinates.rank, self.coordinates.shape))

        input_shape = self.x.shape
        coord_shape = self.coordinates.shape
        if (not is_symbolic(input_shape[0]) and not is_symbolic(coord_shape[0])
                and input_shape[0] != coord_shape[0]):
            raise ValueError(
                'input "x" and "coordinates" to the "resample" must agree on '
                "dimension of batch size: {} vs. {}".format(
                    input_shape[0], coord_shape[0]))
        if not is_symbolic(coord_shape[-1]) and coord_shape[-1] != 2:
            raise ValueError(
                'input "coordinates" to the "resample" op last dimension must be 2. '
                "Got {} for last dimension".format(coord_shape[-1]))

        ret_shape = list(input_shape)
        ret_shape[2] = coord_shape[1]  # Output height
        ret_shape[3] = coord_shape[2]  # Output width
        return types.tensor(self.x.dtype, tuple(ret_shape))
Ejemplo n.º 5
0
    def type_inference(self):
        x_type = self.x.dtype
        x_shape = np.array(self.x.shape)

        reps = self.reps.sym_val

        if reps is None:
            out_shape = tuple([get_new_symbol() for _ in range(self.x.rank)])
            return types.tensor(x_type, out_shape)

        if len(reps) == 0 or len(reps) > self.x.rank:
            msg = ("Length of the reps ({}) must be at least 1, and "
                   "not greater than the rank of the input x ({})")
            raise ValueError(msg.format(len(reps), self.x.rank))

        if len(reps) < self.x.rank:
            reps = [1] * (self.x.rank - len(reps)) + list(reps)

        out_shape = []
        for i, rep in enumerate(reps):
            if not is_symbolic(rep):
                if rep <= 0:
                    raise ValueError(
                        "All entries of reps parameter must be greater than 0")

            if is_symbolic(rep) or is_symbolic(x_shape[i]):
                out_shape.append(get_new_symbol())
            else:
                out_shape.append(rep * x_shape[i])

        out_shape = tuple(out_shape)

        return types.tensor(x_type, out_shape)
Ejemplo n.º 6
0
    def type_inference(self):
        concat_dim_len = 0
        if len(self.values) == 0:
            raise ValueError("Concat {} got 0 values".format(self.name))

        # Validate values have the same rank
        rank = self.values[0].rank
        for v in self.values:
            if v.rank != rank:
                msg = "Input {} has rank {} != other inputs rank {}"
                raise ValueError(msg.format(v.name, v.rank, rank))

        # Check concat axis is within (-rank, rank)
        concat_axis = self.axis.val
        if concat_axis < 0:
            concat_axis += rank
        if rank > 0 and (concat_axis < 0 or concat_axis >= rank):
            msg = "In {} of op_type {}: axis out of bound for input " + "(rank {})"
            raise ValueError(msg.format(self.name, self.op_type, rank))

        # Validate primitive types are compatible
        dtype = self.values[0].dtype
        for v in self.values[1:]:
            new_dtype = promoted_primitive_type(v.dtype, dtype)
            if new_dtype is None:
                msg = "Incompatible primitive types concat: {} vs {}"
                raise ValueError(msg.format(v.dtype, dtype))
            dtype = new_dtype

        # validate that non-axis dimensions match
        retshape = list(self.values[0].shape)
        for v in self.values[1:]:
            for i in range(rank):
                if is_symbolic(retshape[i]) or is_symbolic(v.shape[i]):
                    continue
                if i != concat_axis and retshape[i] != v.shape[i]:
                    msg = 'Dimension mismatch in {} ("{}"): shapes {} vs. {}'
                    raise ValueError(
                        msg.format(self.op_type, self.name, retshape, v.shape)
                    )

        # Get length of concat dim
        concat_dim_len = 0
        for v in self.values:
            if len(v.shape) == 0:
                taxis = 1
            else:
                taxis = v.shape[concat_axis]
            if is_symbolic(taxis):
                concat_dim_len = get_new_symbol()
                break
            concat_dim_len += taxis

        if len(retshape) == 0:
            retshape = [concat_dim_len]
        else:
            retshape[concat_axis] = concat_dim_len

        return types.tensor(dtype, retshape)
Ejemplo n.º 7
0
    def __init__(self, shapes, default=None):
        """
        A shape class that is used for setting multiple valid shape in InputType.

        Parameters
        ----------
        shapes: list of Shape objects, or Shape-compatible lists.
            The valid shapes of the inputs.
            
            If input provided is not Shape object, but can be converted to Shape,
            the Shape object would be stored in ``shapes`` instead.
        
        default: tuple of int or None
            The default shape that is used for initiating the model, and set in
            the metadata of the model file.
            
            If None, then the first element in ``shapes`` is used.
        """
        from coremltools.converters.mil.mil import get_new_symbol

        if not isinstance(shapes, (list, tuple)):
            raise ValueError(
                "EnumeratedShapes should be list or tuple of shape, got type {} instead"
                .format(type(shapes)))
        if len(shapes) < 2:
            raise ValueError(
                "EnumeratedShapes should be take a list or tuple with len >= 2, got {} instead"
                .format(len(shapes)))

        self.shapes = []
        for idx, s in enumerate(shapes):
            if isinstance(s, Shape):
                self.shapes.append(s)
            else:
                self.shapes.append(Shape(s))

        self.symbolic_shape = self.shapes[0].symbolic_shape
        for shape in self.shapes:
            for idx, s in enumerate(shape.symbolic_shape):
                if is_symbolic(self.symbolic_shape[idx]):
                    continue
                elif is_symbolic(s):
                    self.symbolic_shape[idx] = s
                elif s != self.symbolic_shape[idx]:
                    self.symbolic_shape[idx] = get_new_symbol()

        if default is not None:
            if not isinstance(default, (list, tuple)):
                raise ValueError(
                    "Default shape should be list or tuple, got type {} instead"
                    .format(type(default)))
            for idx, s in enumerate(default):
                if not isinstance(s, (np.generic, int)) and not is_symbolic(s):
                    raise ValueError(
                        "Default shape invalid, got error at index {} which is {}"
                        .format(idx, s))
        else:
            default = self.shapes[0].default
        self.default = default
Ejemplo n.º 8
0
def _set_symbolic_inputs(proto, symbolic_inputs):
    # Set symbolic input shapes by -1 infered from graph
    for input_name, shape in symbolic_inputs.items():
        lb = [1 if is_symbolic(d) else d for d in shape]
        ub = [-1 if is_symbolic(d) else d for d in shape]
        set_multiarray_ndshape_range(
            proto, input_name, lower_bounds=lb, upper_bounds=ub
        )
Ejemplo n.º 9
0
 def _get_dim_value(shape1, shape2, dim):
     if is_symbolic(shape1[dim]) and is_symbolic(shape2[dim]):
         return shape1[dim]
     elif is_symbolic(shape1[dim]):
         return shape1[dim]
     elif is_symbolic(shape2[dim]):
         return shape2[dim]
     else:
         return max(shape1[dim], shape2[dim])
Ejemplo n.º 10
0
 def compare_elem(dt, ds):
     if dt is None or dt < 0:
         return True
     elif dt == ds:
         return True
     elif is_symbolic(ds):
         if is_symbolic(dt) and dt != ds:
             logging.warning("Symbolic dim {} and {}".format(ds, dt) +\
                             " assumed to be equal")
         return True
     else:
         return False
Ejemplo n.º 11
0
    def type_inference(self):
        if self.x.rank < 3:
            raise ValueError(
                'input to the "upsample_bilinear" op must have rank at least 3'
            )

        ret_shape = list(self.x.shape)
        ret_shape[-1] = np.floor(self.scale_factor_width.val *
                                 ret_shape[-1]) if not is_symbolic(
                                     ret_shape[-1]) else get_new_symbol()
        ret_shape[-2] = np.floor(self.scale_factor_height.val *
                                 ret_shape[-2]) if not is_symbolic(
                                     ret_shape[-2]) else get_new_symbol()
        return types.tensor(self.x.dtype, ret_shape)
Ejemplo n.º 12
0
    def enforce_volumetric_constraint(left_volume, inshape):
        left_symbols = set()
        if is_symbolic(left_volume):
            left_symbols = left_volume.free_symbols
        # Generally, we want to solve for right in terms of left. But this
        # is kinda annoying actually.
        shape = list(inshape)

        # Handling when reshape is given 0 instead of actual input
        # input tensor shape: [4, 3, 2], reshape:[0, -1], output tensor shape: [4, 6]
        if shape.count(-1) > 1:
            raise ValueError(
                "Reshape op supports only one dimension to be -1. Given {}".format(
                    shape.count(-1)
                )
            )

        infer_dim_index = shape.index(-1) if -1 in shape else None
        right_volume = 1
        for i in shape:
            if i != -1:
                right_volume = right_volume * i

        if infer_dim_index:
            shape[infer_dim_index] = left_volume // right_volume

        if not is_symbolic(right_volume):
            return shape

        constraints = [left_volume - right_volume]
        solve_for = [s for s in shape if is_symbolic(s)]

        for rightsym in solve_for:
            sol = sm.solve(constraints, [rightsym], dict=True)
            if not isinstance(sol, list):
                sol = [sol]
            # look for an acceptable solution
            for s in sol:
                if 0 in s.values():
                    continue
                for i in range(len(shape)):
                    if shape[i] in s:
                        v = s[shape[i]]
                        if len(v.free_symbols - left_symbols) > 0:
                            continue
                        try:
                            shape[i] = int(v)
                        except:
                            shape[i] = v
        return shape
Ejemplo n.º 13
0
    def type_inference(self):
        if self.begin.rank != 1:
            raise ValueError(
                "begin should be 1-D tensor, got {}-D tensor instead".format(
                    self.begin.rank))
        if self.size.rank != 1:
            raise ValueError(
                "size should be 1-D tensor, got {}-D tensor instead".format(
                    self.size.rank))
        if self.x.rank != self.begin.shape[0]:
            raise ValueError(
                "Length of begin {} doesn't equal to input rank {}.".format(
                    len(self.begin.shape[0]), len(self.x.rank)))
        if self.x.rank != self.size.shape[0]:
            raise ValueError(
                "Length of size {} doesn't equal to input rank {}.".format(
                    len(self.size.shape[0]), len(self.x.rank)))

        x_shape = self.x.shape
        ret_shape = []
        if self.size.sym_val is None:
            ret_shape = [get_new_symbol() for _ in range(self.x.rank)]
            return types.tensor(self.x.dtype, tuple(ret_shape))

        for idx, s in enumerate(self.size.sym_val):
            if is_symbolic(s):
                ret_shape.append(s)
            elif s != -1:
                ret_shape.append(s)
            elif self.begin.sym_val is not None:
                ret_shape.append(x_shape[idx] - self.begin.sym_val[idx])
            else:
                ret_shape.append(get_new_symbol())

        return types.tensor(self.x.dtype, tuple(ret_shape))
Ejemplo n.º 14
0
 def value_inference(self):
     if any_symbolic(self.x.shape):
         # convert elements in shape to int32
         res = [x if is_symbolic(x) else np.int32(x) for x in self.x.shape]
         return np.array(res)
     else:
         return np.array(self.x.shape).astype(np.int32)
Ejemplo n.º 15
0
 def _does_block_contain_symbolic_shape(block):
     for op in block.operations:
         for b in op.blocks:
             if _does_block_contain_symbolic_shape(b):
                 return True
         for out in op.outputs:
             if types.is_tensor(out.sym_type):
                 shape = out.sym_type.get_shape()
                 if any_symbolic(shape):
                     return True
             elif types.is_scalar(out.sym_type) or types.is_str(
                     out.sym_type):
                 if is_symbolic(out.val):
                     return True
             elif types.is_list(out.sym_type):
                 if types.is_tensor(out.elem_type):
                     if any_symbolic(out.elem_type.get_shape()):
                         return True
                 else:
                     raise NotImplementedError(
                         "\'{}\' type in a list not handled".format(
                             out.elem_type))
             else:
                 raise NotImplementedError(
                     "\'{}\' type is not handled".format(out.sym_type))
     return False
Ejemplo n.º 16
0
def reshape_with_symbol(v, shape):
    """
    Perform basic reshape if v is symbolic (not array of symbols).
    """
    if is_symbolic(v):
        return np.array(v).reshape(shape)
    shape = [int(s) for s in shape]
    return v.reshape(shape)
Ejemplo n.º 17
0
    def value_inference(self):
        if self.x.sym_val is None or self.begin.val is None or self.end.val is None:
            return None
        x_shape = self.x.shape
        begin = [int(i) for i in list(self.begin.val[:])]
        end = [int(i) for i in list(self.end.val[:])]
        stride = [1] * self.x.rank if self.stride is None else self.stride.val
        begin_mask = (
            [False] * self.x.rank if self.begin_mask is None else self.begin_mask.val
        )
        end_mask = [False] * self.x.rank if self.end_mask is None else self.end_mask.val
        squeeze_mask = (
            [False] * self.x.rank
            if self.squeeze_mask is None
            else self.squeeze_mask.val
        )

        slices = []
        for idx, mask in enumerate(begin_mask):
            if mask:
                begin[idx] = None
        for idx, mask in enumerate(end_mask):
            if mask:
                end[idx] = None
        squeeze_axes = []
        for idx, mask in enumerate(squeeze_mask):
            if mask:
                end[idx] = None
                stride[
                    idx
                ] = 2147483647  # We slice out only 1 element by setting stride to INF
                squeeze_axes.append(idx)
        for idx in range(self.x.rank):
            slices.append(slice(begin[idx], end[idx], stride[idx]))

        slices = tuple(slices)
        res = self.x.sym_val[slices]

        # remove squeezed axes
        if len(squeeze_axes) > 0:
            if len(squeeze_axes) == len(res.shape):
                if len(res) == 0:
                    logging.warning("%s seems to be a 0 sized tensor", self.name)
                    return np.array([])
                res = res.tolist()[0]
                if is_symbolic(res):
                    return res
                elif self.x.dtype == types.int32 or self.x.dtype == types.int64:
                    res = np.int32(res)
                elif self.x.dtype == types.float or self.x.dtype == types.double:
                    res = np.float32(res)
                else:
                    raise ValueError(
                        "Unable to convert type {}".format(self.x.sym_val.dtype)
                    )
            else:
                res = np.squeeze(res, axis=tuple(squeeze_axes))
        return res
Ejemplo n.º 18
0
def _try_to_transform(reduce_sum_op, block):

    ops_to_remove = []

    # check that the dimensions in the shape of the input to the reduce_sum op,
    # over which the reduction operation is being performed, are known
    input_shape = reduce_sum_op.x.shape
    if input_shape is None:
        return False
    axes = None
    if reduce_sum_op.axes is not None:
        axes = reduce_sum_op.axes.val
    if axes is None:
        return False
    count = 1
    for dim in axes:
        if is_symbolic(input_shape[dim]):
            return False
        count *= input_shape[dim]

    # check that output of reduce_sum is not a block output
    if reduce_sum_op.outputs[0] in block.outputs:
        return False
    ops_to_remove.append(reduce_sum_op)

    # check that reduce_sum op is followed by either:
    # - mul op with scalar value 1/count
    # or
    # - real_div op with scalar value count
    if _check_child_op_type(reduce_sum_op, "mul"):
        child_op = list(reduce_sum_op.outputs[0].child_ops)[0]
        other_input = child_op.x if child_op.y == reduce_sum_op.outputs[0] else child_op.y
        if not _check_var_scalar_value(other_input, 1.0 / count, 1e-6):
            return False
    elif _check_child_op_type(reduce_sum_op, "real_div"):
        child_op = list(reduce_sum_op.outputs[0].child_ops)[0]
        if child_op.x != reduce_sum_op.outputs[0]:
            return False
        other_input = child_op.y
        if not _check_var_scalar_value(other_input, count, 1e-2):
            return False
    else:
        return False

    ops_to_remove.append(child_op)

    # remove all the ops, and replace with a reduce_mean op
    out_name = child_op.outputs[0].name
    x = mb.reduce_mean(x=reduce_sum_op.x,
                       axes = reduce_sum_op.axes.val,
                       keep_dims = reduce_sum_op.keep_dims.val,
                       name=out_name,
                       before_op=child_op)
    child_op.enclosing_block.replace_uses_of_var_after_op(
        anchor_op=child_op, old_var=child_op.outputs[0], new_var=x
    )
    block.remove_ops(ops_to_remove)
    return True
Ejemplo n.º 19
0
def broadcast_shapes(shape_x, shape_y):
    """
    Check and broadcast given input shapes.
    :param shape_x: tuple of int or symbols
        Shape of the first tensor (possibly symbolic).
    :param shape_y: tuple of int or symbols
        Shape of the second tensor (possibly symbolic).
    :return: tuple of int or symbols
        Result from broadcast.
    """
    shape_x = tuple(shape_x)
    shape_y = tuple(shape_y)
    if len(shape_x) < len(shape_y):
        shape_x = tuple([1] * (len(shape_y) - len(shape_x))) + shape_x
    if len(shape_y) < len(shape_x):
        shape_y = tuple([1] * (len(shape_x) - len(shape_y))) + shape_y

    ret_shapes = list()
    for i in range(len(shape_x)):
        x_unknown = is_symbolic(shape_x[i])
        y_unknown = is_symbolic(shape_y[i])
        if shape_x[i] == 1:
            ret_shapes.append(shape_y[i])
        elif shape_y[i] == 1:
            ret_shapes.append(shape_x[i])
        elif not y_unknown and shape_y[i] > 1:
            if not x_unknown and shape_x[i] != shape_y[i]:
                raise ValueError(
                    "Incompatible dim {} in shapes {} vs. {}".format(
                        i, shape_x, shape_y))
            ret_shapes.append(shape_y[i])
        elif not x_unknown and shape_x[i] > 1:
            if not y_unknown and shape_x[i] != shape_y[i]:
                raise ValueError(
                    "Incompatible dim {} in shapes {} vs. {}".format(
                        i, shape_x, shape_y))
            ret_shapes.append(shape_x[i])
        elif x_unknown or y_unknown:
            ret_shapes.append(get_new_symbol())
        else:
            if shape_x[i] != shape_y[i]:
                raise AssertionError
            ret_shapes.append(shape_x[i])

    return tuple(ret_shapes)
Ejemplo n.º 20
0
def _is_compatible_symbolic_array(a, b):
    """
    A helper function which check if two numpy array with symbolic value.
    For instance, a = np.array([is0, is2])
                  b = np.array([is1, 1])
    are considered compatible.
                  a = np.array([is0, 1])
                  b = np.array([is1, -1])
    are not.
    """
    if not a.shape == b.shape:
        return False
    a = a.flatten()
    b = b.flatten()
    for t, v in zip(a, b):
        if not is_symbolic(t) and not is_symbolic(v):
            if t != v:
                return False
    return True
Ejemplo n.º 21
0
    def value_inference(self):

        is_all_rank_zero = all([v.rank == 0 for v in self.values])
        values = [
            v.sym_val if v.sym_val is not None else get_new_symbol()
            for v in self.values
        ]

        if any([is_symbolic(v) for v in values]) and not is_all_rank_zero:
            return None

        return np.stack(values, self.axis.val)
Ejemplo n.º 22
0
    def type_inference(self):
        x_type = self.x.dtype
        x_shape = list(self.x.shape)
        y_shape = list(self.y.shape)

        if self.transpose_x.val:
            x_shape = list(x_shape)
            x_shape[-1], x_shape[-2] = x_shape[-2], x_shape[-1]
            x_shape = tuple(x_shape)
        if self.transpose_y.val:
            y_shape = list(y_shape)
            y_shape[-1], y_shape[-2] = y_shape[-2], y_shape[-1]
            y_shape = tuple(y_shape)
        if not (x_shape[-1] == y_shape[-2] or is_symbolic(x_shape[-1])
                or is_symbolic(y_shape[-2])):
            msg = "Op {} (matmul): x {}, y {} are not broadcastable"
            raise ValueError(msg.format(self.name, self.x.shape, self.y.shape))

        ret_shape = list(broadcast_shapes(x_shape[:-2], y_shape[:-2]))
        ret_shape += [x_shape[-2], y_shape[-1]]
        return types.tensor(x_type, tuple(ret_shape))
Ejemplo n.º 23
0
            def type_inference(self):
                x_type = self.x.dtype
                x_shape = self.x.shape
                k = self.k.val
                axis = self.axis.val

                if not is_symbolic(x_shape[axis]) and k > x_shape[axis]:
                    msg = "K={} is greater than size of the given axis={}"
                    raise ValueError(msg.format(k, axis))

                ret_shape = list(x_shape)
                ret_shape[axis] = k
                return types.tensor(x_type, ret_shape), types.tensor(types.int32, ret_shape)
Ejemplo n.º 24
0
 def type_inference(self):
     x_type = self.x.dtype
     x_shape = self.x.shape
     weight_shape = self.weight.shape
     assert len(weight_shape) == 2
     if not (x_shape[-1] == weight_shape[-1] or is_symbolic(x_shape[-1])
             or is_symbolic(weight_shape[-1])):
         msg = "Op '{}' (linear op): Size of the last dimension of x, which is {}, " \
               "does not match the last dimension of weights, which is {}"
         raise ValueError(
             msg.format(self.name, x_shape[-1], weight_shape[-1]))
     if self.bias is not None:
         assert len(self.bias.shape) == 1
         if len(self.bias.val) != weight_shape[-2]:
             msg = "Op '{}' (linear op): Size of the bias, which is {}, " \
                   "does not match the first dimension of weights, which is {}"
             raise ValueError(
                 msg.format(self.name, len(self.bias.val),
                            weight_shape[-2]))
     shape = list(x_shape)
     shape[-1] = weight_shape[0]
     return types.tensor(x_type, tuple(shape))
Ejemplo n.º 25
0
    def _get_num_splits_and_sizes(self):
        """
        Return:
        - num_splits: int
        - sizes: list of int/symbols. Of length num_splits

        Raise ValueError if num_splits cannot be determined.
        """
        if self.num_splits is None and self.split_sizes is None:
            msg = (
                "At least one of num_splits and split_sizes "
                + "must be specified in split op {}"
            )
            raise ValueError(msg.format(self.name))

        axis = self.axis.val

        if self.num_splits is not None:
            num_splits = self.num_splits.val
            if self.split_sizes is None:
                # Even split
                if (
                    not is_symbolic(self.x.shape[axis])
                    and self.x.shape[axis] % num_splits != 0
                ):
                    msg = "num_split {} does not divide split " + "dim (length = {})"
                    raise ValueError(msg.format(num_splits, self.x.shape[axis]))
                size = self.x.shape[axis] / num_splits
                return num_splits, [size] * num_splits

            # self.split_sizes is not None
            if self.split_sizes.sym_val is not None:
                return num_splits, self.split_sizes.sym_val

            # self.split_size.sym_val is None.
            sizes = [get_new_symbol() for _ in range(num_splits)]
            return num_splits, sizes

        # self.num_splits is None, self.split_sizes is not None
        if self.split_sizes.sym_val is not None:
            return len(self.split_sizes.sym_val), self.split_sizes.sym_val

        # self.num_splits is None, self.split_sizes is not None
        # self.split_sizes.sym_val is None
        if any_symbolic(self.split_sizes.shape):
            raise ValueError("Unable to determine number of splits")

        num_splits = len(self.split_sizes.shape)
        sizes = [get_new_symbol() for _ in range(num_splits)]
        return num_splits, sizes
Ejemplo n.º 26
0
    def type_inference(self):
        if self.axis.val < -self.data.rank or self.axis.val >= self.data.rank:
            raise IndexError(
                "Axis value {} is out of bounds for {} node {}".format(
                    self.axis.val, self.op_type, self.name
                )
            )

        axis = self.axis.val
        axis = axis if axis >= 0 else axis + self.data.rank
        expected_updates_shape = (
            self.data.shape[:axis] + self.indices.shape + self.data.shape[axis + 1 :]
        )

        err = "Updates shape {} is incorrect. It should be {}.".format(self.updates.shape, expected_updates_shape)
        if len(self.updates.shape) == len(expected_updates_shape):
            for dim1, dim2 in zip(self.updates.shape, expected_updates_shape):
                if not is_symbolic(dim1) and not is_symbolic(dim2):
                    if dim1 != dim2:
                        raise ValueError(err)
        else:
            raise ValueError(err)

        return self.data.sym_type
Ejemplo n.º 27
0
 def _get_type_val(self):
     x_type = self.x.dtype
     x_shape = self.x.shape
     x_vol = np.prod(x_shape)
     # shape is const, and thus sym_val is not None
     sym_shape = self.shape.sym_val
     sym_shape = [get_new_symbol() if d == -1 else d for d in sym_shape]
     try:
         ret_shape = reshape.enforce_volumetric_constraint(x_vol, sym_shape)
     except:
         ret_shape = sym_shape
     ret_val = None
     if self.x.val is not None and all(isscalar(a) and not is_symbolic(a) for a in ret_shape):
         ret_val = reshape_with_symbol(self.x.val, ret_shape)
     return types.tensor(x_type, tuple(ret_shape)), ret_val
Ejemplo n.º 28
0
    def type_inference(self):
        x_shape = self.x.shape
        block_shape = self.block_shape.val
        crops = self.crops.val

        if self.x.rank != 4:
            msg = "Input to batch_to_space op must be rank 4. Instead got an input with rank {}".format(
                self.x.rank)
            raise ValueError(msg)

        if crops.shape != (block_shape.shape[0], 2):
            msg = "block_shape and crops must have shape [2], [2, 2] accordingly in the batch_to_space op. "\
            "Got {}, {}.".format(block_shape.shape, crops.shape)
            raise ValueError(msg)

        m = block_shape.shape[0]
        if m != 2:
            msg = "batch_to_space op only supports spatial dimensions = 2. Got {}".format(
                m)
            raise ValueError(msg)

        b = x_shape[0]
        c = x_shape[1]
        spatial_shape = x_shape[2:2 + m]

        if self.x.rank != m + 2:
            raise ValueError("The input rank of batch_to_space op must exactly be " \
                             "len(block_shape){} + 2! Got {}".format(self.block_shape.val, self.x.rank))

        if not is_symbolic(b) and b % np.prod(block_shape) != 0:
            msg = (
                "Batch size must be perfectly divided by the product of block_shape. Got batch size {}, and block_shape {}."
            ).format(b, block_shape)
            raise ValueError(msg)

        new_b = b / np.prod(block_shape)
        new_spatial_shape = [
            spatial_shape[i] * block_shape[i] for i in range(m)
        ]
        cropped_spatial_shape = [
            x - crops[i][0] - crops[i][1]
            for i, x in enumerate(new_spatial_shape)
        ]
        ret_shape = [new_b, c] + cropped_spatial_shape
        x_type = self.x.dtype

        return types.tensor(x_type, ret_shape)
Ejemplo n.º 29
0
    def value_inference(self):

        is_all_rank_zero = all([v.rank == 0 for v in self.values])
        values = [
            v.sym_val if v.sym_val is not None else get_new_symbol()
            for v in self.values
        ]

        # we only infer values for values whose ranks are all zero,
        # or don't have symbolic values.
        # Note that cases like values = [[1, is0], [2]] aren't in such case.
        if any([is_symbolic(v) for v in values]) and not is_all_rank_zero:
            return None

        if not isinstance(values[0], np.ndarray) or values[0].shape == ():
            return np.stack(values, axis=self.axis.val)

        return np.concatenate(values, axis=self.axis.val)
Ejemplo n.º 30
0
 def value_inference(self):
     if any_symbolic(self.begin.sym_val):
         return None
     if any_symbolic(self.size.sym_val):
         return None
     if self.x.val is None:
         return None
     slices = []
     for i in range(self.x.rank):
         begin_val = self.begin.val[i]
         if begin_val < 0:
             if is_symbolic(self.x.shape[i]):
                 return None
             begin_val += self.x.shape[i]
         if self.size.val[i] > 0:
             slices.append(slice(begin_val, begin_val + self.size.val[i]))
         else:
             slices.append(slice(begin_val, None, None))
     return self.x.val[tuple(slices)]