【问题标题】:scipy.optimize on pandas dataframescipy.optimize 在熊猫数据框上
【发布时间】:2019-03-21 03:24:22
【问题描述】:

我试图搜索它,但结果很差。

有人可以向我解释一下如何在 Pandas DataFrame 上执行 optimize.minimize,因此最小化的是 DataFrame 中的类别和结果列之间的错误

考虑这个例子:

import pandas as pd

df = pd.DataFrame({'prod': ['prod1', 'prod2', 'prod3', 'prod4', 'prod5', 'prod6'],
                   'cat': ['cat1', 'cat1', 'cat2', 'cat2', 'cat3', 'cat1'],
                   'dog': ['dog1', 'dog2', 'dog1', 'dog2', 'dog2', 'dog3'],
                   'result': [20, 10, 30, 50, 45, 120]})

对于每个 cat1、cat2、cat3、dog1、dog2 和 dog3,我想找到最小化这个等式的值:

import numpy as np

np.average(np.abs(df['result'] - ('min for values in cat column * min for values in dog column'))) / np.average(df['result'])

我可以使用 Solver 在 Excel 中复制它

prod    cat     dog result  cat*dog abs
prod1   cat1    dog1    20  17.38   2.61
prod2   cat1    dog2    10  27.34   17.35
prod3   cat2    dog1    30  26.91   3.09
prod4   cat2    dog2    50  42.32   7.67
prod5   cat3    dog2    45  45.00   0.00
prod6   cat1    dog3    120 20.64   99.36

所以我想要找到的最终分数是:

平均腹肌 22 / 平均成绩 45.83 = 0.47

这些是 Solver 为动物返回的值:

cat1    3.59194254
cat2    5.559980313
cat3    5.91078751
dog1    4.840109868
dog2    7.613201994
dog3    5.746396256

如何在 Python 中复制它?

【问题讨论】:

    标签: python pandas optimization scipy solver


    【解决方案1】:

    您需要定义一个optimize.minimize 可以运行的函数(以便它知道它试图最小化什么)。

    import pandas as pd
    import numpy as np
    from scipy import optimize
    
    df = pd.DataFrame({'prod': ['prod1', 'prod2', 'prod3', 'prod4', 'prod5', 'prod6'],
                       'cat': ['cat1', 'cat1', 'cat2', 'cat2', 'cat3', 'cat1'],
                       'dog': ['dog1', 'dog2', 'dog1', 'dog2', 'dog2', 'dog3'],
                       'result': [20, 10, 30, 50, 45, 120]})
    

    因此,让我们按照您的描述定义 animal_error 函数 - 第一个参数是具有一些值的一维数组(根据优化的要求)。第二个参数是这些数组值的相应字符串,第三个参数是您的数据框。大部分代码只是将您的数据框字符串转换为可以计算的值。

    def animal_error(val, animal, df):
        assert len(val) == len(animal)
        lookup = dict()
        for i in range(len(val)):
            lookup[animal[i]] = val[i]
        df = df.replace(lookup)
        error = np.abs(df['result'] - np.multiply(df['cat'], df['dog']))
        return np.mean(error) / np.mean(df['result'])
    

    现在,您可以将字符串变成一个数组:

    animals = np.concatenate([df['dog'].unique(), df['cat'].unique()])
    

    为求解器设置一个合理的初始值:

    initial = np.repeat(np.sqrt(df['result'].mean()), animals.size)
    

    然后运行最小化器:

    res = optimize.minimize(animal_error, args=(animals, df), x0=initial, method = 'Nelder-Mead', options={'maxiter':10000})
    res_df = pd.DataFrame({'animal': animals, 'min_val':res.x})
    

    最终结果如下:

    >>> res.fun
    0.08676411624175694
    
      animal    min_val
    0   dog1   3.754194
    1   dog2   5.296533
    2   dog3  22.526566
    3   cat1   5.327044
    4   cat2   9.307979
    5   cat3   8.496109
    

    我认为您的成本函数描述可能有点偏差,因此您可能需要对其进行调整。

    【讨论】:

    • 如何确定“合理的初始值”?顺便说一句,谢谢! :)
    • @Jurek 由于您的成本函数是 (r - xy)/r,并且成本函数的理想值是 0,我认为 (r - x0*x0)/r = 0 (x0 = sqrt(r)) 将是一个不错的起点。老实说,问 10 个人,得到 10 个不同的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多