结果证明这是一个非常有趣的问题 - 感谢您提出这个问题!首先,请记住,您希望您的损失函数完全由微分运算定义,以便您可以通过它进行反向传播。这意味着任何旧的任意逻辑都不一定会这样做。重申您的问题:您希望找到两个变量的可微函数,当这两个变量取不同符号的值时,该函数会急剧增加,而当它们具有相同符号时会增加得更慢。此外,您希望控制这些值相对于彼此急剧增加的方式。因此,我们想要具有两个可配置常量的东西。我开始构建一个满足这些需求的函数,但后来想起了一个你可以在任何高中几何教科书中找到的函数:elliptic paraboloid!
标准制定不符合签署协议对称的要求,所以我不得不介绍一个rotation。上图就是结果。请注意,当符号不一致时,它会急剧增加,而当它们一致时,它会变得不那么急剧,并且控制此行为的输入常量是可配置的。下面的代码是定义和绘制损失函数所需的全部内容。我认为我以前从未使用过几何形式作为损失函数 - 非常简洁。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
def elliptic_paraboloid_loss(x, y, c_diff_sign, c_same_sign):
# Compute a rotated elliptic parabaloid.
t = np.pi / 4
x_rot = (x * np.cos(t)) + (y * np.sin(t))
y_rot = (x * -np.sin(t)) + (y * np.cos(t))
z = ((x_rot**2) / c_diff_sign) + ((y_rot**2) / c_same_sign)
return(z)
c_diff_sign = 4
c_same_sign = 2
a = np.arange(-5, 5, 0.1)
b = np.arange(-5, 5, 0.1)
loss_map = np.zeros((len(a), len(b)))
for i, a_i in enumerate(a):
for j, b_j in enumerate(b):
loss_map[i, j] = elliptic_paraboloid_loss(a_i, b_j, c_diff_sign, c_same_sign)
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y = np.meshgrid(a, b)
surf = ax.plot_surface(X, Y, loss_map, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
plt.show()