TensorFlow.NET.Samples/ImageProcessing/RetrainImageClassifierTransferLearningTFNET.cs
/// <summary>
/// Adds a new softmax and fully-connected layer for training and eval.
/// 
/// We need to retrain the top layer to identify our new classes, so this function
/// adds the right operations to the graph, along with some variables to hold the
/// weights, and then sets up all the gradients for the backward pass.
/// 
/// The set up for the softmax and fully-connected layers is based on:
/// https://www.tensorflow.org/tutorials/mnist/beginners/index.html
/// </summary>
/// <param name="class_count"></param>
/// <param name="final_tensor_name"></param>
/// <param name="bottleneck_tensor"></param>
/// <param name="quantize_layer"></param>
/// <param name="is_training"></param>
/// <returns></returns>
Adds a new softmax and fully-connected layer for training and eval.

We need to retrain the top layer to identify our new classes, so this function
adds the right operations to the graph, along with some variables to hold the
weights, and then sets up all the gradients for the backward pass.


Adds a new softmax and fully - connected layer for training and eval . We need to retrain the top layer to identify our new classes so this function adds the right operations to the graph along with some variables to hold the weights and then sets up all the gradients for the backward pass .
private (Operation, Tensor, Tensor, Tensor, Tensor) add_final_retrain_ops(int class_count, string final_tensor_name,
            Tensor bottleneck_tensor, bool quantize_layer, bool is_training)
        {
            var (batch_size, bottleneck_tensor_size) = (bottleneck_tensor.TensorShape.Dimensions[0], bottleneck_tensor.TensorShape.Dimensions[1]);
            with(tf.name_scope("input"), scope =>
            {
                bottleneck_input = tf.placeholder_with_default(
                    bottleneck_tensor,
                    shape: bottleneck_tensor.TensorShape.Dimensions,
                    name: "BottleneckInputPlaceholder");
                ground_truth_input = tf.placeholder(tf.int64, new TensorShape(batch_size), name: "GroundTruthInput");
            });
            string layer_name = "final_retrain_ops";
            Tensor logits = null;
            with(tf.name_scope(layer_name), scope =>
            {
                RefVariable layer_weights = null;
                with(tf.name_scope("weights"), delegate
                {
                    var initial_value = tf.truncated_normal(new int[] { bottleneck_tensor_size, class_count }, stddev: 0.001f);
                    layer_weights = tf.Variable(initial_value, name: "final_weights");
                    variable_summaries(layer_weights);
                });
                RefVariable layer_biases = null;
                with(tf.name_scope("biases"), delegate
                {
                    layer_biases = tf.Variable(tf.zeros(class_count), name: "final_biases");
                    variable_summaries(layer_biases);
                });
                with(tf.name_scope("Wx_plus_b"), delegate
                {
                    logits = tf.matmul(bottleneck_input, layer_weights) + layer_biases;
                    tf.summary.histogram("pre_activations", logits);
                });
            });
            final_tensor = tf.nn.softmax(logits, name: final_tensor_name);
            if (quantize_layer)
            {
                throw new NotImplementedException("quantize_layer");
            }
            tf.summary.histogram("activations", final_tensor);
            if (!is_training)
                return (null, null, bottleneck_input, ground_truth_input, final_tensor);
            Tensor cross_entropy_mean = null;
            with(tf.name_scope("cross_entropy"), delegate
            {
                cross_entropy_mean = tf.losses.sparse_softmax_cross_entropy(
                    labels: ground_truth_input, logits: logits);
            });
            tf.summary.scalar("cross_entropy", cross_entropy_mean);
            with(tf.name_scope("train"), delegate
            {
                var optimizer = tf.train.GradientDescentOptimizer(learning_rate);
                train_step = optimizer.minimize(cross_entropy_mean);
            });
            return (train_step, cross_entropy_mean, bottleneck_input, ground_truth_input,
                final_tensor);
        }
private ( Operation , Tensor , Tensor , Tensor , Tensor ) add_final_retrain_ops ( int class_count , string final_tensor_name , Tensor bottleneck_tensor , bool quantize_layer , bool is_training ) { var ( batch_size , bottleneck_tensor_size ) = ( bottleneck_tensor . TensorShape . Dimensions [ 0 ] , bottleneck_tensor . TensorShape . Dimensions [ 1 ] ) ; with ( tf . name_scope ( " " ) , scope => { bottleneck_input = tf . placeholder_with_default ( bottleneck_tensor , shape : bottleneck_tensor . TensorShape . Dimensions , name : " " ) ; ground_truth_input = tf . placeholder ( tf . int64 , new TensorShape ( batch_size ) , name : " " ) ; } ) ; string layer_name = " " ; Tensor logits = null ; with ( tf . name_scope ( layer_name ) , scope => { RefVariable layer_weights = null ; with ( tf . name_scope ( " " ) , delegate { var initial_value = tf . truncated_normal ( new int [ ] { bottleneck_tensor_size , class_count } , stddev : 0.001f ) ; layer_weights = tf . Variable ( initial_value , name : " " ) ; variable_summaries ( layer_weights ) ; } ) ; RefVariable layer_biases = null ; with ( tf . name_scope ( " " ) , delegate { layer_biases = tf . Variable ( tf . zeros ( class_count ) , name : " " ) ; variable_summaries ( layer_biases ) ; } ) ; with ( tf . name_scope ( " " ) , delegate { logits = tf . matmul ( bottleneck_input , layer_weights ) + layer_biases ; tf . summary . histogram ( " " , logits ) ; } ) ; } ) ; final_tensor = tf . nn . softmax ( logits , name : final_tensor_name ) ; if ( quantize_layer ) { throw new NotImplementedException ( " " ) ; } tf . summary . histogram ( " " , final_tensor ) ; if ( ! is_training ) return ( null , null , bottleneck_input , ground_truth_input , final_tensor ) ; Tensor cross_entropy_mean = null ; with ( tf . name_scope ( " " ) , delegate { cross_entropy_mean = tf . losses . sparse_softmax_cross_entropy ( labels : ground_truth_input , logits : logits ) ; } ) ; tf . summary . scalar ( " " , cross_entropy_mean ) ; with ( tf . name_scope ( " " ) , delegate { var optimizer = tf . train . GradientDescentOptimizer ( learning_rate ) ; train_step = optimizer . minimize ( cross_entropy_mean ) ; } ) ; return ( train_step , cross_entropy_mean , bottleneck_input , ground_truth_input , final_tensor ) ; }
Adds a new softmax and fully-connected layer for training and eval.
Adds a new softmax and fully - connected layer for training and eval .
// Organizing the following ops so they are easier to see in TensorBoard. // The tf.contrib.quantize functions rewrite the graph in place for // quantization. The imported model graph has already been rewritten, so upon // calling these rewrites, only the newly added final layer will be // transformed. /*if (is_training)
                    tf.contrib.quantize.create_training_graph();
                else
                    tf.contrib.quantize.create_eval_graph();*/ // If this is an eval graph, we don't need to add loss ops or an optimizer.
None
class_count
int
None
final_tensor_name
string
None
bottleneck_tensor
Tensor
None
quantize_layer
bool
None
is_training
bool
None