如何在python中实现平滑钳制函数?

如何在python中实现平滑钳制函数?,python,pandas,numpy,clamp,smoothstep,Python,Pandas,Numpy,Clamp,Smoothstep,夹紧功能是夹紧(x,min,max)=min如果xmax,否则x 我需要一个类似于钳制函数的函数,但它是平滑的(即具有连续导数) 正常钳位: np.clip(x, mi, mx) 平滑夹具(保证与xmax的正常夹具一致): 出于某些目的,Sigmoid将优于Smoothclamp,因为Sigmoid是一个可逆函数-不会丢失任何信息 出于其他目的,您可能需要确定f(x)=xmax For all x>xmax-在这种情况下,平滑钳位更好。另外,正如在另一个答案中所提到的,这里有一系列的平滑钳位函

夹紧功能是
夹紧(x,min,max)=min如果xmax,否则x

我需要一个类似于钳制函数的函数,但它是平滑的(即具有连续导数)

正常钳位:

np.clip(x, mi, mx)
平滑夹具(保证与xmax的正常夹具一致):

出于某些目的,Sigmoid将优于Smoothclamp,因为Sigmoid是一个可逆函数-不会丢失任何信息

出于其他目的,您可能需要确定f(x)=xmax For all x>xmax-在这种情况下,平滑钳位更好。另外,正如在另一个答案中所提到的,这里有一系列的平滑钳位函数,尽管这里给出的函数对于我来说已经足够了(除了光滑导数之外,不需要其他特殊性质)

绘制它们:

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) )

def clampoid(x,mi,mx):返回mi+(mx mi)*(lambda t:0.5*(1+200**(-t+0.5))**(-1)+0.5*np。其中(t<0,0,np)。其中(t您要寻找的是类似函数的东西,它有一个自由参数
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()
结果如下:


内置函数min和max不需要numpy。但曲线下的区域是否保留?@guidot,使用numpy函数的另一个很好的原因是它们是矢量化的。因此,您可以将此类函数应用于整个向量(矩阵)没有循环,通常是数量级FASTY。FY:对于正常钳位,可以使用.@ GueOT,考虑下面的例子:<代码>导入NoPy作为NP;A= NP。RAND(10 ** 6);%TimeIt max(A);%TimIT NP.MAX(A);< /代码> -在我的PC上,矢量化的NUMPY函数占用了127倍的时间;回答得很好。出于我的目的,我更喜欢我的实现(显然我有偏见!)因为它是一个单行程序,n=1的smoothstep完全符合我的要求-我不关心二阶导数是否平滑。谢谢!当然,只是想加入另一个选项。你的选项显然更简单,但这对更一般的应用程序非常有效。@JonasAdler不确定此实现是否真的适用于不同的最小值或最大值。ot她的一个RokoMijic Scales你确定吗?我试过了,它对我很有效。本质上,在重新缩放后,你可以将这个问题理解为一个问题。你选择的内核决定你执行的近似类型。如果你的内核有无限的支持,你将得到一种S形近似。如果它有有限的支持,函数将每个最小值和最大值
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
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()