首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在python中实现平滑的钳位功能?

如何在python中实现平滑的钳位功能?
EN

Stack Overflow用户
提问于 2017-07-18 11:25:29
回答 3查看 9.4K关注 0票数 13

钳位功能是clamp(x, min, max) = min if x < min, max if x > max, else x

我需要一个像钳子函数一样的函数,但它是光滑的(即有一个连续的导数)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-18 11:25:29

正常钳:

代码语言:javascript
复制
np.clip(x, mi, mx)

Smooth钳(保证x< min和x>max与正常钳相一致):

代码语言:javascript
复制
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) )

乙状体(近似钳位,从不小于分钟,也不大于最大值)

代码语言:javascript
复制
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箝函数家族。

策划他们:

代码语言:javascript
复制
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()

这两种方法的算术平均数也是潜在的用途:

代码语言:javascript
复制
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) )
票数 10
EN

Stack Overflow用户

发布于 2017-07-18 11:57:04

您要寻找的是类似于斯摩斯步函数的东西,它有一个自由参数N,给出了“光滑性”,即多少导数应该是连续的。其定义如下:

这在几个库中使用,可以在numpy中实现

代码语言:javascript
复制
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的增加而增加平滑度,您可以像这样显示它:

代码语言:javascript
复制
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()

由此得出的结果是:

票数 12
EN

Stack Overflow用户

发布于 2022-12-04 11:47:13

作为一种选择,如果您想确保有对应的钳位函数,您可以将正常的钳位函数与光滑的钟状函数(如洛伦兹函数或高斯函数)进行转换。

这将保证正常的钳位功能与其平滑版本之间的对应。平滑本身将由您选择在卷积中使用的基本光滑函数来定义。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45165452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档