python - 如何绘制多元积分函数的 3D 图,并找到其全局最小值
问题描述
我有一个成本函数f(r, Q),可以在下面的代码中获得。成本函数f(r, Q)是两个变量r 和 Q的函数。我想在下面给出的范围内绘制所有 r 和 Q 值的成本函数值,并找到f(r, Q)的全局最小值。
r 和 Q 的范围分别为:
0 < r < 5000
5000 < Q < 15000
该图应位于 r、Q 和 f(r,Q) 轴上。
成本函数的代码:
from numpy import sqrt, pi, exp
from scipy import optimize
from scipy.integrate import quad
import numpy as np
mean, std = 295, 250
l = 7
m = 30
p = 15
w = 7
K = 100
c = 5
h = 0.001 # per unit per day
# defining Cumulative distribution function
def cdf(x):
cdf_eqn = lambda t: (1 / (std * sqrt(2 * pi))) * exp(-(((t - mean) ** 2) / (2 * std ** 2)))
cdf = quad(cdf_eqn, -np.inf, x)[0]
return cdf
# defining Probability density function
def pdf(x):
return (1 / (std * sqrt(2 * pi))) * exp(-(((x - mean) ** 2) / (2 * std ** 2)))
# getting the equation in place
def G(r, Q):
return K + c * Q \
+ w * (quad(cdf, 0, Q)[0] + quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]) \
+ p * (mean * l - r + quad(cdf, 0, r)[0])
def CL(r, Q):
return (Q - r + mean * l - quad(cdf, 0, Q)[0]
- quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
+ quad(cdf, 0, r)[0]) / mean
def I(r, Q):
return h * (Q + r - mean * l - quad(cdf, 0, Q)[0]
- quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
+ quad(cdf, 0, r)[0]) / 2
def f(params):
r, Q = params
TC = G(r, Q)/CL(r, Q) + I(r, Q)
return TC
如何在 3D 图中绘制此函数f(r,Q),并获得全局最小值或最小值以及r 和 Q在该特定点的值。
此外,我已经尝试使用scipy.optimize.minimize
最小化成本函数 f(r, Q),但我面临的问题是,它输出结果 - 与优化参数中给出的初始猜测几乎相同。最小化。下面是最小化函数的代码:
initial_guess = [2500., 10000.]
result = optimize.minimize(f, initial_guess, bounds=[(1, 5000), (5000, 15000)], tol=1e-3)
print(result)
输出:
fun: 2712.7698818644253
hess_inv: <2x2 LbfgsInvHessProduct with dtype=float64>
jac: array([-0.01195986, -0.01273293])
message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'
nfev: 6
nit: 1
status: 0
success: True
x: array([ 2500.01209628, 10000.0127784 ])
输出x: array([ 2500.01209628, 10000.0127784 ])
- 我怀疑这是真正的答案,也几乎与提供的初始猜测相同。我在最小化方面做错了什么还是有其他方法可以做到这一点?所以我想绘制成本函数并自己寻找。
如果我能有一个互动的情节来玩,那就太好了
解决方案
我的回答只与绘图有关,但最后我会评论极小极大的问题。
对于您需要的 3D 曲面图,恕我直言,矫枉过正,我将向您展示如何使用contourf
并contour
很好地了解您的功能正在发生什么。
一、代码——关键点:
- 您的代码不能在向量上下文中执行,因此我编写了一个显式循环来计算值,
- 由于 Matplotib 设计,矩阵数据的 x 轴与列相关联,必须考虑到这一点,
countour
和的结果contourf
必须保存,因为它们分别用于标签和颜色条,- 没有标签或传说,因为我不知道你在做什么。
也就是说,这是代码
import matplotlib.pyplot as plt
import numpy as np
from numpy import sqrt, pi, exp
from scipy.integrate import quad
mean, std = 295, 250
l, m, p = 7, 30, 15
w, K, c = 7, 100, 5
h = 0.001 # per unit per day
# defining Cumulative distribution function
def cdf(x):
cdf_eqn = lambda t: (1 / (std * sqrt(2 * pi))) * exp(-(((t - mean) ** 2) / (2 * std ** 2)))
cdf = quad(cdf_eqn, -np.inf, x)[0]
return cdf
# defining Probability density function
def pdf(x):
return (1 / (std * sqrt(2 * pi))) * exp(-(((x - mean) ** 2) / (2 * std ** 2)))
# getting the equation in place
def G(r, Q):
return K + c * Q \
+ w * (quad(cdf, 0, Q)[0] + quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]) \
+ p * (mean * l - r + quad(cdf, 0, r)[0])
def CL(r, Q):
return (Q - r + mean * l - quad(cdf, 0, Q)[0]
- quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
+ quad(cdf, 0, r)[0]) / mean
def I(r, Q):
return h * (Q + r - mean * l - quad(cdf, 0, Q)[0]
- quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
+ quad(cdf, 0, r)[0]) / 2
# pulling it all together
def f(r, Q):
TC = G(r, Q)/CL(r, Q) + I(r, Q)
return TC
nr, nQ = 6, 11
r = np.linspace(0, 5000, nr)
Q = np.linspace(5000, 15000, nQ)
z = np.zeros((nr, nQ)) # r ←→ y, Q ←→ x
for i, ir in enumerate(r):
for j, jQ in enumerate(Q):
z[i, j] = f(ir, jQ)
print('%2d: '%i, ','.join('%8.3f'%v for v in z[i]))
fig, ax = plt.subplots()
cf = plt.contourf(Q, r, z)
cc = plt.contour( Q, r, z, colors='k')
plt.clabel(cc)
plt.colorbar(cf, orientation='horizontal')
ax.set_aspect(1)
plt.show()
这里是它的执行结果
$ python cost.py
0: 4093.654,3661.777,3363.220,3120.073,2939.119,2794.255,2675.692,2576.880,2493.283,2426.111,2359.601
1: 4072.865,3621.468,3315.193,3068.710,2887.306,2743.229,2626.065,2528.934,2447.123,2381.802,2316.991
2: 4073.852,3622.443,3316.163,3069.679,2888.275,2744.198,2627.035,2529.905,2448.095,2382.775,2317.965
3: 4015.328,3514.874,3191.722,2939.397,2758.876,2618.292,2505.746,2413.632,2336.870,2276.570,2216.304
4: 3881.198,3290.628,2947.273,2694.213,2522.845,2394.095,2293.867,2213.651,2148.026,2098.173,2047.140
5: 3616.675,2919.726,2581.890,2352.015,2208.814,2106.289,2029.319,1969.438,1921.555,1887.398,1849.850
$
我可以补充一点,全局最小值和全局最大值位于拐角处,而在近似区域r ≈ 1000 和r ≈ 2000中有两条局部最小值(下线)和局部最大值(上线)的亚水平线。
推荐阅读
- python - 在 Python 中执行跨列计算
- python - Python:如何修复 Python 中的 AttributeError?
- asp.net-core - 使用 Kestrel 和 IdentityServer4 在 LAN 中托管 ASP.NET CORE 5
- python - 在 GPU 上使用 keras 进行集成预测
- r - 错误(函数(...,row.names = NULL,check.rows = FALSE,check.names = TRUE,:参数暗示不同的行数:1、3、4
- r - 基于 x 轴标签的颜色
- magento - 如何在管理员产品搜索之前添加观察者事件
- c - while(tab[i+1] == 0) 和 while(tab[++i] == 0) 之间的区别
- mysql - 使用索引列过滤器的 SELECT 查询 RDS 实例 CPU 利用率超过 90%
- php - 在 aftervalidate 中使验证无效