/// <summary> /// Transpose two axes in the neural network. /// </summary> /// <param name="input">The neural network to transpose.</param> /// <param name="axis1">The first axis to transpose.</param> /// <param name="axis2">The second axis to transpose.</param> /// <returns>The neural network with the axes transposed.</returns> public static CNTK.Variable TransposeAxes( this CNTK.Variable input, CNTK.Axis axis1, CNTK.Axis axis2) { return(CNTK.CNTKLib.TransposeAxes(input, axis1, axis2)); }
/// <summary> /// The mean absolute error loss function for linear models. /// </summary> /// <param name="prediction">The prediction variable</param> /// <param name="labels">The label variable</param> /// <returns></returns> public static CNTK.Function MeanAbsoluteError(CNTK.Variable prediction, CNTK.Variable labels) { var absolute_errors = CNTK.CNTKLib.Abs(CNTK.CNTKLib.Minus(prediction, labels)); var result = CNTK.CNTKLib.ReduceMean(absolute_errors, new CNTK.Axis(0)); // TODO -- allStaticAxes? return(result); }
/// <summary> /// Get a new batch of images to train the discriminator. /// The batch will contain generated images with label 1 and actual images with label 0. /// </summary> /// <param name="discriminatorVar">The input variable for the discriminator.</param> /// <param name="generatedImages">The list of generated images.</param> /// <param name="actualImages">The list of actual images.</param> /// <param name="batchSize">The batch size.</param> /// <param name="start">The start position in the training partition.</param> /// <returns>A tuple with the feature batch and label batch for training.</returns> public static (CNTK.Value featureBatch, CNTK.Value labelBatch) GetTrainingBatch( CNTK.Variable discriminatorVar, IList <IList <float> > generatedImages, float[][] actualImages, int batchSize, int start) { // set up a Gaussian random number generator var random = new Random(); var gaussianRandom = new GaussianRandom(random); // create a training batch for the discriminator // the first half of the mini-batch are the fake images (marked with label='1') // the second half are real images (marked with label='0') var combined_images = new float[2 * batchSize][]; var labels = new float[2 * batchSize]; for (int i = 0; i < batchSize; i++) { combined_images[i] = generatedImages[i].ToArray(); labels[i] = (float)(1 + 0.05 * gaussianRandom.NextGaussian()); combined_images[i + batchSize] = actualImages[start + i]; labels[i + batchSize] = (float)(0.05 * gaussianRandom.NextGaussian()); } // create batches var combined_images_minibatch = discriminatorVar.GetBatch(combined_images, 0, combined_images.Length); var labels_minibatch = CNTK.Value.CreateBatch(new CNTK.NDShape(0), labels, NetUtil.CurrentDevice, true); // return results return(combined_images_minibatch, labels_minibatch); }
/// <summary> /// Add an LSTM layer to the neural network. /// </summary> /// <param name="input">The neural network to expand</param> /// <param name="lstmDimensions">The number of lstm dimensions to user</param> /// <param name="cellDimensions">The number of cell dimensions to use</param> /// <returns>The neural network with the dropout layer added</returns> public static CNTK.Variable LSTM( this CNTK.Variable input, int lstmDimensions, int cellDimensions) { return(LSTMSequenceClassifier.LSTM(input, lstmDimensions, cellDimensions, NetUtil.CurrentDevice, "lstm")); }
/// <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); }
/// <summary> /// Add a dense layer to a neural network. /// </summary> /// <param name="input">The neural network to expand.</param> /// <param name="outputDim">The number of dimensions in the dense layer.</param> /// <param name="outputName">The name of the layer.</param> /// <returns>The neural network with the dense layer added.</returns> public static CNTK.Variable Dense( this CNTK.Variable input, int outputDim, string outputName = "") { var shape = CNTK.NDShape.CreateNDShape(new int[] { outputDim, CNTK.NDShape.InferredDimension }); var timesParam = new CNTK.Parameter( shape, CNTK.DataType.Float, CNTK.CNTKLib.GlorotUniformInitializer( CNTK.CNTKLib.DefaultParamInitScale, CNTK.CNTKLib.SentinelValueForInferParamInitRank, CNTK.CNTKLib.SentinelValueForInferParamInitRank, 1), CurrentDevice, "timesParam_" + outputName); var timesFunction = CNTK.CNTKLib.Times( timesParam, input, 1 /* output dimension */, 0 /* CNTK should infer the input dimensions */); var plusParam = new CNTK.Parameter( CNTK.NDShape.CreateNDShape(new int[] { CNTK.NDShape.InferredDimension }), 0.0f, CurrentDevice, "plusParam_" + outputName); var result = CNTK.CNTKLib.Plus(plusParam, timesFunction, outputName); return(result); }
/// <summary> /// The mean squared error loss function for linear models. /// </summary> /// <param name="prediction">The prediction variable</param> /// <param name="labels">The label variable</param> /// <returns></returns> public static CNTK.Function MeanSquaredError(CNTK.Variable prediction, CNTK.Variable labels) { var squared_errors = CNTK.CNTKLib.Square(CNTK.CNTKLib.Minus(prediction, labels)); var result = CNTK.CNTKLib.ReduceMean(squared_errors, new CNTK.Axis(0)); // TODO -- allStaticAxes? return(result); }
/// <summary> /// Add a dense layer to a neural network. /// </summary> /// <param name="input">The neural network to expand.</param> /// <param name="outputDim">The number of dimensions in the dense layer.</param> /// <param name="activation">The activation function in the dense layer.</param> /// <param name="outputName">The name of the layer.</param> /// <returns>The neural network with the dense layer added.</returns> public static CNTK.Variable Dense( this CNTK.Variable input, int outputDim, Func <CNTK.Variable, CNTK.Function> activation, string outputName = "") { return((CNTK.Variable)activation(Dense(input, outputDim, outputName))); }
/// <summary> /// Add a pooling layer to a neural network. /// </summary> /// <param name="input">The neural network to expand</param> /// <param name="poolingType">The type of pooling to perform</param> /// <param name="windowShape">The shape of the pooling window</param> /// <param name="strides">The stride lengths</param> /// <returns>The neural network with the pooling layer added.</returns> public static CNTK.Variable Pooling( this CNTK.Variable input, CNTK.PoolingType poolingType, CNTK.NDShape windowShape, int[] strides) { return(CNTK.CNTKLib.Pooling(input, poolingType, windowShape, strides)); }
CNTK.Function gram_matrix(CNTK.Variable x) { var x_shape = x.Shape.Dimensions.ToArray(); var features = CNTK.CNTKLib.Reshape(x, new int[] { x_shape[0] * x_shape[1], x_shape[2] }, name: "gram_matrix_reshape_"); var gram = CNTK.CNTKLib.TransposeTimes(features, features, name: "gram_matrix_transpose_times_"); return(gram); }
/// <summary> /// Multiply all tensor elements in the network by the given scalar. /// </summary> /// <typeparam name="T">The type of the scalar to multiply by</typeparam> /// <param name="input">The neural network</param> /// <param name="scalar">The scalar to multiply by</param> /// <returns>The neural network with the multiplication layer added</returns> public static CNTK.Variable MultiplyBy <T>( this CNTK.Variable input, T scalar) { var scalarTensor = CNTK.Constant.Scalar <T>(scalar, NetUtil.CurrentDevice); return(CNTK.CNTKLib.ElementTimes(scalarTensor, input)); }
/// <summary> /// The binary accuracy loss function for binary classifiers. /// </summary> /// <param name="prediction">The prediction variable</param> /// <param name="labels">The label variable</param> /// <returns></returns> public static CNTK.Function BinaryAccuracy(CNTK.Variable prediction, CNTK.Variable labels) { var round_predictions = CNTK.CNTKLib.Round(prediction); var equal_elements = CNTK.CNTKLib.Equal(round_predictions, labels); var result = CNTK.CNTKLib.ReduceMean(equal_elements, CNTK.Axis.AllStaticAxes()); return(result); }
/// <summary> /// Add a one-hot encoder to the neural network. /// </summary> /// <param name="input">The neural network to expand</param> /// <param name="numberOfClasses">The number of output classes to encode</param> /// <param name="outputSparse">Indicates if the output is a sparse vector</param> /// <returns>The neural network with the dropout layer added</returns> public static CNTK.Variable OneHotOp( this CNTK.Variable input, int numberOfClasses, bool outputSparse ) { return(CNTK.CNTKLib.OneHotOp(input, (uint)numberOfClasses, outputSparse, new CNTK.Axis(0))); }
/// <summary> /// Create a style transfer base model from a VGG19 network. /// </summary> /// <param name="feature">The input feature to use.</param> /// <returns>A neural network containing the content and style layers of the VGG19 network.</returns> public static CNTK.Function StyleTransferBase( this CNTK.Variable input) { // extract all content and style layers var layers = ((CNTK.Function)input).GetContentAndStyleLayers(); // return a model from these layers return(CNTK.Function.Combine(layers, "content_and_styles").Clone(CNTK.ParameterCloningMethod.Freeze)); }
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_); }
static public CNTK.Function get_model(CNTK.Variable features, CNTK.DeviceDescriptor computeDevice, bool allow_block5_finetuning = false) { // load the original VGG16 model download_model_if_needed(); var model = CNTK.Function.Load(fullpath, computeDevice); // get the last VGG16 layer before the first fully connected layer var last_frozen_layer = model.FindByName(allow_block5_finetuning ? "pool4" : "pool5"); // get the first layer, and the "data" input variable var conv1_1_layer = model.FindByName("conv1_1"); var data = conv1_1_layer.Inputs.First((v) => v.Name == "data"); // the data should be a 224x224x3 input tensor if (!data.Shape.Dimensions.SequenceEqual(new int[] { 224, 224, 3 })) { System.Console.WriteLine("There's a problem here. Please email"); System.Environment.Exit(2); } // allow different dimensions for input (e.g., 150x150x3) var replacements = new System.Collections.Generic.Dictionary <CNTK.Variable, CNTK.Variable>() { { data, features } }; // clone the original VGG16 model up to the pool_node, freeze all weights, and use a custom input tensor var frozen_model = CNTK.CNTKLib .Combine(new CNTK.VariableVector() { last_frozen_layer.Output }, "frozen_output") .Clone(CNTK.ParameterCloningMethod.Freeze, replacements); if (!allow_block5_finetuning) { return(frozen_model); } var pool5_layer = model.FindByName("pool5"); replacements = new System.Collections.Generic.Dictionary <CNTK.Variable, CNTK.Variable>() { { last_frozen_layer.Output, frozen_model.Output } }; var model_with_finetuning = CNTK.CNTKLib .Combine(new CNTK.VariableVector() { pool5_layer.Output }, "finetuning_output") .Clone(CNTK.ParameterCloningMethod.Clone, replacements); return(model_with_finetuning); }
/// <summary> /// Get a batch from the given variable. /// </summary> /// <param name="variable">The variable to use.</param> /// <param name="source">The variable data.</param> /// <param name="begin">The index of the first value to use.</param> /// <param name="end">The index of the last value to use.</param> /// <returns>A batch of values taken from the given variable.</returns> public static CNTK.Value GetBatch( this CNTK.Variable variable, float[] source, int begin, int end) { var result = new float[end - begin]; Array.Copy(source, begin, result, 0, result.Length); return(CNTK.Value.CreateBatch(variable.Shape, result, NetUtil.CurrentDevice, true)); }
CNTK.Value create_x_minibatch(bool sequence_mode, CNTK.Variable x, GeneratorsInfo gi, SamplesTargets st, CNTK.DeviceDescriptor computeDevice) { if (sequence_mode == false) { return(CNTK.Value.CreateBatch(x.Shape, st.samples, computeDevice)); } var sequence_length = gi.lookback / gi.step; var minibatch_size = st.samples.Length / sequence_length / gi.num_records; var x_shape = CNTK.NDShape.CreateNDShape(new int[] { gi.num_records, sequence_length, minibatch_size }); var ndArrayView = new CNTK.NDArrayView(x_shape, st.samples, computeDevice, readOnly: true); return(new CNTK.Value(ndArrayView)); }
/// <summary> /// Add an embedding layer to the neural network. /// </summary> /// <param name="input">The neural network to expand</param> /// <param name="embeddingDimensions">The number of embedding dimensions to create</param> /// <returns>The neural network with the dropout layer added</returns> public static CNTK.Variable Embedding( this CNTK.Variable input, int embeddingDimensions) { var weight_shape = new int[] { embeddingDimensions, CNTK.NDShape.InferredDimension }; var E = new CNTK.Parameter( weight_shape, CNTK.DataType.Float, CNTK.CNTKLib.GlorotUniformInitializer(), NetUtil.CurrentDevice); return(CNTK.CNTKLib.Times(E, input)); }
CNTK.Function style_loss(CNTK.Variable style, CNTK.Variable combination) { var style_gram = gram_matrix(style); var combination_gram = gram_matrix(combination); var diff_ = CNTK.CNTKLib.Minus(style_gram, combination_gram, name: "style_loss_diff_"); var square_ = CNTK.CNTKLib.Square(diff_, name: "style_loss_square_"); var sum_ = CNTK.CNTKLib.ReduceSum(square_, CNTK.Axis.AllStaticAxes(), name: "style_loss_reduce_sum_"); var max_ = CNTK.CNTKLib.ReduceMax(style_gram, CNTK.Axis.AllStaticAxes(), name: "style_loss_reduce_max"); var style_gram_total_size = style_gram.Output.Shape.Dimensions[0] * style_gram.Output.Shape.Dimensions[1]; var scaling_factor = CNTK.Constant.Scalar((float)style_gram_total_size, computeDevice); var result = CNTK.CNTKLib.ElementDivide(sum_, scaling_factor, name: "style_loss_result_"); result = CNTK.CNTKLib.ElementDivide(result, max_, name: "style_loss_"); return(result); }
/// <summary> /// Get a batch from the given variable. /// </summary> /// <param name="variable">The variable to use.</param> /// <param name="source">The variable data.</param> /// <param name="begin">The index of the first value to use.</param> /// <param name="end">The index of the last value to use.</param> /// <returns>A batch of values taken from the given variable.</returns> public static CNTK.Value GetBatch( this CNTK.Variable variable, float[][] source, int begin, int end) { var num_indices = end - begin; var result = new CNTK.NDArrayView[num_indices]; var row_index = 0; for (var index = begin; index != end; index++) { var dataBuffer = source[index]; var ndArrayView = new CNTK.NDArrayView(variable.Shape, dataBuffer, CNTK.DeviceDescriptor.CPUDevice, true); result[row_index++] = ndArrayView; } return(CNTK.Value.Create(variable.Shape, result, NetUtil.CurrentDevice, true)); }
/// <summary> /// Get a batch from the given variable. /// </summary> /// <param name="variable">The variable to use.</param> /// <param name="source">The variable data.</param> /// <param name="indices">The array of data indices to use.</param> /// <param name="begin">The first index to use.</param> /// <param name="end">The last index to use.</param> /// <returns>A batch of values taken from the given variable.</returns> public static CNTK.Value GetBatch( this CNTK.Variable variable, float[] source, int[] indices, int begin, int end) { var num_indices = end - begin; var row_length = variable.Shape.TotalSize; var result = new float[num_indices]; var row_index = 0; for (var index = begin; index != end; index++) { result[row_index++] = source[indices[index]]; } return(CNTK.Value.CreateBatch(variable.Shape, result, NetUtil.CurrentDevice, true)); }
public static DataSourceBase <float, IList <float> > FromVariable(CNTK.Variable variable) { var array = variable.GetValue(); if (array.IsSparse) { throw new NotImplementedException("Sparse value is not supported yet"); } if (array.DataType != CNTK.DataType.Float) { throw new NotImplementedException("Only float value is supported"); } var value = new CNTK.Value(array); var result = value.GetDenseData <float>(variable); return(new DataSourceBase <float, IList <float> >(result[0], value.Shape.Dimensions.ToArray())); }
List <List <double> > train_mse_cntk(bool sequence_mode, CNTK.Variable x, CNTK.Variable y, CNTK.Function model, GeneratorsInfo gi, int epochs, int steps_per_epoch, CNTK.DeviceDescriptor computeDevice) { var loss_function = CNTK.CNTKLib.SquaredError(model, y); var accuracy_function = loss_function; var lr = 0.001; var parameterVector = new CNTK.ParameterVector((System.Collections.ICollection)model.Parameters()); var learner = CNTK.CNTKLib.AdamLearner(parameterVector, new CNTK.TrainingParameterScheduleDouble(lr /*, (uint)batch_size*/), new CNTK.TrainingParameterScheduleDouble(0.9 /*, (uint)batch_size*/), unitGain: false); var trainer = CNTK.CNTKLib.CreateTrainer(model, loss_function, accuracy_function, new CNTK.LearnerVector() { learner }); var evaluator = CNTK.CNTKLib.CreateEvaluator(accuracy_function); var history = fit_generator(sequence_mode, x, y, model, trainer, evaluator, gi, epochs, steps_per_epoch, computeDevice); return(history); }
/// <summary> /// Get a sequence batch from the given variable. /// </summary> /// <param name="variable">The variable to use.</param> /// <param name="sequenceLength">The number of time periods in the data sequence.</param> /// <param name="source">The variable data.</param> /// <param name="begin">The index of the first value to use.</param> /// <param name="end">The index of the last value to use.</param> /// <returns>A batch of values taken from the given variable.</returns> public static CNTK.Value GetSequenceBatch( this CNTK.Variable variable, int sequenceLength, float[] source, int begin, int end) { System.Diagnostics.Debug.Assert((variable.Shape.Dimensions.Count == 0) || ((variable.Shape.Dimensions.Count == 1) && (variable.Shape.Dimensions[0] == 1))); var num_indices = end - begin; var cpu_tensors = new float[num_indices][]; var row_index = 0; for (var index = begin; index != end; index++) { cpu_tensors[row_index] = new float[sequenceLength]; cpu_tensors[row_index][sequenceLength - 1] = source[index]; row_index++; } var result = CNTK.Value.CreateBatchOfSequences(variable.Shape, cpu_tensors, NetUtil.CurrentDevice, true); return(result); }
/// <summary> /// Add a 1D convolution layer to a neural network. /// </summary> /// <param name="input">The neural network to expand.</param> /// <param name="outputChannels">The number of output channels</param> /// <param name="filterShape">The shape of the filter</param> /// <param name="padding">Use padding or not?</param> /// <param name="bias">Use bias or not?</param> /// <param name="strides">The stride lengths</param> /// <param name="activation">The activation function to use</param> /// <param name="outputName">The name of the layer.</param> /// <returns>The neural network with the convolution layer added.</returns> public static CNTK.Variable Convolution1D( this CNTK.Variable input, int outputChannels, int filterShape, bool padding = false, bool bias = true, int[] strides = null, Func <CNTK.Variable, string, CNTK.Function> activation = null, string outputName = "") { var convolution_map_size = new int[] { filterShape, CNTK.NDShape.InferredDimension, outputChannels }; if (strides == null) { strides = new int[] { 1 }; } return(Convolution(convolution_map_size, input, padding, bias, strides, activation, outputName)); }
static public CNTK.Function Convolution2DWithReLU(CNTK.Variable input, int num_output_channels, int[] filter_shape, CNTK.DeviceDescriptor device, bool use_padding = false, bool use_bias = true, string outputName = "") { var convolution_map_size = new int[] { filter_shape[0], filter_shape[1], CNTK.NDShape.InferredDimension, num_output_channels }; var W = new CNTK.Parameter( CNTK.NDShape.CreateNDShape(convolution_map_size), CNTK.DataType.Float, CNTK.CNTKLib.GlorotUniformInitializer(CNTK.CNTKLib.DefaultParamInitScale, CNTK.CNTKLib.SentinelValueForInferParamInitRank, CNTK.CNTKLib.SentinelValueForInferParamInitRank, 1), device, outputName + "_W"); var result = CNTK.CNTKLib.Convolution(W, input, CNTK.NDShape.CreateNDShape(new int[] { 1 }) /*strides*/, new CNTK.BoolVector(new bool[] { true }) /* sharing */, new CNTK.BoolVector(new bool[] { use_padding })); if (use_bias) { var b = new CNTK.Parameter(CNTK.NDShape.CreateNDShape(new int[] { 1, 1, CNTK.NDShape.InferredDimension }), 0.0f, device, outputName + "_b"); result = CNTK.CNTKLib.Plus(result, b); } result = CNTK.CNTKLib.ReLU(result, outputName); return(result); }
/// <summary> /// Get a sequence batch from the given variable. /// </summary> /// <param name="variable">The variable to use.</param> /// <param name="sequenceLength">The number of time periods in the data sequence.</param> /// <param name="source">The variable data.</param> /// <param name="begin">The index of the first value to use.</param> /// <param name="end">The index of the last value to use.</param> /// <returns>A batch of values taken from the given variable.</returns> public static CNTK.Value GetSequenceBatch( this CNTK.Variable variable, int sequenceLength, float[][] source, int begin, int end) { System.Diagnostics.Debug.Assert((variable.Shape.Dimensions.Count == 0) || ((variable.Shape.Dimensions.Count == 1) && (variable.Shape.Dimensions[0] == 1))); System.Diagnostics.Debug.Assert(source[0].Length == sequenceLength); var num_indices = end - begin; var cpu_blob = new float[num_indices * sequenceLength]; var row_index = 0; for (var index = begin; index != end; index++) { System.Buffer.BlockCopy(source[index], 0, cpu_blob, row_index * sequenceLength * sizeof(float), sequenceLength * sizeof(float)); row_index++; } var blob_shape = variable.Shape.AppendShape(new int[] { sequenceLength, end - begin }); var ndArrayView = new CNTK.NDArrayView(blob_shape, cpu_blob, NetUtil.CurrentDevice); return(new CNTK.Value(ndArrayView)); }
/// <summary> /// Cast a network layer to a Function. /// </summary> /// <param name="input">The neural network to expand.</param> /// <returns>The neural network layer cast to a Function instance.</returns> public static CNTK.Function ToNetwork( this CNTK.Variable input) { return((CNTK.Function)input); }
public static IDataSource <float> VariableToDataSource(CNTK.Variable variable) { return(DataSourceFactory.FromVariable(variable)); }