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

oiopk7p5  于 5个月前  发布在  Python
关注(0)|答案(1)|浏览(70)

我是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时,我仍然得到错误。我在下面包含了我的代码。我的猜测转换矩阵目前是实际的转换矩阵,以保持简单。

import numpy as np
from scipy import optimize
import math

rows,cols = 4,4 #number of rows and columns in the matrices
model = np.array([
    [1, 0, 0, 0], 
    [0, 1, 0, 0], 
    [0, 0, 1, 0], 
    [0, 0, 0, 1]
])
#4x4 identity matix, guess and inputArray are multiplied to create the model of goalArray

guess = np.array([
    [1, -1, 2, 0], 
    [0,  2, 0, 0], 
    [1,  0, 0, 1], 
    [0,  1, 2, 0]
])
#4x4 identity matrix, changed by optimize.fmin to find the transformation matrix that gives goalArray when multiplied with inputArray

inputArray = np.array([
    [2, 4, 6, 9], 
    [2, 3, 1, 0], 
    [7, 2, 6, 4], 
    [1, 5, 2, 1]
])
#4x4 matrix provided by generatePoints([2 9 2 pi -pi pi], 4) xyz_in

goalArray = np.array([
    [14, 5, 17, 17], 
    [4,  6, 2,   0], 
    [3,  9, 8,  10], 
    [16, 7, 13,  8]
])
#4x4 matrix provided by generatePoints([2 9 2 pi -pi pi], 4) xyz_out + eye(4) for noise

#objective function passed to optimize.fmin
#multiplies inputArray by the guess transition matrix
#then finds the difference between each value in the goalArray and the model
#and adds them to find the error
def objfunc(guess, inputArray, goalArray):
    sum = 0
    model = guess @ inputArray

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

print(guess.shape) #prints (4,4)
print(inputArray.shape) #prints (4,4)
print(objfunc(guess, inputArray, goalArray)) #prints 0.0
minimum = optimize.fmin(objfunc, guess, args=(inputArray, goalArray)) #minimize error to find the guess transition matrix between inputArray and goalArray

#print("minimum value:", minimum[0])
#print("error:", minimum[1])
#print(guess)

字符串

abithluo

abithluo1#

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

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

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

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


可以替换为

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


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

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


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

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


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

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


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

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


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

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


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

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

相关问题