In [1]:
import numpy as np
import pwlf
# generate sin wave data
x = np.linspace(0, 10, num=100)
y = np.sin(x * np.pi / 2)
# add noise to the data
y = np.random.normal(0, 0.05, 100) + y
my_pwlf_2 = pwlf.PiecewiseLinFit(x, y, degree=2)
res2 = my_pwlf_2.fitfast(5, pop=50)
In [2]:
import matplotlib.pyplot as plt
%matplotlib inline
# first line
xhat = np.linspace(my_pwlf_2.fit_breaks[0], my_pwlf_2.fit_breaks[1], 100)
yhat = my_pwlf_2.beta[0] + my_pwlf_2.beta[1]*(xhat-my_pwlf_2.fit_breaks[0]) + my_pwlf_2.beta[6]*(xhat-my_pwlf_2.fit_breaks[0])**2
plt.figure()
plt.plot(x, y, 'o')
plt.plot(xhat, yhat, '-.', label='First segment')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
In [3]:
# second segment
xhat2 = np.linspace(my_pwlf_2.fit_breaks[1], my_pwlf_2.fit_breaks[2], 100)
yhat2 = (my_pwlf_2.beta[0] +
(my_pwlf_2.beta[1])*(xhat2-my_pwlf_2.fit_breaks[0]) +
(my_pwlf_2.beta[2])*(xhat2-my_pwlf_2.fit_breaks[1]) +
(my_pwlf_2.beta[6])*(xhat2-my_pwlf_2.fit_breaks[0])**2 +
(my_pwlf_2.beta[7])*(xhat2-my_pwlf_2.fit_breaks[1])**2)
plt.plot(x, y, 'o')
plt.plot(xhat, yhat, '-.', label='First segment')
plt.plot(xhat2, yhat2, '-.', label='Second segment')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
In [4]:
# Third segment
xhat3 = np.linspace(my_pwlf_2.fit_breaks[2], my_pwlf_2.fit_breaks[3], 100)
yhat3 = (my_pwlf_2.beta[0] +
(my_pwlf_2.beta[1])*(xhat3-my_pwlf_2.fit_breaks[0]) +
(my_pwlf_2.beta[2])*(xhat3-my_pwlf_2.fit_breaks[1]) +
(my_pwlf_2.beta[3])*(xhat3-my_pwlf_2.fit_breaks[2]) +
(my_pwlf_2.beta[6])*(xhat3-my_pwlf_2.fit_breaks[0])**2 +
(my_pwlf_2.beta[7])*(xhat3-my_pwlf_2.fit_breaks[1])**2 +
(my_pwlf_2.beta[8])*(xhat3-my_pwlf_2.fit_breaks[2])**2)
plt.plot(x, y, 'o')
plt.plot(xhat, yhat, '-.', label='First segment')
plt.plot(xhat2, yhat2, '-.', label='Second segment')
plt.plot(xhat3, yhat3, '-.', label='Third segment')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
In [5]:
# Fourth segment
xhat4 = np.linspace(my_pwlf_2.fit_breaks[3], my_pwlf_2.fit_breaks[4], 100)
yhat4 = (my_pwlf_2.beta[0] +
(my_pwlf_2.beta[1])*(xhat4-my_pwlf_2.fit_breaks[0]) +
(my_pwlf_2.beta[2])*(xhat4-my_pwlf_2.fit_breaks[1]) +
(my_pwlf_2.beta[3])*(xhat4-my_pwlf_2.fit_breaks[2]) +
(my_pwlf_2.beta[4])*(xhat4-my_pwlf_2.fit_breaks[3]) +
(my_pwlf_2.beta[6])*(xhat4-my_pwlf_2.fit_breaks[0])**2 +
(my_pwlf_2.beta[7])*(xhat4-my_pwlf_2.fit_breaks[1])**2 +
(my_pwlf_2.beta[8])*(xhat4-my_pwlf_2.fit_breaks[2])**2 +
(my_pwlf_2.beta[9])*(xhat4-my_pwlf_2.fit_breaks[3])**2)
plt.plot(x, y, 'o')
plt.plot(xhat, yhat, '-.', label='First')
plt.plot(xhat2, yhat2, '-.', label='Second')
plt.plot(xhat3, yhat3, '-.', label='Third')
plt.plot(xhat4, yhat4, '-.', label='Fourth')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
In [6]:
# Fifth segment
xhat5 = np.linspace(my_pwlf_2.fit_breaks[4], my_pwlf_2.fit_breaks[5], 100)
yhat5 = (my_pwlf_2.beta[0] +
(my_pwlf_2.beta[1])*(xhat5-my_pwlf_2.fit_breaks[0]) +
(my_pwlf_2.beta[2])*(xhat5-my_pwlf_2.fit_breaks[1]) +
(my_pwlf_2.beta[3])*(xhat5-my_pwlf_2.fit_breaks[2]) +
(my_pwlf_2.beta[4])*(xhat5-my_pwlf_2.fit_breaks[3]) +
(my_pwlf_2.beta[5])*(xhat5-my_pwlf_2.fit_breaks[4]) +
(my_pwlf_2.beta[6])*(xhat5-my_pwlf_2.fit_breaks[0])**2 +
(my_pwlf_2.beta[7])*(xhat5-my_pwlf_2.fit_breaks[1])**2 +
(my_pwlf_2.beta[8])*(xhat5-my_pwlf_2.fit_breaks[2])**2 +
(my_pwlf_2.beta[9])*(xhat5-my_pwlf_2.fit_breaks[3])**2 +
(my_pwlf_2.beta[10])*(xhat5-my_pwlf_2.fit_breaks[4])**2)
plt.plot(x, y, 'o')
plt.plot(xhat, yhat, '-.', label='First')
plt.plot(xhat2, yhat2, '-.', label='Second')
plt.plot(xhat3, yhat3, '-.', label='Third')
plt.plot(xhat4, yhat4, '-.', label='Fourth')
plt.plot(xhat5, yhat5, '-.', label='Fifth')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
In [7]:
from sympy import Symbol
from sympy.utilities import lambdify
x = Symbol('x')
def get_symbolic_eqn(pwlf_, segment_number):
if pwlf_.degree < 1:
raise ValueError('Degree must be at least 1')
if segment_number < 1 or segment_number > pwlf_.n_segments:
raise ValueError('segment_number not possible')
# assemble degree = 1 first
for line in range(segment_number):
if line == 0:
my_eqn = pwlf_.beta[0] + (pwlf_.beta[1])*(x-pwlf_.fit_breaks[0])
else:
my_eqn += (pwlf_.beta[line+1])*(x-pwlf_.fit_breaks[line])
# assemble all other degrees
if pwlf_.degree > 1:
for k in range(2, pwlf_.degree + 1):
for line in range(segment_number):
beta_index = pwlf_.n_segments*(k-1) + line + 1
my_eqn += (pwlf_.beta[beta_index])*(x-pwlf_.fit_breaks[line])**k
return my_eqn.simplify()
eqn1 = get_symbolic_eqn(my_pwlf_2, 1)
In [8]:
eqn_list = []
f_list = []
for i in range(my_pwlf_2.n_segments):
eqn_list.append(get_symbolic_eqn(my_pwlf_2, i + 1))
print('Equation number: ', i + 1)
print(eqn_list[-1])
f_list.append(lambdify(x, eqn_list[-1]))
In [9]:
yhat1 = f_list[0](xhat)
yhat2 = f_list[1](xhat2)
yhat3 = f_list[2](xhat3)
yhat4 = f_list[3](xhat4)
yhat5 = f_list[4](xhat5)
xtemp = np.linspace(0,10, 1000)
plt.plot(my_pwlf_2.x_data, my_pwlf_2.y_data, 'o')
plt.plot(xtemp, my_pwlf_2.predict(xtemp), '-k', label='Predict')
plt.plot(xhat, yhat1, '-.', label='First')
plt.plot(xhat2, yhat2, '-.', label='Second')
plt.plot(xhat3, yhat3, '-.', label='Third')
plt.plot(xhat4, yhat4, '-.', label='Fourth')
plt.plot(xhat5, yhat5, '-.', label='Fifth')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()