Python:在scipy.optimize.newton中将列表作为参数传递
我想在Python:在scipy.optimize.newton中将列表作为参数传递,python,python-2.7,numpy,scipy,pythonxy,Python,Python 2.7,Numpy,Scipy,Pythonxy,我想在optimize.newton中将列表作为参数传递。 我已经导入了一个csv,并将每一行存储在一个数组中。此操作的代码如下所示: with open('rand1.csv','rb') as f: array=[] for line in f: array.append(line) 现在,如果我看一下数组[1],它看起来像:'2,6,76,45,78,1\r\n' 我将一个函数定义为: def func(a,b,c,d,e,f): return a
optimize.newton
中将列表作为参数传递。
我已经导入了一个csv,并将每一行存储在一个数组中。此操作的代码如下所示:
with open('rand1.csv','rb') as f:
array=[]
for line in f:
array.append(line)
现在,如果我看一下数组[1]
,它看起来像:'2,6,76,45,78,1\r\n'
我将一个函数定义为:
def func(a,b,c,d,e,f):
return a*b*c-d*e-f
我运行的牛顿法如下:
res=[optimize.newton(func,5102,args=(x)) for x in array[0]]
但是它给了我一个TypeError
说“:只能将tuple(而不是“str”)连接到tuple”
有人能帮我吗?我知道元组元素必须用逗号分隔,我也尝试过编写
args=(x,)
,但它不起作用。首先你需要删除尾随的'\r','\t'
,为此你可以使用.strip()
,现在你有了一个字符串,其中所需的元素用逗号分隔,在这里,您可以使用.split()
方法,将要拆分的字符传递给给定的字符串。最后,我们使用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]
结合以上所有步骤,我们可以清楚地将其写成:
with open('rand1.csv','rb') as f:
array=[]
for line in f:
array.append(map(int,line.strip().split(',')))
首先,请记住,在代码中,
array
实际上不是一个numpy数组-它是一个普通的Python字符串列表。可以通过拆分字符串并将元素转换为整数来处理此列表,如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.newton
时,args=
参数应该得到6个参数值的序列。原始代码不起作用,因为数组中的每一行都包含一个字符串,而不是6个数值。既然data
*是一个nrows x 6数组,那么每行将包含6个数值,因此您现在只需执行以下操作:
res = [optimize.newton(func, 5102, args=row) for row in data]
*请注意,我已将变量array
重命名为data
,以避免与np.array
类混淆
更新
您的原始代码中还有一个错误,我最初没有发现。请参阅以下文档:
func:函数
需要其零的函数。它必须是形式为f(x,a,b,c…)的单个变量的函数,其中a,b,c。。。是可以在args参数中传递的额外参数
x0:浮动
零点的初始估计值,应该在实际零点附近
现在看看您的函数定义:
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个参数,因此您会得到一个错误。解决此问题的正确方法取决于如何解释函数的参数。牛顿的目标是找到一个x的值,使得f(x,a,b,c,…)=0
您希望将6个参数中的哪一个最小化func()
over
充分解释
一个稍微有趣的问题是,当您将额外的参数作为数组(例如,args=data[0]
)而不是元组传递时,为什么不会出现错误。答案有点复杂,但如果你感兴趣,请继续阅读
如果查看一下,您可以找到第一次调用函数的行:
q0 = func(*((p0,) + args))
在这种情况下,p0
和p1
将是x0
到newton()
的参数,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个参数。但是,当args
是np.array
时:
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中修复此问题。首先strip()
行(在追加之前)并使用.split(',')
方法这有助于我摆脱“\r',“\t”,但我仍然无法运行optimize.newton函数。这里有什么建议吗?谢谢,这稍微解决了我的问题。但我在这里没有更多的疑问。如果我在一个有8行6列的csv上运行您的代码,它就可以正常工作。如果我是正确的,形成的阵列将是8x6。“res”变量将有8个值。但如果我只想为第一行运行优化代码呢?我无法为数据[0]中的行运行以下命令:res=[optimize.newton(func,5102,args=row)。此外,如果我通过手动指定值来运行代码,则会为