Python:传递列表作为中的参数scipy.optimize.newton

2024-06-28 20:09:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我想把list作为参数传递给optimize.newton。 我导入了一个csv并将每一行存储在一个数组中。代码如下:

with open('rand1.csv','rb') as f:
    array=[]
    for line in f:
        array.append(line)

现在,如果我看array[1],它看起来是:'2,6,76,45,78,1\r\n'

我将一个函数定义为:

^{pr2}$

我将牛顿法作为:

res=[optimize.newton(func,5102,args=(x)) for x in array[0]]

但它给了我一个TypeError的说法": can only concatenate tuple (not "str") to tuple"

有人能帮我吗?我知道元组元素必须用逗号分隔,我也试过写args=(x,),但没用。在


Tags: csv代码inforwithlineargsnewton
2条回答

{{{1}你可以在第一个cd2}的字符串上使用逗号},你可以使用。最后,我们使用map()函数,它将一个函数作为第一个参数(在本例中为int),第二个参数是一个列表或一个元组,并将作为第一个参数传递的函数映射该元组列表中的每个元素。在

line = '2,6,76,45,78,1\r\n'
line_stripped = line.strip()
print line_stripped
>>> '2,6,76,45,78,1'

line_splitted = line_stripped.split(",")
print line_splitted
>>> '2' ,'6', '76', '45', '78', '1'

line_integers = map(int,line_splitted)
print line_integers
>>> [2, 6, 76, 45, 78, 1]

结合以上所有步骤,我们可以清楚地将其写为:

^{pr2}$

首先,请记住,在您的代码中,array实际上并不是numpy数组,它是一个普通的Python list字符串。可以通过拆分字符串并将元素转换为整数来处理此列表,就像Anmol uppal的答案一样,但是将csv文件的内容直接转换成nrows x 6 numpy数组要简单得多,例如使用np.loadtxt

import numpy as np

data = np.loadtxt('rand1.csv', delimiter=',', dtype=np.int)
print(repr(data[0]))
# array([ 2,  6, 76, 45, 78,  1])

现在当您调用optimize.newtonargs=参数应该得到一个由6个参数值组成的序列。由于array中的每一行包含一个字符串,而不是6个数值,所以原始代码无法正常工作。既然data*是一个nrows x 6数组,那么每一行都将包含6个数值,因此您现在只需执行以下操作:

^{pr2}$

*请注意,我已将变量array重命名为data,以避免与np.array类混淆


更新

在你的原始代码中还有一个我一开始没有发现的错误。查看^{}的文档:

func : function

The function whose zero is wanted. It must be a function of a single variable of the form f(x,a,b,c...), where a,b,c... are extra arguments that can be passed in the args parameter.

x0:浮动

An initial estimate of the zero that should be somewhere near the actual zero.

现在看看你的函数定义:

def func(a,b,c,d,e,f):
    return a*b*c-d*e-f

func()(您称之为a)的第一个参数应该对应于x参数,那么只有5额外参数(b ... f根据您的定义)需要使用args=传递。当你打电话的时候

optimize.newton(func, 5102, args=(422, 858, 129, 312, 79, 371))

5102被解释为x0参数,并作为第一个参数传递给func()args=元组中的6值被视为额外的参数,因此您的函数实际上总共获得了7个参数:

func(5102, 422, 858, 129, 312, 79, 371)

显然,func()被定义为接受6个参数,因此会得到一个错误。解决此问题的正确方法取决于如何解释函数的参数。newton的目标是找到一个x的值,使得f(x,a,b,c,…)=0。在

6个参数中,您希望最小化func()中的哪一个?在


完整的解释

一个稍微有趣的问题是,当您以数组(例如args=data[0])而不是元组的形式传递额外的参数时,为什么没有得到错误消息。答案有点复杂,但如果你感兴趣,请继续阅读。在

如果您查看the source code for ^{},您可以找到第一次调用函数的行:

q0 = func(*((p0,) + args))

在本例中,p0和{}将是newton()x0参数,args是一组额外参数:

q0 = func(*((5102,) + (422, 858, 129, 312, 79, 371)))

(p0,)是一个元组,如果args也是一个元组,那么{}运算符将把这两个元组连接在一起:

q0 = func(*(5102, 422, 858, 129, 312, 79, 371))

最后,*解压元组以将参数传递给func。最后的通话应该是这样的:

q0 = func(5102, 422, 858, 129, 312, 79, 371)

这将引发一个错误,因为一个6参数函数有7个参数。然而{28}是

q0 = func(*(5102,) +  array([422, 858, 129, 312, 79, 371]))

+args中的每个元素添加p0

q0 = func(*(5524, 5960, 5231, 5414, 5181, 5473))

因为现在只有6个参数要去func()调用将成功,但是newton将收敛到错误的答案!在

我认为这在scipy中不是特别好的设计-它让我很困惑,因为在大多数其他情况下,任何类似数组的输入都可以,包括列表、元组、数组等。公平地说,它确实在newton的文档中指出args=应该是一个元组,但为了安全起见,我还是会进行类型检查或显式地将其转换为元组。我可以试着在scipy里解决这个问题。在

相关问题 更多 >