使用 odeint 的手动函数和矩阵乘法结果之间的差异

Posted

技术标签:

【中文标题】使用 odeint 的手动函数和矩阵乘法结果之间的差异【英文标题】:Difference between Results in Manual Function and Matrix Multiplication with odeint 【发布时间】:2021-12-30 08:37:45 【问题描述】:

我目前正在尝试开发一个执行矩阵乘法的函数,同时在Python 中使用odeint 扩展一个微分方程,我看到了奇怪的结果。

我转换了函数:


    def f(x, t):
        return [
            -0.1 * x[0] + 2 * x[1],
            -2 * x[0] - 0.1 * x[1]        
        ]

到下面,以便我可以合并不同的矩阵。 我有下面的值矩阵和函数,它采用该矩阵的特定值:

from scipy.integrate import odeint
x0_train = [2,0]
dt = 0.01
t = np.arange(0, 1000, dt)
matrix_a = np.array([-0.09999975, 1.999999, -1.999999, -0.09999974])
# Function to run odeint with
def f(x, t, a):
    return [
        a[0] * x[0] + a[1] * x[1],
        a[2] * x[0] - a[3] * x[1]
    ]
odeint(f, x0_train, t, args=(matrix_a,))

>>> array([[ 2.        ,  0.        ],
       [ 1.99760115, -0.03999731],
       [ 1.99440529, -0.07997867],
       ...,
       [ 1.69090227,  1.15608741],
       [ 1.71199436,  1.12319701],
       [ 1.73240339,  1.08985846]])

这似乎是对的,但是当我创建自己的函数来执行乘法/回归时,我看到数组底部的结果完全不同。我有两个稀疏数组,它们提供与matrix_a 相同的条件,但它们周围有零。

from sklearn.preprocessing import PolynomialFeatures
new_matrix_a = array([[ 0.        , -0.09999975,  1.999999  ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ],
       [ 0.        , -1.999999  , -0.09999974,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ]])
# New function
def f_new(x, t, parameters):
    polynomials = PolynomialFeatures(degree=5)
    x = np.array(x).reshape(-1,2)
    #x0_train_array_reshape = x0_train_array.reshape(1,2)
    polynomial_transform = polynomials.fit(x)
    polynomial_features = polynomial_transform.fit_transform(x).T
    x_ode = np.matmul(parameters[0],polynomial_features)
    y_ode = np.matmul(parameters[1],polynomial_features)
    return np.concatenate((x_ode, y_ode), axis=None).tolist()

odeint(f_new, x0_train, t, args=(new_matrix_a,))

>>> array([[ 2.00000000e+00,  0.00000000e+00],
       [ 1.99760142e+00, -3.99573216e-02],
       [ 1.99440742e+00, -7.98188169e-02],
       ...,
       [-3.50784051e-21, -9.99729456e-22],
       [-3.50782881e-21, -9.99726119e-22],
       [-3.50781711e-21, -9.99722781e-22]])

如您所见,我在数组末尾得到了完全不同的值。我一直在运行我的代码,但似乎找不到它们不同的原因。是否有人有明确的原因或我的f_new 做错了什么?理想情况下,我想开发一个可以在 matrix_a 中获取任何值的函数,这就是我尝试创建这个新函数的原因。

提前致谢。

【问题讨论】:

第一个代码中a[3]之前的减号有原因吗?如果那是一个加号,那么它将是标准矩阵乘法。 我添加了一个更新的功能。它过去被更多地硬编码为Python。但是,在odeint 结果末尾进行矩阵乘法时,我得到的结果与硬编码函数不同。所以我仍然对结果有点困惑。但是我创建的ff_new 有相似的结果。 【参考方案1】:

您或许应该在第一个版本中更多地使用 numpy,以避免在常规算法中出现符号错误。

def f(x, t, a):
    return a.reshape([2,2]) @ x # or use matmul, or a.reshape([2,2]).dot(x)

或者,为了提高效率,传递已经改过的a

【讨论】:

以上是关于使用 odeint 的手动函数和矩阵乘法结果之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

numpy 矩阵乘法的奇怪性能结果

codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数

为啥 scipy sparse 和 numpy 数组的乘法函数会给出不同的结果?

使用三种不同方法的矩阵乘法会给出不同的结果,具体取决于值的数量

numpy的矩阵乘法

scipy.integrate.odeint可以计算矩阵的微分方程吗