2017-01-27 5 views
1

Ich habe die folgenden x, y-Datenkann nicht numpy piecewise mit 3 Segmente

x = np.array([-1.280199006, -1.136209343, -1.048070216, -0.9616764178, -0.8752826199, -0.7871434926, -0.6981317008, -0.6108652382, -0.5235987756, -0.4372049776, 
-0.3490658504, -0.2644173817, -0.1762782545, 
-0.0907571211, 0, 0.09250245036, 0.1762782545, 0.2661627109, 0.3516838443, 0.4345869837, 0.529707428, 0.6108652382, 0.7007496947, 0.7880161573, 0.872664626, 
0.9616764178, 1.055051533, 1.160643953, 1.274090354, 1.413716694]) 

y = np.array([-0.05860218717, -0.05275174988, -0.04961805822, -0.02860635697, -0.04150466841, -0.02672933264, -0.02422597285, -0.03056176732, -0.02885180089, -0.02085851636, 
-0.02873319291, -0.02374542821, -0.02132671806, 
-0.02088924602, -0.0216617248, -0.01835553738, -0.01369531698, -0.01331112368, -0.01156455074, -0.009163690404, -0.003542622659, -0.003515924976, -0.003828831726, -0.002622163805, -0.001622083468, 
-0.00297346133, -0.001845415856, -0.001913228234, -0.001495496086, -0.001454621173]) 

und würde tun es mit numpy piecewise passen mit mindestens 3 Liniensegmente

habe ich versucht, dieses

def piecewise_linear(x, x0, x1, y0, y1, k1, k2, k3): 
    conds = [x<x0, (x>=x0) & (x<x1),x>=x1] 
    funcs = [lambda x:k1*(x-x0) + y0, lambda x:k2*(x-x0) + y0, lambda x:k2*(x1-x0) + y0 + k3*(x-x1)] 
    return np.piecewise(x, conds, funcs) 
p , e = curve_fit(piecewise_linear, x, y) 
xd = np.linspace(-1.3, 1.5, 100) 
plt.plot(x, y, "o") 
plt.plot(xd, piecewise_linear(xd, *p)) 

aber es setzt

x1 = 0,266162745743

und

x0 = 0,323723668069

d.h x0> x1. Es endet mit einer 2-Segment-Anpassung.

Was mache ich falsch? Muss ich die Daten skalieren? Allgemeiner gibt es eine Möglichkeit zu steuern, wie viele Segmente stückweise verwendet werden?

+1

Das Problem ist höchstwahrscheinlich nicht mit 'stückweise', sondern mit' curve_fit'. Denk darüber nach; es ist 'curve_fit', das' x0' und 'x1' wählt. Sie könnten versuchen, 'curve_fit' mit einer ersten Schätzung zu versehen und sicherstellen, dass' x1' in dieser Schätzung größer ist als 'x0'. –

+0

@Paul Panzer Guter Punkt. Versuchte ein paar erste Vermutungen ohne viel Veränderung. Werde mehr versuchen. – JennyToy

+1

Und sollte nicht die dritte Ihrer Lambdas sein? Lambda x: k2 * (x1-x0) + y0 + k3 * (x-x1) '? Das ist zumindest das, was du brauchst, um deine Stücke miteinander zu verbinden. –

Antwort

1

Das Problem ist, dass piecewise ein Array anstelle einer Funktion zurückgeben. Daher ist y1 kein unabhängiger Parameter. Ein Weg, um die Funktion zu definieren, ist Booleschen Wert in einem arithmetischen Kontext (True = 1, Falsch = 0) zu verwenden:

def f(x,x0,y0,x1,k1,k2,k3): 
    # x0,y0 : first breakpoint 
    # x1 : second breakpoint 
    # k1,k2,k3 : 3 slopes. 

    y1=y0+ k2*(x1-x0) # for continuity 
    return (
    (x<x0)    * (y0 + k1*(x-x0))  + 
    ((x>=x0) & (x<x1)) * (y0 + k2*(x-x0))  + 
    (x>=x1)    * (y1 + k3*(x-x1))) 

p0=(-.7,-0.03,.5,0.03,0.02,0.01) 
p , e = curve_fit(f, x, y,p0) 
close() 
plt.plot(x, y, "o") 
plot(x,f(x,*p)) 
show() 

Hier ist ein Sitz ist. enter image description here