Desired error not necessarily achieved due to precision loss

I have the following code which attempts to minimize a log likelihood function. #!/usr/bin/python import math import random import numpy as np from scipy.optimize import minimize def loglikelihood(

I have the following code which attempts to minimize a log likelihood function.

#!/usr/bin/python
import math
import random
import numpy as np
from scipy.optimize import minimize

def loglikelihood(params, data):
    (mu, alpha, beta) = params
    tlist = np.array(data)
    r = np.zeros(len(tlist))
    for i in xrange(1,len(tlist)):
        r[i] = math.exp(-beta*(tlist[i]-tlist[i-1]))*(1+r[i-1])
    loglik  = -tlist[-1]*mu
    loglik = loglik+alpha/beta*sum(np.exp(-beta*(tlist[-1]-tlist))-1)
    loglik = loglik+np.sum(np.log(mu+alpha*r))
    return -loglik

atimes = [ 148.98894201,  149.70253172,  151.13717804,  160.35968355,
        160.98322609,  161.21331798,  163.60755544,  163.68994973,
        164.26131871,  228.79436067]
a= 0.01
alpha = 0.5
beta = 0.6
print loglikelihood((a, alpha, beta), atimes)

res = minimize(loglikelihood, (0.01, 0.1,0.1), method = 'BFGS',args = (atimes,))
print res

It gives me

28.3136498357
./test.py:17: RuntimeWarning: invalid value encountered in log
  loglik = loglik+np.sum(np.log(mu+alpha*r))
   status: 2
  success: False
     njev: 14
     nfev: 72
 hess_inv: array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])
      fun: 32.131359359964378
        x: array([ 0.01,  0.1 ,  0.1 ])
  message: 'Desired error not necessarily achieved due to precision loss.'
      jac: array([ -2.8051672 ,  13.06962156, -48.97879982])

Notice that it hasn’t managed to optimize the parameters at all and the minimized value 32 is bigger than 28 which is what you get with a= 0.01, alpha = 0.5, beta = 0.6 . It’s possible this problem could be avoided by choosing better initial guesses but if so, how can I do this automatically?


Nelder-Mead, TNC and SLSQP work as drop-in replacements. None of the other methods do.

$begingroup$

I am getting the warning in the post subject when attempting to optimize a function in Python with the scipy.optimize.fmin_bfgs function.
The complete output:

Warning: Desired error not necessarily achieveddue to precision loss

     Current function value: nan
     Iterations: 1
     Function evaluations: 18
     Gradient evaluations: 3

It is not a fatal error, I am getting answers, but they are far from the optimum I search.

Are there any typical «noob» errors that might generate this error? I started working with this package only yesterday; as it is, I’m not even sure where to start looking.
Any help is appreciated!

Aron Ahmadia's user avatar

Aron Ahmadia

6,8914 gold badges33 silver badges54 bronze badges

asked Apr 21, 2012 at 13:47

ACEG's user avatar

$endgroup$

$begingroup$

It is helpful in situations like this to take a look at the source code. This is easy because everything in scipy is open source!

As you can see from reading the source code, the warning message is printed when warnflag==2. This gets set elsewhere in the code when the linesearch function returns None (it fails).

So why does linesearch fail? The goal of an optimization algorithm is to find the minima of some objective function through a successive set of iterations. The line search, in this case, is trying to find a step size where the approximations in BFGS are still valid. When the Hessian of your function or its gradient are ill-behaved in some way, the bracketed step size could be computed as zero, even though the gradient is non-zero.

I guess my suggestion is to either go to the literature (Nocedal and Wright has a good discussion of line search and the BFGS method) or to your function and make sure that it is well-behaved in the region you are searching.

answered Apr 21, 2012 at 15:51

Aron Ahmadia's user avatar

Aron AhmadiaAron Ahmadia

6,8914 gold badges33 silver badges54 bronze badges

$endgroup$

5

#python #scipy #scipy-optimize-minimize

#питон #сципи #scipy-оптимизировать-минимизировать

Вопрос:

Я пытаюсь решить набор уравнений с помощью scipy.minimize, однако я не получаю удовлетворительных результатов, так что, возможно, я что-то делаю не так. Я хочу решить следующую систему уравнений.

 12.25 * (x   y * 2.2   z * 4.84) - 8.17437483750257 = 0 12.25 * (x   y * 3.1   z * 9.61) - 21.9317236606432 = 0 12.25 * (x   y * 4   z * 16) - 107.574834524443 = 0  

Используя Wolfram Alpha, я получаю ответы

 x=22.626570068753, y=-17.950683342597, z=3.6223614029055  

Которые действительно решают систему уравнений, давая остаточную ошибку

 9.407585821463726e-12  

Теперь, используя scipy.минимизировать, я делаю:

 import numpy as np from scipy.optimize import fsolve from scipy.optimize import minimize  def my_func(p):  points = [8.17437483750257, 21.9317236606432, 107.574834524443]  h1 = abs(12.25 * (p[0]   p[1] * 2.2   p[2] * 4.84) - points[0])  h2 = abs(12.25 * (p[0]   p[1] * 3.1   p[2] * 9.61) - points[1])  h3 = abs(12.25 * (p[0]   p[1] * 4   p[2] * 16) - points[2])  return h1   h2   h3  ini = np.array([22, -15, 5]) # Initial points close to solution res = minimize(my_func, ini) print(res)     fun: 1.4196640741924451  hess_inv: array([[ 20.79329103, -14.63447889, 2.36145776],  [-14.63447889, 10.30037625, -1.66214485],  [ 2.36145776, -1.66214485, 0.26822135]])  jac: array([ 12.25 , 60.02499545, 254.43249989])  message: 'Desired error not necessarily achieved due to precision loss.'  nfev: 261  nit: 8  njev: 64  status: 2  success: False  x: array([ 21.39197235, -17.08623345, 3.48344393])  

Во-первых, он говорит, что успех=Ложь, а во-вторых, он находит решения, которые не являются оптимальными.

Почему, имея начальные значения, близкие к оптимальному решению, он не может найти эти решения.

Что-то не так с определением оптимизатора?

Попробовал запустить его, дав начальные значения [0,0,0], и это просто дает ужасные результаты

 ini = np.array([0, 0, 0]) # Initial points close to solution res = minimize(my_func, ini) print(res)  fun: 73.66496363902732  hess_inv: array([[ 0.98461683, -0.04223651, -0.1207056 ],  [-0.04223651, 0.88596592, -0.31885642],  [-0.1207056 , -0.31885642, 0.13448927]])  jac: array([ 12.25 , 15.92499924, -18.98750019])  message: 'Desired error not necessarily achieved due to precision loss.'  nfev: 164  nit: 1  njev: 40  status: 2  success: False  x: array([0.02901304, 0.08994042, 0.29448233])  

Примечание: Я не хочу использовать fsolve для поиска решений, но minimize . Причина в том, что моя реальная проблема заключается в том, что у меня больше уравнений, чем неизвестных, поэтому в конце я хочу найти решение, которое минимизирует ошибки всех этих уравнений. Однако, поскольку это не давало хороших результатов, я хотел сначала протестировать простую проблему, для которой существует точное решение. Но даже в этом случае это не работает. Как только я решу эту задачу, я расширю ее, добавив дополнительные уравнения.

Комментарии:

1. Ваша система линейна, почему вы хотите использовать подход нелинейной оптимизации, а не просто решать ее с помощью линейной алгебры???

2. Я отредактировал вопрос. В конце концов, мне нужен оптимизатор для системы с большим количеством уравнений, чем неизвестных. Система по-прежнему будет линейной, но решение не будет точным, это будет просто минимальная ошибка. Как я могу получить линейный минимизатор для решения этой проблемы?

3. Это звучит как обобщенный метод моментов. Помогает ли возведение в квадрат различий вместо использования абсолютных значений? Например. h1 =(12.25 * (p[0] p[1] * 2.2 p[2] * 4.84) - points[0])**2

4. @ForceBru. Да! Я изменил сумму для квадрата, и это дает точный результат. Спасибо. Если вы сформулируете это как ответ, я приму его

5. @SembeiNorimaki Если у вас больше уравнений, чем неизвестных, но система все еще линейна, то ее все еще можно решить с помощью линейной алгебры, решение состоит в использовании линейных наименьших квадратов, как в f.ex. numpy.linalg.lstsq

Ответ №1:

…моя реальная проблема заключается в том, что у меня больше уравнений, чем неизвестных, поэтому в конце я хочу найти решение, которое минимизирует ошибки всех этих уравнений

Это очень похоже на проблему, решаемую в обобщенном методе моментов (GMM), где у вас также больше уравнений, чем неизвестных.

Проблемы такого рода обычно решаются с использованием метода наименьших квадратов. Предположим, вся ваша система выглядит так:

 h1(x, y, z) = 0 h2(x, y, z) = 0 h3(x, y, z) = 0 h4(x, y, z) = 0  

Он имеет 3 неизвестных и 4 уравнения. Тогда ваша целевая функция будет:

 F(x, y, z) = H(x, y, z)' * W * H(x, y, z)  
  • H(x, y, z) является вектором всего hj(x, y, z) вышеперечисленного
  • H(x, y, z)' является ли его транспонирование
  • W является весовой матрицей

Если W это матрица идентичности, вы получаете целевую функцию наименьших квадратов. Затем, F(x, y, z) это квадратичная форма (в основном парабола в нескольких измерениях), которую должно быть просто оптимизировать, потому что она выпуклая и гладкая.

В вашем коде используются абсолютные значения , такие как h1 = abs(12.25 * (p[0] p[1] * 2.2 p[2] * 4.84) - points[0]) , но abs может быть трудно различить вблизи источника, но именно там находится ваш оптимум, поскольку вы, по сути, хотите h1 равняться нулю.

Вы можете приблизить функцию абсолютного значения, возведя ошибку в квадрат:

 h1 =(12.25 * (p[0]   p[1] * 2.2   p[2] * 4.84) - points[0])**2  

Это приводит в основном к тому же подходу, что и GMM (или наименьшие квадраты), и дает вам функцию, которую легко оптимизировать, так как квадрат гладкий вблизи начала координат.

Комментарии:

1. Да, в конце концов я закончил использовать метод наименьших квадратов, и я получаю лучшие результаты, чем при использовании нелинейного оптимизатора scipy.

Ответ №2:

Проблемы оптимизации (и решатели) обычно выигрывают от хорошей (гладкой) «поверхности оптимизации». Когда вы используете abs функцию, она создает «прерывистую» поверхность с точками, производные которых не являются непрерывными.

Если вместо использования abs вы используете квадратичную функцию (которая имеет тот же эффект), вы получите решение, близкое к тому, что вы ожидаете. Просто измените my_func на:

 def my_func(p):  points = [8.17437483750257, 21.9317236606432, 107.574834524443]  h1 = (12.25 * (p[0]   p[1] * 2.2   p[2] * 4.84) - points[0])**2  h2 = (12.25 * (p[0]   p[1] * 3.1   p[2] * 9.61) - points[1])**2  h3 = (12.25 * (p[0]   p[1] * 4   p[2] * 16) - points[2])**2  return h1   h2   h3  

Что у меня есть, так это:

 fun: 8.437863292878727e-10  hess_inv: array([[ 0.64753863, -0.43474506, 0.06909179],  [-0.43474506, 0.29487798, -0.04722923],  [ 0.06909179, -0.04722923, 0.00761762]])  jac: array([-6.26698693e-12, 6.22490927e-10, -5.11716516e-10])  message: 'Optimization terminated successfully.'  nfev: 55  nit: 7  njev: 11  status: 0  success: True  x: array([ 22.62653789, -17.95066124, 3.62235782])  

Я получаю следующее предупреждение об использовании оптимизации SciPy fmin_bfgs() в NeuralNetwork. Все должно быть понятно и просто, по алгоритму Backpropagation.

1 Примеры обучения Feed Forward.
2 Рассчитайте срок погрешности для каждого блока.
3 Накопительный градиент (в первом примере я пропускаю термин регуляризации).

Starting Loss: 7.26524579601
Check gradient: 2.02493576268
Warning: Desired error not necessarily achieved due to precision loss.
         Current function value: 5.741300
         Iterations: 3
         Function evaluations: 104
         Gradient evaluations: 92
Trained Loss: 5.74130012926

Я только что выполнил ту же задачу с MATLAB, которая успешно выполнилась с функциями fmin для оптимизации, но не могу понять, что я упустил в реализации Python. Как видите, даже scipy.optimize.check_grad возвращает слишком большое значение.

def feed_forward(x, theta1, theta2):
    hidden_dot = np.dot(add_bias(x), np.transpose(theta1))
    hidden_p = sigmoid(hidden_dot)

    p = sigmoid(np.dot(add_bias(hidden_p), np.transpose(theta2)))
    return hidden_dot, hidden_p, p


def cost(thetas, x, y, hidden, lam):
    theta1, theta2 = get_theta_from(thetas, x, y, hidden)
    _, _, p = feed_forward(x, theta1, theta2)

    # regularization = (lam / (len(x) * 2)) * (
    #     np.sum(np.square(np.delete(theta1, 0, 1)))
    #     + np.sum(np.square(np.delete(theta2, 0, 1))))

    complete = -1 * np.dot(np.transpose(y), np.log(p)) 
               - np.dot(np.transpose(1 - y), np.log(1 - p))
    return np.sum(complete) / len(x)  # + regularization


def vector(z):
    # noinspection PyUnresolvedReferences
    return np.reshape(z, (np.shape(z)[0], 1))



def gradient(thetas, x, y, hidden, lam):
    theta1, theta2 = get_theta_from(thetas, x, y, hidden)
    hidden_dot, hidden_p, p = feed_forward(x, theta1, theta2)

    error_o = p - y
    error_h = np.multiply(np.dot(
        error_o, np.delete(theta2, 0, 1)), sigmoid_gradient(hidden_dot))

    x = add_bias(x)
    hidden_p = add_bias(hidden_p)

    theta1_grad, theta2_grad = 
        np.zeros(theta1.shape[::-1]), np.zeros(theta2.shape[::-1])
    records = y.shape[0]

    for i in range(records):
        theta1_grad = theta1_grad + np.dot(
            vector(x[i]), np.transpose(vector(error_h[i])))
        theta2_grad = theta2_grad + np.dot(
            vector(hidden_p[i]), np.transpose(vector(error_o[i])))

    theta1_grad = np.transpose(
        theta1_grad / records)  # + (lam / records * theta1)

    theta2_grad = np.transpose(
        theta2_grad / records)  # + (lam / records * theta2)

    return np.append(theta1_grad, theta2_grad)


def get_theta_shapes(x, y, hidden):
    return (hidden, x.shape[1] + 1), 
           (y.shape[1], hidden + 1)


def get_theta_from(thetas, x, y, hidden):
    t1_s, t2_s = get_theta_shapes(x, y, hidden)
    split = t1_s[0] * t1_s[1]

    theta1 = np.reshape(thetas[:split], t1_s)
    theta2 = np.reshape(thetas[split:], t2_s)
    return theta1, theta2



def train(x, y, hidden_size, lam):
    y = get_binary_y(y)

    t1_s, t2_s = get_theta_shapes(x, y, hidden_size)
    thetas = np.append(
        rand_init(t1_s[0], t1_s[1]),
        rand_init(t2_s[0], t2_s[1]))

    initial_cost = cost(thetas, x, y, hidden_size, lam)
    print("Starting Loss: " + str(initial_cost))

    check_grad1 = scipy.optimize.check_grad(
        cost, gradient, thetas, x, y, hidden_size, lam)
    print("Check gradient: " + str(check_grad1))

    trained_theta = scipy.optimize.fmin_bfgs(
        cost, thetas, fprime=gradient, args=(x, y, hidden_size, lam))

    print("Trained Loss: " +
          str(cost(trained_theta, x, y, hidden_size, lam)))

2 ответа

Опять же, было несколько проблем с расчетом, чтобы устранить все предупреждения и сделать успешный запуск оптимизации Scipy, то же самое с функциями оптимизации Matlab fminc. (Рабочие примеры Python можно найти в Github)

1. Обновите расчетную стоимость до правильной. Умножьте поэлементно на функцию затрат. Правильным решением по стоимости будет (со сроком регуляризации):

def cost(thetas, x, y, hidden, lam):
    theta1, theta2 = get_theta_from(thetas, x, y, hidden)
    _, _, p = feed_forward(x, theta1, theta2)

    regularization = (lam / (len(x) * 2)) * (
        np.sum(np.square(np.delete(theta1, 0, 1)))
        + np.sum(np.square(np.delete(theta2, 0, 1))))

    complete = np.nan_to_num(np.multiply((-y), np.log(
        p)) - np.multiply((1 - y), np.log(1 - p)))
    avg = np.sum(complete) / len(x)
    return avg + regularization

2. После выполнения этой операции мы получим значения nan в термине Оптимизированный Theta от Scipy. В этом случае мы выполняем np.nan_to_num выше. Примечание! Это Matlab fminc правильно работает с неожиданными числами.

3. Примените правильную регуляризацию и не забудьте удалить регуляризацию для значений смещения. Правильная функция градиента должна выглядеть так:

def gradient(thetas, x, y, hidden, lam):
    theta1, theta2 = get_theta_from(thetas, x, y, hidden)
    hidden_dot, hidden_p, p = feed_forward(x, theta1, theta2)

    error_o = p - y
    error_h = np.multiply(np.dot(
        error_o, theta2),
        sigmoid_gradient(add_bias(hidden_dot)))

    x = add_bias(x)
    error_h = np.delete(error_h, 0, 1)

    theta1_grad, theta2_grad = 
        np.zeros(theta1.shape[::-1]), np.zeros(theta2.shape[::-1])
    records = y.shape[0]

    for i in range(records):
        theta1_grad = theta1_grad + np.dot(
            vector(x[i]), np.transpose(vector(error_h[i])))
        theta2_grad = theta2_grad + np.dot(
            vector(hidden_p[i]), np.transpose(vector(error_o[i])))

    reg_theta1 = theta1.copy()
    reg_theta1[:, 0] = 0

    theta1_grad = np.transpose(
        theta1_grad / records) + ((lam / records) * reg_theta1)

    reg_theta2 = theta2.copy()
    reg_theta2[:, 0] = 0

    theta2_grad = np.transpose(
        theta2_grad / records) + ((lam / records) * reg_theta2)

    return np.append(
        theta1_grad, theta2_grad)


0

GensaGames
26 Июн 2018 в 18:54

Просто интересно, почему вы пропустили этап регуляризации? Вы пробовали запускать программу с регуляризацией?


0

kamykam
15 Июн 2018 в 15:08

3 / 3 / 0

Регистрация: 02.04.2017

Сообщений: 273

1

Как минимизировать такую функцию?

28.09.2019, 12:43. Показов 916. Ответов 7


Есть список значений Y и список X и я хочу минимизировать функцию такого вида(прикрепил картинку).

Также есть начальные значения Theta0 = 1.537, Theta1 = 1.143, Theta2 = 0.01604. Как минимизировать такую функцию?

Миниатюры

Как минимизировать такую функцию?
 

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



1315 / 1240 / 213

Регистрация: 19.02.2010

Сообщений: 3,569

28.09.2019, 13:00

2

Превращайте эту полиномиальную регрессию в линейную путём ввода новой независимой переменной Z=X^2, далее любыми способами решения задачи линейной множественной регрессии. Например, через решение СЛАУ методом Гаусса.



0



Key27

3 / 3 / 0

Регистрация: 02.04.2017

Сообщений: 273

28.09.2019, 17:43

 [ТС]

3

VTsaregorodtsev, Немного не правильно выразился. Попробую на конкретном примере
Как с помощью scipy найти минимум функции трех переменных
https://www.cyberforum.ru/cgi-bin/latex.cgi?frac{1}{2}(5.59 -  (Theta_0+3.35Theta_1+11.22Theta_2))^2tominlimits_{Theta_0,Theta_1,Theta_2}?

Добавлено через 39 минут
Это делается примерно так:

Python
1
2
3
4
5
6
def f(params):
    a, b, c = params
    return 1/2*((5.59-(a + 3.35*b + 11.22*c)))**2
 
initial_guess = [1.537, 1.143, 0.01604]
result = minimize(f, initial_guess)

А что делать, когда нужно найти минимум суммы https://www.cyberforum.ru/cgi-bin/latex.cgi?sumlimits_{i=1}^{n} 0.5*(Y_i - (Theta_0 + Theta_1X_i + Theta_2X_i^2  )^2, где X и Y — два списка?

Добавлено через 11 минут
Пробовал так:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def f(params,X,y,i):
    a, b, c = params
    return (y[i]-(a + X[i]*b + X[i]**2*c))
 
 
def f2(params):
    sum = 0
    for i in range(len(y)):
        sum += 0.5*(f(params,X,y,i))**2
 
    return(sum)
 
initial_guess = [1.537, 1.143, 0.01604]
result = minimize(f2, initial_guess)

Но получаю ошибку

Bash
1
ValueError: Desired error not necessarily achieved due to precision loss.



0



Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

30.09.2019, 11:49

4



0



woldemas

653 / 457 / 212

Регистрация: 06.09.2013

Сообщений: 1,265

30.09.2019, 15:18

5

Цитата
Сообщение от Key27
Посмотреть сообщение

А что делать, когда нужно найти минимум суммы

Надо просто продифференцировать и приравнять производные к нулю. Если лень это делать, то можно найти формулу для коэффициентов множественной регрессии:
https://www.cyberforum.ru/cgi-bin/latex.cgi?Theta = (X^T X)^{-1} X^T Y
В данном случае незачем использовать scipy можно обойтись одним numpy, что-то типа

Python
1
2
3
4
5
6
import numpy as np
x = np.array(...)
y = np.array(...)
x = x.reshape(-1, 1)
x_ext = np.hstack((np.ones(x.shape), x, x**2))
theta = np.linalg.inv(np.dot(x_ext.T, x_ext)).dot(x_ext.T).dot(y)



0



Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

30.09.2019, 15:44

6

woldemas, не надо диференцировать.
100 к одному, задача именно на минимизацию путём градиентного спуска или чем-то подобным.
normal equation подходит в случае, когда признаков немного и способ не этого урока



0



653 / 457 / 212

Регистрация: 06.09.2013

Сообщений: 1,265

30.09.2019, 16:43

7

Цитата
Сообщение от dondublon
Посмотреть сообщение

задача именно на минимизацию путём градиентного спуска

Это в чистом виде полиномиальная регрессия (если я правильно понял обозначения — ТС там в скобках путается). Градиентный спуск даст тот же результат — там же целевая функция квадратичная.



0



Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

30.09.2019, 16:52

8

woldemas, да я вижу, что регрессия.
Тут ведь дело не просто в том, чтобы результат получить, а научиться вызывать минимизацию в соответствии с учебным курсом



0



Понравилась статья? Поделить с друзьями:

Читайте также:

  • Design time error
  • Description unexpected error minecraft
  • Description the server encountered an internal error that prevented it from fulfilling this request
  • Description mod loading error has occurred
  • Description invalid query как исправить

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии