Scipy minimal_scalar给出错误答案

时间:2019-03-05 07:48:24

标签: python optimization scipy minimize

修改: 提供更好解决方案的两件事: 1)使目标函数返回绝对值。 2)将方法从“绑定”更改为“金色”。

我在使用Scipy的最小化方法“ minimize_scalar”时遇到麻烦。 该方法未找到最小值,同时报告说已找到解决方案。该解决方案不满足收敛极限。

下面遵循完整的示例代码来说明问题。

# 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”,考虑到我们的容忍度,这应该是一个很小的数字。

有人知道为什么这行不通吗?

0 个答案:

没有答案