【发布时间】:2021-08-24 01:18:09
【问题描述】:
我想在 python 中使用 gekko 包实现 MLE(最大似然估计)。假设我们有一个DataFrame,它包含两列:['Loss', 'Target'],它的长度等于 500。
首先我们必须导入我们需要的包:
from gekko import GEKKO
import numpy as np
import pandas as pd
然后我们像这样简单地创建DataFrame:
My_DataFrame = pd.DataFrame({"Loss":np.linspace(-555.795 , 477.841 , 500) , "Target":0.0})
My_DataFrame = My_DataFrame.sort_values(by=["Loss"] , ascending=False).reset_index(drop=True)
My_DataFrame
['Target'] 列的某些组件 应使用我在图片下方写下的公式计算(其余部分保持为零。我在继续中解释了更多信息,请继续阅读),以便您可以完美地看到它。公式的两个主要元素是“Kasi”和“Betaa”。我想为他们找到最大化My_DataFrame[‘Target’] 总和的最佳价值。所以你明白了,接下来会发生什么!
现在让我向您展示我是如何为此目的编写代码的。首先我定义我的目标函数:
def obj_function(Array):
"""
[Purpose]:
+ it will calculate each component of My_DataFrame["Target"] column! then i can maximize sum(My_DataFrame["Target"]) and find best 'Kasi' and 'Betaa' for it!
[Parameters]:
+ This function gets Array that contains 'Kasi' and 'Betaa'.
Array[0] represents 'Kasi' and Array[1] represents 'Betaa'
[returns]:
+ returns a pandas.series.
actually it returns new components of My_DataFrame["Target"]
"""
# in following code if you don't know what is `qw`, just look at the next code cell right after this cell (I mean next section).
# in following code np.where(My_DataFrame["Loss"] == item)[0][0] is telling me the row's index of item.
for item in My_DataFrame[My_DataFrame["Loss"]>160]['Loss']:
My_DataFrame.iloc[np.where(My_DataFrame["Loss"] == item)[0][0] , 1] = qw.log10((1/Array[1])*( 1 + (Array[0]*(item-160)/Array[1])**( (-1/Array[0]) - 1 )))
return My_DataFrame["Target"]
如果您对obj_function 函数中的for loop 中发生的事情感到困惑,请查看下图,它包含一个简短的示例!如果没有,请跳过这部分:
那么我们只需要进行优化。为此,我使用gekko 包。 请注意我想找到“Kasi”和“Betaa”的最佳值,所以我有两个主要变量,我没有任何约束!
那么让我们开始吧:
# i have 2 variables : 'Kasi' and 'Betaa', so I put nd=2
nd = 2
qw = GEKKO()
# now i want to specify my variables ('Kasi' and 'Betaa') with initial values --> Kasi = 0.7 and Betaa = 20.0
x = qw.Array(qw.Var , nd , value = [0.7 , 20])
# So i guess now x[0] represents 'Kasi' and x[1] represents 'Betaa'
qw.Maximize(np.sum(obj_function(x)))
然后当我想用qw.solve()解决优化时:
qw.solve()
但我收到了这个错误:
例外:此稳态 IMODE 只允许标量值。
我该如何解决这个问题? (为方便起见,将完整的脚本收集在下一节中)
from gekko import GEKKO
import numpy as np
import pandas as pd
My_DataFrame = pd.DataFrame({"Loss":np.linspace(-555.795 , 477.841 , 500) , "Target":0.0})
My_DataFrame = My_DataFrame.sort_values(by=["Loss"] , ascending=False).reset_index(drop=True)
def obj_function(Array):
"""
[Purpose]:
+ it will calculate each component of My_DataFrame["Target"] column! then i can maximize sum(My_DataFrame["Target"]) and find best 'Kasi' and 'Betaa' for it!
[Parameters]:
+ This function gets Array that contains 'Kasi' and 'Betaa'.
Array[0] represents 'Kasi' and Array[1] represents 'Betaa'
[returns]:
+ returns a pandas.series.
actually it returns new components of My_DataFrame["Target"]
"""
# in following code if you don't know what is `qw`, just look at the next code cell right after this cell (I mean next section).
# in following code np.where(My_DataFrame["Loss"] == item)[0][0] is telling me the row's index of item.
for item in My_DataFrame[My_DataFrame["Loss"]>160]['Loss']:
My_DataFrame.iloc[np.where(My_DataFrame["Loss"] == item)[0][0] , 1] = qw.log10((1/Array[1])*( 1 + (Array[0]*(item-160)/Array[1])**( (-1/Array[0]) - 1 )))
return My_DataFrame["Target"]
# i have 2 variables : 'Kasi' and 'Betaa', so I put nd=2
nd = 2
qw = GEKKO()
# now i want to specify my variables ('Kasi' and 'Betaa') with initial values --> Kasi = 0.7 and Betaa = 20.0
x = qw.Array(qw.Var , nd)
for i,xi in enumerate([0.7, 20]):
x[i].value = xi
# So i guess now x[0] represents 'Kasi' and x[1] represents 'Betaa'
qw.Maximize(qw.sum(obj_function(x)))
提出的潜在脚本在这里:
from gekko import GEKKO
import numpy as np
import pandas as pd
My_DataFrame = pd.read_excel("[<FILE_PATH_IN_YOUR_MACHINE>]\\Losses.xlsx")
# i'll put link of "Losses.xlsx" file in the end of my explaination
# so you can download it from my google drive.
loss = My_DataFrame["Loss"]
def obj_function(x):
k,b = x
target = []
for iloss in loss:
if iloss>160:
t = qw.log((1/b)*(1+(k*(iloss-160)/b)**((-1/k)-1)))
target.append(t)
return target
qw = GEKKO(remote=False)
nd = 2
x = qw.Array(qw.Var,nd)
# initial values --> Kasi = 0.7 and Betaa = 20.0
for i,xi in enumerate([0.7, 20]):
x[i].value = xi
# bounds
k,b = x
k.lower=0.1; k.upper=0.8
b.lower=10; b.upper=500
qw.Maximize(qw.sum(obj_function(x)))
qw.options.SOLVER = 1
qw.solve()
print('k = ',k.value[0])
print('b = ',b.value[0])
python 输出:
目标函数 = -1155.4861315885942
b = 500.0
k = 0.1
注意在python输出中b代表“Betaa”,k代表“Kasi”。
输出看起来有点奇怪,所以我决定测试一下!为此我使用了 Microsoft Excel Solver!
(我把excel文件的链接放在我解释的最后,所以你可以自己检查一下,如果
你想要的。)如下图所示,已经完成了excel优化和最佳解决方案
已成功找到(优化结果见下图结果)。
excel 输出:
目标函数 = -108.21
Betaa = 32.53161
卡斯 = 0.436246
如您所见,python output 和 excel output 之间存在巨大差异,并且似乎 excel 的表现相当不错! 所以我猜问题仍然存在,建议的 python 脚本性能不佳......Implementation_in_Excel.xls Microsoft excel 应用程序优化文件可用here。(你也可以看到优化数据选项卡中的选项 --> 分析 --> Slover。)
在 excel 和 python 中用于优化的数据是相同的,可用here(非常简单,包含 501 行和 1 列)。
*如果您无法下载文件,请告诉我,我会更新它们。
【问题讨论】:
标签: python python-3.x optimization gekko mle