#python #curve-fitting #scipy-optimize
Вопрос:
У меня есть кривая, которая была создана ранее, она выглядит как на графике ниже:
Теперь я хочу подогнать бары под эту кривую, но пользователь должен иметь возможность указать количество «баров» (т. Е. Количество уникальных значений), которые можно использовать для этой подгонки. Я пытаюсь использовать scipy optimize для этого, чтобы минимизировать суммарную разницу между значениями решения и значениями кривой, код ниже:
import numpy as np
from scipy.optimize import minimize
numUniqueValues = 5
curve_values = [0.0007888599259157635, 0.0003086843188366031, 0.0009603512141583208, 0.003326930991905611, 0.03865413636987241, 0.0622856358896968, 0.07346686788311153, 0.06907669090410207, 0.05083001783509398, 0.047262999039648784, 0.046577033886678554, 0.04314720812182741, 0.053093702839895736, 0.05782686239539032, 0.07082590204417616, 0.07648511455618055, 0.07614213197969544, 0.07885169433392783, 0.057895458910687335, 0.043044313348881875, 0.03186308135546714, 0.01059816161339004, 0.004493071751955, 0.002195088489504733]
sum_curve_values = sum(curve_values)
def objective(x):
diff_vector = []
for i in range(len(curve_values)):
diff_vector.append(x[i]-curve_values[i])
return np.sum(np.absolute(np.array(diff_vector)))**2
# Equality constraint (sum of solution values = sum of curve values)
def constraint1(x):
return sum_curve_values-sum(x)
# Equality constraint (number of unique values in solution = numUniqueValues)
def constraint2(x):
unique_x = np.unique(np.array(x))
return numUniqueValues-len(unique_x)
x0 = [sum_curve_values/len(curve_values)]*len(curve_values)
b = (0.0,1.0)
bnds = tuple(b for i in range(len(curve_values)))
con1 = {'type':'eq', 'fun':constraint1}
con2 = {'type':'eq', 'fun':constraint2}
cons = [con1,con2]
sol = minimize(objective,x0,method='SLSQP',bounds=bnds,constraints=cons)
Решатель не удовлетворяет ограничению уникального числа значений в решении (в данном случае 5). И само «решение» тоже выглядит немного по-другому. Какие-нибудь советы?
import matplotlib.pyplot as plt
xticks = np.linspace(0,23,24)
fig, ax = plt.subplots(1,1,figsize=(15,10))
ax.plot(xticks,curve_values,linewidth=2)
ax.bar(xticks,sol.x,1,color='g',alpha=0.5)
ax.set_xticks(xticks)
plt.style.use('ggplot')
Комментарии:
1. Ваша функция ограничения уникальности не дифференцируема. Кроме того, я не думаю, что можно смоделировать ограничение уникальности, не возвращаясь к задаче смешанного целочисленного программирования вместо непрерывной задачи.