Это итеративный подход, подобный этому посту .Это отличается в том смысле, что форма графика не позволяет использовать выпуклую оболочку.Таким образом, идея состоит в том, чтобы создать функцию стоимости, которая пытается минимизировать площадь графика, оплачивая при этом высокую стоимость, если точка находится над графиком.В зависимости от типа графика в OP функцию стоимости необходимо адаптировать.Также необходимо проверить, действительно ли в конечном результате все точки находятся ниже графика.Здесь можно поиграть с деталями функции стоимости.Например, можно включить смещение в tanh
, например tanh( slope * ( x - offset) )
, чтобы отодвинуть решение дальше от данных.
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import leastsq
def g( x, a, s ):
return a * np.exp(-x**2 / s**2 )
def cost_function( params, xData, yData, slope, val ):
a,s = params
area = 0.5 * np.sqrt( np.pi ) * a * s
diff = np.fromiter ( ( y - g( x, a, s) for x, y in zip( xData, yData ) ), np.float )
cDiff = np.fromiter( ( val * ( 1 + np.tanh( slope * d ) ) for d in diff ), np.float )
out = np.concatenate( [ [area] , cDiff ] )
return out
xData = np.linspace( -5, 5, 500 )
yData = np.fromiter( ( g( x, .77, 2 ) * np.sin( 257.7 * x )**2 for x in xData ), np.float )
sol=[ [ 1, 2.2 ] ]
for i in range( 1, 6 ):
solN, err = leastsq( cost_function, sol[-1] , args=( xData, yData, 10**i, 1 ) )
sol += [ solN ]
print sol
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1)
ax.scatter( xData, yData, s=1 )
for solN in sol:
solY = np.fromiter( ( g( x, *solN ) for x in xData ), np.float )
ax.plot( xData, solY )
plt.show()
, что дает
>> [0.8627445 3.55774814]
>> [0.77758636 2.52613376]
>> [0.76712184 2.1181137 ]
>> [0.76874125 2.01910211]
>> [0.7695663 2.00262339]
и