How to use a loss function that is not differentiable?
I am trying to find a codebook at the output of a fully connected neural network which chooses points such that the minimum distance (Euclidean norm) between the so produced codebook is maximized. The input to the neural network is the points that need to be mapped into higher dimension of the output space.
For instance, if the input dimension is 2 and output dimension is 3, the following mapping (and any permutations) works best: 00 - 000, 01 - 011, 10 - 101, 11 - 110
``` import tensorflow as tf import numpy as np import itertools
input_bits = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='input_bits') code_out = tf.placeholder(dtype=tf.float32, shape=[None, 3], name='code_out') np.random.seed(1331)
def find_code(message): weight1 = np.random.normal(loc=0.0, scale=0.01, size=[2, 3]) init1 = tf.constant_initializer(weight1) out = tf.layers.dense(inputs=message, units=3, activation=tf.nn.sigmoid, kernel_initializer=init1) return out
code = find_code(input_bits)
distances = [] for i in range(0, 3): for j in range(i+1, 3): distances.append(tf.linalg.norm(code_out[i]-code_out[j])) min_dist = tf.reduce_min(distances)
avg_dist = tf.reduce_mean(distances)
loss = -min_dist
opt = tf.train.AdamOptimizer().minimize(loss)
init_variables = tf.global_variables_initializer() sess = tf.Session() sess.run(init_variables)
saver = tf.train.Saver()
count = int(1e4)
for i in range(count): input_bit = [list(k) for k in itertools.product([0, 1], repeat=2)] code_preview = sess.run(code, feed_dict={input_bits: input_bit}) sess.run(opt, feed_dict={input_bits: input_bit, code_out: code_preview}) ```
Since the loss function itself is not differentiable, I am getting the error
ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables
Am I doing something silly or is there a way to circumvent this? Any help in this regard is appreciated. Thanks in advance.
UPDATE:
``` import tensorflow as tf import numpy as np import itertools from random import shuffle
input_bits = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='input_bits') learning_rate_val = tf.placeholder(dtype=tf.float32, shape=(), name='learning_rate')
def find_code(message): weight1 = np.random.normal(loc=0.0, scale=0.01, size=[2, 3]) init1 = tf.constant_initializer(weight1) out1 = tf.layers.dense(inputs=message, units=3, activation=tf.nn.sigmoid, kernel_initializer=init1) return out1
code = find_code(input_bits)
distances = [] for i in range(0, 4): for j in range(i+1, 4): distances.append(tf.linalg.norm(code[i]-code[j])) min_dist = tf.reduce_min(distances)
avg_dist = tf.reduce_mean(distances)
loss = - min_dist
opt = tf.train.AdamOptimizer().minimize(loss)
init_variables = tf.global_variables_initializer() sess = tf.Session() sess.run(init_variables)
saver = tf.train.Saver()
count = int(9e5) threshold = 0.5
for i in range(count): input_bit = [list(k) for k in itertools.product([0, 1], repeat=2)] shuffle(input_bit) input_bit = 2 * np. 695