Сципис minim_scalar дает неправильный ответ - PullRequest
0 голосов
/ 05 марта 2019

edit: 2 вещи, которые дают намного лучшие решения: 1) Сделайте так, чтобы целевая функция возвращала абсолютное значение.2) Измените метод с «Ограниченный» на «Золотой».

У меня возникли проблемы с методом минимизации «minimal_scalar» от Scipy.Метод не находит минимума, и в то же время в отчете говорится, что решение найдено.Решение не удовлетворяет пределу сходимости.

Ниже приведен полный пример кода, иллюстрирующего проблему.

# Import modules
import pandas as pd
import numpy as np
from scipy.optimize import minimize_scalar # Optmimizer

# Construct data
np.random.seed(1)
observations = 200
columns = ['colA', 'colB', 'colC']
df= pd.DataFrame(columns=columns)
for i in range(observations):
    df.loc[i] = 'colA%d'%i, np.abs(np.asscalar(.6*np.random.randn(1))), \
                        np.abs(np.asscalar(2.5*np.random.randn(1)))
df.head()

, который дает

    colA      colB      colC
0  colA0  0.974607  1.529391
1  colA1  0.316903  2.682422
2  colA2  0.519245  5.753847
3  colA3  1.046887  1.903017
4  colA4  0.191423  0.623426

Функция цели:

def objectFunction(colBRightLimit, colBLeftLimit, 
                                     data, 
                                     wantedShare):
    """
    Calculates column share for given lower and upper limits for the values
    in the column.
    """
    wantedIndices = (data["colB"] >= colBLeftLimit) & \
                                    (data["colB"] < colBRightLimit)
    wantedRows = data[wantedIndices]
    numberOfObservationsInColumn = len(wantedRows)
    columnShare = numberOfObservationsInColumn/len(data)
    differenceFromWantedShares = columnShare - wantedShare
    return differenceFromWantedShares  

Оптимизация

wantedColumnShare = 0.1
colBLeftLimit = 0   
tolerance = 1e-6
res = minimize_scalar(objectFunction, 
                      method='bounded', 
                      bounds=(np.min(df["colB"]), np.max(df["colB"])),
                      args=(colBLeftLimit, df, wantedColumnShare),  
                      options={'xatol': tolerance})
                      #tol=tolerance)
optimalRightColBLimit = res.x
optimalRightColBLimit 

Что дает

0.99999947848782

Отчет

res

Что дает

     fun: -0.1
 message: 'Solution found.'
    nfev: 30
  status: 0
 success: True
       x: 0.99999947848782

Проблема состоит в том, что значение целевой функции становится равным «-0,1», и это должно быть очень маленькое число, учитывая нашу погрешность.

Кто-нибудь видит, почему это не работает?

...