我有以下优化代码,它由变量 n
参数化。
from symfit import parameters, Eq, Ge, Fit
import numpy as np
n = 3
xdata = np.sort(np.random.choice(range(1, 4*n), n)) # Make fake data
print(xdata)
p1, p2, p3 = parameters('p1, p2, p3')
model = p1*p2*p3
constraints = [
Eq(xdata[0]*p1+(xdata[1]-xdata[0])*p2+(xdata[2]-xdata[1])*p3, 1),
Ge(p1, p2),
Ge(p2, p3),
Ge(p3, 0)
]
fit = Fit(- model, constraints=constraints)
fit_result = fit.execute()
print(fit_result)
我想将它用于更大的 n
值,但我不知道如何更改行
p1, p2, p3 = parameters('p1, p2, p3')
model = p1*p2*p3
和约束
来应对任意大的n
。
代码使用了 symfit图书馆。该链接显示了如何使用 parameters
的示例以及指向文档的链接。
如何做到这一点?
最佳答案
Numpy 与 symfit
库的交互真的很好。使用它时,您尝试概括的所有操作都相当微不足道。
设置
n = 3
_data = np.sort(np.random.choice(np.arange(1, 4 * n), n))
字符串格式化
您可以使用简单的迭代器和
str.join
动态创建参数的tuple
,然后您可以将其传递给parameters
构造函数获取参数的元组
。
params = parameters(', '.join(f'p{i}' for i in range(1, n+1)))
^^
# p1, p2, p3 = parameters('p1, p2, p3')
np.prod
这个操作非常简单。
np.prod
计算:product of array elements over a given axis
当应用于
/li>symfit
参数的tuple
时,生成您想要的p1*p2*...pn
model = np.prod(params)
^^
# model = p1*p2*p3
np.concatenate
+np.diff
可能是概括起来最复杂的一行,但仍然不太难理解。您想要将数据数组中连续元素的差异乘以您的参数,然后对结果求和。由于第一个元素与前一个元素没有区别,您可以使用
np.concatenate
将其添加回去。
u = np.concatenate((_data[:1], np.diff(_data)))
c1 = Eq(np.sum(params * u), 1)
^^
# Eq(xdata[0]*p1+(xdata[1]-xdata[0])*p2+(xdata[2]-xdata[1])*p3, 1)
np.column_stack
您希望滚动查看作为约束的参数:
p1-p2
、p2-p3
、...pn, 0
。这只是用原始tuple
参数堆叠一个零填充的一次性元组,然后使用列表推导解包到您的Ge
构造函数中。
ges = [Ge(*group) for group in np.column_stack((params, params[1:] + (0,)))]
适合!
我这里什么都没改!
constraints = [c1, *ges]
fit = Fit(- model, constraints=constraints)
fit_result = fit.execute()
关于python - Python中如何任意扩展Symfit的参数个数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55580926/