我在numpy数组中有一些data
。
我想根据以下规则使用线性函数来缩放数据:
对于我的第一次尝试,我做了一个评分功能:
import numpy as np
from scipy.optimize import minimize
def score(x):
return abs(np.mean(x[0]*data+x[1]) - 65) + abs(x[0]*np.min(data)+x[1] - 50)
我在abs(x[0]*np.min(data)+x[1] - 50)
上添加了徒劳的尝试,以使其满足规则2。
然后我尝试了:
x0 = [0.85,0]
res = minimize(score,x0)
np.set_printoptions(suppress=True)
print res
这给出了:
fun: 4.8516444911893615
hess_inv: array([[ 0.0047, -0.1532],
[-0.1532, 5.2375]])
jac: array([-50.9628, -2. ])
message: 'Desired error not necessarily achieved due to precision loss.'
nfev: 580
nit: 2
njev: 142
status: 2
success: False
x: array([0.7408, 1.4407])
换句话说,优化失败了。
我还想设置系数的界限,例如: bounds = [(0.7,1.3),(-5,5)]
。
我的问题是,使用缩放最小值至少为50的边界条件运行优化的正确方法是什么?另外,我怎样才能使优化运行而不失败?
答案 0 :(得分:2)
请考虑以下事项:
import numpy as np
from scipy.optimize import minimize
data = np.array([ 59. , 59.5, 61. , 61.5, 62.5, 63. , 63. , 65.5, 66.5,
67. , 68. , 69. , 69.5, 70.5, 70.5, 70.5, 71. , 72. ,
72. , 73.5, 73.5, 74. , 75. , 75.5, 78. , 79. , 79. ,
79. , 79.5, 80.5, 80.5, 80.5, 80.5, 80.5, 82.5, 82.5,
82.5, 83. , 83. , 83. , 83. , 83. , 83.5, 83.5, 84. ,
84.5, 84.5, 84.5, 86. , 86. , 86. , 86.5, 86.5, 87.5,
88. , 88. , 88.5, 89. , 90. , 90.5, 90.5, 90.5, 91. ,
91.5, 91.5, 92. , 92. , 93. , 93. , 93. , 93.5, 93.5,
94. , 94. , 94. , 94. , 94. , 94. , 94.5, 94.5, 94.5,
94.5, 95.5, 95.5, 95.5, 95.5, 95.5, 95.5, 96. , 96. ,
96. , 96.5, 96.5, 96.5, 98. , 98. , 98. , 98. , 98. ,
98. , 98. , 98. , 98.5, 98.5, 98.5, 98.5, 98.5, 100. ,
100. , 100. , 100. ])
def scale(data, coeffs):
m,b = coeffs
return (m * data) + b
def score(coeffs):
scaled = scale(data, coeffs)
# Penalty components
p_1 = abs(np.mean(scaled) - 65)
p_2 = max(0, (50 - np.min(scaled)))
return p_1 + p_2
res = minimize(score, (0.85, 0.0), method = 'Powell')
#np.set_printoptions(suppress=True)
print(res)
post = scale(data, res.x)
print(np.mean(post))
print(np.min(post))
print(score(res.x))
输出:
direc: array([[ -3.05475495e-02, 2.62047576e+00], [ 7.54828106e-07, -6.47892698e-05]]) fun: 1.4210854715202004e-14 message: 'Optimization terminated successfully.' nfev: 360 nit: 8 status: 0 success: True x: array([ 0.55914442, 17.02691959])
print(np.mean(post)) # 65.0
print(np.min(post)) # 50.0164406291
print(score(res.x)) # 1.42108547152e-14
一些事情:
scale
辅助函数来清理代码,因为我在score
函数中使用它以及在末尾显示缩放数据。score
功能已修复并分为两个单独的处罚(每个要求一个)。它计算一次缩放矢量(并将其称为scaled
),然后计算惩罚分量。max
调用,此得分函数在min(data)= 50附近有一个奇数非平滑区域。这可能会导致某些优化方法出现问题。我使用Powell算法,因为我之前使用过它,并且在使用min / max运算符时遇到了类似的问题。维基百科says:
该方法可用于计算连续但复杂函数的局部最小值,尤其是没有基础数学定义的函数,因为没有必要采用导数
更熟悉优化方法的人可能会建议更好的替代方案。
(编辑)最后,关于边界条件的问题。通常,当我们谈论边界条件时,我们谈论的是自变量的边界,我们正在优化的向量(这里是coeffs
或x
的元素) - 例如,“x [0]必须小于0“,或”x [1]必须介于0和1之间“ - 不是你想要的。
答案 1 :(得分:2)
很抱歉,如果我理解你错了,但只是根据这两条规则扩展数据是直接的线性代数:
e = np.mean(data)
m = e - np.min(data)
data * (65-50)/m + (65 - e*(65-50)/m)
# i.e. (data-e) * (65-50)/m + 65
这恰好意味着65和最低50。