#python #numpy
Вопрос:
В моем коде python я продолжаю получать следующую ошибку:
Ошибка типа: Для 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 gt; 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) gt; 0.0005: alpha = (alpha_l alpha_u)/2 sprime = s_prime(x_k, alpha, d_k)[0][0] if abs(sprime) lt; 0.001: break elif sprime gt; 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 lt;modulegt; 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 "lt;__array_function__ internalsgt;", 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 "lt;__array_function__ internalsgt;", 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
Комментарии:
1. Покажите полную обратную связь. Я не вижу
svd_n
вызова функции в вашем коде, но обратная связь должна сообщить нам, как это вызывается. Затем вам нужно проверить тип и тип dtype аргументов этой функции, чтобы увидеть, что отличается от документации.2. Я отредактировал его.
3.Так что это один из
norm
звонков. В чемshape
dtype
смысл этих аргументов:grad_f(x)
f_bold(x)
4. Не удалось показать dtype, но формы: Форма grad_f = (3, 3); форма f_bold = ()
5. Я думаю, что есть проблема с тем, что возвращает ваша функция grad_f; проверьте, соответствуют ли ваши выходные данные этой функции ожидаемым выходам (с точки зрения формы/структуры).
Ответ №1:
Похоже 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]]) ^^^^ ^^^^ ^^^^
Ответ №2:
Я добавил пару отпечатков в ваш код и запустил это:
In [63]: sdm_3eqs() lt;ipython-input-62-2b082fcea817gt;: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 "lt;ipython-input-63-8732d4079184gt;", line 1, in lt;modulegt; sdm_3eqs() File "lt;ipython-input-62-2b082fcea817gt;", 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 "lt;__array_function__ internalsgt;", 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 "lt;__array_function__ internalsgt;", 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
представляет собой массив dtype объекта (3,3) со смесью поплавков и массивов.
И в последней версии numpy такого рода ошибка указывает тип проблемы dtype, который, как я подозревал, является объектом «O».
norm
не может обрабатывать массив такого рода. Вот почему я попросил dtype
один из 2 norm
аргументов.
Ответ №3:
Я решил эту проблему.
В некоторых функциях предполагалось, что это точечное произведение двух матриц.
напр.:
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 gt; 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) gt; 0.0005: alpha = (alpha_l alpha_u)/2 sprime = s_prime(x_k, alpha, d_k) if abs(sprime) lt; 0.001: break elif sprime gt; 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()