autopepped
This commit is contained in:
Родитель
554f6f81fc
Коммит
3cf7665c83
|
@ -15,13 +15,13 @@ _FLOATX = 'float32'
|
|||
|
||||
CNTK_TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates")
|
||||
CNTK_TRAIN_TEMPLATE_PATH = os.path.join(
|
||||
CNTK_TEMPLATE_DIR, "cntk_train_template.cntk")
|
||||
CNTK_TEMPLATE_DIR, "cntk_train_template.cntk")
|
||||
CNTK_TEST_TEMPLATE_PATH = os.path.join(
|
||||
CNTK_TEMPLATE_DIR, "cntk_test_template.cntk")
|
||||
CNTK_TEMPLATE_DIR, "cntk_test_template.cntk")
|
||||
CNTK_PREDICT_TEMPLATE_PATH = os.path.join(
|
||||
CNTK_TEMPLATE_DIR, "cntk_predict_template.cntk")
|
||||
CNTK_TEMPLATE_DIR, "cntk_predict_template.cntk")
|
||||
CNTK_EVAL_TEMPLATE_PATH = os.path.join(
|
||||
CNTK_TEMPLATE_DIR, "cntk_eval_template.cntk")
|
||||
CNTK_TEMPLATE_DIR, "cntk_eval_template.cntk")
|
||||
CNTK_TRAIN_CONFIG_FILENAME = "train.cntk"
|
||||
CNTK_TEST_CONFIG_FILENAME = "test.cntk"
|
||||
CNTK_PREDICT_CONFIG_FILENAME = "predict.cntk"
|
||||
|
@ -52,6 +52,7 @@ def get_new_context():
|
|||
|
||||
|
||||
class AbstractContext(object, metaclass=ABCMeta):
|
||||
|
||||
'''
|
||||
This is the abstract CNTK context. It provides an API to run CNTK actions.
|
||||
'''
|
||||
|
@ -85,7 +86,7 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
else:
|
||||
os.mkdir(self.directory)
|
||||
|
||||
self.name = name
|
||||
self.name = name
|
||||
self.device_id = device_id
|
||||
self.clean_up = clean_up
|
||||
self.input_nodes = set()
|
||||
|
@ -110,19 +111,19 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
:param reader: the reader to use for reading the data
|
||||
:param override_existing: if the folder exists already override it
|
||||
'''
|
||||
|
||||
|
||||
model_dir = os.path.join(self.directory, 'Models')
|
||||
if os.path.exists(model_dir) and os.listdir(model_dir) == []:
|
||||
if override_existing:
|
||||
print ("Overriding the existing models")
|
||||
if override_existing:
|
||||
print("Overriding the existing models")
|
||||
sh.rmtree(model_dir)
|
||||
else:
|
||||
raise Exception("Directory '%s' already exists, set the flag override_existing to true if you want to override it"
|
||||
%self.directory)
|
||||
|
||||
% self.directory)
|
||||
|
||||
tmpl = open(CNTK_TRAIN_TEMPLATE_PATH, "r").read()
|
||||
model_filename = os.path.join(model_dir, self.name)
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
if reader:
|
||||
readers.append(reader)
|
||||
|
||||
|
@ -138,17 +139,17 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
def _generate_test_config(self, reader):
|
||||
'''
|
||||
Generates the configuration file for the test action.
|
||||
'''
|
||||
'''
|
||||
tmpl = open(CNTK_TEST_TEMPLATE_PATH, "r").read()
|
||||
model_filename = os.path.join(self.directory, 'Models', self.name)
|
||||
|
||||
# if no reader is passed generate the reader from the network
|
||||
if reader:
|
||||
reader_config = reader.generate_config()
|
||||
else:
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
reader_config = '\n'.join(r.generate_config() for r in readers)
|
||||
|
||||
else:
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
reader_config = '\n'.join(r.generate_config() for r in readers)
|
||||
|
||||
tmpl_dict = {
|
||||
'DevideId': self.device_id,
|
||||
'ModelPath': model_filename,
|
||||
|
@ -163,14 +164,15 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
'''
|
||||
tmpl = open(CNTK_PREDICT_TEMPLATE_PATH, "r").read()
|
||||
model_filename = os.path.join(self.directory, 'Models', self.name)
|
||||
output_filename_base = os.path.join(self.directory, 'Outputs', self.name)
|
||||
output_filename_base = os.path.join(
|
||||
self.directory, 'Outputs', self.name)
|
||||
|
||||
# if no reader is passed generate the reader from the network
|
||||
if reader:
|
||||
reader_config = reader.generate_config()
|
||||
else:
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
reader_config = '\n'.join(r.generate_config() for r in readers)
|
||||
else:
|
||||
description, has_inputs, readers = self.root_node.to_config()
|
||||
reader_config = '\n'.join(r.generate_config() for r in readers)
|
||||
|
||||
tmpl_dict = {
|
||||
'DevideId': self.device_id,
|
||||
|
@ -179,13 +181,13 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
'Reader': reader_config,
|
||||
}
|
||||
return tmpl % tmpl_dict
|
||||
|
||||
|
||||
def _generate_eval_config(self, root_node, reader):
|
||||
'''
|
||||
Generates the configuration file for write action.
|
||||
:param root_node: the node to evaluate.
|
||||
:param reader: the reader used to load the data, None if the network does not have input
|
||||
'''
|
||||
'''
|
||||
model_description, has_input, readers = root_node.to_config()
|
||||
if reader:
|
||||
readers.append(reader)
|
||||
|
@ -199,14 +201,14 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
reader = NumPyReader(data, fn)
|
||||
from .ops.cntk1 import Input
|
||||
dummy_input_node = Input(2, var_name='dummy_node')
|
||||
reader.add_input(dummy_input_node, 0, 2)
|
||||
reader.add_input(dummy_input_node, 0, 2)
|
||||
model_description += "dummy_node = Input(2, tag='output')"
|
||||
readers.append(reader)
|
||||
|
||||
tmpl = open(CNTK_EVAL_TEMPLATE_PATH, "r").read()
|
||||
output_filename = os.path.join(self.directory, CNTK_OUTPUT_FILENAME)
|
||||
tmpl_dict = {
|
||||
'DevideId': self.device_id,
|
||||
'DevideId': self.device_id,
|
||||
'OutputFile': output_filename,
|
||||
'ModelDescription': model_description,
|
||||
'Reader': '\n'.join(r.generate_config() for r in readers),
|
||||
|
@ -214,7 +216,7 @@ class AbstractContext(object, metaclass=ABCMeta):
|
|||
return tmpl % tmpl_dict
|
||||
|
||||
@abstractmethod
|
||||
def train(self, optimizer, reader=None, override_existing = True):
|
||||
def train(self, optimizer, reader=None, override_existing=True):
|
||||
'''
|
||||
Abstract method for the action train.
|
||||
:param reader: the reader to use for this action. Alternatively, you
|
||||
|
@ -289,7 +291,7 @@ class Context(AbstractContext):
|
|||
|
||||
return output.decode("utf-8")
|
||||
|
||||
def train(self, optimizer, reader=None, override_existing = True):
|
||||
def train(self, optimizer, reader=None, override_existing=True):
|
||||
'''
|
||||
Run the train action locally.
|
||||
:param optimizer: the SGD optimizer to use for training
|
||||
|
@ -297,7 +299,8 @@ class Context(AbstractContext):
|
|||
can attach a reader directly to the input node.
|
||||
:param override_existing: if the folder exists already override it
|
||||
'''
|
||||
config_content = self._generate_train_config(optimizer, reader, override_existing)
|
||||
config_content = self._generate_train_config(
|
||||
optimizer, reader, override_existing)
|
||||
return self._call_cntk(CNTK_TRAIN_CONFIG_FILENAME, config_content)
|
||||
|
||||
def test(self, reader=None):
|
||||
|
@ -324,7 +327,8 @@ class Context(AbstractContext):
|
|||
Regular expression to parse the shape information of the nodes out of
|
||||
CNTK's output
|
||||
'''
|
||||
VAR_SHAPE_REGEX = re.compile('^Validating --> (?P<var_name>[^ ]+) = [^>]*> \[(?P<shape>[^]]+)')
|
||||
VAR_SHAPE_REGEX = re.compile(
|
||||
'^Validating --> (?P<var_name>[^ ]+) = [^>]*> \[(?P<shape>[^]]+)')
|
||||
SHAPE_STRIDE_REGEX = re.compile('\{.*?\}')
|
||||
|
||||
@staticmethod
|
||||
|
@ -349,7 +353,7 @@ class Context(AbstractContext):
|
|||
var_shape[var_name] = tuple(shape_list)
|
||||
|
||||
return var_shape
|
||||
|
||||
|
||||
def _eval(self, node, reader):
|
||||
# FIXME manually setting the tag to output might have side-effects
|
||||
node.tag = 'output'
|
||||
|
@ -357,7 +361,8 @@ class Context(AbstractContext):
|
|||
output = self._call_cntk(CNTK_EVAL_CONFIG_FILENAME, config_content)
|
||||
shapes = Context._parse_shapes_from_output(output)
|
||||
|
||||
out_name = os.path.join(self.directory, CNTK_OUTPUT_FILENAME + '.' + node.var_name)
|
||||
out_name = os.path.join(
|
||||
self.directory, CNTK_OUTPUT_FILENAME + '.' + node.var_name)
|
||||
data = np.loadtxt(out_name)
|
||||
|
||||
return data, shapes
|
||||
|
@ -374,7 +379,8 @@ class Context(AbstractContext):
|
|||
Returns the output generated by `node`
|
||||
'''
|
||||
if not isinstance(node, ComputationNode):
|
||||
raise ValueError('node is not of type ComputationNode, but %s'%type(node))
|
||||
raise ValueError(
|
||||
'node is not of type ComputationNode, but %s' % type(node))
|
||||
|
||||
data, shapes = self._eval(node, reader)
|
||||
|
||||
|
@ -382,7 +388,7 @@ class Context(AbstractContext):
|
|||
expected_shape = shapes[node.var_name]
|
||||
|
||||
receieved_all = data.size == expected_size
|
||||
if not receieved_all:
|
||||
if not receieved_all:
|
||||
# For some reason the CNTK write action has issues with multi-row
|
||||
# output. So we have to CNTK reshape it to one row and do it again,
|
||||
# but then NumPy reshape using node's expected shape.
|
||||
|
@ -390,15 +396,16 @@ class Context(AbstractContext):
|
|||
reshaped = NewReshape(node, expected_size)
|
||||
data, _ = self._eval(reshaped, reader)
|
||||
|
||||
if not (len(expected_shape)==2 and expected_shape[1] == 1):
|
||||
if not (len(expected_shape) == 2 and expected_shape[1] == 1):
|
||||
# CNTK outputs e.g. [2 x 1] although it is just a vector.
|
||||
# TODO find better way to distinguis between
|
||||
# TODO find better way to distinguis between
|
||||
data = data.reshape(expected_shape)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class ClusterContext(AbstractContext):
|
||||
|
||||
'''
|
||||
This is a sub-class of AbstractContext, use it to submit your workloads to the cluster.
|
||||
'''
|
||||
|
|
|
@ -8,7 +8,7 @@ from cntk import *
|
|||
|
||||
if (__name__ == "__main__"):
|
||||
|
||||
X = constant(np.asarray([[2,3], [4,5]]))
|
||||
X = constant(np.asarray([[2, 3], [4, 5]]))
|
||||
out = 2.5 * X + 100
|
||||
|
||||
with Context('demo', clean_up=False) as ctx:
|
||||
|
|
|
@ -7,10 +7,11 @@ from cntk import *
|
|||
if (__name__ == "__main__"):
|
||||
X = Input(2)
|
||||
X.attach_uci_fast_reader("Train-3Classes.txt", 0)
|
||||
|
||||
|
||||
y = Input(3)
|
||||
y.attach_uci_fast_reader("Train-3Classes.txt", 2, True, 1, "SimpleMapping-3Classes.txt")
|
||||
|
||||
y.attach_uci_fast_reader(
|
||||
"Train-3Classes.txt", 2, True, 1, "SimpleMapping-3Classes.txt")
|
||||
|
||||
W = LearnableParameter(3, 2)
|
||||
b = LearnableParameter(3, 1)
|
||||
|
||||
|
@ -26,4 +27,4 @@ if (__name__ == "__main__"):
|
|||
ctx.train(my_sgd, None)
|
||||
|
||||
#result = ctx.eval(out)
|
||||
#print(result.argmax(axis=1))
|
||||
# print(result.argmax(axis=1))
|
||||
|
|
|
@ -4,10 +4,11 @@ import os
|
|||
import struct
|
||||
import numpy as np
|
||||
|
||||
|
||||
def loadData(src, cimg):
|
||||
print ('Downloading ' + src)
|
||||
print('Downloading ' + src)
|
||||
gzfname, h = urllib.request.urlretrieve(src, './delete.me')
|
||||
print ('Done.')
|
||||
print('Done.')
|
||||
try:
|
||||
with gzip.open(gzfname) as gz:
|
||||
n = struct.unpack('I', gz.read(4))
|
||||
|
@ -17,21 +18,24 @@ def loadData(src, cimg):
|
|||
# Read number of entries.
|
||||
n = struct.unpack('>I', gz.read(4))[0]
|
||||
if n != cimg:
|
||||
raise Exception('Invalid file: expected {0} entries.'.format(cimg))
|
||||
raise Exception(
|
||||
'Invalid file: expected {0} entries.'.format(cimg))
|
||||
crow = struct.unpack('>I', gz.read(4))[0]
|
||||
ccol = struct.unpack('>I', gz.read(4))[0]
|
||||
if crow != 28 or ccol != 28:
|
||||
raise Exception('Invalid file: expected 28 rows/cols per image.')
|
||||
raise Exception(
|
||||
'Invalid file: expected 28 rows/cols per image.')
|
||||
# Read data.
|
||||
res = np.fromstring(gz.read(cimg * crow * ccol), dtype = np.uint8)
|
||||
res = np.fromstring(gz.read(cimg * crow * ccol), dtype=np.uint8)
|
||||
finally:
|
||||
os.remove(gzfname)
|
||||
return res.reshape((cimg, crow * ccol))
|
||||
|
||||
|
||||
def loadLabels(src, cimg):
|
||||
print ('Downloading ' + src)
|
||||
print('Downloading ' + src)
|
||||
gzfname, h = urllib.request.urlretrieve(src, './delete.me')
|
||||
print ('Done.')
|
||||
print('Done.')
|
||||
try:
|
||||
with gzip.open(gzfname) as gz:
|
||||
n = struct.unpack('I', gz.read(4))
|
||||
|
@ -41,26 +45,31 @@ def loadLabels(src, cimg):
|
|||
# Read number of entries.
|
||||
n = struct.unpack('>I', gz.read(4))
|
||||
if n[0] != cimg:
|
||||
raise Exception('Invalid file: expected {0} rows.'.format(cimg))
|
||||
raise Exception(
|
||||
'Invalid file: expected {0} rows.'.format(cimg))
|
||||
# Read labels.
|
||||
res = np.fromstring(gz.read(cimg), dtype = np.uint8)
|
||||
res = np.fromstring(gz.read(cimg), dtype=np.uint8)
|
||||
finally:
|
||||
os.remove(gzfname)
|
||||
return res.reshape((cimg, 1))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
trnData = loadData('http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz', 60000)
|
||||
trnLbl = loadLabels('http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz', 60000)
|
||||
trnData = loadData(
|
||||
'http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz', 60000)
|
||||
trnLbl = loadLabels(
|
||||
'http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz', 60000)
|
||||
trn = np.hstack((trnLbl, trnData))
|
||||
if not os.path.exists('./Data'):
|
||||
os.mkdir('./Data')
|
||||
print ('Writing train text file...')
|
||||
np.savetxt(r'./Data/Train-28x28.txt', trn, fmt = '%u', delimiter='\t')
|
||||
print ('Done.')
|
||||
testData = loadData('http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz', 10000)
|
||||
testLbl = loadLabels('http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz', 10000)
|
||||
print('Writing train text file...')
|
||||
np.savetxt(r'./Data/Train-28x28.txt', trn, fmt='%u', delimiter='\t')
|
||||
print('Done.')
|
||||
testData = loadData(
|
||||
'http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz', 10000)
|
||||
testLbl = loadLabels(
|
||||
'http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz', 10000)
|
||||
test = np.hstack((testLbl, testData))
|
||||
print ('Writing test text file...')
|
||||
np.savetxt(r'./Data/Test-28x28.txt', test, fmt = '%u', delimiter='\t')
|
||||
print ('Done.')
|
||||
print('Writing test text file...')
|
||||
np.savetxt(r'./Data/Test-28x28.txt', test, fmt='%u', delimiter='\t')
|
||||
print('Done.')
|
||||
|
|
|
@ -8,55 +8,59 @@ from cntk import *
|
|||
# MNIST Example, one hidden layer neural network
|
||||
# =====================================================================================
|
||||
|
||||
|
||||
def dnn_sigmoid_layer(in_dim, out_dim, x, param_scale):
|
||||
W = LearnableParameter(out_dim, in_dim, initValueScale=param_scale)
|
||||
b = LearnableParameter(out_dim, 1, initValueScale=param_scale)
|
||||
W = LearnableParameter(out_dim, in_dim, initValueScale=param_scale)
|
||||
b = LearnableParameter(out_dim, 1, initValueScale=param_scale)
|
||||
t = Times(W, x)
|
||||
z = Plus(t, b)
|
||||
return Sigmoid(z)
|
||||
|
||||
|
||||
def dnn_layer(in_dim, out_dim, x, param_scale):
|
||||
W = LearnableParameter(out_dim, in_dim, initValueScale=param_scale)
|
||||
b = LearnableParameter(out_dim, 1, initValueScale=param_scale)
|
||||
t = Times(W, x)
|
||||
return Plus(t, b)
|
||||
|
||||
|
||||
if (__name__ == "__main__"):
|
||||
|
||||
# Network definition
|
||||
feat_dim=784
|
||||
label_dim=10
|
||||
hidden_dim=200
|
||||
|
||||
training_filename=os.path.join("Data", "Train-28x28.txt")
|
||||
test_filename=os.path.join("Data", "Test-28x28.txt")
|
||||
|
||||
|
||||
# Network definition
|
||||
feat_dim = 784
|
||||
label_dim = 10
|
||||
hidden_dim = 200
|
||||
|
||||
training_filename = os.path.join("Data", "Train-28x28.txt")
|
||||
test_filename = os.path.join("Data", "Test-28x28.txt")
|
||||
|
||||
features = Input(feat_dim, var_name='features')
|
||||
features.attach_uci_fast_reader(training_filename, 1)
|
||||
|
||||
|
||||
feat_scale = Constant(0.00390625)
|
||||
feats_scaled = Scale(feat_scale, features)
|
||||
|
||||
|
||||
labels = Input(label_dim, tag='label', var_name='labels')
|
||||
labels.attach_uci_fast_reader(training_filename, 0, True, 1, os.path.join("Data", "labelsmap.txt"))
|
||||
|
||||
h1 = dnn_sigmoid_layer(feat_dim, hidden_dim, feats_scaled, 1)
|
||||
labels.attach_uci_fast_reader(
|
||||
training_filename, 0, True, 1, os.path.join("Data", "labelsmap.txt"))
|
||||
|
||||
h1 = dnn_sigmoid_layer(feat_dim, hidden_dim, feats_scaled, 1)
|
||||
out = dnn_layer(hidden_dim, label_dim, h1, 1)
|
||||
out.tag = 'output'
|
||||
|
||||
ec = CrossEntropyWithSoftmax(labels, out)
|
||||
ec.tag = 'criterion'
|
||||
|
||||
# Build the optimizer (settings are scaled down)
|
||||
my_sgd = SGD(epoch_size = 600, minibatch_size = 32, learning_ratesPerMB = 0.1, max_epochs = 5, momentum_per_mb = 0)
|
||||
|
||||
# Create a context or re-use if already there
|
||||
with Context('mnist_one_layer', root_node= ec, clean_up=False) as ctx:
|
||||
# CNTK actions
|
||||
#ctx.train(my_sgd)
|
||||
features.attach_uci_fast_reader(test_filename, 1)
|
||||
labels.attach_uci_fast_reader(test_filename, 0, True, 1, os.path.join("Data", "labelsmap.txt"))
|
||||
ctx.predict()
|
||||
ctx.test()
|
||||
ctx.predict()
|
||||
|
||||
ec = CrossEntropyWithSoftmax(labels, out)
|
||||
ec.tag = 'criterion'
|
||||
|
||||
# Build the optimizer (settings are scaled down)
|
||||
my_sgd = SGD(epoch_size=600, minibatch_size=32,
|
||||
learning_ratesPerMB=0.1, max_epochs=5, momentum_per_mb=0)
|
||||
|
||||
# Create a context or re-use if already there
|
||||
with Context('mnist_one_layer', root_node=ec, clean_up=False) as ctx:
|
||||
# CNTK actions
|
||||
# ctx.train(my_sgd)
|
||||
features.attach_uci_fast_reader(test_filename, 1)
|
||||
labels.attach_uci_fast_reader(
|
||||
test_filename, 0, True, 1, os.path.join("Data", "labelsmap.txt"))
|
||||
ctx.predict()
|
||||
ctx.test()
|
||||
ctx.predict()
|
||||
|
|
|
@ -2,13 +2,16 @@ from abc import ABCMeta, abstractmethod
|
|||
import numpy as np
|
||||
import scipy.sparse as sparse
|
||||
|
||||
|
||||
def _tuple_to_cntk_shape(shape):
|
||||
return ':'.join(str(v) for v in shape)
|
||||
|
||||
# Indent model description by how many spaces
|
||||
MODEL_INDENTATION = 8
|
||||
|
||||
|
||||
class ComputationNode(object):
|
||||
|
||||
'''
|
||||
Base class for all nodes and operators. Provides a NumPy-like interface
|
||||
with operators that are converted to CNTK operators.
|
||||
|
@ -16,22 +19,24 @@ class ComputationNode(object):
|
|||
|
||||
def __init__(self, name, params=None, var_name=None, reader=None):
|
||||
if not isinstance(name, str):
|
||||
raise ValueError("Parameter 'name' has to be a string and not '%s'"%type(name))
|
||||
raise ValueError(
|
||||
"Parameter 'name' has to be a string and not '%s'" % type(name))
|
||||
if var_name is not None and not isinstance(var_name, str):
|
||||
raise ValueError("Parameter 'var_name' has to be a string and not '%s'"%type(var_name))
|
||||
|
||||
raise ValueError(
|
||||
"Parameter 'var_name' has to be a string and not '%s'" % type(var_name))
|
||||
|
||||
self.name = name
|
||||
self.params = params
|
||||
self.var_name = var_name
|
||||
self.var_name = var_name
|
||||
self.consumers = []
|
||||
for p in self.params:
|
||||
if hasattr(p, 'consumers'):
|
||||
p.consumers.append(self)
|
||||
|
||||
|
||||
self.reader = None
|
||||
|
||||
|
||||
def _is_input(self):
|
||||
return isinstance(self, InputComputationNodeBase)
|
||||
return isinstance(self, InputComputationNodeBase)
|
||||
|
||||
def __add__(self, other):
|
||||
if not isinstance(other, ComputationNode):
|
||||
|
@ -132,7 +137,7 @@ class ComputationNode(object):
|
|||
return param
|
||||
|
||||
def _to_config_recursively(self, desc, unrolled_nodes, inputs,
|
||||
readers, node_counter=0):
|
||||
readers, node_counter=0):
|
||||
param_variable_names = []
|
||||
if self.params:
|
||||
for p_name in self.params:
|
||||
|
@ -146,7 +151,7 @@ class ComputationNode(object):
|
|||
# Special treatment for special operator.
|
||||
# Used like RowStack(v0:v1:v2)
|
||||
inputs_param = p_value
|
||||
else:
|
||||
else:
|
||||
inputs_param = [p_value]
|
||||
|
||||
input_nodes_vars = []
|
||||
|
@ -161,7 +166,8 @@ class ComputationNode(object):
|
|||
unrolled_nodes[pv] = child_var
|
||||
input_nodes_vars.append(child_var)
|
||||
|
||||
param_variable_names.append(_tuple_to_cntk_shape(input_nodes_vars))
|
||||
param_variable_names.append(
|
||||
_tuple_to_cntk_shape(input_nodes_vars))
|
||||
else:
|
||||
param_variable_names.append(
|
||||
self._param_to_brainscript(p_name, p_value))
|
||||
|
@ -180,7 +186,8 @@ class ComputationNode(object):
|
|||
|
||||
params = self._get_cntk_param_string(param_variable_names)
|
||||
|
||||
line = ' '*MODEL_INDENTATION + "%s = %s(%s)" % (self.var_name, self.name, params)
|
||||
line = ' ' * MODEL_INDENTATION + \
|
||||
"%s = %s(%s)" % (self.var_name, self.name, params)
|
||||
desc.append(line)
|
||||
|
||||
return self.var_name, node_counter, desc
|
||||
|
@ -190,28 +197,28 @@ class ComputationNode(object):
|
|||
Helper method to generate the CNTK configuration for this node.
|
||||
'''
|
||||
unrolled_nodes = {}
|
||||
inputs=set()
|
||||
readers=set()
|
||||
inputs = set()
|
||||
readers = set()
|
||||
var_name, node_counter, desc = self._to_config_recursively(
|
||||
desc=[],
|
||||
unrolled_nodes=unrolled_nodes,
|
||||
desc=[],
|
||||
unrolled_nodes=unrolled_nodes,
|
||||
inputs=inputs,
|
||||
readers=readers)
|
||||
|
||||
return var_name, node_counter, desc, len(inputs)>0, readers
|
||||
|
||||
return var_name, node_counter, desc, len(inputs) > 0, readers
|
||||
|
||||
def _dedupe_readers(self, readers):
|
||||
import copy
|
||||
readers_map = {}
|
||||
for r in readers:
|
||||
filename = r['FileName']
|
||||
if filename in readers_map:
|
||||
readers_map = {}
|
||||
for r in readers:
|
||||
filename = r['FileName']
|
||||
if filename in readers_map:
|
||||
readers_map[filename].inputs_def.extend(r.inputs_def)
|
||||
else:
|
||||
readers_map[filename] = copy.deepcopy(r)
|
||||
|
||||
|
||||
return [r for r in readers_map.values()]
|
||||
|
||||
|
||||
def to_config(self):
|
||||
'''
|
||||
Generate CNTK configuration for this node including the configuration
|
||||
|
@ -221,52 +228,57 @@ class ComputationNode(object):
|
|||
|
||||
return "\n".join(desc), has_inputs, self._dedupe_readers(readers)
|
||||
|
||||
|
||||
class InputComputationNodeBase(ComputationNode, metaclass=ABCMeta):
|
||||
|
||||
'''
|
||||
Base class for all non-image input nodes nodes and operators. Provides methods to attach
|
||||
a reader to an input node
|
||||
'''
|
||||
|
||||
|
||||
def attach_text_format_reader(self, filename, input_alias=None, format='dense'):
|
||||
'''
|
||||
attach a TextFormatReader to the node
|
||||
'''
|
||||
self.reader = CNTKTextFormatReader(filename)
|
||||
self.reader.add_input(self, input_alias, self.dims, format)
|
||||
|
||||
def attach_uci_fast_reader(self,
|
||||
filename,
|
||||
input_start,
|
||||
islabel = False,
|
||||
num_label_cols=None,
|
||||
|
||||
def attach_uci_fast_reader(self,
|
||||
filename,
|
||||
input_start,
|
||||
islabel=False,
|
||||
num_label_cols=None,
|
||||
label_mapping_file=None,
|
||||
custom_delimiter=None):
|
||||
custom_delimiter=None):
|
||||
'''
|
||||
attach a UCIFastReader to the node
|
||||
'''
|
||||
self.reader = UCIFastReader(filename, custom_delimiter)
|
||||
|
||||
self.reader = UCIFastReader(filename, custom_delimiter)
|
||||
|
||||
if islabel:
|
||||
self.reader.add_input(self, input_start, num_label_cols, self.dims, label_mapping_file)
|
||||
self.reader.add_input(
|
||||
self, input_start, num_label_cols, self.dims, label_mapping_file)
|
||||
else:
|
||||
self.reader.add_input(self, input_start, self.dims)
|
||||
|
||||
|
||||
|
||||
class ImageInputComputationNodeBase(ComputationNode, metaclass=ABCMeta):
|
||||
|
||||
'''
|
||||
Base class for all image input nodes nodes and operators. Provides methods to attach
|
||||
a reader to an input node
|
||||
'''
|
||||
|
||||
|
||||
def attach_image_reader(self, filename, **kw):
|
||||
'''
|
||||
attach a TextFormatReader to the node
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
# importing after defining ComputationNode to work around circular imports
|
||||
from cntk.ops.cntk1 import *
|
||||
from cntk.ops import cntk1 as cntk1_ops # to have a separate namespace when we want to override below
|
||||
# to have a separate namespace when we want to override below
|
||||
from cntk.ops import cntk1 as cntk1_ops
|
||||
from .reader import UCIFastReader, CNTKTextFormatReader
|
||||
|
||||
# redefine some operators to work with NumPy and sequences as input
|
||||
|
@ -275,10 +287,12 @@ from .reader import UCIFastReader, CNTKTextFormatReader
|
|||
def _dense_seq_to_str(seq):
|
||||
return ' '.join(seq.astype(np.str))
|
||||
|
||||
|
||||
def _sparse_seq_to_str(seq):
|
||||
#return ' '.join('%s:%s'%(k,seq[k]) for k in sorted(seq.items()))
|
||||
# return ' '.join('%s:%s'%(k,seq[k]) for k in sorted(seq.items()))
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def _seq_to_text_format(sequences, alias):
|
||||
'''
|
||||
`sequences` is a NumPy array
|
||||
|
@ -292,14 +306,16 @@ def _seq_to_text_format(sequences, alias):
|
|||
elif sparse.issparse(first_elem):
|
||||
seq_to_str = _sparse_seq_to_str
|
||||
else:
|
||||
raise ValueError('sequence elements have to be of type numpy.ndarray (dense) or dictionary (sparse), you gave "%s"'%str(first_elem))
|
||||
raise ValueError(
|
||||
'sequence elements have to be of type numpy.ndarray (dense) or dictionary (sparse), you gave "%s"' % str(first_elem))
|
||||
|
||||
lines = []
|
||||
for idx, seq in enumerate(sequences):
|
||||
lines.append('%i|%s %s'%(idx, alias, seq_to_str(seq)))
|
||||
lines.append('%i|%s %s' % (idx, alias, seq_to_str(seq)))
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def _get_constant_node(value, **kw):
|
||||
'''
|
||||
This function creates a node that represents `value` as a constant tensor
|
||||
|
@ -316,14 +332,15 @@ def _get_constant_node(value, **kw):
|
|||
# of the overall context without having to always pass it
|
||||
# explicitly?
|
||||
|
||||
from cntk.context import get_context
|
||||
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 = tempfile.NamedTemporaryFile(
|
||||
prefix='_param_', suffix='.txt', dir=get_context().directory, delete=False)
|
||||
tf.close()
|
||||
|
||||
if isinstance(value, list):
|
||||
|
@ -331,7 +348,7 @@ def _get_constant_node(value, **kw):
|
|||
|
||||
if len(value.shape) == 1:
|
||||
# 1D list: interpret as one scalar per sample
|
||||
value = value[:,np.newaxis]
|
||||
value = value[:, np.newaxis]
|
||||
|
||||
if sparse.issparse(value):
|
||||
raise ValueError('only dense data is supported')
|
||||
|
@ -348,31 +365,33 @@ def _get_constant_node(value, **kw):
|
|||
|
||||
from cntk.reader import CNTKTextFormatReader
|
||||
param_node = cntk1_ops.LearnableParameter(
|
||||
size,
|
||||
1,
|
||||
learningRateMultiplier=0.0,
|
||||
init='fromFile',
|
||||
initFromFilePath=tf.name,
|
||||
**kw)
|
||||
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)
|
||||
dims=value.shape,
|
||||
var_name=var_name)
|
||||
|
||||
return reshape_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
|
||||
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)
|
||||
# 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):
|
||||
|
@ -380,14 +399,14 @@ def _get_input_node(value, **kw):
|
|||
|
||||
if len(value.shape) == 1:
|
||||
# 1D list: interpret as one scalar per sample
|
||||
value = value[:,np.newaxis]
|
||||
value = value[:, np.newaxis]
|
||||
|
||||
if 'alias' in kw:
|
||||
alias = kw['alias']
|
||||
del kw['alias'] # don't confuse with constructor's parameters
|
||||
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)
|
||||
alias = '_I_%i' % np.random.randint(1000)
|
||||
|
||||
with open(tf.name, 'w') as f:
|
||||
f.write(_seq_to_text_format(value, alias))
|
||||
|
@ -403,13 +422,15 @@ def _get_input_node(value, **kw):
|
|||
|
||||
return input_node
|
||||
|
||||
|
||||
def is_sequence(data):
|
||||
'''
|
||||
Checks whether the data is a CNTK sequence, which is expressed in Python as
|
||||
a list of varying sized NumPy objects.
|
||||
'''
|
||||
is_list = isinstance(data, list)
|
||||
return is_list and len(data)>0 and isinstance(data[0], np.ndarray)
|
||||
return is_list and len(data) > 0 and isinstance(data[0], np.ndarray)
|
||||
|
||||
|
||||
def is_tensor(data):
|
||||
'''
|
||||
|
@ -421,7 +442,7 @@ def is_tensor(data):
|
|||
if not isinstance(data, list):
|
||||
return False
|
||||
|
||||
while len(data)>0:
|
||||
while len(data) > 0:
|
||||
# All but the innermost dimension's values have to be lists
|
||||
try:
|
||||
data[0][0]
|
||||
|
@ -436,6 +457,7 @@ def is_tensor(data):
|
|||
|
||||
return True
|
||||
|
||||
|
||||
def input(value, **kw):
|
||||
'''
|
||||
Defining Input as a factory override that creates either a Constant()
|
||||
|
@ -446,7 +468,7 @@ def input(value, **kw):
|
|||
|
||||
In case the `value` is a list of NumPy arrays, a CNTK Input() operator is
|
||||
returned, interpreting every element as a sequence of tensors.
|
||||
|
||||
|
||||
In case the `value` is a NumPy array or list of lists, a CNTK Input()
|
||||
operator is returned, interpreting it as a dense tensor.
|
||||
|
||||
|
@ -455,7 +477,8 @@ def input(value, **kw):
|
|||
if is_sequence(value) or is_tensor(value):
|
||||
return _get_input_node(value, **kw)
|
||||
else:
|
||||
raise ValueError('value type is not supported: %s'%type(value))
|
||||
raise ValueError('value type is not supported: %s' % type(value))
|
||||
|
||||
|
||||
def constant(value, **kw):
|
||||
'''
|
||||
|
@ -467,7 +490,7 @@ def constant(value, **kw):
|
|||
|
||||
In case the `value` is a list of NumPy arrays, a CNTK Input() operator is
|
||||
returned, interpreting every element as a sequence of tensors.
|
||||
|
||||
|
||||
In case the `value` is a NumPy array or list of lists, a CNTK Input()
|
||||
operator is returned, interpreting it as a dense tensor.
|
||||
|
||||
|
@ -479,5 +502,4 @@ def constant(value, **kw):
|
|||
if is_tensor(value):
|
||||
return _get_constant_node(value, **kw)
|
||||
else:
|
||||
raise ValueError('value type is not supported: %s'%type(value))
|
||||
|
||||
raise ValueError('value type is not supported: %s' % type(value))
|
||||
|
|
|
@ -2,97 +2,134 @@
|
|||
|
||||
from cntk.graph import ComputationNode, InputComputationNodeBase, ImageInputComputationNodeBase
|
||||
|
||||
|
||||
class Print(ComputationNode):
|
||||
|
||||
def __init__(self, value, format='', name='Print', var_name=None):
|
||||
super(Print, self).__init__(params=['value', 'format'], name=name, var_name=var_name)
|
||||
super(Print, self).__init__(
|
||||
params=['value', 'format'], name=name, var_name=var_name)
|
||||
self.value = value
|
||||
self.format = format
|
||||
self.params_with_defaults = ['format']
|
||||
|
||||
|
||||
class Debug(ComputationNode):
|
||||
|
||||
def __init__(self, value, say='', enabled=True, name='Debug', var_name=None):
|
||||
super(Debug, self).__init__(params=['value', 'say', 'enabled'], name=name, var_name=var_name)
|
||||
super(Debug, self).__init__(
|
||||
params=['value', 'say', 'enabled'], name=name, var_name=var_name)
|
||||
self.value = value
|
||||
self.say = say
|
||||
self.enabled = enabled
|
||||
self.params_with_defaults = ['say', 'enabled']
|
||||
|
||||
|
||||
class Format(ComputationNode):
|
||||
|
||||
def __init__(self, value, format, name='Format', var_name=None):
|
||||
super(Format, self).__init__(params=['value', 'format'], name=name, var_name=var_name)
|
||||
super(Format, self).__init__(
|
||||
params=['value', 'format'], name=name, var_name=var_name)
|
||||
self.value = value
|
||||
self.format = format
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Replace(ComputationNode):
|
||||
|
||||
def __init__(self, s, from_, to, name='Replace', var_name=None):
|
||||
super(Replace, self).__init__(params=['s', 'from_', 'to'], name=name, var_name=var_name)
|
||||
super(Replace, self).__init__(
|
||||
params=['s', 'from_', 'to'], name=name, var_name=var_name)
|
||||
self.s = s
|
||||
self.from_ = from_
|
||||
self.to = to
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Substr(ComputationNode):
|
||||
|
||||
def __init__(self, s, begin, num, name='Substr', var_name=None):
|
||||
super(Substr, self).__init__(params=['s', 'begin', 'num'], name=name, var_name=var_name)
|
||||
super(Substr, self).__init__(
|
||||
params=['s', 'begin', 'num'], name=name, var_name=var_name)
|
||||
self.s = s
|
||||
self.begin = begin
|
||||
self.num = num
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Chr(ComputationNode):
|
||||
|
||||
def __init__(self, c, name='Chr', var_name=None):
|
||||
super(Chr, self).__init__(params=['c'], name=name, var_name=var_name)
|
||||
self.c = c
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Length(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Length', var_name=None):
|
||||
super(Length, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
super(Length, self).__init__(
|
||||
params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Ceil(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Ceil', var_name=None):
|
||||
super(Ceil, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Round(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Round', var_name=None):
|
||||
super(Round, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Sign(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Sign', var_name=None):
|
||||
super(Sign, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Min(ComputationNode):
|
||||
|
||||
def __init__(self, a, b, name='Min', var_name=None):
|
||||
super(Min, self).__init__(params=['a', 'b'], name=name, var_name=var_name)
|
||||
super(Min, self).__init__(
|
||||
params=['a', 'b'], name=name, var_name=var_name)
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Max(ComputationNode):
|
||||
|
||||
def __init__(self, a, b, name='Max', var_name=None):
|
||||
super(Max, self).__init__(params=['a', 'b'], name=name, var_name=var_name)
|
||||
super(Max, self).__init__(
|
||||
params=['a', 'b'], name=name, var_name=var_name)
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Fac(ComputationNode):
|
||||
|
||||
def __init__(self, n, name='Fac', var_name=None):
|
||||
super(Fac, self).__init__(params=['n'], name=name, var_name=var_name)
|
||||
self.n = n
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class LearnableParameter(ComputationNode):
|
||||
|
||||
def __init__(self, rows, cols, learningRateMultiplier=1.0, init='uniform', initValueScale=1, value=0, initFromFilePath='', initOnCPUOnly=True, randomSeed=-1, name='LearnableParameter', var_name=None):
|
||||
super(LearnableParameter, self).__init__(params=['rows', 'cols', 'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed'], name=name, var_name=var_name)
|
||||
super(LearnableParameter, self).__init__(params=[
|
||||
'rows', 'cols', 'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed'], name=name, var_name=var_name)
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
self.learningRateMultiplier = learningRateMultiplier
|
||||
|
@ -102,11 +139,15 @@ class LearnableParameter(ComputationNode):
|
|||
self.initFromFilePath = initFromFilePath
|
||||
self.initOnCPUOnly = initOnCPUOnly
|
||||
self.randomSeed = randomSeed
|
||||
self.params_with_defaults = ['learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed']
|
||||
self.params_with_defaults = [
|
||||
'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed']
|
||||
|
||||
|
||||
class ParameterTensor(ComputationNode):
|
||||
|
||||
def __init__(self, dims, learningRateMultiplier=1.0, init='uniform', initValueScale=1, value=0, initFromFilePath='', initOnCPUOnly=True, randomSeed=-1, name='ParameterTensor', var_name=None):
|
||||
super(ParameterTensor, self).__init__(params=['dims', 'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed'], name=name, var_name=var_name)
|
||||
super(ParameterTensor, self).__init__(params=[
|
||||
'dims', 'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed'], name=name, var_name=var_name)
|
||||
self.dims = dims
|
||||
self.learningRateMultiplier = learningRateMultiplier
|
||||
self.init = init
|
||||
|
@ -115,25 +156,35 @@ class ParameterTensor(ComputationNode):
|
|||
self.initFromFilePath = initFromFilePath
|
||||
self.initOnCPUOnly = initOnCPUOnly
|
||||
self.randomSeed = randomSeed
|
||||
self.params_with_defaults = ['learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed']
|
||||
self.params_with_defaults = [
|
||||
'learningRateMultiplier', 'init', 'initValueScale', 'value', 'initFromFilePath', 'initOnCPUOnly', 'randomSeed']
|
||||
|
||||
|
||||
class Input(InputComputationNodeBase):
|
||||
|
||||
def __init__(self, dims, tag='feature', name='Input', var_name=None):
|
||||
super(Input, self).__init__(params=['dims', 'tag'], name=name, var_name=var_name)
|
||||
super(Input, self).__init__(
|
||||
params=['dims', 'tag'], name=name, var_name=var_name)
|
||||
self.dims = dims
|
||||
self.tag = tag
|
||||
self.params_with_defaults = ['tag']
|
||||
|
||||
|
||||
class SparseInput(InputComputationNodeBase):
|
||||
|
||||
def __init__(self, dims, tag='feature', name='SparseInput', var_name=None):
|
||||
super(SparseInput, self).__init__(params=['dims', 'tag'], name=name, var_name=var_name)
|
||||
super(SparseInput, self).__init__(
|
||||
params=['dims', 'tag'], name=name, var_name=var_name)
|
||||
self.dims = dims
|
||||
self.tag = tag
|
||||
self.params_with_defaults = ['tag']
|
||||
|
||||
|
||||
class ImageInput(ImageInputComputationNodeBase):
|
||||
|
||||
def __init__(self, imageWidth, imageHeight, imageChannels, imageLayout='CHW', tag='feature', name='ImageInput', var_name=None):
|
||||
super(ImageInput, self).__init__(params=['imageWidth', 'imageHeight', 'imageChannels', 'imageLayout', 'tag'], name=name, var_name=var_name)
|
||||
super(ImageInput, self).__init__(params=[
|
||||
'imageWidth', 'imageHeight', 'imageChannels', 'imageLayout', 'tag'], name=name, var_name=var_name)
|
||||
self.imageWidth = imageWidth
|
||||
self.imageHeight = imageHeight
|
||||
self.imageChannels = imageChannels
|
||||
|
@ -141,9 +192,12 @@ class ImageInput(ImageInputComputationNodeBase):
|
|||
self.tag = tag
|
||||
self.params_with_defaults = ['imageLayout', 'tag']
|
||||
|
||||
|
||||
class SparseImageInput(ImageInputComputationNodeBase):
|
||||
|
||||
def __init__(self, imageWidth, imageHeight, imageChannels, imageLayout='CHW', tag='feature', name='SparseImageInput', var_name=None):
|
||||
super(SparseImageInput, self).__init__(params=['imageWidth', 'imageHeight', 'imageChannels', 'imageLayout', 'tag'], name=name, var_name=var_name)
|
||||
super(SparseImageInput, self).__init__(params=[
|
||||
'imageWidth', 'imageHeight', 'imageChannels', 'imageLayout', 'tag'], name=name, var_name=var_name)
|
||||
self.imageWidth = imageWidth
|
||||
self.imageHeight = imageHeight
|
||||
self.imageChannels = imageChannels
|
||||
|
@ -151,33 +205,45 @@ class SparseImageInput(ImageInputComputationNodeBase):
|
|||
self.tag = tag
|
||||
self.params_with_defaults = ['imageLayout', 'tag']
|
||||
|
||||
|
||||
class EnvironmentInput(ComputationNode):
|
||||
|
||||
def __init__(self, propertyName, name='EnvironmentInput', var_name=None):
|
||||
super(EnvironmentInput, self).__init__(params=['propertyName'], name=name, var_name=var_name)
|
||||
super(EnvironmentInput, self).__init__(
|
||||
params=['propertyName'], name=name, var_name=var_name)
|
||||
self.propertyName = propertyName
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class PastValue(ComputationNode):
|
||||
|
||||
def __init__(self, dims, input, timeStep=1, defaultHiddenActivation=0.1, name='PastValue', var_name=None):
|
||||
super(PastValue, self).__init__(params=['dims', 'input', 'timeStep', 'defaultHiddenActivation'], name=name, var_name=var_name)
|
||||
super(PastValue, self).__init__(params=[
|
||||
'dims', 'input', 'timeStep', 'defaultHiddenActivation'], name=name, var_name=var_name)
|
||||
self.dims = dims
|
||||
self.input = input
|
||||
self.timeStep = timeStep
|
||||
self.defaultHiddenActivation = defaultHiddenActivation
|
||||
self.params_with_defaults = ['timeStep', 'defaultHiddenActivation']
|
||||
|
||||
|
||||
class FutureValue(ComputationNode):
|
||||
|
||||
def __init__(self, dims, input, timeStep=1, defaultHiddenActivation=0.1, name='FutureValue', var_name=None):
|
||||
super(FutureValue, self).__init__(params=['dims', 'input', 'timeStep', 'defaultHiddenActivation'], name=name, var_name=var_name)
|
||||
super(FutureValue, self).__init__(params=[
|
||||
'dims', 'input', 'timeStep', 'defaultHiddenActivation'], name=name, var_name=var_name)
|
||||
self.dims = dims
|
||||
self.input = input
|
||||
self.timeStep = timeStep
|
||||
self.defaultHiddenActivation = defaultHiddenActivation
|
||||
self.params_with_defaults = ['timeStep', 'defaultHiddenActivation']
|
||||
|
||||
|
||||
class Shift(ComputationNode):
|
||||
|
||||
def __init__(self, input, fromOffset, boundaryValue, boundaryMode=-1, dim=-1, name='Shift', var_name=None):
|
||||
super(Shift, self).__init__(params=['input', 'fromOffset', 'boundaryValue', 'boundaryMode', 'dim'], name=name, var_name=var_name)
|
||||
super(Shift, self).__init__(params=[
|
||||
'input', 'fromOffset', 'boundaryValue', 'boundaryMode', 'dim'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.fromOffset = fromOffset
|
||||
self.boundaryValue = boundaryValue
|
||||
|
@ -185,87 +251,121 @@ class Shift(ComputationNode):
|
|||
self.dim = dim
|
||||
self.params_with_defaults = ['boundaryMode', 'dim']
|
||||
|
||||
|
||||
class RowSlice(ComputationNode):
|
||||
|
||||
def __init__(self, startIndex, numRows, input, name='RowSlice', var_name=None):
|
||||
super(RowSlice, self).__init__(params=['startIndex', 'numRows', 'input'], name=name, var_name=var_name)
|
||||
super(RowSlice, self).__init__(
|
||||
params=['startIndex', 'numRows', 'input'], name=name, var_name=var_name)
|
||||
self.startIndex = startIndex
|
||||
self.numRows = numRows
|
||||
self.input = input
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class RowRepeat(ComputationNode):
|
||||
|
||||
def __init__(self, input, numRepeats, name='RowRepeat', var_name=None):
|
||||
super(RowRepeat, self).__init__(params=['input', 'numRepeats'], name=name, var_name=var_name)
|
||||
super(RowRepeat, self).__init__(
|
||||
params=['input', 'numRepeats'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.numRepeats = numRepeats
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class RowStack(ComputationNode):
|
||||
|
||||
def __init__(self, inputs, name='RowStack', var_name=None):
|
||||
super(RowStack, self).__init__(params=['inputs'], name=name, var_name=var_name)
|
||||
super(RowStack, self).__init__(
|
||||
params=['inputs'], name=name, var_name=var_name)
|
||||
self.inputs = inputs
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Reshape(ComputationNode):
|
||||
|
||||
def __init__(self, input, numRows, imageWidth=0, imageHeight=0, imageChannels=0, name='Reshape', var_name=None):
|
||||
super(Reshape, self).__init__(params=['input', 'numRows', 'imageWidth', 'imageHeight', 'imageChannels'], name=name, var_name=var_name)
|
||||
super(Reshape, self).__init__(params=[
|
||||
'input', 'numRows', 'imageWidth', 'imageHeight', 'imageChannels'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.numRows = numRows
|
||||
self.imageWidth = imageWidth
|
||||
self.imageHeight = imageHeight
|
||||
self.imageChannels = imageChannels
|
||||
self.params_with_defaults = ['imageWidth', 'imageHeight', 'imageChannels']
|
||||
self.params_with_defaults = [
|
||||
'imageWidth', 'imageHeight', 'imageChannels']
|
||||
|
||||
|
||||
class NewReshape(ComputationNode):
|
||||
|
||||
def __init__(self, input, dims, beginDim=0, endDim=0, name='NewReshape', var_name=None):
|
||||
super(NewReshape, self).__init__(params=['input', 'dims', 'beginDim', 'endDim'], name=name, var_name=var_name)
|
||||
super(NewReshape, self).__init__(
|
||||
params=['input', 'dims', 'beginDim', 'endDim'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.dims = dims
|
||||
self.beginDim = beginDim
|
||||
self.endDim = endDim
|
||||
self.params_with_defaults = ['beginDim', 'endDim']
|
||||
|
||||
|
||||
class TransposeDimensions(ComputationNode):
|
||||
|
||||
def __init__(self, input, dim1, dim2, name='TransposeDimensions', var_name=None):
|
||||
super(TransposeDimensions, self).__init__(params=['input', 'dim1', 'dim2'], name=name, var_name=var_name)
|
||||
super(TransposeDimensions, self).__init__(
|
||||
params=['input', 'dim1', 'dim2'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.dim1 = dim1
|
||||
self.dim2 = dim2
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Times(ComputationNode):
|
||||
|
||||
def __init__(self, A, B, outputRank=1, name='Times', var_name=None):
|
||||
super(Times, self).__init__(params=['A', 'B', 'outputRank'], name=name, var_name=var_name)
|
||||
super(Times, self).__init__(
|
||||
params=['A', 'B', 'outputRank'], name=name, var_name=var_name)
|
||||
self.A = A
|
||||
self.B = B
|
||||
self.outputRank = outputRank
|
||||
self.params_with_defaults = ['outputRank']
|
||||
|
||||
|
||||
class Logistic(ComputationNode):
|
||||
|
||||
def __init__(self, label, probability, name='Logistic', var_name=None):
|
||||
super(Logistic, self).__init__(params=['label', 'probability'], name=name, var_name=var_name)
|
||||
super(Logistic, self).__init__(
|
||||
params=['label', 'probability'], name=name, var_name=var_name)
|
||||
self.label = label
|
||||
self.probability = probability
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class WeightedLogistic(ComputationNode):
|
||||
|
||||
def __init__(self, label, probability, instanceWeight, name='WeightedLogistic', var_name=None):
|
||||
super(WeightedLogistic, self).__init__(params=['label', 'probability', 'instanceWeight'], name=name, var_name=var_name)
|
||||
super(WeightedLogistic, self).__init__(
|
||||
params=['label', 'probability', 'instanceWeight'], name=name, var_name=var_name)
|
||||
self.label = label
|
||||
self.probability = probability
|
||||
self.instanceWeight = instanceWeight
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ReconcileMBLayout(ComputationNode):
|
||||
|
||||
def __init__(self, dataInput, layoutInput, name='ReconcileMBLayout', var_name=None):
|
||||
super(ReconcileMBLayout, self).__init__(params=['dataInput', 'layoutInput'], name=name, var_name=var_name)
|
||||
super(ReconcileMBLayout, self).__init__(
|
||||
params=['dataInput', 'layoutInput'], name=name, var_name=var_name)
|
||||
self.dataInput = dataInput
|
||||
self.layoutInput = layoutInput
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Convolution(ComputationNode):
|
||||
|
||||
def __init__(self, weightNode, inputValueNode, kernelWidth, kernelHeight, outputChannels, horizontalSubsample, verticalSubsample, zeroPadding=False, maxTempMemSizeInSamples=0, imageLayout='CHW', name='Convolution', var_name=None):
|
||||
super(Convolution, self).__init__(params=['weightNode', 'inputValueNode', 'kernelWidth', 'kernelHeight', 'outputChannels', 'horizontalSubsample', 'verticalSubsample', 'zeroPadding', 'maxTempMemSizeInSamples', 'imageLayout'], name=name, var_name=var_name)
|
||||
super(Convolution, self).__init__(params=['weightNode', 'inputValueNode', 'kernelWidth', 'kernelHeight', 'outputChannels',
|
||||
'horizontalSubsample', 'verticalSubsample', 'zeroPadding', 'maxTempMemSizeInSamples', 'imageLayout'], name=name, var_name=var_name)
|
||||
self.weightNode = weightNode
|
||||
self.inputValueNode = inputValueNode
|
||||
self.kernelWidth = kernelWidth
|
||||
|
@ -276,11 +376,15 @@ class Convolution(ComputationNode):
|
|||
self.zeroPadding = zeroPadding
|
||||
self.maxTempMemSizeInSamples = maxTempMemSizeInSamples
|
||||
self.imageLayout = imageLayout
|
||||
self.params_with_defaults = ['zeroPadding', 'maxTempMemSizeInSamples', 'imageLayout']
|
||||
self.params_with_defaults = [
|
||||
'zeroPadding', 'maxTempMemSizeInSamples', 'imageLayout']
|
||||
|
||||
|
||||
class MaxPooling(ComputationNode):
|
||||
|
||||
def __init__(self, input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayout='CHW', name='MaxPooling', var_name=None):
|
||||
super(MaxPooling, self).__init__(params=['input', 'windowWidth', 'windowHeight', 'horizontalSubsample', 'verticalSubsample', 'imageLayout'], name=name, var_name=var_name)
|
||||
super(MaxPooling, self).__init__(params=[
|
||||
'input', 'windowWidth', 'windowHeight', 'horizontalSubsample', 'verticalSubsample', 'imageLayout'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.windowWidth = windowWidth
|
||||
self.windowHeight = windowHeight
|
||||
|
@ -289,9 +393,12 @@ class MaxPooling(ComputationNode):
|
|||
self.imageLayout = imageLayout
|
||||
self.params_with_defaults = ['imageLayout']
|
||||
|
||||
|
||||
class AveragePooling(ComputationNode):
|
||||
|
||||
def __init__(self, input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayout='CHW', name='AveragePooling', var_name=None):
|
||||
super(AveragePooling, self).__init__(params=['input', 'windowWidth', 'windowHeight', 'horizontalSubsample', 'verticalSubsample', 'imageLayout'], name=name, var_name=var_name)
|
||||
super(AveragePooling, self).__init__(params=[
|
||||
'input', 'windowWidth', 'windowHeight', 'horizontalSubsample', 'verticalSubsample', 'imageLayout'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.windowWidth = windowWidth
|
||||
self.windowHeight = windowHeight
|
||||
|
@ -300,9 +407,12 @@ class AveragePooling(ComputationNode):
|
|||
self.imageLayout = imageLayout
|
||||
self.params_with_defaults = ['imageLayout']
|
||||
|
||||
|
||||
class BatchNormalization(ComputationNode):
|
||||
|
||||
def __init__(self, input, scale, bias, runMean, runInvStdDev, eval, spatial, normalizationTimeConstant=0, epsilon=1e-05, useCntkEngine=True, imageLayout='CHW', name='BatchNormalization', var_name=None):
|
||||
super(BatchNormalization, self).__init__(params=['input', 'scale', 'bias', 'runMean', 'runInvStdDev', 'eval', 'spatial', 'normalizationTimeConstant', 'epsilon', 'useCntkEngine', 'imageLayout'], name=name, var_name=var_name)
|
||||
super(BatchNormalization, self).__init__(params=['input', 'scale', 'bias', 'runMean', 'runInvStdDev', 'eval',
|
||||
'spatial', 'normalizationTimeConstant', 'epsilon', 'useCntkEngine', 'imageLayout'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.scale = scale
|
||||
self.bias = bias
|
||||
|
@ -314,287 +424,409 @@ class BatchNormalization(ComputationNode):
|
|||
self.epsilon = epsilon
|
||||
self.useCntkEngine = useCntkEngine
|
||||
self.imageLayout = imageLayout
|
||||
self.params_with_defaults = ['normalizationTimeConstant', 'epsilon', 'useCntkEngine', 'imageLayout']
|
||||
self.params_with_defaults = [
|
||||
'normalizationTimeConstant', 'epsilon', 'useCntkEngine', 'imageLayout']
|
||||
|
||||
|
||||
class Abs(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Abs', var_name=None):
|
||||
super(Abs, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ClassBasedCrossEntropyWithSoftmax(ComputationNode):
|
||||
|
||||
def __init__(self, labelClassDescriptorVectorSequence, mainInputInfo, mainWeight, classLogProbsBeforeSoftmax, name='ClassBasedCrossEntropyWithSoftmax', var_name=None):
|
||||
super(ClassBasedCrossEntropyWithSoftmax, self).__init__(params=['labelClassDescriptorVectorSequence', 'mainInputInfo', 'mainWeight', 'classLogProbsBeforeSoftmax'], name=name, var_name=var_name)
|
||||
super(ClassBasedCrossEntropyWithSoftmax, self).__init__(params=[
|
||||
'labelClassDescriptorVectorSequence', 'mainInputInfo', 'mainWeight', 'classLogProbsBeforeSoftmax'], name=name, var_name=var_name)
|
||||
self.labelClassDescriptorVectorSequence = labelClassDescriptorVectorSequence
|
||||
self.mainInputInfo = mainInputInfo
|
||||
self.mainWeight = mainWeight
|
||||
self.classLogProbsBeforeSoftmax = classLogProbsBeforeSoftmax
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ColumnElementTimes(ComputationNode):
|
||||
|
||||
def __init__(self, aVectorSequence, anotherVectorSequence, name='ColumnElementTimes', var_name=None):
|
||||
super(ColumnElementTimes, self).__init__(params=['aVectorSequence', 'anotherVectorSequence'], name=name, var_name=var_name)
|
||||
super(ColumnElementTimes, self).__init__(
|
||||
params=['aVectorSequence', 'anotherVectorSequence'], name=name, var_name=var_name)
|
||||
self.aVectorSequence = aVectorSequence
|
||||
self.anotherVectorSequence = anotherVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class CosDistance(ComputationNode):
|
||||
|
||||
def __init__(self, aVectorSequence, anotherVectorSequence, name='CosDistance', var_name=None):
|
||||
super(CosDistance, self).__init__(params=['aVectorSequence', 'anotherVectorSequence'], name=name, var_name=var_name)
|
||||
super(CosDistance, self).__init__(
|
||||
params=['aVectorSequence', 'anotherVectorSequence'], name=name, var_name=var_name)
|
||||
self.aVectorSequence = aVectorSequence
|
||||
self.anotherVectorSequence = anotherVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class CosDistanceWithNegativeSamples(ComputationNode):
|
||||
|
||||
def __init__(self, aVectorSequence, anotherVectorSequence, numShifts, numNegSamples, name='CosDistanceWithNegativeSamples', var_name=None):
|
||||
super(CosDistanceWithNegativeSamples, self).__init__(params=['aVectorSequence', 'anotherVectorSequence', 'numShifts', 'numNegSamples'], name=name, var_name=var_name)
|
||||
super(CosDistanceWithNegativeSamples, self).__init__(params=[
|
||||
'aVectorSequence', 'anotherVectorSequence', 'numShifts', 'numNegSamples'], name=name, var_name=var_name)
|
||||
self.aVectorSequence = aVectorSequence
|
||||
self.anotherVectorSequence = anotherVectorSequence
|
||||
self.numShifts = numShifts
|
||||
self.numNegSamples = numNegSamples
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Cosine(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Cosine', var_name=None):
|
||||
super(Cosine, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
super(Cosine, self).__init__(
|
||||
params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class CrossEntropy(ComputationNode):
|
||||
|
||||
def __init__(self, refProbVectorSequence, outProbVectorSequence, name='CrossEntropy', var_name=None):
|
||||
super(CrossEntropy, self).__init__(params=['refProbVectorSequence', 'outProbVectorSequence'], name=name, var_name=var_name)
|
||||
super(CrossEntropy, self).__init__(params=[
|
||||
'refProbVectorSequence', 'outProbVectorSequence'], name=name, var_name=var_name)
|
||||
self.refProbVectorSequence = refProbVectorSequence
|
||||
self.outProbVectorSequence = outProbVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class CrossEntropyWithSoftmax(ComputationNode):
|
||||
|
||||
def __init__(self, labelVectorSequence, outProbVectorSequence, name='CrossEntropyWithSoftmax', var_name=None):
|
||||
super(CrossEntropyWithSoftmax, self).__init__(params=['labelVectorSequence', 'outProbVectorSequence'], name=name, var_name=var_name)
|
||||
super(CrossEntropyWithSoftmax, self).__init__(params=[
|
||||
'labelVectorSequence', 'outProbVectorSequence'], name=name, var_name=var_name)
|
||||
self.labelVectorSequence = labelVectorSequence
|
||||
self.outProbVectorSequence = outProbVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class DiagTimes(ComputationNode):
|
||||
|
||||
def __init__(self, diagonalMatrixAsColumnVector, matrix, name='DiagTimes', var_name=None):
|
||||
super(DiagTimes, self).__init__(params=['diagonalMatrixAsColumnVector', 'matrix'], name=name, var_name=var_name)
|
||||
super(DiagTimes, self).__init__(
|
||||
params=['diagonalMatrixAsColumnVector', 'matrix'], name=name, var_name=var_name)
|
||||
self.diagonalMatrixAsColumnVector = diagonalMatrixAsColumnVector
|
||||
self.matrix = matrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Dropout(ComputationNode):
|
||||
|
||||
def __init__(self, activationVectorSequence, name='Dropout', var_name=None):
|
||||
super(Dropout, self).__init__(params=['activationVectorSequence'], name=name, var_name=var_name)
|
||||
super(Dropout, self).__init__(
|
||||
params=['activationVectorSequence'], name=name, var_name=var_name)
|
||||
self.activationVectorSequence = activationVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ElementTimes(ComputationNode):
|
||||
|
||||
def __init__(self, aMatrix, anotherMatrix, name='ElementTimes', var_name=None):
|
||||
super(ElementTimes, self).__init__(params=['aMatrix', 'anotherMatrix'], name=name, var_name=var_name)
|
||||
super(ElementTimes, self).__init__(
|
||||
params=['aMatrix', 'anotherMatrix'], name=name, var_name=var_name)
|
||||
self.aMatrix = aMatrix
|
||||
self.anotherMatrix = anotherMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ErrorPrediction(ComputationNode):
|
||||
|
||||
def __init__(self, labelVectorSequence, outVectorSequence, name='ErrorPrediction', var_name=None):
|
||||
super(ErrorPrediction, self).__init__(params=['labelVectorSequence', 'outVectorSequence'], name=name, var_name=var_name)
|
||||
super(ErrorPrediction, self).__init__(
|
||||
params=['labelVectorSequence', 'outVectorSequence'], name=name, var_name=var_name)
|
||||
self.labelVectorSequence = labelVectorSequence
|
||||
self.outVectorSequence = outVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Exp(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Exp', var_name=None):
|
||||
super(Exp, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class GatherPacked(ComputationNode):
|
||||
|
||||
def __init__(self, indexSequence, sourceData, name='GatherPacked', var_name=None):
|
||||
super(GatherPacked, self).__init__(params=['indexSequence', 'sourceData'], name=name, var_name=var_name)
|
||||
super(GatherPacked, self).__init__(
|
||||
params=['indexSequence', 'sourceData'], name=name, var_name=var_name)
|
||||
self.indexSequence = indexSequence
|
||||
self.sourceData = sourceData
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class GMMLogLikelihood(ComputationNode):
|
||||
|
||||
def __init__(self, unnormalizedPriorVector, meansAsRows, logStdDevAsRows, dataVectorSequence, name='GMMLogLikelihood', var_name=None):
|
||||
super(GMMLogLikelihood, self).__init__(params=['unnormalizedPriorVector', 'meansAsRows', 'logStdDevAsRows', 'dataVectorSequence'], name=name, var_name=var_name)
|
||||
super(GMMLogLikelihood, self).__init__(params=[
|
||||
'unnormalizedPriorVector', 'meansAsRows', 'logStdDevAsRows', 'dataVectorSequence'], name=name, var_name=var_name)
|
||||
self.unnormalizedPriorVector = unnormalizedPriorVector
|
||||
self.meansAsRows = meansAsRows
|
||||
self.logStdDevAsRows = logStdDevAsRows
|
||||
self.dataVectorSequence = dataVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class InvStdDev(ComputationNode):
|
||||
|
||||
def __init__(self, dataVectorSequence, name='InvStdDev', var_name=None):
|
||||
super(InvStdDev, self).__init__(params=['dataVectorSequence'], name=name, var_name=var_name)
|
||||
super(InvStdDev, self).__init__(
|
||||
params=['dataVectorSequence'], name=name, var_name=var_name)
|
||||
self.dataVectorSequence = dataVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class KhatriRaoProduct(ComputationNode):
|
||||
|
||||
def __init__(self, leftMatrix, rightMatrix, name='KhatriRaoProduct', var_name=None):
|
||||
super(KhatriRaoProduct, self).__init__(params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
super(KhatriRaoProduct, self).__init__(
|
||||
params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
self.leftMatrix = leftMatrix
|
||||
self.rightMatrix = rightMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Log(ComputationNode):
|
||||
|
||||
def __init__(self, x, name='Log', var_name=None):
|
||||
super(Log, self).__init__(params=['x'], name=name, var_name=var_name)
|
||||
self.x = x
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class LogSoftmax(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='LogSoftmax', var_name=None):
|
||||
super(LogSoftmax, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(LogSoftmax, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class MatrixL1Reg(ComputationNode):
|
||||
|
||||
def __init__(self, matrix, name='MatrixL1Reg', var_name=None):
|
||||
super(MatrixL1Reg, self).__init__(params=['matrix'], name=name, var_name=var_name)
|
||||
super(MatrixL1Reg, self).__init__(
|
||||
params=['matrix'], name=name, var_name=var_name)
|
||||
self.matrix = matrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class MatrixL2Reg(ComputationNode):
|
||||
|
||||
def __init__(self, matrix, name='MatrixL2Reg', var_name=None):
|
||||
super(MatrixL2Reg, self).__init__(params=['matrix'], name=name, var_name=var_name)
|
||||
super(MatrixL2Reg, self).__init__(
|
||||
params=['matrix'], name=name, var_name=var_name)
|
||||
self.matrix = matrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Mean(ComputationNode):
|
||||
|
||||
def __init__(self, dataVectorSequence, name='Mean', var_name=None):
|
||||
super(Mean, self).__init__(params=['dataVectorSequence'], name=name, var_name=var_name)
|
||||
super(Mean, self).__init__(
|
||||
params=['dataVectorSequence'], name=name, var_name=var_name)
|
||||
self.dataVectorSequence = dataVectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Minus(ComputationNode):
|
||||
|
||||
def __init__(self, leftMatrix, rightMatrix, name='Minus', var_name=None):
|
||||
super(Minus, self).__init__(params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
super(Minus, self).__init__(
|
||||
params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
self.leftMatrix = leftMatrix
|
||||
self.rightMatrix = rightMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Negate(ComputationNode):
|
||||
|
||||
def __init__(self, input, name='Negate', var_name=None):
|
||||
super(Negate, self).__init__(params=['input'], name=name, var_name=var_name)
|
||||
super(Negate, self).__init__(
|
||||
params=['input'], name=name, var_name=var_name)
|
||||
self.input = input
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class PackedIndex(ComputationNode):
|
||||
|
||||
def __init__(self, targetObject, indexSequence, name='PackedIndex', var_name=None):
|
||||
super(PackedIndex, self).__init__(params=['targetObject', 'indexSequence'], name=name, var_name=var_name)
|
||||
super(PackedIndex, self).__init__(
|
||||
params=['targetObject', 'indexSequence'], name=name, var_name=var_name)
|
||||
self.targetObject = targetObject
|
||||
self.indexSequence = indexSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class PerDimMeanVarDeNormalization(ComputationNode):
|
||||
|
||||
def __init__(self, dataVectorSequence, meanVector, invStdDevVector, name='PerDimMeanVarDeNormalization', var_name=None):
|
||||
super(PerDimMeanVarDeNormalization, self).__init__(params=['dataVectorSequence', 'meanVector', 'invStdDevVector'], name=name, var_name=var_name)
|
||||
super(PerDimMeanVarDeNormalization, self).__init__(params=[
|
||||
'dataVectorSequence', 'meanVector', 'invStdDevVector'], name=name, var_name=var_name)
|
||||
self.dataVectorSequence = dataVectorSequence
|
||||
self.meanVector = meanVector
|
||||
self.invStdDevVector = invStdDevVector
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class PerDimMeanVarNormalization(ComputationNode):
|
||||
|
||||
def __init__(self, dataVectorSequence, meanVector, invStdDevVector, name='PerDimMeanVarNormalization', var_name=None):
|
||||
super(PerDimMeanVarNormalization, self).__init__(params=['dataVectorSequence', 'meanVector', 'invStdDevVector'], name=name, var_name=var_name)
|
||||
super(PerDimMeanVarNormalization, self).__init__(params=[
|
||||
'dataVectorSequence', 'meanVector', 'invStdDevVector'], name=name, var_name=var_name)
|
||||
self.dataVectorSequence = dataVectorSequence
|
||||
self.meanVector = meanVector
|
||||
self.invStdDevVector = invStdDevVector
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Plus(ComputationNode):
|
||||
|
||||
def __init__(self, leftMatrix, rightMatrix, name='Plus', var_name=None):
|
||||
super(Plus, self).__init__(params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
super(Plus, self).__init__(
|
||||
params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
self.leftMatrix = leftMatrix
|
||||
self.rightMatrix = rightMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class RectifiedLinear(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='RectifiedLinear', var_name=None):
|
||||
super(RectifiedLinear, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(RectifiedLinear, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Scale(ComputationNode):
|
||||
|
||||
def __init__(self, scalarScalingFactor, matrix, name='Scale', var_name=None):
|
||||
super(Scale, self).__init__(params=['scalarScalingFactor', 'matrix'], name=name, var_name=var_name)
|
||||
super(Scale, self).__init__(
|
||||
params=['scalarScalingFactor', 'matrix'], name=name, var_name=var_name)
|
||||
self.scalarScalingFactor = scalarScalingFactor
|
||||
self.matrix = matrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class ScatterPacked(ComputationNode):
|
||||
|
||||
def __init__(self, cond, indexSequence, sourceData, name='ScatterPacked', var_name=None):
|
||||
super(ScatterPacked, self).__init__(params=['cond', 'indexSequence', 'sourceData'], name=name, var_name=var_name)
|
||||
super(ScatterPacked, self).__init__(
|
||||
params=['cond', 'indexSequence', 'sourceData'], name=name, var_name=var_name)
|
||||
self.cond = cond
|
||||
self.indexSequence = indexSequence
|
||||
self.sourceData = sourceData
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Sigmoid(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='Sigmoid', var_name=None):
|
||||
super(Sigmoid, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(Sigmoid, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Softmax(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='Softmax', var_name=None):
|
||||
super(Softmax, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(Softmax, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Hardmax(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='Hardmax', var_name=None):
|
||||
super(Hardmax, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(Hardmax, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Sqrt(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='Sqrt', var_name=None):
|
||||
super(Sqrt, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class SquareError(ComputationNode):
|
||||
|
||||
def __init__(self, aMatrix, anotherMatrix, name='SquareError', var_name=None):
|
||||
super(SquareError, self).__init__(params=['aMatrix', 'anotherMatrix'], name=name, var_name=var_name)
|
||||
super(SquareError, self).__init__(
|
||||
params=['aMatrix', 'anotherMatrix'], name=name, var_name=var_name)
|
||||
self.aMatrix = aMatrix
|
||||
self.anotherMatrix = anotherMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class SumColumnElements(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='SumColumnElements', var_name=None):
|
||||
super(SumColumnElements, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
super(SumColumnElements, self).__init__(
|
||||
params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class SumElements(ComputationNode):
|
||||
|
||||
def __init__(self, matrix, name='SumElements', var_name=None):
|
||||
super(SumElements, self).__init__(params=['matrix'], name=name, var_name=var_name)
|
||||
super(SumElements, self).__init__(
|
||||
params=['matrix'], name=name, var_name=var_name)
|
||||
self.matrix = matrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Tanh(ComputationNode):
|
||||
|
||||
def __init__(self, z, name='Tanh', var_name=None):
|
||||
super(Tanh, self).__init__(params=['z'], name=name, var_name=var_name)
|
||||
self.z = z
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class TimeReverse(ComputationNode):
|
||||
|
||||
def __init__(self, vectorSequence, name='TimeReverse', var_name=None):
|
||||
super(TimeReverse, self).__init__(params=['vectorSequence'], name=name, var_name=var_name)
|
||||
super(TimeReverse, self).__init__(
|
||||
params=['vectorSequence'], name=name, var_name=var_name)
|
||||
self.vectorSequence = vectorSequence
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class TransposeTimes(ComputationNode):
|
||||
|
||||
def __init__(self, leftMatrix, rightMatrix, name='TransposeTimes', var_name=None):
|
||||
super(TransposeTimes, self).__init__(params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
super(TransposeTimes, self).__init__(
|
||||
params=['leftMatrix', 'rightMatrix'], name=name, var_name=var_name)
|
||||
self.leftMatrix = leftMatrix
|
||||
self.rightMatrix = rightMatrix
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Where(ComputationNode):
|
||||
|
||||
def __init__(self, cond, name='Where', var_name=None):
|
||||
super(Where, self).__init__(params=['cond'], name=name, var_name=var_name)
|
||||
super(Where, self).__init__(
|
||||
params=['cond'], name=name, var_name=var_name)
|
||||
self.cond = cond
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
@ -602,33 +834,47 @@ Parameter = LearnableParameter
|
|||
ColumnwiseCrossProduct = KhatriRaoProduct
|
||||
ClassificationError = ErrorPrediction
|
||||
Delay = PastValue
|
||||
|
||||
|
||||
class Constant(Parameter):
|
||||
|
||||
def __init__(self, value, rows=1, cols=1, name='Constant', var_name=None):
|
||||
super(Constant, self).__init__(rows, cols, learningRateMultiplier=0, init='fixedValue', value=value, name=name, var_name=var_name)
|
||||
self.params=['value', 'rows', 'cols']
|
||||
super(Constant, self).__init__(rows, cols, learningRateMultiplier=0,
|
||||
init='fixedValue', value=value, name=name, var_name=var_name)
|
||||
self.params = ['value', 'rows', 'cols']
|
||||
self.params_with_defaults = ['rows', 'cols']
|
||||
|
||||
|
||||
class ReshapeDimension(NewReshape):
|
||||
|
||||
def __init__(self, x, dim, tensorShape, name='ReshapeDimension', var_name=None):
|
||||
super(ReshapeDimension, self).__init__(x, tensorShape, beginDim=dim, endDim=dim + 1, name=name, var_name=var_name)
|
||||
self.params=['x', 'dim', 'tensorShape']
|
||||
super(ReshapeDimension, self).__init__(
|
||||
x, tensorShape, beginDim=dim, endDim=dim + 1, name=name, var_name=var_name)
|
||||
self.params = ['x', 'dim', 'tensorShape']
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class FlattenDimensions(NewReshape):
|
||||
|
||||
def __init__(self, x, dim, num, name='FlattenDimensions', var_name=None):
|
||||
super(FlattenDimensions, self).__init__(x, 0, beginDim=dim, endDim=dim + num, name=name, var_name=var_name)
|
||||
self.params=['x', 'dim', 'num']
|
||||
super(FlattenDimensions, self).__init__(
|
||||
x, 0, beginDim=dim, endDim=dim + num, name=name, var_name=var_name)
|
||||
self.params = ['x', 'dim', 'num']
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class SplitDimension(ReshapeDimension):
|
||||
|
||||
def __init__(self, x, dim, N, name='SplitDimension', var_name=None):
|
||||
super(SplitDimension, self).__init__(x, dim, '<not yet supported>', name=name, var_name=var_name)
|
||||
self.params=['x', 'dim', 'N']
|
||||
super(SplitDimension, self).__init__(
|
||||
x, dim, '<not yet supported>', name=name, var_name=var_name)
|
||||
self.params = ['x', 'dim', 'N']
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
||||
class Transpose(TransposeDimensions):
|
||||
|
||||
def __init__(self, x, name='Transpose', var_name=None):
|
||||
super(Transpose, self).__init__(x, 1, 2, name=name, var_name=var_name)
|
||||
self.params=['x']
|
||||
self.params = ['x']
|
||||
self.params_with_defaults = []
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ class SGD(dict):
|
|||
|
||||
"""This is the Stochastic Gradien Descent optimizer used to train the networks
|
||||
"""
|
||||
def __init__(self, epoch_size = 0, minibatch_size = 1, learning_ratesPerMB = "0.1", \
|
||||
learning_rates_per_sample = None, momentum_per_mb = "0.9", \
|
||||
momentum_per_sample = None, max_epochs = 5, dropout_rate = None):
|
||||
|
||||
def __init__(self, epoch_size=0, minibatch_size=1, learning_ratesPerMB="0.1",
|
||||
learning_rates_per_sample=None, momentum_per_mb="0.9",
|
||||
momentum_per_sample=None, max_epochs=5, dropout_rate=None):
|
||||
""" SGD constructor
|
||||
|
||||
:param epoch_size: the number of samples to use in each epoch. An intermediate
|
||||
|
@ -53,7 +53,7 @@ class SGD(dict):
|
|||
"""
|
||||
|
||||
config = []
|
||||
for k,v in self.items():
|
||||
for k, v in self.items():
|
||||
if (v is not None):
|
||||
config.append('{0} = {1}\r\n'.format(k,v))
|
||||
config.append('{0} = {1}\r\n'.format(k, v))
|
||||
return ''.join(config)
|
||||
|
|
|
@ -22,6 +22,7 @@ class AbstractReader(dict, metaclass=ABCMeta):
|
|||
|
||||
def __ne__(self, x): return x is not self
|
||||
|
||||
|
||||
class UCIFastReader(AbstractReader):
|
||||
|
||||
"""This is the reader class the maps to UCIFastReader of CNTK
|
||||
|
@ -36,7 +37,7 @@ class UCIFastReader(AbstractReader):
|
|||
self["FileName"] = filename
|
||||
self["CustomDelimiter"] = custom_delimiter
|
||||
self.inputs_def = []
|
||||
|
||||
|
||||
def add_input(self, name_or_node, input_start, input_dim, num_of_classes=None, label_mapping_file=None):
|
||||
"""Add an input to the reader
|
||||
:param name_or_node: either name of the input in the network definition or the node itself
|
||||
|
@ -47,10 +48,11 @@ class UCIFastReader(AbstractReader):
|
|||
the mapping file path, it can be simply with all the possible classes, one per line
|
||||
"""
|
||||
if not name_or_node or input_start is None or input_dim is None:
|
||||
raise ValueError("one of the parameters of add_input is None")
|
||||
|
||||
self.inputs_def.append((name_or_node, input_start, input_dim, num_of_classes, label_mapping_file))
|
||||
|
||||
raise ValueError("one of the parameters of add_input is None")
|
||||
|
||||
self.inputs_def.append(
|
||||
(name_or_node, input_start, input_dim, num_of_classes, label_mapping_file))
|
||||
|
||||
def generate_config(self):
|
||||
"""Generate the reader configuration block
|
||||
"""
|
||||
|
@ -66,14 +68,14 @@ class UCIFastReader(AbstractReader):
|
|||
template += '''\
|
||||
customDelimiter = %(CustomDelimiter)s
|
||||
'''
|
||||
|
||||
|
||||
if self.inputs_def is not None:
|
||||
for (name_or_node, start, dim, num_of_classes, map_file) in self.inputs_def:
|
||||
for (name_or_node, start, dim, num_of_classes, map_file) in self.inputs_def:
|
||||
if (isinstance(name_or_node, ComputationNode)):
|
||||
name = name_or_node.var_name
|
||||
else:
|
||||
name = name_or_node
|
||||
|
||||
|
||||
template += '''\
|
||||
{0} = [
|
||||
start = {1}
|
||||
|
@ -83,22 +85,23 @@ class UCIFastReader(AbstractReader):
|
|||
if num_of_classes:
|
||||
template += '''\
|
||||
labelDim= {0}
|
||||
'''.format(num_of_classes)
|
||||
'''.format(num_of_classes)
|
||||
if map_file:
|
||||
template += '''\
|
||||
labelMappingFile= "{0}"
|
||||
'''.format(map_file)
|
||||
|
||||
'''.format(map_file)
|
||||
|
||||
template += '''\
|
||||
]
|
||||
'''
|
||||
|
||||
|
||||
template += '''\
|
||||
]
|
||||
'''
|
||||
|
||||
|
||||
return template % self
|
||||
|
||||
|
||||
class CNTKTextFormatReader(AbstractReader):
|
||||
|
||||
"""This is the reader class the maps to CNTKTextFormatReader of CNTK
|
||||
|
@ -120,12 +123,12 @@ class CNTKTextFormatReader(AbstractReader):
|
|||
format: dense or sparse
|
||||
"""
|
||||
if not name_or_node or input_dim is None or format is None:
|
||||
raise ValueError("one of the parameters of add_input is None")
|
||||
|
||||
raise ValueError("one of the parameters of add_input is None")
|
||||
|
||||
input_alias = input_alias or name_or_node
|
||||
|
||||
|
||||
self.inputs_def.append((name_or_node, input_alias, input_dim, format))
|
||||
|
||||
|
||||
def generate_config(self):
|
||||
"""Generate the reader configuration block
|
||||
"""
|
||||
|
@ -138,10 +141,10 @@ class CNTKTextFormatReader(AbstractReader):
|
|||
template += '''
|
||||
input = [
|
||||
'''
|
||||
|
||||
for (name_or_node, input_alias, dim, format) in self.inputs_def:
|
||||
|
||||
for (name_or_node, input_alias, dim, format) in self.inputs_def:
|
||||
if (isinstance(name_or_node, ComputationNode)):
|
||||
name = name_or_node.var_name
|
||||
name = name_or_node.var_name
|
||||
else:
|
||||
name = name_or_node
|
||||
|
||||
|
@ -149,23 +152,23 @@ class CNTKTextFormatReader(AbstractReader):
|
|||
a = name
|
||||
else:
|
||||
a = input_alias
|
||||
|
||||
|
||||
template += '''
|
||||
{0}=[
|
||||
alias = "{1}"
|
||||
dim = {2}
|
||||
format = "{3}"
|
||||
]'''.format(name, a, dim, format)
|
||||
|
||||
|
||||
template += '''
|
||||
]
|
||||
]
|
||||
'''
|
||||
return template % self
|
||||
|
||||
|
||||
def NumPyReader(data, filename):
|
||||
#TODO: get rid of this
|
||||
|
||||
# TODO: get rid of this
|
||||
"""
|
||||
This is a factory that wraps Python arrays with a UCIFastReader.
|
||||
"""
|
||||
|
@ -182,4 +185,3 @@ def NumPyReader(data, filename):
|
|||
np.savetxt(filename, data, delimiter=' ', newline='\r\n', fmt=format_str)
|
||||
|
||||
return UCIFastReader(filename)
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from ..context import *
|
||||
|
||||
|
||||
def test_parse_shapes():
|
||||
output = '''\
|
||||
output = '''\
|
||||
FormNestedNetwork: WARNING: Was called twice for v3 Plus operation
|
||||
|
||||
Validating network. 5 nodes to process in pass 1.
|
||||
|
@ -24,13 +25,12 @@ Validating network, final pass.
|
|||
Post-processing network complete.
|
||||
'''
|
||||
|
||||
expected = {
|
||||
'dummy_node':(2,),
|
||||
'v0':(4,1),
|
||||
'v1':(2,2),
|
||||
'v2':(1,1),
|
||||
'v3':(2,2)
|
||||
}
|
||||
|
||||
assert Context._parse_shapes_from_output(output) == expected
|
||||
expected = {
|
||||
'dummy_node': (2,),
|
||||
'v0': (4, 1),
|
||||
'v1': (2, 2),
|
||||
'v2': (1, 1),
|
||||
'v3': (2, 2)
|
||||
}
|
||||
|
||||
assert Context._parse_shapes_from_output(output) == expected
|
||||
|
|
|
@ -51,50 +51,56 @@ def test_overload_exception():
|
|||
with pytest.raises(ValueError):
|
||||
C(range(0, 10))[0:3:2]
|
||||
|
||||
|
||||
def _to_list(desc):
|
||||
return [line.strip() for line in desc.split('\n')]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("root_node, expected", [
|
||||
(C(2, var_name='c0'), ["c0 = Constant(2, rows=1, cols=1)"]),
|
||||
# Input should behave as Constant in case of scalars
|
||||
(I([1,2], var_name='i1'), ["i1 = Input(2:1, tag='feature')"]),
|
||||
(I([1, 2], var_name='i1'), ["i1 = Input(2:1, tag='feature')"]),
|
||||
(Plus(C(0), C(1)),
|
||||
["v0 = Constant(0, rows=1, cols=1)", "v1 = Constant(1, rows=1, cols=1)", "v2 = Plus(v0, v1)"]),
|
||||
])
|
||||
def test_description(root_node, expected):
|
||||
description, has_inputs, readers = root_node.to_config()
|
||||
description, has_inputs, readers = root_node.to_config()
|
||||
assert _to_list(description) == expected
|
||||
|
||||
|
||||
def test_graph_with_same_node_twice():
|
||||
v0 = C(1)
|
||||
root_node = Plus(v0, v0)
|
||||
expected = ['v0 = Constant(1, rows=1, cols=1)', 'v1 = Plus(v0, v0)']
|
||||
description, has_inputs, readers = root_node.to_config()
|
||||
description, has_inputs, readers = root_node.to_config()
|
||||
assert _to_list(description) == expected
|
||||
assert readers == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize("alias, data, expected", [
|
||||
('', [A([1,0]), A([0,0,1,0])], ValueError), # no alias given
|
||||
('A', [object()], ValueError),
|
||||
])
|
||||
('', [A([1, 0]), A([0, 0, 1, 0])], ValueError), # no alias given
|
||||
('A', [object()], ValueError),
|
||||
])
|
||||
def test_sequence_conversion_exceptions(alias, data, expected):
|
||||
with pytest.raises(expected):
|
||||
_seq_to_text_format(data, alias=alias)
|
||||
|
||||
|
||||
def test_constant_var_name():
|
||||
var_name = 'NODE'
|
||||
node = C([A([])], var_name=var_name)
|
||||
assert node.var_name == var_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("alias, data, expected", [
|
||||
('W', [A([])], """\
|
||||
0|W \
|
||||
"""),
|
||||
('W', [A([1,0]), A([0,0,1,0])], """\
|
||||
('W', [A([1, 0]), A([0, 0, 1, 0])], """\
|
||||
0|W 1 0
|
||||
1|W 0 0 1 0\
|
||||
"""),
|
||||
])
|
||||
])
|
||||
def test_sequence_conversion_dense(alias, data, expected):
|
||||
assert _seq_to_text_format(data, alias=alias) == expected
|
||||
|
||||
|
@ -103,43 +109,44 @@ if False:
|
|||
('W', [A({})], """\
|
||||
0|W \
|
||||
"""),
|
||||
('W', [{3:1, 50:1, 2:0}, {1:-5}], """\
|
||||
('W', [{3: 1, 50: 1, 2: 0}, {1: -5}], """\
|
||||
0|W 2:0 3:1 50:1
|
||||
1|W 1:-5\
|
||||
"""),
|
||||
])
|
||||
])
|
||||
def test_sequence_conversion_sparse(alias, data, expected):
|
||||
# We use the dictionary in data to create a SciPy sparse dictionary of
|
||||
# keys, which we then feed to the converter.
|
||||
dok_data = []
|
||||
for data_elem in data:
|
||||
d = scipy.sparse.dok_matrix((100,1))
|
||||
for k,v in data_elem.items():
|
||||
d = scipy.sparse.dok_matrix((100, 1))
|
||||
for k, v in data_elem.items():
|
||||
d[k] = v
|
||||
dok_data.append(d)
|
||||
assert _seq_to_text_format(dok_data, alias=alias) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data, expected", [
|
||||
([], True),
|
||||
([1], True),
|
||||
([[1,2]], True),
|
||||
([[1, 2]], True),
|
||||
([[]], True),
|
||||
([[A([1,2])]], False),
|
||||
([A([1,2])], False),
|
||||
([A([1,2]), A([])], False),
|
||||
])
|
||||
([[A([1, 2])]], False),
|
||||
([A([1, 2])], False),
|
||||
([A([1, 2]), A([])], False),
|
||||
])
|
||||
def test_is_tensor(data, expected):
|
||||
assert is_tensor(data) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data, expected", [
|
||||
([], False),
|
||||
([1], False),
|
||||
([[1,2]], False),
|
||||
([[1, 2]], False),
|
||||
([[]], False),
|
||||
([[A([1,2])]], False),
|
||||
([A([1,2])], True),
|
||||
([A([1,2]), A([])], True),
|
||||
])
|
||||
([[A([1, 2])]], False),
|
||||
([A([1, 2])], True),
|
||||
([A([1, 2]), A([])], True),
|
||||
])
|
||||
def test_is_sequence(data, expected):
|
||||
assert is_sequence(data) == expected
|
||||
|
||||
|
|
|
@ -10,15 +10,18 @@ from ..reader import *
|
|||
C = constant
|
||||
I = input
|
||||
|
||||
|
||||
def _test(root_node, expected, clean_up=True):
|
||||
with get_new_context() as ctx:
|
||||
ctx.clean_up = clean_up
|
||||
assert not ctx.input_nodes
|
||||
result = ctx.eval(root_node)
|
||||
expected = np.asarray(expected)
|
||||
assert result.shape == expected.shape or result.shape == (1,1) and expected.shape==()
|
||||
assert result.shape == expected.shape or result.shape == (
|
||||
1, 1) and expected.shape == ()
|
||||
assert np.all(result == expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('root_node, expected', [
|
||||
# __add__ / __radd__
|
||||
(C(0) + C(1), 1),
|
||||
|
@ -41,11 +44,13 @@ def _test(root_node, expected, clean_up=True):
|
|||
|
||||
# normal ops
|
||||
|
||||
(C(np.ones((2,3))*3), [[3,3,3], [3,3,3]]),
|
||||
(C(np.ones((2,3))*3)+np.vstack([np.ones(3), np.ones(3)+1]), [[4,4,4], [5,5,5]]),
|
||||
(C(np.ones((2,3))*3)*np.vstack([np.ones(3), np.ones(3)+1]), [[3,3,3], [6,6,6]]),
|
||||
(C(np.ones((2, 3)) * 3), [[3, 3, 3], [3, 3, 3]]),
|
||||
(C(np.ones((2, 3)) * 3) + \
|
||||
np.vstack([np.ones(3), np.ones(3) + 1]), [[4, 4, 4], [5, 5, 5]]),
|
||||
(C(np.ones((2, 3)) * 3) * \
|
||||
np.vstack([np.ones(3), np.ones(3) + 1]), [[3, 3, 3], [6, 6, 6]]),
|
||||
|
||||
# special treatment of inputs in RowStack
|
||||
# special treatment of inputs in RowStack
|
||||
# (RowStack((C(1), C(2))), [[1],[2]]), # TODO figure out the real semantic
|
||||
# of RowStack
|
||||
|
||||
|
@ -57,7 +62,7 @@ def _test(root_node, expected, clean_up=True):
|
|||
# to ComputationNode
|
||||
(abs(C(-3)), 3),
|
||||
(abs(C(3)), 3),
|
||||
(abs(C([[-1,2],[50,-0]])), [[1,2],[50,0]]),
|
||||
(abs(C([[-1, 2], [50, -0]])), [[1, 2], [50, 0]]),
|
||||
|
||||
# more complex stuff
|
||||
#(Plus(C(5), 3), 8),
|
||||
|
@ -65,20 +70,21 @@ def _test(root_node, expected, clean_up=True):
|
|||
def test_overload_eval(root_node, expected):
|
||||
_test(root_node, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('root_node, expected', [
|
||||
# __add__ / __radd__
|
||||
(C(np.asarray([1,2]))+0, [1,2]),
|
||||
(C(np.asarray([1,2]))+.1, [1.1,2.1]),
|
||||
(.1+C(np.asarray([1,2])), [1.1,2.1]),
|
||||
(C(np.asarray([1,2]))*0, [0,0]),
|
||||
(C(np.asarray([1,2]))*.1, [0.1,0.2]),
|
||||
(.1*C(np.asarray([1,2])), [0.1,0.2]),
|
||||
(C(np.asarray([[1,2],[3,4]]))+.1, [[1.1,2.1],[3.1,4.1]]),
|
||||
(C(np.asarray([[1,2],[3,4]]))*2, [[2,4],[6,8]]),
|
||||
(2*C(np.asarray([[1,2],[3,4]])), [[2,4],[6,8]]),
|
||||
(2*C(np.asarray([[1,2],[3,4]]))+100, [[102,104],[106,108]]),
|
||||
(C(np.asarray([[1,2],[3,4]]))*C(np.asarray([[1,2],[3,4]])), [[1,4],[9,16]]),
|
||||
(C(np.asarray([1, 2])) + 0, [1, 2]),
|
||||
(C(np.asarray([1, 2])) + .1, [1.1, 2.1]),
|
||||
(.1 + C(np.asarray([1, 2])), [1.1, 2.1]),
|
||||
(C(np.asarray([1, 2])) * 0, [0, 0]),
|
||||
(C(np.asarray([1, 2])) * .1, [0.1, 0.2]),
|
||||
(.1 * C(np.asarray([1, 2])), [0.1, 0.2]),
|
||||
(C(np.asarray([[1, 2], [3, 4]])) + .1, [[1.1, 2.1], [3.1, 4.1]]),
|
||||
(C(np.asarray([[1, 2], [3, 4]])) * 2, [[2, 4], [6, 8]]),
|
||||
(2 * C(np.asarray([[1, 2], [3, 4]])), [[2, 4], [6, 8]]),
|
||||
(2 * C(np.asarray([[1, 2], [3, 4]])) + 100, [[102, 104], [106, 108]]),
|
||||
(C(np.asarray([[1, 2], [3, 4]]))
|
||||
* C(np.asarray([[1, 2], [3, 4]])), [[1, 4], [9, 16]]),
|
||||
])
|
||||
def test_ops_on_numpy(root_node, expected, tmpdir):
|
||||
_test(root_node, expected, clean_up=False)
|
||||
|
||||
|
|
|
@ -8,18 +8,18 @@ from .. import cntk1_ops
|
|||
|
||||
allclose = np.testing.assert_allclose
|
||||
|
||||
|
||||
def test_NumPyReader(tmpdir):
|
||||
data = [[1, 2], [3, 4]]
|
||||
fn = str(tmpdir / 'test.txt')
|
||||
reader = NumPyReader(data, fn)
|
||||
|
||||
input_node = cntk1_ops.Input(2, var_name='testInput')
|
||||
reader.add_input(input_node, 0,2)
|
||||
reader.add_input(input_node, 0, 2)
|
||||
out = input_node + 2
|
||||
|
||||
with get_new_context() as ctx:
|
||||
result = ctx.eval(out, reader)
|
||||
assert np.all(result == np.asarray(data)+2)
|
||||
assert np.all(result == np.asarray(data) + 2)
|
||||
|
||||
# TODO test other readers
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from cntk.utils import CNTK_EXECUTABLE_PATH
|
|||
# BrainSCript's node definitions are created when a build is triggered so we
|
||||
# should be able to find the file in the path of the cntk exeutable.
|
||||
CNTKCORE_DEFS = os.path.join(
|
||||
os.path.dirname(CNTK_EXECUTABLE_PATH), 'CNTK.core.bs')
|
||||
os.path.dirname(CNTK_EXECUTABLE_PATH), 'CNTK.core.bs')
|
||||
|
||||
REGEX_STANDARD = re.compile(r'(?P<operator>\w+)\((?P<operands>.*?)\) = .*')
|
||||
REGEX_COMPNODE = re.compile(
|
||||
|
@ -78,14 +78,14 @@ class %(name)s(%(parentclass)s):
|
|||
|
||||
def __init__(self, comp_match):
|
||||
self.name = comp_match.group('operator')
|
||||
|
||||
|
||||
if self.name in INPUT_NODES:
|
||||
self.parentclass = 'InputComputationNodeBase'
|
||||
self.parentclass = 'InputComputationNodeBase'
|
||||
elif self.name in IMAGE_INPUT_NODES:
|
||||
self.parentclass = 'ImageInputComputationNodeBase'
|
||||
self.parentclass = 'ImageInputComputationNodeBase'
|
||||
else:
|
||||
self.parentclass = 'ComputationNode'
|
||||
|
||||
|
||||
self.raw_operands = comp_match.group('operands')
|
||||
|
||||
self.operands = []
|
||||
|
|
Загрузка…
Ссылка в новой задаче