Пример #1
0
    def _to_config_description(self):
        if self.reader is None:
            if not self.unmapped_nodes:
                # No inputs in the graph
                return ''

            # We have found only inputs that were directly initialized.
            # In this case, we need to serialize them into one file.

            from .context import get_context
            from .utils import get_temp_filename
            filename = get_temp_filename(get_context().directory)

            if len(self.node_map) > 0:
                raise ValueError(
                    'you cannot have inputs initialized with ' +
                    'NumPy arrays together with inputs that are ' +
                    ' initialized with a custom reader')

            self._serialize_unmapped_nodes(filename)

            # All the data we got, was through NumPy. In this case, we assume
            # that all the required randomization has happened already.
            r = CNTKTextFormatReader(filename, randomize=None)

            return r._to_config_description(self)

        else:
            return self.reader._to_config_description(self)
Пример #2
0
    def _to_config_description(self):
        if self.reader is None:
            if not self.unmapped_nodes:
                # No inputs in the graph
                return ''

            # We have found only inputs that were directly initialized.
            # In this case, we need to serialize them into one file.

            from .context import get_context
            from .utils import get_temp_filename
            filename = get_temp_filename(get_context().directory)

            if len(self.node_map) > 0:
                raise ValueError('you cannot have inputs initialized with '+
                        'NumPy arrays together with inputs that are ' +
                        ' initialized with a custom reader')

            self._serialize_unmapped_nodes(filename)
            
            # All the data we got, was through NumPy. In this case, we assume
            # that all the required randomization has happened already.
            r = CNTKTextFormatReader(filename, randomize=None)

            return r._to_config_description(self)

        else:
            return self.reader._to_config_description(self)
Пример #3
0
def _get_input_node(list_of_tensors, has_sequence_dimension, **kw):
    '''
    :param list_of_tensors: list of tensors potentially having sequences of
    different lengths.
    '''

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because the obvious first
    # choice, mkstemp(), would later fail in cntk.exe because the file would
    # still be locked.
    tf = tempfile.NamedTemporaryFile(prefix='_input_', suffix='.txt',
                                     dir=get_context().directory, delete=False)
    tf.close()

    if 'alias' in kw:        
        alias = kw['alias']
        del kw['alias']  # don't confuse with constructor's parameters
        
    if not alias:
        # TODO make sure we don't have clashes
        alias = '_I_%i' % np.random.randint(1000)

    shapes = set()
    with open(tf.name, 'w') as f:
        for idx,tensor in enumerate(list_of_tensors):
            if isinstance(tensor, list):
                tensor = np.asarray(tensor)

            if has_sequence_dimension:
                # collecting the shapes ignoring the sequence dimension
                shapes.add(tensor.shape[1:])
            else:
                shapes.add(tensor.shape)

            f.write(_tensor_to_text_format(idx, alias, tensor,
                has_sequence_dimension) + '\n')

    # ignoring the sequence dimension, all shapes should be equal
    if len(shapes)!=1:
        raise ValueError('except for the sequence dimensions all shapes ' +
                'should be the same - instead we have: %s'%(", ".join(str(s) for s in shapes)))

    # shapes now contains only one shape, which has the sequence dimension
    # removed.
    value_shape = shapes.pop()

    cntk_shape = value_shape if value_shape else (1,)
    
    node = cntk1_ops.Input(cntk_shape, **kw)
    node.reader = CNTKTextFormatReader(tf.name, alias)
        
    return node
Пример #4
0
def _get_constant_node(value, **kw):
    '''
    This function creates a node that represents `value` as a constant tensor
    in the graph.

    To be as generic as possible, we 
     - flatten the data 
     - initialize a ParameterTensor operator with it
     - ensure that the graph does not backprob to it.  
     - Finally we to reshape it.
    '''

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because when using the
    # obvious first choice, mkstemp(), would later fail in cntk.exe because the
    # file would still be locked.
    # TODO make it same filename as alias
    tf = tempfile.NamedTemporaryFile(prefix='_param_',
                                     suffix='.txt',
                                     dir=get_context().directory,
                                     delete=False)
    tf.close()

    if isinstance(value, list) or np.isscalar(value):
        value = np.asarray(value)

    if sparse.issparse(value):
        raise ValueError('only dense data is supported')

    with open(tf.name, 'w') as f:
        value.ravel().tofile(f, sep='\n')

    from cntk.reader import CNTKTextFormatReader

    cntk_shape = numpy_to_cntk_shape(value.shape)

    dims = np.multiply.reduce(cntk_shape)

    # TODO switch to ConstantTensor once it is in the core.bs file
    node = cntk1_ops.ParameterTensor(dims=dims,
                                     learningRateMultiplier=0.0,
                                     init='fromFile',
                                     initFromFilePath=tf.name,
                                     **kw)

    if len(cntk_shape) > 1:
        node = cntk1_ops.NewReshape(node, dims=cntk_shape)

    return node
Пример #5
0
def _get_constant_node(value, **kw):
    """
    This function creates a node that represents `value` as a constant tensor
    in the graph.

    To be as generic as possible, we 
     - flatten the data 
     - initialize a LearnableParameter operator with it
     - ensure that the graph does not backprob to it.  
     - Finally we to reshape it.
    """

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because when using the
    # obvious first choice, mkstemp(), would later fail in cntk.exe because the
    # file would still be locked.
    # TODO make it same filename as alias
    tf = tempfile.NamedTemporaryFile(prefix="_param_", suffix=".txt", dir=get_context().directory, delete=False)
    tf.close()

    if isinstance(value, list):
        value = np.asarray(value)

    if len(value.shape) == 1:
        # 1D list: interpret as one scalar per sample
        value = value[:, np.newaxis]

    if sparse.issparse(value):
        raise ValueError("only dense data is supported")

    with open(tf.name, "w") as f:
        # TODO value.ravel() ?
        np.ndarray.flatten(value).tofile(f, sep="\n")

    size = np.multiply.reduce(value.shape[:])

    # The var_name specified by the user should be set to the operator that
    # is finally returned, which is the shape node.
    var_name = kw.pop("var_name", None)

    from cntk.reader import CNTKTextFormatReader

    param_node = cntk1_ops.LearnableParameter(
        size, 1, learningRateMultiplier=0.0, init="fromFile", initFromFilePath=tf.name, **kw
    )

    reshape_node = cntk1_ops.NewReshape(param_node, dims=value.shape, var_name=var_name)

    return reshape_node
Пример #6
0
def eval(node):
    """ 
    It evaluates a node that has taken a numpy array as input. Note that sequences
    are not supported yet by this method
    
    Examples:
        Plus with two matrices
        >>> print (cntk.eval(cntk.ops.plus([[-30.,40.], [1.,2.]], [[-30.,40.], [1.,2.]])))
        #   [array([[[-60., 80.], [2., 4.]]])]
        
        Times with broadcast of a scalar over a matrix
        >>> print (cntk.eval(cntk.ops.element_times([[-30.,40.], [1.,2.]], 5)))
        #   [array([[[-150., 200.], [5., 10.]]])]        

    Args:
        node (:class:`cntk.graph.ComputationNode`): the node to evaluate        

    Returns:
        NumPy array containing the result
    """

    from cntk.context import get_context
    from cntk.ops import input_numpy, constant
    from cntk.graph import ComputationNode

    # call a helper method to get a context
    ctx = get_context()
    first = True

    # The params are passed as arryas, e.g. plus([1,2], [3,4]),  and we need to
    # wrap them with input and parameter nodes.
    if node.params:
        for p in node.params:
            if p in node.inputs:
                val = getattr(node, p)
                if not isinstance(val, ComputationNode):
                    # One param needs to be an Input() node. This will being fixed in
                    # CNTK soon, so that we can remove this workaround and evaluate a
                    # network with no inputs.
                    if first:
                        if not isinstance(val, list):
                            # inputs have the outmost dimension for sequences
                            val = [val]

                        ir = input_numpy([val], alias=p, name=p)
                        setattr(node, p, ir)
                        first = False
                    else:
                        setattr(node, p, constant(getattr(node, p), name=p))
                else:
                    if val.op_name == 'CNTK2.Input' and first:
                        first = False

    return ctx.eval(node)
Пример #7
0
def eval(node):        
    """ 
    It evaluates a node that has taken a numpy array as input. Note that sequences
    are not supported yet by this method
    
    Examples:
        Plus with two matrices
        >>> print (cntk.eval(cntk.ops.plus([[-30.,40.], [1.,2.]], [[-30.,40.], [1.,2.]])))
        #   [array([[[-60., 80.], [2., 4.]]])]
        
        Times with broadcast of a scalar over a matrix
        >>> print (cntk.eval(cntk.ops.element_times([[-30.,40.], [1.,2.]], 5)))
        #   [array([[[-150., 200.], [5., 10.]]])]        

    Args:
        node (:class:`cntk.graph.ComputationNode`): the node to evaluate        

    Returns:
        NumPy array containing the result
    """    
    
    from cntk.context import get_context        
    from cntk.ops import input_numpy, constant
    from cntk.graph import ComputationNode
    
    # call a helper method to get a context
    ctx = get_context()    
    first = True    
    
    # The params are passed as arryas, e.g. plus([1,2], [3,4]),  and we need to 
    # wrap them with input and parameter nodes.
    if node.params:
        for p in node.params:
            if p in node.inputs:
                val = getattr(node, p)
                if not isinstance(val, ComputationNode):
                    # One param needs to be an Input() node. This will being fixed in 
                    # CNTK soon, so that we can remove this workaround and evaluate a 
                    # network with no inputs.
                    if first:
                        if not isinstance(val, list):                
                            # inputs have the outmost dimension for sequences
                            val = [val]
    
                        ir = input_numpy([val], alias=p, name=p)
                        setattr(node, p, ir)
                        first = False
                    else:
                        setattr(node, p, constant(getattr(node, p), name=p))
                else:
                    if val.op_name == 'CNTK2.Input' and first:
                        first = False
                        
    return ctx.eval(node)
Пример #8
0
def _get_constant_node(value, **kw):
    '''
    This function creates a node that represents `value` as a constant tensor
    in the graph.

    To be as generic as possible, we 
     - flatten the data 
     - initialize a ParameterTensor operator with it
     - ensure that the graph does not backprob to it.  
     - Finally we to reshape it.
    '''

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because when using the
    # obvious first choice, mkstemp(), would later fail in cntk.exe because the
    # file would still be locked.
    # TODO make it same filename as alias
    tf = tempfile.NamedTemporaryFile(
        prefix='_param_', suffix='.txt', dir=get_context().directory, delete=False)
    tf.close()

    if isinstance(value, list) or np.isscalar(value):
        value = np.asarray(value)

    if sparse.issparse(value):
        raise ValueError('only dense data is supported')

    with open(tf.name, 'w') as f:
        value.ravel().tofile(f, sep='\n')

    from cntk.reader import CNTKTextFormatReader

    cntk_shape = numpy_to_cntk_shape(value.shape)

    dims = np.multiply.reduce(cntk_shape)

    # TODO switch to ConstantTensor once it is in the core.bs file
    node = cntk1_ops.ParameterTensor(
        dims=dims,
        learningRateMultiplier=0.0,
        init='fromFile',
        initFromFilePath=tf.name,
        **kw)

    if len(cntk_shape) > 1:
        node = cntk1_ops.NewReshape(node, dims=cntk_shape)

    return node
Пример #9
0
def eval(node):
    """
    It evaluates a node that has taken a numpy array as input. Note that sequences
    are not supported yet by this method
    
    Examples:
        Plus with two matrices
        >>> print (cntk.eval(cntk.ops.plus([[-30.,40.], [1.,2.]], [[-30.,40.], [1.,2.]])))
        #   [array([[[-60., 80.], [2., 4.]]])]
        
        Times with broadcast of a scalar over a matrix
        >>> print (cntk.eval(cntk.ops.element_times([[-30.,40.], [1.,2.]], 5)))
        #   [array([[[-150., 200.], [5., 10.]]])]        

    Args:
        node (cntk.graph.ComputationNode): the node to evaluate        
    Returns:
        numpy array containing the result
    """

    from cntk.context import get_context
    # call a helper method to get a context
    ctx = get_context()
    first = True

    # the params are passed as arryas e.g. plus([1,2], [3,4]), we need to
    # wrap them with input and parameter nodes
    if node.params:
        for p in node.params:
            if p in node.inputs:
                val = getattr(node, p)
                # one param needs to be an Input() node. This is being fixed in
                #CNTK we will remove this workaround onces we can evaluate a
                #network with no inputs
                if first:
                    if not isinstance(val, list):
                        # inputs have the outmost dimension for sequences
                        val = [val]
                    setattr(node, p,
                            input_reader([val], False, var_name=p, alias=p))
                    first = False
                else:
                    setattr(node, p, constant(getattr(node, p), name=p))
    return ctx.eval(node)
Пример #10
0
def eval(node):        
    """
    It evaluates a node that has taken a numpy array as input. Note that sequences
    are not supported yet by this method
    
    Examples:
        Plus with two matrices
        >>> print (cntk.eval(cntk.ops.plus([[-30.,40.], [1.,2.]], [[-30.,40.], [1.,2.]])))
        #   [array([[[-60., 80.], [2., 4.]]])]
        
        Times with broadcast of a scalar over a matrix
        >>> print (cntk.eval(cntk.ops.element_times([[-30.,40.], [1.,2.]], 5)))
        #   [array([[[-150., 200.], [5., 10.]]])]        

    Args:
        node (cntk.graph.ComputationNode): the node to evaluate        
    Returns:
        numpy array containing the result
    """    
    
    from cntk.context import get_context        
    # call a helper method to get a context
    ctx = get_context()    
    first = True    
    
    # the params are passed as arryas e.g. plus([1,2], [3,4]), we need to 
    # wrap them with input and parameter nodes
    if node.params:
        for p in node.params:
            if p in node.inputs:
                val = getattr(node, p)
                # one param needs to be an Input() node. This is being fixed in 
                #CNTK we will remove this workaround onces we can evaluate a 
                #network with no inputs
                if first:
                    if not isinstance(val, list):                
                        # inputs have the outmost dimension for sequences
                        val = [val]
                    setattr(node, p, input_reader([val], False, var_name=p, alias=p))            
                    first = False
                else:
                    setattr(node, p, constant(getattr(node, p), name=p))
    return ctx.eval(node)
Пример #11
0
def _get_input_node(value, **kw):
    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because the obvious first
    # choice, mkstemp(), would later fail in cntk.exe because the file would still be locked.
    tf = tempfile.NamedTemporaryFile(prefix='_input_',
                                     suffix='.txt',
                                     dir=get_context().directory,
                                     delete=False)
    tf.close()

    if isinstance(value, list):
        value = np.asarray(value)

    if len(value.shape) == 1:
        # 1D list: interpret as one scalar per sample
        value = value[:, np.newaxis]

    if 'alias' in kw:
        alias = kw['alias']
        del kw['alias']  # don't confuse with constructor's parameters
    else:
        # TODO make sure we don't have clashes
        alias = '_I_%i' % np.random.randint(1000)

    with open(tf.name, 'w') as f:
        f.write(_seq_to_text_format(value, alias))

    from cntk.reader import CNTKTextFormatReader
    input_node = cntk1_ops.Input(value.shape, **kw)
    input_node.reader = CNTKTextFormatReader(tf.name)
    # In case we have the shape (2,3), which will be initialized at Input() as
    # '2:3', we have 2*3 = 6 dimensions when flattened out for the reader. Note
    # that the first dimension is the sample.
    dims = np.multiply.reduce(value.shape[:])
    input_node.reader.add_input(input_node, alias, dims)

    return input_node
Пример #12
0
def _get_input_node(value, **kw):
    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because the obvious first
    # choice, mkstemp(), would later fail in cntk.exe because the file would still be locked.
    tf = tempfile.NamedTemporaryFile(prefix="_input_", suffix=".txt", dir=get_context().directory, delete=False)
    tf.close()

    if isinstance(value, list):
        value = np.asarray(value)

    if len(value.shape) == 1:
        # 1D list: interpret as one scalar per sample
        value = value[:, np.newaxis]

    if "alias" in kw:
        alias = kw["alias"]
        del kw["alias"]  # don't confuse with constructor's parameters
    else:
        # TODO make sure we don't have clashes
        alias = "_I_%i" % np.random.randint(1000)

    with open(tf.name, "w") as f:
        f.write(_seq_to_text_format(value, alias))

    from cntk.reader import CNTKTextFormatReader

    input_node = cntk1_ops.Input(value.shape, **kw)
    input_node.reader = CNTKTextFormatReader(tf.name)
    # In case we have the shape (2,3), which will be initialized at Input() as
    # '2:3', we have 2*3 = 6 dimensions when flattened out for the reader. Note
    # that the first dimension is the sample.
    dims = np.multiply.reduce(value.shape[:])
    input_node.reader.add_input(input_node, alias, dims)

    return input_node
Пример #13
0
    def _to_config_description(self):
        if self.reader is None:
            if not self.unmapped_nodes:
                # No inputs in the graph
                return ''

            # We have found only inputs that were directly initialized.
            # In this case, we need to serialize them into one file.

            from .context import get_context
            from .utils import get_temp_filename
            filename = get_temp_filename(get_context().directory)

            assert not self.node_map
            self._serialize_unmapped_nodes(filename)
            
            r = CNTKTextFormatReader(filename)

            return r._to_config_description(self)

        else:
            return self.reader._to_config_description(self)
Пример #14
0
def _get_input_node(list_of_tensors, has_sequence_dimension, **kw):
    '''
    :param list_of_tensors: list of tensors potentially having sequences of
    different lengths.
    '''

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because the obvious first
    # choice, mkstemp(), would later fail in cntk.exe because the file would
    # still be locked.
    tf = tempfile.NamedTemporaryFile(prefix='_input_',
                                     suffix='.txt',
                                     dir=get_context().directory,
                                     delete=False)
    tf.close()

    if 'alias' in kw:
        alias = kw['alias']
        del kw['alias']  # don't confuse with constructor's parameters
    else:
        # TODO make sure we don't have clashes
        alias = '_I_%i' % np.random.randint(1000)

    shapes = set()
    with open(tf.name, 'w') as f:
        for idx, tensor in enumerate(list_of_tensors):
            if isinstance(tensor, list):
                tensor = np.asarray(tensor)

            if has_sequence_dimension:
                # collecting the shapes ignoring the sequence dimension
                shapes.add(tensor.shape[1:])
            else:
                shapes.add(tensor.shape)

            f.write(
                _tensor_to_text_format(idx, alias, tensor,
                                       has_sequence_dimension) + '\n')

    # ignoring the sequence dimension, all shapes should be equal
    if len(shapes) != 1:
        raise ValueError('except for the sequence dimensions all shapes ' +
                         'should be the same - instead we have: %s' %
                         (", ".join(str(s) for s in shapes)))

    # shapes now contains only one shape, which has the sequence dimension
    # removed.
    value_shape = shapes.pop()

    cntk_shape = numpy_to_cntk_shape(value_shape)

    from cntk.reader import CNTKTextFormatReader

    # In case we have the shape (2,3) and assuming we have only sequences of
    # lengths 1, the input will be initialized with dim=3 (column major)
    # followed by a reshape node that has the dims '2:3'. So we have 2*3 = 6
    # dimensions when flattened out for the reader.
    dims = int(np.multiply.reduce(cntk_shape))
    node = cntk1_ops.Input(dims, **kw)
    node.reader = CNTKTextFormatReader(tf.name)
    node.reader.add_input(node, alias, dims)

    if len(cntk_shape) > 1:
        node = cntk1_ops.NewReshape(node, dims=cntk_shape)

    return node
Пример #15
0
def _get_constant_node(value, **kw):
    '''
    This function creates a node that represents `value` as a constant tensor
    in the graph.

    To be as generic as possible, we 
     - flatten the data 
     - initialize a LearnableParameter operator with it
     - ensure that the graph does not backprob to it.  
     - Finally we to reshape it.
    '''

    # FIXME We need to better manage the context. How can we get hold
    # of the overall context without having to always pass it
    # explicitly?

    from cntk.context import get_context
    import tempfile

    # We have to use NamedTemporaryFile and close it, because when using the
    # obvious first choice, mkstemp(), would later fail in cntk.exe because the
    # file would still be locked.
    # TODO make it same filename as alias
    tf = tempfile.NamedTemporaryFile(prefix='_param_',
                                     suffix='.txt',
                                     dir=get_context().directory,
                                     delete=False)
    tf.close()

    if isinstance(value, list):
        value = np.asarray(value)

    if len(value.shape) == 1:
        # 1D list: interpret as one scalar per sample
        value = value[:, np.newaxis]

    if sparse.issparse(value):
        raise ValueError('only dense data is supported')

    with open(tf.name, 'w') as f:
        # TODO value.ravel() ?
        np.ndarray.flatten(value).tofile(f, sep='\n')

    size = np.multiply.reduce(value.shape[:])

    # The var_name specified by the user should be set to the operator that
    # is finally returned, which is the shape node.
    var_name = kw.pop('var_name', None)

    from cntk.reader import CNTKTextFormatReader
    param_node = cntk1_ops.LearnableParameter(size,
                                              1,
                                              learningRateMultiplier=0.0,
                                              init='fromFile',
                                              initFromFilePath=tf.name,
                                              **kw)

    reshape_node = cntk1_ops.NewReshape(param_node,
                                        dims=value.shape,
                                        var_name=var_name)

    return reshape_node