scipy Python optmize.fmin错误:当传递给函数的矩阵大小相同时,矩阵大小不同

oiopk7p5  于 2024-01-09  发布在  Python
关注(0)|答案(1)|浏览(210)

我是python的新手,所以有可能我做了一些非常简单的错误而不知道它。我使用scipy的optimize.fmin来优化两点之间的转换矩阵。我写了一个目标函数来乘以我的“猜测”转换矩阵和初始点,然后找到结果矩阵的每个元素和我的第二个点之间的差异。我一直得到错误:“matmul:输入操作数1的核心维度0不匹配,当我调用optimize. fmin时,gufunc signature(n?,k),(k,m?)->(n?,m?)(大小4不同于16)”。
当optimize.fmin被调用时,我的猜测矩阵似乎从4x 4变成了1x 16。
我添加了print语句来打印我的猜测和初始点矩阵的大小,这使得它们都是4x 4。然后我调用我的目标函数,它执行得很好。但是当我调用optimize. fmin时,我仍然得到错误。我在下面包含了我的代码。我的猜测转换矩阵目前是实际的转换矩阵,以保持简单。

  1. import numpy as np
  2. from scipy import optimize
  3. import math
  4. rows,cols = 4,4 #number of rows and columns in the matrices
  5. model = np.array([
  6. [1, 0, 0, 0],
  7. [0, 1, 0, 0],
  8. [0, 0, 1, 0],
  9. [0, 0, 0, 1]
  10. ])
  11. #4x4 identity matix, guess and inputArray are multiplied to create the model of goalArray
  12. guess = np.array([
  13. [1, -1, 2, 0],
  14. [0, 2, 0, 0],
  15. [1, 0, 0, 1],
  16. [0, 1, 2, 0]
  17. ])
  18. #4x4 identity matrix, changed by optimize.fmin to find the transformation matrix that gives goalArray when multiplied with inputArray
  19. inputArray = np.array([
  20. [2, 4, 6, 9],
  21. [2, 3, 1, 0],
  22. [7, 2, 6, 4],
  23. [1, 5, 2, 1]
  24. ])
  25. #4x4 matrix provided by generatePoints([2 9 2 pi -pi pi], 4) xyz_in
  26. goalArray = np.array([
  27. [14, 5, 17, 17],
  28. [4, 6, 2, 0],
  29. [3, 9, 8, 10],
  30. [16, 7, 13, 8]
  31. ])
  32. #4x4 matrix provided by generatePoints([2 9 2 pi -pi pi], 4) xyz_out + eye(4) for noise
  33. #objective function passed to optimize.fmin
  34. #multiplies inputArray by the guess transition matrix
  35. #then finds the difference between each value in the goalArray and the model
  36. #and adds them to find the error
  37. def objfunc(guess, inputArray, goalArray):
  38. sum = 0
  39. model = guess @ inputArray
  40. for i in range(rows):
  41. for j in range(cols):
  42. sum = sum + math.sqrt((goalArray[i][j] - model[i][j]) ** 2)
  43. return sum
  44. print(guess.shape) #prints (4,4)
  45. print(inputArray.shape) #prints (4,4)
  46. print(objfunc(guess, inputArray, goalArray)) #prints 0.0
  47. minimum = optimize.fmin(objfunc, guess, args=(inputArray, goalArray)) #minimize error to find the guess transition matrix between inputArray and goalArray
  48. #print("minimum value:", minimum[0])
  49. #print("error:", minimum[1])
  50. #print(guess)

字符串

abithluo

abithluo1#

调用optimize.fmin时,我的猜测矩阵似乎从4x4变为1x16。
是的
简短的回答是,scipy.optimize.fmin在调用objfun之前,先对输入数组guess进行重构(转换为1D)。要使代码正常工作,您至少需要在objfunc的开头将guess整形为(4, 4)

  1. def objfunc(guess, inputArray, goalArray):
  2. guess = guess.reshape((4, 4)) # add this
  3. ... # the rest is unchanged

字符串
以及在提取结果之后。
还有其他几件事你应该做。例如,你不需要在目标函数中使用for循环。也就是说,

  1. for i in range(rows):
  2. for j in range(cols):
  3. sum = sum + math.sqrt((goalArray[i][j] - model[i][j]) ** 2)


可以替换为

  1. sum = np.sum(np.sqrt((goalArray - model) ** 2)


因为算术运算是按元素对NumPy数组执行的。
但这很容易看出,你是在对每一项求平方,然后立即求平方根。如果你想求绝对值,请使用abs

  1. sum = np.sum(np.abs(goalArray - model))


如果要在求和后求平方根:

  1. sum = np.sqrt(np.sum((goalArray - model) ** 2))


无论哪种方式,如果使用numpy.linalg.norm,其意图都将更加明确:

  1. sum = np.linalg.norm((goalArray - model).ravel(), ord=2)
  2. # use ord=1 for the sum of the absolute values
  3. # use ord=2 for the root of the sum of the squares
  4. # If you don't `ravel`, you can instead get a matrix norm


另外,optimize.fmin是一个遗留函数。对于新代码,请使用optimize.minimize。(请注意,minimize的文档明确要求您的猜测必须是1D,并且传递到目标函数的参数x将是1D。)

  1. minimum = optimize.minimize(objfunc, guess.ravel(), args=(inputArray, goalArray))
  2. print(minimum.fun)
  3. print(minimum.message)
  4. print(minimum.x.reshape((4, 4)))


这样,如果默认的优化方法不能给予足够好的结果,您就可以轻松地使用其他优化方法。

  1. minimum = optimize.minimize(objfunc, guess.ravel(), args=(inputArray, goalArray), method='slsqp')
  2. # default method is BFGS


如果你使用绝对值的和,大多数可能不会给予你很好的结果,因为目标函数不会是光滑的。从技术上讲,method='Nelder-Mead'(本质上是fmin所做的)是唯一一个不依赖于梯度的函数,但这仍然不能保证它能很好地解决你的问题。
但我假设你想对一个真实的非线性问题进行非线性优化,如果inputArray是非奇异的,这个问题可以用线性代数来解决。

  1. np.linalg.solve(inputArray.T, goalArray.T).T

展开查看全部

相关问题