diff --git a/bindings/python/cntk/io/__init__.py b/bindings/python/cntk/io/__init__.py
index aeeec61db..06915d54e 100644
--- a/bindings/python/cntk/io/__init__.py
+++ b/bindings/python/cntk/io/__init__.py
@@ -118,7 +118,7 @@ class MinibatchSource(cntk_py.MinibatchSource):
the next minibatch. Must be > 0.
minibatch_size_in_sequences (`int`, defaults to `None`): number of
samples to retrieve for the next minibatch. Must be > 0.
- input_map (`dict`): mapping of :class:`cntk.ops.variables.Variable`
+ input_map (`dict`): mapping of :class:`cntk.ops.variabls.Variable`
to :class:`StreamInformation` which will be used to convert the
returned data.
device (`DeviceDescriptor`, defaults to `None`): CNTK DeviceDescriptor
@@ -126,7 +126,7 @@ class MinibatchSource(cntk_py.MinibatchSource):
Returns:
A mapping of :class:`StramInformation` to :class:`MinibatchData` if
``input_map`` was not specified. Otherwise, the returned value will
- be a mapping of :class:`cntk.ops.variables.Variable` to class:`MinibatchData`.
+ be a mapping of :class:`cntk.ops.variabls.Variable` to class:`MinibatchData`.
'''
if device is None:
device = use_default_device()
@@ -223,8 +223,7 @@ class ReaderConfig(dict):
deserializers ('list', default is empty): list of deserializers
(:class:`ImageDeserializer` for now).
randomize (`bool`, default True): randomize images before every epoch
- epoch_size (`int`): epoch size. FULL_DATA_SWEEP means one pass;
- INFINITELY_REPEAT means duplicate infinitely (with different randomization each time).
+ epoch_size (`int`): epoch size
'''
def __init__(self, deserializers=None, randomize=True, epoch_size=INFINITELY_REPEAT):
@@ -235,7 +234,6 @@ class ReaderConfig(dict):
self['deserializers'] = self.deserializers = deserializers or []
self['randomize'] = randomize
- # TODO: This should be deleted; do it the other way round and create MinibatchSource() directly with the same parameter
@typemap
def minibatch_source(self):
'''
@@ -417,9 +415,9 @@ class ImageDeserializer(Deserializer):
class CTFDeserializer(Deserializer):
'''
This class configures the text reader that reads text-encoded files from a file with lines of the form
- [Sequence_Id](Sample)+
+ [Sequence_Id](Sample)+
where
- Sample=|Input_Name (Value )*
+ Sample=|Input_Name (Value )*
Args:
filename (`str`): file name containing the text input
See also:
@@ -440,17 +438,17 @@ class CTFDeserializer(Deserializer):
# TODO: should be a private method; use constructor only
def map_input(self, node, dim, format="dense", alias=None):
'''
- Maps node (either node instance or node name) to a part of the text input,
+ Maps node (either node instance or node name) to a part of the text input,
either specified by the node name or the alias in the text file.
Example: for node name 'Apples' an input line could look like this:
|Apples 0 1 2 3 4 5 6 7 8 9
Args:
node (`str` or input node): node or its name
- dim (`int`): specifies the dimension of the input value vector
- (for dense input this directly corresponds to the number of values in each sample,
+ dim (`int`): specifies the dimension of the input value vector
+ (for dense input this directly corresponds to the number of values in each sample,
for sparse this represents the upper bound on the range of possible index values).
- format (`str`, default 'dense'): 'dense' or 'sparse'. Specifies the input type.
- alias (`str`, default None): None or alias name. Optional abbreviated name that
+ format (`str`, default 'dense'): 'dense' or 'sparse'. Specifies the input type.
+ alias (`str`, default None): None or alias name. Optional abbreviated name that
is used in the text file to avoid repeating long input names. For details please
see https://github.com/Microsoft/CNTK/wiki/CNTKTextFormat-Reader
'''
@@ -504,6 +502,22 @@ class StreamConfiguration(cntk_py.StreamConfiguration):
return super(StreamConfiguration, self).__init__(name, dim, is_sparse, stream_alias)
+# wrapper around text_format_minibatch_source() that attaches a record of streams
+# TODO: This should not exist; use MinibatchSource(CTFDeserializer(...))
+def _unused_CNTKTextFormatMinibatchSource(path, streams, epoch_size=None): # TODO: delete this
+ from cntk.utils import _ClassFromDict
+ # convert streams into StreamConfiguration format
+ # TODO: stream_alias should default to 'key'
+ stream_configs = [ StreamConfiguration(key, dim=value.dim, is_sparse=value.is_sparse, stream_alias=value.stream_alias) for (key, value) in streams.items() ]
+ if epoch_size is not None: # TODO: use MAX_UI64, now that we have access
+ source = text_format_minibatch_source(path, stream_configs, epoch_size)
+ else:
+ source = text_format_minibatch_source(path, stream_configs)
+ # attach a dictionary of the streams
+ source.streams = _ClassFromDict({ name : source.stream_info(name) for name in streams.keys() })
+ return source
+
+
# stream definition for use in StreamDefs
# returns a record { stream_alias, is_sparse, optional dim, optional transforms }
from cntk.utils import Record
diff --git a/bindings/python/cntk/utils/progress_print.py b/bindings/python/cntk/utils/progress_print.py
index be49e8a5c..39002c955 100644
--- a/bindings/python/cntk/utils/progress_print.py
+++ b/bindings/python/cntk/utils/progress_print.py
@@ -147,7 +147,6 @@ class ProgressPrinter:
else:
print(' Minibatch[{:4d}-{:4d}]: loss = {:0.6f} * {:d}'.format(
first_mb, self.updates, avg_loss, samples))
- return self.samples_since_start # so that we can trigger on this
def update_with_trainer(self, trainer, with_metric=False):
'''
@@ -158,7 +157,7 @@ class ProgressPrinter:
trainer (:class:`cntk.trainer.Trainer`): trainer from which information is gathered
with_metric (`bool`): whether to update the metric accumulators
'''
- self.update(trainer.previous_minibatch_loss_average, trainer.previous_minibatch_sample_count, trainer.previous_minibatch_evaluation_average if with_metric else None)
+ self.update(trainer.previous_minibatch_loss_average,trainer.previous_minibatch_sample_count, trainer.previous_minibatch_evaluation_average if with_metric else None)
# print the total number of parameters to log
diff --git a/bindings/python/examples/CNTKv2.pyproj b/bindings/python/examples/CNTKv2.pyproj
index 0ddd48681..b5fd92ed6 100644
--- a/bindings/python/examples/CNTKv2.pyproj
+++ b/bindings/python/examples/CNTKv2.pyproj
@@ -5,7 +5,7 @@
2.0
{1a078fc2-21c0-4f42-9a5b-0e84e944bc74}
- CifarConvNet\CifarConvNet.py
+ test\language_understanding_test.py
$(RepoRootPath)$(Platform)\$(Configuration);$(RepoRootPath)bindings\python;$(RepoRootPath)bindings\python\examples
.
.
diff --git a/bindings/python/examples/CifarConvNet/CifarConvNet.py b/bindings/python/examples/CifarConvNet/CifarConvNet.py
index 172af3ea9..88c2741c4 100644
--- a/bindings/python/examples/CifarConvNet/CifarConvNet.py
+++ b/bindings/python/examples/CifarConvNet/CifarConvNet.py
@@ -17,11 +17,9 @@ from cntk import Trainer
from cntk.learner import momentum_sgd, learning_rate_schedule
from cntk.ops import cross_entropy_with_softmax, classification_error, relu, convolution, pooling, PoolingType_Max
-########################
-# variables and paths #
-########################
-
-# paths (are relative to current python file)
+#
+# Paths relative to current python file.
+#
abs_path = os.path.dirname(os.path.abspath(__file__))
cntk_path = os.path.normpath(os.path.join(abs_path, "..", "..", "..", ".."))
data_path = os.path.join(cntk_path, "Examples", "Image", "Datasets", "CIFAR-10")
@@ -44,9 +42,9 @@ def create_reader(map_file, mean_file, train):
# transformation pipeline for the features has jitter/crop only when training
transforms = []
- if is_training:
+ if train:
transforms += [
- ImageDeserializer.crop(crop_type='Random', ratio=0.8, jitter_type='uniRatio') # is_training uses jitter
+ ImageDeserializer.crop(crop_type='Random', ratio=0.8, jitter_type='uniRatio') # train uses jitter
]
transforms += [
ImageDeserializer.scale(width=image_width, height=image_height, channels=num_channels, interpolations='linear'),
@@ -56,11 +54,7 @@ def create_reader(map_file, mean_file, train):
return MinibatchSource(ImageDeserializer(map_file, StreamDefs(
features = StreamDef(field='image', transforms=transforms), # first column in map file is referred to as 'image'
labels = StreamDef(field='label', shape=num_classes) # and second as 'label'
- )), randomize=is_training, epoch_size = INFINITELY_REPEAT if is_training else FULL_DATA_SWEEP)
-
-########################
-# define the model #
-########################
+ )))
#
# Define a VGG like network for Cifar dataset.
@@ -122,12 +116,11 @@ def train_and_evaluate(reader_train, reader_test, max_epochs):
# loss and metric
ce = cross_entropy_with_softmax(z, label_var)
- pe = classification_error (z, label_var)
+ pe = classification_error(z, label_var)
# training config
epoch_size = 50000
minibatch_size = 64
- epoch_size = 1000 ; max_epochs = 1 # for faster testing
# For basic model
lr_per_sample = [0.00015625]*10+[0.000046875]*10+[0.0000156]
@@ -147,8 +140,7 @@ def train_and_evaluate(reader_train, reader_test, max_epochs):
}
log_number_of_parameters(z) ; print()
- progress_printer = ProgressPrinter(freq=100, first=10, tag='Training')
- #progress_printer = ProgressPrinter(tag='Training')
+ progress_printer = ProgressPrinter(tag='Training')
# perform model training
for epoch in range(max_epochs): # loop over epochs
@@ -159,14 +151,13 @@ def train_and_evaluate(reader_train, reader_test, max_epochs):
sample_count += data[label_var].num_samples # count samples processed so far
progress_printer.update_with_trainer(trainer, with_metric=True) # log progress
- loss, metric, actual_samples = progress_printer.epoch_summary(with_metric=True)
-
- #return loss, metric # return values from last epoch
-
+ progress_printer.epoch_summary(with_metric=True)
+
#
# Evaluation action
#
- minibatch_size = 1000
+ epoch_size = 10000
+ minibatch_size = 16
# process minibatches and evaluate the model
metric_numer = 0
diff --git a/bindings/python/examples/CifarResNet/CifarResNet.py b/bindings/python/examples/CifarResNet/CifarResNet.py
index 4b2caa350..ef6e5ac46 100644
--- a/bindings/python/examples/CifarResNet/CifarResNet.py
+++ b/bindings/python/examples/CifarResNet/CifarResNet.py
@@ -94,9 +94,10 @@ def create_resnet_model(input, num_classes):
bn_time_const = 4096
c_map1 = 16
+
+ feat_scale = 0.00390625
- # feat_scale = 0.00390625
- # input_norm = element_times(feat_scale, input)
+ input_norm = element_times(feat_scale, input)
conv = conv_bn_relu_layer(input, c_map1, [3, 3], [1, 1], bn_time_const)
r1_1 = resnet_basic_stack3(conv, c_map1, bn_time_const)
diff --git a/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py b/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py
index f9c4d3ff2..84829835b 100644
--- a/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py
+++ b/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py
@@ -10,16 +10,15 @@ from cntk.blocks import * # non-layer like building blocks such as LSTM()
from cntk.layers import * # layer-like stuff such as Linear()
from cntk.models import * # higher abstraction level, e.g. entire standard models and also operators like Sequential()
from cntk.utils import *
-from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs, INFINITELY_REPEAT, FULL_DATA_SWEEP
+from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs
from cntk import Trainer
from cntk.learner import adam_sgd, learning_rate_schedule, momentum_schedule
from cntk.ops import cross_entropy_with_softmax, classification_error
########################
-# variables and paths #
+# variables and stuff #
########################
-# paths
cntk_dir = os.path.dirname(os.path.abspath(__file__)) + "/../../../.." # data resides in the CNTK folder
data_dir = cntk_dir + "/Examples/Tutorials/SLUHandsOn" # under Examples/Tutorials
vocab_size = 943 ; num_labels = 129 ; num_intents = 26 # number of words in vocab, slot labels, and intent labels
@@ -36,12 +35,12 @@ hidden_dim = 300
# define the reader #
########################
-def create_reader(path, is_training):
+def create_reader(path):
return MinibatchSource(CTFDeserializer(path, StreamDefs(
query = StreamDef(field='S0', shape=input_dim, is_sparse=True),
intent_unused = StreamDef(field='S1', shape=num_intents, is_sparse=True), # BUGBUG: unused, and should infer dim
slot_labels = StreamDef(field='S2', shape=label_dim, is_sparse=True)
- )), randomize=is_training, epoch_size = INFINITELY_REPEAT if is_training else FULL_DATA_SWEEP)
+ )))
########################
# define the model #
@@ -74,7 +73,6 @@ def train(reader, model, max_epochs):
# training config
epoch_size = 36000
minibatch_size = 70
- epoch_size = 1000 ; max_epochs = 1 # for faster testing
num_mbs_to_show_result = 100
momentum_as_time_constant = minibatch_size / -math.log(0.9) # TODO: Change to round number. This is 664.39. 700?
@@ -117,45 +115,6 @@ def train(reader, model, max_epochs):
#trace_node('stabilizer_param')
loss, metric, actual_samples = progress_printer.epoch_summary(with_metric=True)
- return loss, metric # return values from last epoch
-
-########################
-# eval action #
-########################
-
-def evaluate(reader, model):
- # Input variables denoting the features and label data
- query = Input(input_dim, is_sparse=False)
- slot_labels = Input(num_labels, is_sparse=True) # TODO: make sparse once it works
-
- # apply model to input
- z = model(query)
-
- # loss and metric
- ce = cross_entropy_with_softmax(z, slot_labels)
- pe = classification_error (z, slot_labels)
-
- # define mapping from reader streams to network inputs
- input_map = {
- query : reader.streams.query,
- slot_labels : reader.streams.slot_labels
- }
-
- # process minibatches and perform evaluation
- dummy_learner = adam_sgd(z.parameters, lr_per_sample=1, momentum_time_constant=0, low_memory=True) # BUGBUG: should not be needed
- evaluator = Trainer(z, ce, pe, [dummy_learner])
- progress_printer = ProgressPrinter(freq=100, first=10, tag='Evaluation') # more detailed logging
- #progress_printer = ProgressPrinter(tag='Evaluation')
-
- while True:
- minibatch_size = 1000
- data = reader.next_minibatch(minibatch_size, input_map=input_map) # fetch minibatch
- if not data: # until we hit the end
- break
- metric = evaluator.test_minibatch(data) # evaluate minibatch
- progress_printer.update(0, data[slot_labels].num_samples, metric) # log progress
- loss, metric, actual_samples = progress_printer.epoch_summary(with_metric=True)
-
return loss, metric
#############################
@@ -169,13 +128,10 @@ if __name__=='__main__':
set_fixed_random_seed(1) # BUGBUG: has no effect at present # TODO: remove debugging facilities once this all works
force_deterministic_algorithms()
- # create the model
+ reader = create_reader(data_dir + "/atis.train.ctf")
model = create_model()
-
# train
- reader = create_reader(data_dir + "/atis.train.ctf", is_training=True)
train(reader, model, max_epochs=8)
-
- # test
- reader = create_reader(data_dir + "/atis.test.ctf", is_training=False)
- evaluate(reader, model)
+ # test (TODO)
+ reader = create_reader(data_dir + "/atis.test.ctf")
+ #test(reader, model_dir + "/slu.cmf") # TODO: what is the correct pattern here?
diff --git a/bindings/python/examples/test/cifar_resnet_test.py b/bindings/python/examples/test/cifar_resnet_test.py
index fbb5e21bd..61beef2df 100644
--- a/bindings/python/examples/test/cifar_resnet_test.py
+++ b/bindings/python/examples/test/cifar_resnet_test.py
@@ -10,6 +10,7 @@ import sys
from cntk.utils import cntk_device
from cntk.cntk_py import DeviceKind_GPU
from cntk.device import set_default_device
+from cntk.io import ReaderConfig, ImageDeserializer
import pytest
from examples.CifarResNet.CifarResNet import train_and_evaluate, create_reader
diff --git a/bindings/python/examples/test/language_understanding_test.py b/bindings/python/examples/test/language_understanding_test.py
index d2470cbd4..fe7dba32e 100644
--- a/bindings/python/examples/test/language_understanding_test.py
+++ b/bindings/python/examples/test/language_understanding_test.py
@@ -37,7 +37,7 @@ def test_seq_classification_error(device_id):
# test of the example itself
# this emulates the main code in the PY file
- reader = create_reader(data_dir + "/atis.train.ctf", is_training=True)
+ reader = create_reader(data_dir + "/atis.train.ctf")
model = create_model()
loss_avg, evaluation_avg = train(reader, model, max_epochs=1)
expected_avg = [0.15570838301766451, 0.7846451368305728]
@@ -45,7 +45,7 @@ def test_seq_classification_error(device_id):
# test of a config like in the example but with additions to test many code paths
if device_id >= 0: # BatchNormalization currently does not run on CPU
- reader = create_reader(data_dir + "/atis.train.ctf", is_training=True)
+ reader = create_reader(data_dir + "/atis.train.ctf")
model = create_test_model()
loss_avg, evaluation_avg = train(reader, model, max_epochs=1)
log_number_of_parameters(model, trace_level=1) ; print()