没有梯度的 Tensorflow 损失函数
Tensorflow loss function having no gradients
我可能需要一些帮助来实现损失函数的特定正则化项。但是它没有梯度,我想知道是否有任何方法可以改变它。我在一篇论文中读过这种方法,但是阅读这篇论文对于实际帮助我并不重要。我将只描述问题所在的方法,并在 Google-Colab.
中显示测试代码
神经网络仅由 2 个卷积层组成,最后一层具有 Sigmoid 激活函数。因此,由于 Sigmoid,输出介于 0 和 1 之间。这个值将被视为输出层中每个神经元为 0 或 1 的概率。所以我想用 'tf.keras.backend.switch' 函数以这种方式实现它:
def regularization_term(y_true, y_pred):
zeros = tf.zeros_like(y_pred)
ones = tf.ones_like(y_pred)
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, zeros, ones)
return y_pred_new
我抽取一个随机数并检查条件以使每个值都为 0 或 1。代码中应该清楚这一点。但是,当我这样做时,该术语实际上没有渐变:
ValueError: No gradients provided for any variable: ['conv2d_4/kernel:0', 'conv2d_4/bias:0', 'conv2d_5/kernel:0', 'conv2d_5/bias:0'].
完整的测试代码可以在这个 colab 中找到:https://colab.research.google.com/drive/1YuX00BUAj-BVCZRbr4opo5wHbcaVbYvx?usp=sharing
有什么方法可以实现这个方法同时保持梯度使网络学习?如果有任何不清楚的地方,请询问,我已尽力使我的问题尽可能易于理解。我很高兴能得到任何帮助。
非常感谢!
[编辑,从 GOOGLE_COLAB 复制粘贴,否则忽略:]
#just importing some libraries
import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
from tensorflow.keras import datasets, layers, models
tf.keras.backend.set_floatx('float64')
#length of the dataset
L=16
#THIS REGULARIZATION TERM NEEDS SOME AID
def regularization_term(y_true, y_pred):
zeros = tf.zeros_like(y_pred)
ones = tf.ones_like(y_pred)
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, zeros, ones)
#here is actually some additional operatios, but they dont need to be taken into consideration so I've removed them
return tf.reduce_sum(y_pred_new)
def my_custom_loss(y_true, y_pred):
# I try this only with the regularization term to get the 'No gradients provided' error message
return regularization_term(y_true, y_pred)
#actually i would add a binary crossentropy term to this, i did not here for showcase purpose
enter code here
#creating a dataset for input (initial) and true data (target) for testing purposes
initial = np.random.randint(2,size=(10000,L+2,L+2)).astype("float")
target = np.random.randint(2,size=(10000,L,L)).astype("float")
#adding a model with CNN and 1 hidden layer with relu and 1 output layer with sigmoid
EPOCHS = 2
BATCH_SIZE = 1000
model = models.Sequential()
model.add(layers.Conv2D(1,2,activation='relu',input_shape=[L+2,L+2,1]))
model.add(layers.Conv2D(1,2,activation='sigmoid',input_shape=[L,L,1]))
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),loss=my_custom_loss)
model.fit(initial.reshape(10000,L+2,L+2,1),target.reshape(10000,L,L,1),batch_size = BATCH_SIZE, epochs=EPOCHS, verbose=1)
您在 normalization_term 函数中创建的那 2 个张量,零和一,正在阻止 tf 找到可训练变量的路径。
只需将您的代码更改为以下代码即可
def regularization_term(y_true, y_pred):
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, y_pred * 0, (y_pred*0)+1)
return tf.reduce_sum(y_pred_new)
我可能需要一些帮助来实现损失函数的特定正则化项。但是它没有梯度,我想知道是否有任何方法可以改变它。我在一篇论文中读过这种方法,但是阅读这篇论文对于实际帮助我并不重要。我将只描述问题所在的方法,并在 Google-Colab.
中显示测试代码神经网络仅由 2 个卷积层组成,最后一层具有 Sigmoid 激活函数。因此,由于 Sigmoid,输出介于 0 和 1 之间。这个值将被视为输出层中每个神经元为 0 或 1 的概率。所以我想用 'tf.keras.backend.switch' 函数以这种方式实现它:
def regularization_term(y_true, y_pred):
zeros = tf.zeros_like(y_pred)
ones = tf.ones_like(y_pred)
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, zeros, ones)
return y_pred_new
我抽取一个随机数并检查条件以使每个值都为 0 或 1。代码中应该清楚这一点。但是,当我这样做时,该术语实际上没有渐变:
ValueError: No gradients provided for any variable: ['conv2d_4/kernel:0', 'conv2d_4/bias:0', 'conv2d_5/kernel:0', 'conv2d_5/bias:0'].
完整的测试代码可以在这个 colab 中找到:https://colab.research.google.com/drive/1YuX00BUAj-BVCZRbr4opo5wHbcaVbYvx?usp=sharing
有什么方法可以实现这个方法同时保持梯度使网络学习?如果有任何不清楚的地方,请询问,我已尽力使我的问题尽可能易于理解。我很高兴能得到任何帮助。
非常感谢!
[编辑,从 GOOGLE_COLAB 复制粘贴,否则忽略:]
#just importing some libraries
import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
from tensorflow.keras import datasets, layers, models
tf.keras.backend.set_floatx('float64')
#length of the dataset
L=16
#THIS REGULARIZATION TERM NEEDS SOME AID
def regularization_term(y_true, y_pred):
zeros = tf.zeros_like(y_pred)
ones = tf.ones_like(y_pred)
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, zeros, ones)
#here is actually some additional operatios, but they dont need to be taken into consideration so I've removed them
return tf.reduce_sum(y_pred_new)
def my_custom_loss(y_true, y_pred):
# I try this only with the regularization term to get the 'No gradients provided' error message
return regularization_term(y_true, y_pred)
#actually i would add a binary crossentropy term to this, i did not here for showcase purpose
enter code here
#creating a dataset for input (initial) and true data (target) for testing purposes
initial = np.random.randint(2,size=(10000,L+2,L+2)).astype("float")
target = np.random.randint(2,size=(10000,L,L)).astype("float")
#adding a model with CNN and 1 hidden layer with relu and 1 output layer with sigmoid
EPOCHS = 2
BATCH_SIZE = 1000
model = models.Sequential()
model.add(layers.Conv2D(1,2,activation='relu',input_shape=[L+2,L+2,1]))
model.add(layers.Conv2D(1,2,activation='sigmoid',input_shape=[L,L,1]))
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),loss=my_custom_loss)
model.fit(initial.reshape(10000,L+2,L+2,1),target.reshape(10000,L,L,1),batch_size = BATCH_SIZE, epochs=EPOCHS, verbose=1)
您在 normalization_term 函数中创建的那 2 个张量,零和一,正在阻止 tf 找到可训练变量的路径。
只需将您的代码更改为以下代码即可
def regularization_term(y_true, y_pred):
random = tf.random.uniform(tf.shape(y_pred),minval=0,maxval=1,dtype=tf.dtypes.float64)
y_pred_new = tf.keras.backend.switch(random > y_pred, y_pred * 0, (y_pred*0)+1)
return tf.reduce_sum(y_pred_new)