钳位功能是clamp(x, min, max) = min if x < min, max if x > max, else x。
我需要一个像钳子函数一样的函数,但它是光滑的(即有一个连续的导数)。
发布于 2017-07-18 11:25:29
正常钳:
np.clip(x, mi, mx)Smooth钳(保证x< min和x>max与正常钳相一致):
def smoothclamp(x, mi, mx): return mi + (mx-mi)*(lambda t: np.where(t < 0 , 0, np.where( t <= 1 , 3*t**2-2*t**3, 1 ) ) )( (x-mi)/(mx-mi) )乙状体(近似钳位,从不小于分钟,也不大于最大值)
def sigmoid(x,mi, mx): return mi + (mx-mi)*(lambda t: (1+200**(-t+0.5))**(-1) )( (x-mi)/(mx-mi) )为了某些目的,Sigmoid会比Smooth钳更好,因为Sigmoid是一个可逆的函数--没有信息丢失。
为了其他目的,您可能需要确定f(x) = xmax适用于所有x> xmax --在这种情况下,Smooth钳更好。另外,正如在另一个答案中所提到的,虽然这里给出的函数对于我的目的是足够的(除了光滑的导数之外,没有其他特殊的性质),但是有一个完整的Smooth箝函数家族。
策划他们:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1)
x = np.linspace(-4,7,1000)
ax.plot(x, np.clip(x, -1, 4),'k-', lw=2, alpha=0.8, label='clamp')
ax.plot(x, smoothclamp(x, -1, 4),'g-', lw=3, alpha=0.5, label='smoothclamp')
ax.plot(x, sigmoid(x, -1, 4),'b-', lw=3, alpha=0.5, label='sigmoid')
plt.legend(loc='upper left')
plt.show()

这两种方法的算术平均数也是潜在的用途:
def clampoid(x, mi, mx): return mi + (mx-mi)*(lambda t: 0.5*(1+200**(-t+0.5))**(-1) + 0.5*np.where(t < 0 , 0, np.where( t <= 1 , 3*t**2-2*t**3, 1 ) ) )( (x-mi)/(mx-mi) )发布于 2017-07-18 11:57:04
您要寻找的是类似于斯摩斯步函数的东西,它有一个自由参数N,给出了“光滑性”,即多少导数应该是连续的。其定义如下:

这在几个库中使用,可以在numpy中实现
import numpy as np
from scipy.special import comb
def smoothstep(x, x_min=0, x_max=1, N=1):
x = np.clip((x - x_min) / (x_max - x_min), 0, 1)
result = 0
for n in range(0, N + 1):
result += comb(N + n, n) * comb(2 * N + 1, N - n) * (-x) ** n
result *= x ** (N + 1)
return result它简化为给定N=0的常规钳位函数(0倍可微),并随着N的增加而增加平滑度,您可以像这样显示它:
import matplotlib.pyplot as plt
x = np.linspace(-0.5, 1.5, 1000)
for N in range(0, 5):
y = smoothstep(x, N=N)
plt.plot(x, y, label=str(N))
plt.legend()由此得出的结果是:

发布于 2022-12-04 11:47:13
作为一种选择,如果您想确保有对应的钳位函数,您可以将正常的钳位函数与光滑的钟状函数(如洛伦兹函数或高斯函数)进行转换。
这将保证正常的钳位功能与其平滑版本之间的对应。平滑本身将由您选择在卷积中使用的基本光滑函数来定义。
https://stackoverflow.com/questions/45165452
复制相似问题