Ошибка типа: объект numpy .float64 не вызывается в библиотеке scipy.optimize.minimize - PullRequest
1 голос
/ 14 апреля 2020

Привет. Я пытаюсь реализовать документ по оптимизации «Оптимальный выбор ядра в анализе дискриминанта ядра» и реализовал для него код. Тем не менее, я получаю эту ошибку после попытки разных методов. Я использую функцию scipy.optimize.minimize из библиотеки scipy 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: (для контекста см. Обсуждение комментариев ниже)

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.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2020

Проблема заключалась в том, что в библиотеке минимизации для оптимизации с использованием метода градиента Conjugate требуется функция градиента или массив, который необходимо передать в функцию минимизации. Если мы не передадим градиент, он выдаст ошибку.

Я прошел градиент, и он заработал.

Измененный код:

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])
0 голосов
/ 14 апреля 2020

Итак, ваша проблема в том, что вы уже оценили c_func.

Процедура minimize ожидает, что может быть вызвано , а сам c_func может быть вызван, но когда вы вызываете c_func на theta_val, вы получаете float (или возможно массив чисел с плавающей запятой. Это / это возвращаемые значения вашего c_func.

Если вы хотите найти минимальное значение из сетки, вы можете просто оцените функцию и найдите наименьшее значение. То, что minimize делает для вас, принимает c_func и ищет пространство аргументов, чтобы найти оптимальное theta_val.

Второй аргумент minimize должен быть начальное значение theta_val. Может быть полезно прочитать (если вы этого еще не сделали) учебник по минимизации:

https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html#nelder -mead-simplex-алгоритма-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 объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...