类型错误警告在我的代码中不断发生



在我的python代码中,我一直得到以下错误:

TypeError:没有匹配ufunc svd_n的指定签名和类型转换的循环

代码如下:

import numpy as np
from numpy.linalg import norm
def sdm_3eqs():
def f_bold(x):
return [15*x[0] + x[1]**2 - 4*x[2] - 15, x[0]**2 + 10*x[1] - x[2] - 10, x[1]**3 - 25*x[2] + 24]

def f(x):
f_n = []
for i in range(len(x)):
f_i = f_bold[i]**2
f_n.append(f_i)

return np.sum(f_n)

def M(x):
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
return m

def grad_f(x):
return 2*M(x)*f_bold(x)

def d(x):
return -grad_f(x)/norm(grad_f(x), ord=2)

def s_prime(x, alpha, d):
return grad_f(x + alpha*d)*d

x = [0.5, 0.5, 0.5]
iter = 0
err = 100
while err > 0.005:
x_k = x
d_k = d(x_k)
m = 0
sprime = 300
alpha_l = 0
alpha_u = 1.5
alpha = (alpha_l+alpha_u)/2
while abs(sprime) > 0.0005:
alpha = (alpha_l+alpha_u)/2
sprime = s_prime(x_k, alpha, d_k)[0][0]
if abs(sprime) < 0.001:
break
elif sprime > 0:
alpha_u = alpha
else:
alpha_l = alpha

m += 1

iter += 1
x = x_k + alpha*d_k
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))

print(f'f_bold: {f_bold(x)}')
sdm_3eqs()

我不确定为什么,但它说类型错误来自代码中的第57行:

err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))

如果有人能帮忙,那就太好了!编辑:

Traceback (most recent call last):
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 61, in <module>
sdm_3eqs()
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 57, in sdm_3eqs
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2579, in norm
ret =  _multi_svd_norm(x, row_axis, col_axis, amax)
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 1673, in svd
s = gufunc(a, signature=signature, extobj=extobj)
TypeError: No loop matching the specified signature and casting was found for ufunc svd_n

看起来M(x)函数返回的是一个结构为

的三维数组
[
[   a    [b c d]    e   ]
[[f g h]    i    [k l m]]
[   n       o       p   ]
]

然后你试图将其与f_bold(x)的结果矩阵相乘并计算范数。

我相信这个错误与试图计算这个不规则矩阵的范数有关。特别是,检查M(x)的函数定义,以验证其返回数组的形状/规律性。

line 17: m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
^^^^         ^^^^        ^^^^

我在你的代码中添加了几个打印,并得到了这个运行:

In [63]: sdm_3eqs()
<ipython-input-62-2b082fcea817>:14: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
f_bold
[array([ 6.64610017e-05, -8.57391288e+00, -1.40877199e+01]), array([-3.81306816, -3.03705309, -6.81097338]), array([ 15.47764768,  12.41073581, -18.41883603])]
grad_f
array([[0.0019938300511945783,
array([-36.8081748 , -17.89173085, -17.14782575]), -0.0],
[array([ -8.20903822, -10.93449844,  -7.0767119 ]),
-60.74106175194817,
array([-11.83793275, -21.00337307,  -8.79740011])],
[-123.82118142652486, -24.821471626766595, 920.9418016830625]],
dtype=object)

Traceback (most recent call last):
File "<ipython-input-63-8732d4079184>", line 1, in <module>
sdm_3eqs()
File "<ipython-input-62-2b082fcea817>", line 57, in sdm_3eqs
err = np.linalg.norm(grad_f(x), ord=2)/max(1, np.linalg.norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2579, in norm
ret =  _multi_svd_norm(x, row_axis, col_axis, amax)
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 1672, in svd
s = gufunc(a, signature=signature, extobj=extobj)
UFuncTypeError: Cannot cast ufunc 'svd_n' input from dtype('O') to dtype('float64') with casting rule 'same_kind'

在新的numpy版本中,创建一个"粗糙数组"获取此警告,并告诉我们不是在创建一个简单的数字数组。相反,M是一个对象dtype数组,包含数字和数组的混合。

f_bold是一个数组列表。grad_f是一个(3,3)对象dtype数组,混合了浮点数和数组。

在最新的numpy版本中,这种错误指定了问题类型-我怀疑是'O',对象。

norm不能处理这种数组。这就是为什么我要求2个norm参数中的dtype

我已经解决了。

在某些函数中,它应该是两个矩阵的点积

例如:

def grad_f(x):
return 2*np.dot(M(x), f_bold(x))

下面是更新后的代码:

import numpy as np
from numpy.core.fromnumeric import shape
from numpy.linalg import norm
from numpy import transpose
from numpy import array
from numpy import sum
from matplotlib import pyplot as plt
def sdm_3eqs():
def f_bold(x):
x_1 = x[0]
x_2 = x[1]
x_3 = x[2]
return array([15*x_1 + x_2**2 - 4*x_3 - 15, x_1**2 + 10*x_2 - x_3 - 10, x_2**3 - 25*x_3 + 24], dtype='float32')

def f(x):
f_n = []
for i in range(len(x)):
f_i = f_bold[i]**2
f_n.append(f_i)

return sum(f_n)

def M(x):
x_1 = x[0]
x_2 = x[1]
d1 = 2*x_1
d2 = 2*x_2
d3 = 3*x_2**2
return array([[15, d1, 0], [d2, 10, d3], [-4, -1, -25]], dtype='float32')

def grad_f(x):
return 2*np.dot(M(x), f_bold(x))

def d(x):
return -1*grad_f(x)/norm(grad_f(x), ord=2)

def s_prime(x, alpha, d):
return np.dot(transpose(grad_f(x + alpha*d)), d)

x = array([[0.5], [0.5], [0.5]], dtype='float32')
iter = 0
err = 100
while err > 0.005:
x_k = x
d_k = d(x_k)
m = 0
sprime = 300
alpha_l = 0
alpha_u = 1.5
alpha = (alpha_l+alpha_u)/2
while abs(sprime) > 0.0005:
alpha = (alpha_l+alpha_u)/2
sprime = s_prime(x_k, alpha, d_k)

if abs(sprime) < 0.001:
break
elif sprime > 0:
alpha_u = alpha
else:
alpha_l = alpha

m += 1

iter += 1
x = x_k + alpha*d_k
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))

print(f'nf_bold:nEquation 1 = {f_bold(x)[0][0]}nEquation 2 = {f_bold(x)[1][0]}nEquation 3 = {f_bold(x)[2][0]}n')
sdm_3eqs()