【问题标题】:TypeError: 'numpy.float64' object is not callable in scipy.optimize.minimize LibraryTypeError:“numpy.float64”对象在 scipy.optimize.minimize 库中不可调用
【发布时间】:2020-07-26 16:33:05
【问题描述】:

您好,我正在尝试实施优化论文“Optimal Kernel Selection in Kernel Fisher Discriminant Analysis”,我已经实现了它的代码。但是,在尝试不同的方法后我得到了这个错误。我使用 scipy 库中的 scipy.optimize.minimize 函数https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html#rdd2e1855725e-5

我的代码如下:

def c_func(theta):

    data_pima = pd.read_csv('~/Documents/Uwaterloo_Study_Docs/ECE_602/Project_final/Dataset/PIMA/pima-indians-diabetes.csv')
    data_pima.rename(columns={'1':'Target', '6':'Pregnancies', '148':'Glucose', '72':'BloodPressure', '35':'SkinThickness', '0': 'Insulin',                                                    '33.6': 'BMI', '0.627':'DiabeticPedigreeFunction','50':'Age'},inplace=True)
    X = data_pima.loc[:,:'Age'].values
    y = data_pima['Target'].values
    data_pima_positive = data_pima.loc[(data_pima['Target'] > 0)]
    data_pima_negative = data_pima.loc[(data_pima['Target'] < 1)]


    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30,random_state=42)

    sq_dist = pdist(X, 'sqeuclidean')
    sigma = [10**(0.1), 10**(-0.7), 10**(-0.4), 10**(-0.1), 10**(0.2), 10**(0.5), 10**(0.8), 10**(1.1), 10**(1.4), 10**(1.7)]

    G = 0
    for value in range(10):
        gamma = 1/(sigma[value]**2)
        gamma = -gamma * theta[value] 
        mat_sqr_dist = squareform(sq_dist)
        g = np.exp(gamma * mat_sqr_dist)
        G = np.add(G, g)

    # number of positive sample from the dataset
    m_plus = len(data_pima_positive.index)
    data_pima_positive = data_pima_positive.values
    m_minus = len(data_pima_negative.index)
    one_plus = np.ones(m_plus)
    one_minus = np.ones(m_minus)
    I_plus = np.identity(m_plus)
    J_plus_1value = np.dot(one_plus, one_plus.T)
    J_plus = (1/np.sqrt(m_plus)) * (I_plus - (1/m_plus) * J_plus_1value)
    I_minus = np.identity(m_minus)
    J_minus_1value = np.dot(one_minus, one_minus.T)
    J_minus = (1/np.sqrt(m_minus)) * (I_minus - (1/m_minus) * J_minus_1value)

    J = linalg.block_diag(J_plus, J_minus)
    a_plus_1 = (1/m_plus)* one_plus
    a_minus_1  = (1/m_minus)* one_minus
    zeros_a_plus = np.zeros(len(a_minus_1))
    a_plus = np.block([a_plus_1, zeros_a_plus])
    zeros_a_minus = np.zeros(len(a_plus_1))
    a_minus = np.block([zeros_a_minus, a_minus_1])
    a = a_plus - a_minus
    lambda_val = 10**(-8)
    I = np.identity(len(J))
    J_G = np.matmul(J,G)
    lambda_I = lambda_val*I
    J_G_J = np.matmul(J_G, J)
    value_1 = (lambda_I + J_G_J)
    J_G_a = np.matmul(J_G,a)
    G_J = np.matmul(G,J)
    aT_G_J = np.matmul(a.T,G_J)
    G_a = np.matmul(G,a)
    aT_G_a = np.matmul(a.T, G_a)
    value_1Inv = linalg.inv(value_1)
    aT_G_J_value1Inv = np.matmul(aT_G_J, value_1Inv)
    aT_G_J_value1Inv_J_G_a = np.matmul(aT_G_J_value1Inv, J_G_a)
    func_val = (1/lambda_val)*(aT_G_J_value1Inv_J_G_a - aT_G_a)
    return func_val


if __name__ == "__main__":

    import numpy as np 
    import pandas as pd 
    from sklearn.model_selection import train_test_split
    from scipy.spatial.distance import pdist, squareform 
    from scipy import linalg
    from scipy.optimize import linprog
    from scipy import optimize as optimize

    theta_val = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])

    value = c_func(theta_val)
    result = optimize.minimize(value, theta_val, method='Newton-CG', jac=True, options={'disp':True})
    print(result)

这是我得到的详细错误:

Traceback (most recent call last):
  File "test_project.py", line 76, in <module>
    result = optimize.minimize(value, theta_val, method='Newton-CG', jac=True, options={'disp':True})

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/_minimize.py", line 607, in minimize
    **options)

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 1588, in _minimize_newtoncg
    old_fval = f(x0)

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 327, in function_wrapper
    return function(*(wrapper_args + args))

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 65, in __call__

    fg = self.fun(x, *args)

TypeError: 'numpy.float64' object is not callable

谁能帮我解决这个错误?

log IndexError:(上下文见下面的 cmets 讨论)

Traceback (most recent call last):
  File "test_project.py", line 120, in <module>
    result = optimize.minimize(c_func, theta, method='Newton-CG', jac =True, options={'disp':True})

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/_minimize.py", line 607, in minimize
    **options)

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 1588, in _minimize_newtoncg
    old_fval = f(x0)

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 327, in function_wrapper
    return function(*(wrapper_args + args))

  File "/home/somesh/anaconda3/lib/python3.7/site-packages/scipy/optimize/optimize.py", line 66, in __call__
    self.jac = fg[1]

IndexError: invalid index to scalar variable.

【问题讨论】:

    标签: python-3.x numpy optimization scipy


    【解决方案1】:

    所以你的问题是你已经评估了c_func

    minimize 例程需要 callable 并且 c_func 本身是可调用的,但是当您在 theta_val 上调用 c_func 时,您会得到一个浮点数(或者也许浮点数数组。这/这些是您的c_func返回值

    如果您想从网格中找到最小值,您可以评估函数并找到最小值。 minimize 为您做的是接受 c_func 并搜索参数空间以找到最佳 theta_val

    minimize 的第二个参数应该是theta_val 的起始值。 阅读(如果您还没有)最小化教程可能会对您有所帮助:

    https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html#nelder-mead-simplex-algorithm-method-nelder-mead

    了解它的工作原理。

    您可能想要的电话不是:

    result = optimize.minimize(value, theta_val, method='Newton-CG', jac=True, options={'disp':True})
    

    而是:

    result = optimize.minimize(c_func, theta_val, method='Newton-CG', jac=True, options={'disp':True})
    

    这应该可以工作并返回一个OptimizeResult 对象。

    【讨论】:

    • 当我尝试您的方法时,我收到此错误:IndexError: invalid index to scalar variable。它没有优化。
    • @SomeshGuptait 看起来你唯一使用theta 的地方是行:``` for value in range(10): gamma = 1/(sigma[value]**2) gamma = -gamma * theta[value] ``` 对吗?如果是这样,您能否重新定义函数以使用单个 theta 进行计算,然后您能否查看是否消除了错误?
    • @LucasRobers我需要用 theta 作为向量而不是标量来优化它,以便与论文保持一致。但是,当我尝试您的建议时,我收到此错误:--> ValueError: 具有多个元素的数组的真值是不明确的。使用 a.any() 或 a.all()
    • @SomeshGupta 好的,如果您需要帮助调试 IndexError,那么您需要发布在对 scipy.minimize 进行正确调用时收到的错误,我真的无法帮助您调试错误仅使用异常类型。请发布完整的堆栈跟踪。
    • 我已将它作为“log IndexError”添加到正文中,供您参考。
    【解决方案2】:

    问题在于,在使用共轭梯度法优化的最小化库中,需要将梯度函数或数组传递给最小化函数。如果我们不通过梯度,那么它会给出错误。

    我通过了渐变,它起作用了。

    修改后的代码为:

    def c_func_opt(theta):
    
        data_pima = pd.read_csv('~/Documents/Uwaterloo_Study_Docs/ECE_602    Project_final/Dataset/PIMA/pima-indians-diabetes.csv')
        data_pima.rename(columns={'1':'Target', '6':'Pregnancies',  '148':'Glucose', '72':'BloodPressure', '35':'SkinThickness', '0': 'Insulin','33.6': 'BMI', '0.627':'DiabeticPedigreeFunction','50':'Age'},inplace=True)
        X = data_pima.loc[:,:'Age'].values
        y = data_pima['Target'].values
        data_pima_positive = data_pima.loc[(data_pima['Target'] > 0)]
        data_pima_negative = data_pima.loc[(data_pima['Target'] < 1)]
    
    
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30,random_state=42)
    
        sq_dist = pdist(X, 'sqeuclidean')
        sigma = [10**(0.1), 10**(-0.7), 10**(-0.4), 10**(-0.1), 10**(0.2), 10**(0.5), 10**(0.8), 10**(1.1), 10**(1.4), 10**(1.7)]
        mat_sqr_dist = squareform(sq_dist)
    
        G = 0
        G_list = []
        eq9_value = 0
    
        for value in range(10):
            gamma = 1/(sigma[value]**2)
            gamma = -gamma 
            g = np.exp(gamma * mat_sqr_dist)
            G_g = theta[value] * g
            G_list.append(G_g)
            G = np.add(G, G_g)
    
        m_plus = len(data_pima_positive.index)
        data_pima_positive = data_pima_positive.values
        m_minus = len(data_pima_negative.index)
        one_plus = np.ones(m_plus)
        one_minus = np.ones(m_minus)
        I_plus = np.identity(m_plus)
        J_plus_1value = np.dot(one_plus, one_plus.T)
        J_plus = (1/np.sqrt(m_plus)) * (I_plus - (1/m_plus) * J_plus_1value)
        I_minus = np.identity(m_minus)
        J_minus_1value = np.dot(one_minus, one_minus.T)
        J_minus = (1/np.sqrt(m_minus)) * (I_minus - (1/m_minus) * J_minus_1value)
    
        J = linalg.block_diag(J_plus, J_minus)
        a_plus_1 = (1/m_plus)* one_plus
        a_minus_1  = (1/m_minus)* one_minus
        zeros_a_plus = np.zeros(len(a_minus_1))
        a_plus = np.block([a_plus_1, zeros_a_plus])
        zeros_a_minus = np.zeros(len(a_plus_1))
        a_minus = np.block([zeros_a_minus, a_minus_1])
        a = a_plus - a_minus
        lambda_val = 10**(-8)
        I = np.identity(len(J))
        J_G = np.matmul(J,G)
        lambda_I = lambda_val*I
        J_G_J = np.matmul(J_G, J)
        value_1 = (lambda_I + J_G_J)
        J_G_a = np.matmul(J_G,a)
        G_J = np.matmul(G,J)
        aT_G_J = np.matmul(a.T,G_J)
        G_a = np.matmul(G,a)
        aT_G_a = np.matmul(a.T, G_a)
        value_1Inv = linalg.inv(value_1)
        aT_G_J_value1Inv = np.matmul(aT_G_J, value_1Inv)
        aT_G_J_value1Inv_J_G_a = np.matmul(aT_G_J_value1Inv, J_G_a)
        func1_val = (1/lambda_val)*(aT_G_J_value1Inv_J_G_a - aT_G_a)
    
        eq9_value = 0
        for index_k in range(10):
            gamma = 1/(sigma[value]**2)
            gamma = -gamma 
            g = np.exp(gamma * mat_sqr_dist)
            theta_aT = theta[index_k] * a.T 
            theta_aT_g = np.matmul(theta_aT, g)
            theta_aT_g_a = np.matmul(theta_aT_g, a) 
            eq9_value += theta_aT_g_a
    
        func2_val = (1/lambda_val) * (aT_G_a - eq9_value)
    
        return func2_val
    
    
    def c_func(theta):
    
        data_pima = pd.read_csv('~/Documents/Uwaterloo_Study_Docs/ECE_602/Project_final/Dataset/PIMA/pima-indians-diabetes.csv')
        data_pima.rename(columns={'1':'Target', '6':'Pregnancies', '148':'Glucose', '72':'BloodPressure', '35':'SkinThickness', '0': 'Insulin','33.6': 'BMI', '0.627':'DiabeticPedigreeFunction','50':'Age'},inplace=True)
        X = data_pima.loc[:,:'Age'].values
        y = data_pima['Target'].values
        data_pima_positive = data_pima.loc[(data_pima['Target'] > 0)]
        data_pima_negative = data_pima.loc[(data_pima['Target'] < 1)]
    
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30,random_state=42)
    
        sq_dist = pdist(X, 'sqeuclidean')
        sigma = [10**(0.1), 10**(-0.7), 10**(-0.4), 10**(-0.1), 10**(0.2), 10**(0.5), 10**(0.8), 10**(1.1), 10**(1.4), 10**(1.7)]
        mat_sqr_dist = squareform(sq_dist)
    
        G = 0 
        for value in range(10):
            gamma = 1/(sigma[value]**2)
            gamma = -gamma  
            g = np.exp(gamma * mat_sqr_dist)
            G_g = theta[value] * g 
            G = np.add(G, G_g)
    
        # number of positive sample from the dataset
        m_plus = len(data_pima_positive.index)
        data_pima_positive = data_pima_positive.values
        m_minus = len(data_pima_negative.index)
        one_plus = np.ones(m_plus)
        one_minus = np.ones(m_minus)
        I_plus = np.identity(m_plus)
        J_plus_1value = np.dot(one_plus, one_plus.T)
        J_plus = (1/np.sqrt(m_plus)) * (I_plus - (1/m_plus) * J_plus_1value)
        I_minus = np.identity(m_minus)
        J_minus_1value = np.dot(one_minus, one_minus.T)
        J_minus = (1/np.sqrt(m_minus)) * (I_minus - (1/m_minus) * J_minus_1value)
        J = linalg.block_diag(J_plus, J_minus)
        a_plus_1 = (1/m_plus)* one_plus
        a_minus_1  = (1/m_minus)* one_minus
        zeros_a_plus = np.zeros(len(a_minus_1))
        a_plus = np.block([a_plus_1, zeros_a_plus])
        zeros_a_minus = np.zeros(len(a_plus_1))
        a_minus = np.block([zeros_a_minus, a_minus_1])
        a = a_plus - a_minus
        lambda_val = 10**(-8)
        I = np.identity(len(J))
        J_G = np.matmul(J,G)
        lambda_I = lambda_val*I
        J_G_J = np.matmul(J_G, J)
        value_1 = (lambda_I + J_G_J)
        J_G_a = np.matmul(J_G,a)
        G_J = np.matmul(G,J)
        aT_G_J = np.matmul(a.T,G_J)
        G_a = np.matmul(G,a)
        aT_G_a = np.matmul(a.T, G_a)
        value_1Inv = linalg.inv(value_1)
        aT_G_J_value1Inv = np.matmul(aT_G_J, value_1Inv)
        aT_G_J_value1Inv_J_G_a = np.matmul(aT_G_J_value1Inv, J_G_a)
        func_val = (1/lambda_val)*(aT_G_J_value1Inv_J_G_a - aT_G_a)
    
        grad = []
        for value in range(10):
            gamma = 1/(sigma[value]**2)
            gamma = -gamma  
            g = np.exp(gamma * mat_sqr_dist)
            aT_g = np.matmul(a.T, g)
            aT_g_a = np.matmul(aT_g, a)
            grad.append(aT_g_a)
        return sq_dist, sigma, a, J, grad
    
    def gradient_value(grad):
        lambda_va = 10**(-8)
        grad = (-1/lambda_va)*grad
        return grad
    
    
    if __name__ == "__main__":
    
        import numpy as np 
        import pandas as pd 
        from sklearn.model_selection import train_test_split
        from scipy.spatial.distance import pdist, squareform 
        from scipy import linalg
        from scipy.optimize import LinearConstraint
        from scipy import optimize as optimize
        import cvxpy as cvx
    
        theta = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
        sq_dist, sigma, a, J, grad = c_func(theta)
        grad = np.array(grad)
        grad_val = gradient_value(grad)
        one_vec = np.ones(len(theta))
        one_vec_t_theta = np.matmul(one_vec.T, theta)
        result = optimize.minimize(c_func_opt, theta, method='Newton-CG', jac =     gradient_value, options={'disp':True})   #constraints= cons,
        print(result)
    

    输出:

    Warning: Desired error not necessarily achieved due to precision loss.
             Current function value: -16171400.005492
             Iterations: 1
             Function evaluations: 33
             Gradient evaluations: 25
             Hessian evaluations: 0
         fun: -16171400.005492399
         jac: array([-1.025e+10, -1.025e+10, -1.025e+10, -1.025e+10, -1.025e+10,
           -1.025e+10, -1.025e+10, -1.025e+10, -1.025e+10, -1.025e+10])
     message: 'Warning: Desired error not necessarily achieved due to precision loss.'
        nfev: 33
        nhev: 0
         nit: 1
        njev: 25
      status: 2
     success: False
           x: array([102.5, 102.5, 102.5, 102.5, 102.5, 102.5, 102.5, 102.5, 102.5,
       102.5])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-11
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多