title: How to freeze/lock weights of one TensorFlow variable (e.g., one CNN kernel of one layer)
body: <p>I have a TensorFlow CNN model that is performing well and we would like to implement this model in hardware; i.e., an FPGA. It's a relatively small network but it would be ideal if it were smaller. With that goal, I've examined the kernels and find that there are some where the weights are quite strong and there are others that aren't doing much at all (the kernel values are all close to zero). This occurs specifically in layer 2, corresponding to the tf.Variable() named, "W_conv2". W_conv2 has shape [3, 3, 32, 32]. I would like to freeze/lock the values of W_conv2[:, :, 29, 13] and set them to zero so that the rest of the network can be trained to compensate. Setting the values of this kernel to zero effectively removes/prunes the kernel from the hardware implementation thus achieving the goal stated above.</p>
  
  <p>I have found similar questions with suggestions that generally revolve around one of two approaches; </p>
  
  <p>Suggestion #1: </p>
  
  <pre><code>    tf.Variable(some_initial_value, trainable = False)
  </code></pre>
  
  <p>Implementing this suggestion freezes the entire variable. I want to freeze just a slice, specifically W_conv2[:, :, 29, 13].</p>
  
  <p>Suggestion #2:</p>
  
  <pre><code>    Optimizer = tf.train.RMSPropOptimizer(0.001).minimize(loss, var_list)
  </code></pre>
  
  <p>Again, implementing this suggestion does not allow the use of slices. For instance, if I try the inverse of my stated goal (optimize only a single kernel of a single variable) as follows:</p>
  
  <pre><code>    Optimizer = tf.train.RMSPropOptimizer(0.001).minimize(loss, var_list = W_conv2[:,:,0,0]))
  </code></pre>
  
  <p>I get the following error:</p>
  
  <pre><code>    NotImplementedError: ('Trying to optimize unsupported type ', &lt;tf.Tensor 'strided_slice_2228:0' shape=(3, 3) dtype=float32&gt;)
  </code></pre>
  
  <p>Slicing tf.Variables() isn't possible in the way that I've tried it here. The only thing that I've tried which comes close to doing what I want is using .assign() but this is extremely inefficient, cumbersome, and caveman-like as I've implemented it as follows (after the model is trained):</p>
  
  <pre><code>    for _ in range(10000):
          # get a new batch of data
          # reset the values of W_conv2[:,:,29,13]=0 each time through
          for m in range(3):
              for n in range(3):
                  assign_op = W_conv2[m,n,29,13].assign(0)
                  sess.run(assign_op)
          # re-train the rest of the network
          _, loss_val = sess.run([optimizer, loss], feed_dict = {
                                     dict_stuff_here
                                 })
          print(loss_val)
  </code></pre>
  
  <p>The model was started in Keras then moved to TensorFlow since Keras didn't seem to have a mechanism to achieve the desired results. I'm starting to think that TensorFlow doesn't allow for pruning but find this hard to believe; it just needs the correct implementation.</p>