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», и это должно быть очень маленькое число, учитывая нашу погрешность.
Кто-нибудь видит, почему это не работает?