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)
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)
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
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
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
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)
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
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)
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
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
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)
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
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