如何使 int 列表适合所需的函数

How to fit an int list to a desired function

我有一个 int 列表 x,例如 [43, 43, 46, ....., 487, 496, 502](仅作为示例)
x是一个字数列表,我想在训练文本分类模型的时候把一个字数列表改成一个列表惩罚分数。

我想使用 curve 函数(可能像 math.log?)用于将值从 x 映射到 y,我需要 x 中的最小值(43) 映射到 y(0.8),x(502) 中的最大值映射到 y(0.08),x 中的其他值映射到 y函数。

例如:

x = [43, 43, 46, ....., 487, 496, 502]

y_bounds = [0.8, 0.08]

def creat_curve_func(x, y_bounds, curve_shape='log'):
    ...

func = creat_curve_func(x, y)

assert func(43) == 0.8
assert func(502) == 0.08
func(46)
>>> 0.78652 (just a fake result for example)
func(479)
>>> 0.097 (just a fake result for example)

我很快发现我必须自己尝试一些参数才能得到符合我目的的曲线函数,再试一次。

然后我试着找一个库来做这样的工作,结果scipy.optimize.curve_fit。但它至少需要三个参数:f(我要生成的函数),xdata,ydata(我只有y bounds:0.8, 0.08),只有xdata我有。

有什么好的解决方案吗?

更新

我认为这很容易理解,所以没有写 curve_fit 的失败代码。这是否决票的原因吗?

为什么我不能只使用curve_fit的原因

x = sorted([43, 43, 46, ....., 487, 496, 502])
y = np.linspace(0.8, 0.08, len(x)) # can not set y as this way which lead to the wrong result
def func(x, a, b):
    return a * x +b # I want a curve function in fact, linear is simple to understand here
popt, pcov = curve_fit(func, x, y)

func(42, *popt)
0.47056348146450089 # I want 0.8 here

这样怎么样?

编辑:增加权重。如果您不需要将终点准确地放在曲线上,您可以使用权重:

import scipy.optimize as opti
import numpy as np

xdata = np.array([43, 56, 234, 502], float)
ydata = np.linspace(0.8, 0.08, len(xdata))
weights = np.ones_like(xdata, float)
weights[0] = 0.001
weights[-1] = 0.001

def fun(x, a, b, z):
    return np.log(z/x + a) + b

popt, pcov = opti.curve_fit(fun, xdata, ydata, sigma=weights)

print fun(xdata, *popt)
>>> [ 0.79999994  ...  0.08000009]

编辑: 你也可以玩这些参数,当然:

import scipy.optimize as opti
import numpy as np

xdata = np.array([43, 56, 234, 502], float)
xdata = np.round(np.sort(np.random.rand(100) * (502-43) + 43))
ydata = np.linspace(0.8, 0.08, len(xdata))
weights = np.ones_like(xdata, float)
weights[0] = 0.00001
weights[-1] = 0.00001

def fun(x, a, b, z):
    return np.log(z/x + a) + b

popt, pcov = opti.curve_fit(fun, xdata, ydata, sigma=weights)

print fun(xdata, *popt)
>>>[ 0.8     ...    0.08      ]