多个symfit模型实例共享具有相同名称的参数对象。我想了解这种行为的来源,意图是什么以及是否可以停用。
为了说明我的意思,一个最小的例子:
import symfit as sf
# Create Parameters and Variables
a = sf.Parameter('a',value=0)
b = sf.Parameter('b',value=1,fixed=True)
x, y = sf.variables('x, y')
# Instanciate two models
model1=sf.Model({y:a*x+b})
model2=sf.Model({y:a*x+b})
# They are indeed not the same
id(model1) == id(model2)
>>False
# There are two parameters
print(model1.params)
>>[a,b]
print(model1.params[1].name, model1.params[1].value)
>>b 1
print(model2.params[1].name, model2.params[1].value)
>>b 1
#They are initially identical
# We want to manually modify the fixed one in only one model
model1.params[1].value = 3
# Both have changed
print(model1.params[1].name, model1.params[1].value)
>>b 3
print(model2.params[1].name, model2.params[1].value)
>>b 3
id(model1.params[1]) == id(model2.params[1])
>>True
# The parameter is the same object
我想要使用不同的模型来拟合多个数据流,但是依赖于数据流的不同的固定参数值。重命名模型的每个实例中的参数都可以,但是由于参数代表相同的数量,因此很难看。可以按顺序处理它们并修改其间的参数,但我担心步骤之间的意外交互。
PS:有声誉的人可以创建symfit标签
好问题。原则上这是因为Parameter
对象是sympy.Symbol
的子类,并且来自其docstring:
Symbols are identified by name and assumptions:
>>> from sympy import Symbol
>>> Symbol("x") == Symbol("x")
True
>>> Symbol("x", real=True) == Symbol("x", real=False)
False
这是sympy
内部工作的基础,因此我们也在symfit
中使用。但是值和固定参数不被视为假设,因此它们不用于区分参数。
现在,关于这将如何影响拟合的问题。就像你说的那样,顺序工作是一个很好的解决方案,而且没有任何副作用:
model = sf.Model({y:a*x+b})
b.fixed = True
fit_results = []
for b_value, xdata, ydata in datastream:
b.value = b_value
fit = Fit(model, x=xdata, y=ydata)
fit_results.append(fit.execute())
所以没有必要在每次迭代时定义一个新的Parameter
,b.value
属性在每个循环中都是相同的,所以这不会出错。我能想象出错的唯一方法就是如果你使用threading
,这可能会产生一些竞争条件。但threading
无论如何都不适合CPU绑定任务,multiprocessing
是要走的路。在这种情况下,将产生单独的进程,创建单独的微观世界,因此也应该没有问题。
如果不让我知道,我希望这能回答你的问题。
附:我正在慢慢回答我的方式达到1500以制作那个标签,但是如果有人打败我,那我当然会更开心;)