/// <summary> /// Converts a dataset into sets of training examples for use in CNTK. Used to train recursive models with multiple outputs. /// </summary> /// <typeparam name="T">Supported by<seealso cref="float"/>, <seealso cref="double"/></typeparam> /// <param name="features">A set of attributes for each example (sample), with an example - a sequence</param> /// <param name="labels">A set of labels for each output of the model, the dimension for each output may be different.</param> /// <param name="minibatchSize">Minipack size</param> /// <returns></returns> public IEnumerable <MinibatchMultiOutput> ConvertDatasetToMinibatchMultiOutput <T>(IEnumerable <IList <T[]> > features, IEnumerable <T[][]> labels, int minibatchSize) { int inputDim = features.FirstOrDefault()?[0].Length ?? 0; int outputCount = labels.FirstOrDefault()?.Length ?? 0; var combined = features.Zip(labels, (f, l) => (f, l)); foreach (var segment in GetSegments(combined, minibatchSize)) { var featuresData = segment.Select(p => p.f.SelectMany(q => q)); var labelsData = new T[outputCount][]; for (int i = 0; i < outputCount; i++) { labelsData[i] = segment.SelectMany(p => p.l[i]).ToArray(); } MinibatchMultiOutput minibatch = new MinibatchMultiOutput(); minibatch.Size = segment.Count; minibatch.Features = Value.CreateBatch(new int[] { inputDim }, featuresData, Device); minibatch.Labels = labelsData .Select(label => Value.CreateBatch(new int[] { label.Length / segment.Count }, label, Device)) .ToArray(); yield return(minibatch); } }
/// <summary> /// Converts a 2D dataset into training case sets for use in CNTK. Used to train models with multiple outputs. /// </summary> /// <typeparam name="T">Supported by<seealso cref="float"/>, <seealso cref="double"/></typeparam> /// <param name="features">A set of attributes for each example (sample) in 2D</param> /// <param name="labels">A set of labels for each output of the model, the dimension for each output may be different.</param> /// <param name="minibatchSize">Minipack size</param> /// <returns></returns> public IEnumerable <MinibatchMultiOutput> ConvertDatasetToMinibatchMultiOutput <T>(IEnumerable <T[, ]> features, IEnumerable <T[][]> labels, int minibatchSize) where T : IConvertible { int outputCount = labels.FirstOrDefault()?.Length ?? 0; var combined = features.Zip(labels, (f, l) => (f, l)); foreach (var segment in GetSegments(combined, minibatchSize)) { var featuresData = segment.SelectMany(p => MatrixToVector(p.f)); var labelsData = new T[outputCount][]; for (int i = 0; i < outputCount; i++) { labelsData[i] = segment.SelectMany(p => p.l[i]).ToArray(); } MinibatchMultiOutput minibatch = new MinibatchMultiOutput(); minibatch.Size = segment.Count; minibatch.Features = Value.CreateBatch(new int[] { GetRowsCount(segment[0].f), GetColumnsCount(segment[0].f), 1 }, featuresData, Device); minibatch.Labels = labelsData .Select(label => Value.CreateBatch(new int[] { label.Length / segment.Count }, label, Device)) .ToArray(); yield return(minibatch); } }