/// <summary> /// Use the generator to create a list of fake images/ /// </summary> /// <param name="generator">The generator to use.</param> /// <param name="batchSize">The batch size.</param> /// <param name="latentDimensions">The number of dimensions in the latent input vector.</param> /// <returns>A list of images created by the generator.</returns> public static IList <IList <float> > GenerateImages( CNTK.Function generator, int batchSize, int latentDimensions) { // set up a Gaussian random number generator var random = new Random(); var gaussianRandom = new GaussianRandom(random); // set up randomized input for the generator var random_latent_vectors = gaussianRandom.getFloatSamples(batchSize * latentDimensions); var random_latent_vectors_nd = new CNTK.NDArrayView(new int[] { latentDimensions, 1, batchSize }, random_latent_vectors, NetUtil.CurrentDevice); var generator_inputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { generator.Arguments[0], new CNTK.Value(random_latent_vectors_nd) } }; var generator_outputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { generator.Output, null } }; // run the generator and collect the images generator.Evaluate(generator_inputs, generator_outputs, NetUtil.CurrentDevice); return(generator_outputs[generator.Output].GetDenseData <float>(generator.Output)); }
static void summary(CNTK.Function rootFunction, System.Collections.Generic.List <string> entries, System.Collections.Generic.ISet <CNTK.Function> visited) { if (visited == null) { visited = new System.Collections.Generic.HashSet <CNTK.Function>(); } if (rootFunction.IsComposite) { summary(rootFunction.RootFunction, entries, visited); return; } var numParameters = 0; foreach (var rootInput in rootFunction.Inputs) { if (rootInput.IsParameter) { numParameters += rootInput.Shape.TotalSize; } if (visited.Contains(rootInput.Owner) || (rootInput.Owner == null)) { continue; } summary(rootInput.Owner, entries, visited); } var line = $"{rootFunction.Name,-29}{rootFunction.Output.Shape.AsString(),-26}{numParameters}"; entries.Add(line); entries.Add(underscores); }
/// <summary> /// Return a summary description of the neural network. /// </summary> /// <param name="model">The neural network to describe</param> /// <returns>A string description of the neural network</returns> public static string ToSummary(this CNTK.Function model) { var sb = new StringBuilder(); sb.AppendFormat("\tInput = " + model.Arguments[0].Shape.AsString()); sb.Append(Environment.NewLine); for (int i = 0; i < model.Outputs.Count; i++) { sb.AppendFormat("\tOutput = " + model.Outputs[i].Shape.AsString()); sb.Append(Environment.NewLine); } sb.Append(Environment.NewLine); var numParameters = 0; foreach (var x in model.Parameters()) { var shape = x.Shape; var p = shape.TotalSize; sb.AppendFormat(string.Format("\tFilter Shape:{0,-30} Params:{1}", shape.AsString(), p)); sb.Append(Environment.NewLine); numParameters += p; } sb.AppendFormat(string.Format("\tTotal Number of Parameters: {0:N0}", numParameters)); sb.Append(Environment.NewLine); return(sb.ToString()); }
/// <summary> /// Adds a dream layer to a neural network. /// </summary> /// <param name="input">The neural network to extend.</param> /// <param name="image">The content image.</param> /// <param name="width">The width of the content image.</param> /// <param name="height">The height of the content image.</param> /// <returns>The neural network extended with a dream layer.</returns> public static CNTK.Function DreamLayer( this CNTK.Function input, float[] image, int width, int height) { // set up the dream layer var dream_weights_init = new CNTK.NDArrayView(new int[] { width, height, 3 }, image, NetUtil.CurrentDevice); var dream_weights = new CNTK.Parameter(dream_weights_init, "the_dream"); var dummy_features = CNTK.Variable.InputVariable(new int[] { 1 }, CNTK.DataType.Float, "dummy_features"); var dream_layer = CNTK.CNTKLib.ElementTimes(dream_weights, dummy_features, "the_dream_layer"); // combine the dream layer with the content and style layers var replacements = new Dictionary <CNTK.Variable, CNTK.Variable>() { { input.Arguments[0], dream_layer.Output } }; var model = input.Clone(CNTK.ParameterCloningMethod.Freeze, replacements); // return the finished model var all_outputs = new List <CNTK.Variable>() { dream_layer }; all_outputs.AddRange(model.Outputs); return(CNTK.Function.Combine(all_outputs, name: "overall_model")); }
void create_model(ref CNTK.Function model, ref float[][] labels) { var target_image = preprocess_image(target_image_path, img_height, img_width); var style_reference_image = preprocess_image(style_reference_image_path, img_height, img_width); var base_model = create_base_content_and_styles_model(img_height, img_width); labels = compute_labels(base_model, target_image, style_reference_image); var dream_weights_init = new CNTK.NDArrayView(new int[] { img_width, img_height, 3 }, target_image, computeDevice); var dream_weights = new CNTK.Parameter(dream_weights_init, "the_dream"); var dummy_features = CNTK.Variable.InputVariable(new int[] { 1 }, CNTK.DataType.Float, "dummy_features"); var dream_layer = CNTK.CNTKLib.ElementTimes(dream_weights, dummy_features, "the_dream_layler"); var replacements = new Dictionary <CNTK.Variable, CNTK.Variable>() { { base_model.Arguments[0], dream_layer.Output } }; model = base_model.Clone(CNTK.ParameterCloningMethod.Freeze, replacements); var all_outputs = new List <CNTK.Variable>() { dream_layer }; all_outputs.AddRange(model.Outputs); model = CNTK.Function.Combine(all_outputs, name: "overall_model"); }
/// <summary> /// Load the model from disk. /// </summary> /// <param name="features">The input features for the model.</param> /// <param name="freeze">Set to true to freeze all weights in the network.</param> /// <returns>The fully trained VGG16 model.</returns> public static CNTK.Function GetModel(CNTK.Variable features, bool freeze = false) { // make sure the model has been downloaded if (!IsDownloaded) { Download(); } // load the model into a new function string fullPath = GetFullPath(); var model = CNTK.Function.Load(fullPath, NetUtil.CurrentDevice); // return the model up to the 'pool5' layer, without feature replacements var cloningMethod = freeze ? CNTK.ParameterCloningMethod.Freeze : CNTK.ParameterCloningMethod.Clone; var pool5_node = model.FindByName("pool5"); CNTK.Function cloned_model = null; if (features == null) { cloned_model = CNTK.Function.Combine(new CNTK.Variable[] { pool5_node }).Clone(cloningMethod); return(cloned_model); } // return the model up to the 'pool5' layer, with feature replacements System.Diagnostics.Debug.Assert(model.Arguments.Count == 1); var replacements = new Dictionary <CNTK.Variable, CNTK.Variable>() { { model.Arguments[0], features } }; cloned_model = CNTK.Function.Combine(new CNTK.Variable[] { pool5_node }).Clone(cloningMethod, replacements); return(cloned_model); }
void style_transfer() { CNTK.Function model = null; float[][] labels = null; create_model(ref model, ref labels); train(model, labels); var img_data = inference(model, labels); display_images(img_data); }
CNTK.Function content_loss(CNTK.Variable x, CNTK.Function y) { var diff_ = CNTK.CNTKLib.Minus(x, y, name: "content_loss_diff_"); var square_ = CNTK.CNTKLib.Square(diff_, name: "content_loss_square_"); var sum_ = CNTK.CNTKLib.ReduceSum(square_, CNTK.Axis.AllStaticAxes(), name: "content_loss_sum_"); var scaling = CNTK.Constant.Scalar((float)(1.0 / x.Shape.TotalSize), computeDevice); sum_ = CNTK.CNTKLib.ElementTimes(sum_, scaling, name: "content_loss_"); return(sum_); }
/// <summary> /// Create a Gan by combining a generator and a discriminator. /// </summary> /// <param name="generator">The generator to use.</param> /// <param name="discriminator">The discriminator to use.</param> /// <returns>A new Gan network constructed out of the generator and discriminator.</returns> public static CNTK.Function CreateGan( CNTK.Function generator, CNTK.Function discriminator) { return(discriminator.Clone( CNTK.ParameterCloningMethod.Share, replacements: new Dictionary <CNTK.Variable, CNTK.Variable>() { { discriminator.Arguments[0], generator } })); }
List <CNTK.Variable> traverse_content_and_styles_nodes(CNTK.Function model) { var nodes = new List <CNTK.Variable>(); var node_names = new string[] { "conv5_2", "conv1_1", "conv2_1", "conv3_1", "conv4_1", "conv5_1" }; foreach (var node_name in node_names) { var node = model.FindByName(node_name); nodes.Add(node); } return(nodes); }
/// <summary> /// Get a list of content and style layers from the given neural network. /// </summary> /// <param name="input">The neural network to process.</param> /// <returns>A list of content and style layers in the neural network.</returns> public static List <CNTK.Variable> GetContentAndStyleLayers( this CNTK.Function input) { var layers = new List <CNTK.Variable>(); var layerNames = new string[] { "conv5_2", "conv1_1", "conv2_1", "conv3_1", "conv4_1", "conv5_1" }; foreach (var layerName in layerNames) { var layer = input.FindByName(layerName); layers.Add(layer); } return(layers); }
protected override void createModel() { var model_path = "ch8-1_cntk.model"; model = CNTK.Function.Load(model_path, computeDevice); var replacements = new CNTK.UnorderedMapVariableVariable() { { model.Placeholders()[0], x } }; model.ReplacePlaceholders(replacements); softmaxOutput = CNTK.CNTKLib.Softmax(model.Output); }
CNTK.Function create_loss_function(CNTK.Function model, IList <CNTK.Variable> outputs, IList <CNTK.Variable> labels) { var loss_function = content_loss(outputs[0], labels[0]); for (int i = 1; i < outputs.Count; i++) { var sl = style_loss(outputs[i], labels[i]); loss_function = CNTK.CNTKLib.Plus(loss_function, sl); } Util.summary(loss_function); Util.log_number_of_parameters(model); return(loss_function); }
byte[] inference(CNTK.Function model, float[][] labels) { var batch = create_batch(model, labels); var outputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { model.Outputs[0], null } }; model.Evaluate(batch, outputs, computeDevice); var img = outputs[model.Outputs[0]].GetDenseData <float>(model.Outputs[0])[0].ToArray(); var img_data = Util.convert_from_channels_first(img, offsets); return(img_data); }
/// <summary> /// Create a loss function that can compare the model output with the style image. /// </summary> /// <param name="model">The model to use.</param> /// <param name="outputs">The model outputs.</param> /// <param name="labels">The labels to use.</param> /// <returns>The loss function to use for training.</returns> public static CNTK.Function CreateLossFunction( CNTK.Function model, IList <CNTK.Variable> outputs, IList <CNTK.Variable> labels) { var lossFunction = ContentLossFunction(outputs[0], labels[0]); for (int i = 1; i < outputs.Count; i++) { var sl = StyleLossFunction(outputs[i], labels[i]); lossFunction = CNTK.CNTKLib.Plus(lossFunction, sl); } return(lossFunction); }
/// <summary> /// Infer the image from the trained model. /// </summary> /// <param name="model">The model to use.</param> /// <param name="batch">The evaluation batch to use.</param> /// <returns>The image inferred from the model.</returns> public static byte[] InferImage( this CNTK.Function model, Dictionary <CNTK.Variable, CNTK.Value> batch) { var outputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { model.Outputs[0], null } }; model.Evaluate(batch, outputs, NetUtil.CurrentDevice); var img = outputs[model.Outputs[0]].GetDenseData <float>(model.Outputs[0])[0].ToArray(); return(UnflattenByChannel(img, VGG19_Offsets)); }
public static void summary(CNTK.Function rootFunction) { var entries = new System.Collections.Generic.List <string>(); entries.Add(underscores); entries.Add("Layer (type) Output Shape Trainable Parameters #"); entries.Add(equalSigns); summary(rootFunction, entries, null); foreach (var v in entries) { Console.WriteLine(v); } }
static public void log_number_of_parameters(CNTK.Function model) { Console.WriteLine("\nModel Summary"); Console.WriteLine("\tInput = " + model.Arguments[0].Shape.AsString()); Console.WriteLine("\tOutput = " + model.Output.Shape.AsString()); Console.WriteLine(""); var numParameters = 0; foreach (var x in model.Parameters()) { var shape = x.Shape; var p = shape.TotalSize; Console.WriteLine(string.Format("\tFilter Shape:{0,-30} Param #:{1}", shape.AsString(), p)); numParameters += p; } Console.WriteLine(string.Format("\nTotal Number of Parameters: {0:N0}", numParameters)); Console.WriteLine("---\n"); }
/// <summary> /// Get an RMSProp learner to train the network. /// </summary> /// <param name="input">The network to train.</param> /// <param name="learningRateSchedule">The learning rate schedule.</param> /// <param name="gamma">The gamma value.</param> /// <param name="inc">The inc value.</param> /// <param name="dec">The dec value.</param> /// <param name="max">The max value.</param> /// <param name="min">The min value.</param> /// <returns>An RMSProp learner to train the network.</returns> public static CNTK.Learner GetRMSPropLearner( this CNTK.Function input, double learningRateSchedule, double gamma, double inc, double dec, double max, double min) { var parameterVector = new CNTK.ParameterVector((System.Collections.ICollection)input.Parameters()); return(CNTK.CNTKLib.RMSPropLearner( parameterVector, new CNTK.TrainingParameterScheduleDouble(learningRateSchedule), gamma, inc, dec, max, min)); }
public static (CNTK.Value featureBatch, CNTK.Value labelBatch) GetMisleadingBatch( CNTK.Function gan, int batchSize, int latentDimensions) { // set up a Gaussian random number generator var random = new Random(); var gaussianRandom = new GaussianRandom(random); // prepare a batch to fool the discriminator: we generate fake images // but we label them as real with label=0 var random_latent_vectors = gaussianRandom.getFloatSamples(batchSize * latentDimensions); var misleading_targets = new float[batchSize]; var random_latent_vectors_nd = new CNTK.NDArrayView(new int[] { latentDimensions, 1, batchSize }, random_latent_vectors, NetUtil.CurrentDevice); // return results return( new CNTK.Value(random_latent_vectors_nd), CNTK.Value.CreateBatch(new CNTK.NDShape(0), misleading_targets, NetUtil.CurrentDevice, true) ); }
float[][] compute_labels(CNTK.Function model, float[] target_image, float[] style_reference_image) { var input_shape = model.Arguments[0].Shape.Dimensions.ToArray(); System.Diagnostics.Debug.Assert(input_shape[0] * input_shape[1] * input_shape[2] == target_image.Length); System.Diagnostics.Debug.Assert(target_image.Length == style_reference_image.Length); #if false var cpuDevice = CNTK.DeviceDescriptor.CPUDevice; var target_image_nd = new CNTK.NDArrayView(input_shape, target_image, cpuDevice, readOnly: true); var style_reference_image_nd = new CNTK.NDArrayView(input_shape, style_reference_image, cpuDevice, readOnly: true); var batch_nd = new CNTK.NDArrayView[] { target_image_nd, style_reference_image_nd }; var batch = CNTK.Value.Create(input_shape, batch_nd, computeDevice, readOnly: true); #else var batch_buffer = new float[2 * target_image.Length]; Array.Copy(target_image, 0, batch_buffer, 0, target_image.Length); Array.Copy(style_reference_image, 0, batch_buffer, target_image.Length, target_image.Length); var batch_nd = new CNTK.NDArrayView(new int[] { model.Arguments[0].Shape[0], model.Arguments[0].Shape[1], model.Arguments[0].Shape[2], 1, 2 }, batch_buffer, computeDevice); var batch = new CNTK.Value(batch_nd); #endif var inputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { model.Arguments[0], batch } }; var outputs = new Dictionary <CNTK.Variable, CNTK.Value>(); foreach (var output in model.Outputs) { outputs.Add(output, null); } model.Evaluate(inputs, outputs, computeDevice); float[][] labels = new float[model.Outputs.Count][]; labels[0] = outputs[model.Outputs[0]].GetDenseData <float>(model.Outputs[0])[0].ToArray(); for (int i = 1; i < labels.Length; i++) { labels[i] = outputs[model.Outputs[i]].GetDenseData <float>(model.Outputs[i])[1].ToArray(); } return(labels); }
Dictionary <CNTK.Variable, CNTK.Value> create_batch(CNTK.Function model, float[][] labels) { var dict_inputs = new Dictionary <CNTK.Variable, CNTK.Value>(); for (int i = 0; i < model.Arguments.Count; i++) { var loss_input_variable = model.Arguments[i]; if (loss_input_variable.Name == "dummy_features") { var dummy_scalar_buffer = new float[] { 1 }; var dummy_scalar_nd = new CNTK.NDArrayView(new int[] { 1 }, dummy_scalar_buffer, computeDevice, readOnly: true); dict_inputs[loss_input_variable] = new CNTK.Value(dummy_scalar_nd); } else { var cs_index = Int32.Parse(loss_input_variable.Name.Substring("content_and_style_".Length)); var nd = new CNTK.NDArrayView(loss_input_variable.Shape, labels[cs_index], computeDevice, readOnly: true); dict_inputs[loss_input_variable] = new CNTK.Value(nd); } } return(dict_inputs); }
CNTK.Function create_model_cntk(int model_type, int[] input_shape, CNTK.DeviceDescriptor computeDevice) { CNTK.Function model = null; if (model_type == 0) { var dynamic_axes = new List <CNTK.Axis>() { CNTK.Axis.DefaultDynamicAxis(), CNTK.Axis.DefaultBatchAxis() }; var x_placeholder = CNTK.Variable.PlaceholderVariable(input_shape, dynamic_axes); model = Util.Dense(x_placeholder, 32, computeDevice); model = CNTK.CNTKLib.ReLU(model); model = Util.Dense(model, 1, computeDevice); } else if ((model_type == 1) || (model_type == 2)) { var filename = $"ch6-3_model_type_{model_type}.model"; model = CNTK.Function.Load(filename, computeDevice); Console.WriteLine("Loaded " + filename); } return(model); }
/// <summary> /// Calculate the output labels for style transfer. /// </summary> /// <param name="model">The neural network to use.</param> /// <param name="contentImage">The content image to use.</param> /// <param name="styleImage">The style image to use.</param> /// <returns></returns> public static float[][] CalculateLabels(CNTK.Function model, float[] contentImage, float[] styleImage) { // make sure the content image dimensions match the neural network input size // make sure the content and style images are the same size var input_shape = model.Arguments[0].Shape.Dimensions.ToArray(); System.Diagnostics.Debug.Assert(input_shape[0] * input_shape[1] * input_shape[2] == contentImage.Length); System.Diagnostics.Debug.Assert(contentImage.Length == styleImage.Length); // set up a batch with the content and the style image var batch_buffer = new float[2 * contentImage.Length]; Array.Copy(contentImage, 0, batch_buffer, 0, contentImage.Length); Array.Copy(styleImage, 0, batch_buffer, contentImage.Length, contentImage.Length); var batch_nd = new CNTK.NDArrayView(new int[] { model.Arguments[0].Shape[0], model.Arguments[0].Shape[1], model.Arguments[0].Shape[2], 1, 2 }, batch_buffer, NetUtil.CurrentDevice); var batch = new CNTK.Value(batch_nd); // let the model evaluate the batch var inputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { model.Arguments[0], batch } }; var outputs = new Dictionary <CNTK.Variable, CNTK.Value>(); foreach (var output in model.Outputs) { outputs.Add(output, null); } model.Evaluate(inputs, outputs, NetUtil.CurrentDevice); // collect and return the model outputs float[][] labels = new float[model.Outputs.Count][]; labels[0] = outputs[model.Outputs[0]].GetDenseData <float>(model.Outputs[0])[0].ToArray(); for (int i = 1; i < labels.Length; i++) { labels[i] = outputs[model.Outputs[i]].GetDenseData <float>(model.Outputs[i])[1].ToArray(); } return(labels); }
byte[] inference(CNTK.Function model, float[][] labels) { var batch = create_batch(model, labels); var outputs = new Dictionary <CNTK.Variable, CNTK.Value>() { { model.Outputs[0], null } }; model.Evaluate(batch, outputs, computeDevice); var img = outputs[model.Outputs[0]].GetDenseData <float>(model.Outputs[0])[0].ToArray(); var img_data = new byte[img.Length]; var image_size = img_height * img_width; for (int i = 0; i < img_data.Length; i += 3) { img_data[i] = (byte)Math.Max(0, Math.Min(img[i / 3] + offsets[0], 255)); img_data[i + 1] = (byte)Math.Max(0, Math.Min(img[i / 3 + image_size] + offsets[1], 255)); img_data[i + 2] = (byte)Math.Max(0, Math.Min(img[i / 3 + 2 * image_size] + offsets[2], 255)); } return(img_data); }
void train(CNTK.Function model, float[][] labels) { var content_and_style_outputs = traverse_content_and_styles_nodes(model); var label_variables = new List <CNTK.Variable>(); for (int i = 0; i < labels.Length; i++) { var shape = content_and_style_outputs[i].Shape; var input_variable = CNTK.Variable.InputVariable(shape, CNTK.DataType.Float, "content_and_style_" + i); label_variables.Add(input_variable); } var loss_function = create_loss_function(model, content_and_style_outputs, label_variables); var pv = new CNTK.ParameterVector((System.Collections.ICollection)model.Parameters()); var learner = CNTK.CNTKLib.AdamLearner(pv, new CNTK.TrainingParameterScheduleDouble(10), new CNTK.TrainingParameterScheduleDouble(0.95)); var trainer = CNTK.CNTKLib.CreateTrainer(model, loss_function, loss_function, new CNTK.LearnerVector() { learner }); var batch = create_batch(loss_function, labels); Console.WriteLine("Training on a " + computeDevice.AsString()); var startTime = DateTime.Now; for (int i = 0; i < 301; i++) { trainer.TrainMinibatch(batch, true, computeDevice); if (i % 100 == 0) { Console.WriteLine($"epoch {i}, loss={trainer.PreviousMinibatchLossAverage():F3}"); } } var elapsedTime = DateTime.Now.Subtract(startTime); Console.WriteLine($"Done in {elapsedTime.TotalSeconds:F1} seconds"); }
public static void PredorderTraverse(CNTK.Function rootFunction, int log_level = 0, System.Collections.Generic.ISet <CNTK.Function> visited = null) { Console.WriteLine($"{rootFunction.Name} -> {rootFunction.Output.Shape.AsString()}"); if (visited == null) { visited = new System.Collections.Generic.HashSet <CNTK.Function>(); } visited.Add(rootFunction); if (rootFunction.IsComposite) { PredorderTraverse(rootFunction.RootFunction, log_level, visited); return; } foreach (var rootInput in rootFunction.Inputs) { if (!rootInput.IsOutput) { Console.WriteLine($"\t{rootInput.Name}\t{rootInput.Shape.AsString()}"); if (log_level == 1) { Console.WriteLine("\t\t constant:" + rootInput.IsConstant); Console.WriteLine("\t\t input:" + rootInput.IsInput); Console.WriteLine("\t\t parameter:" + rootInput.IsInput); Console.WriteLine("\t\t placeholder:" + rootInput.IsPlaceholder); } continue; } if (visited.Contains(rootInput.Owner)) { continue; } PredorderTraverse(rootInput.Owner, log_level, visited); } }
public NDArrayTensor(CNTK.Function arr) { InternalTensor = arr; K = new SiaNetBackend(); }
protected Function(CNTK.Function function) : base(function) { UnderlyingFunction = function; }
/// <summary> /// Get an Adam learner to train the network. /// </summary> /// <param name="input">The network to train.</param> /// <param name="learningRateSchedule">The learning rate schedule.</param> /// <param name="momentumSchedule">The moment schedule.</param> /// <param name="unitGain">The unit gain.</param> /// <returns>An Adamlearner to train the network.</returns> public static CNTK.Learner GetAdamLearner( this CNTK.Function input, (double, uint) learningRateSchedule,