在 numpy 中使用多项式时如何矢量化预测
how to vectorize forecasting when using polynomials in numpy
基本上想找到最有效的解决方案 (numpy
),基本上允许我将 np.poly1d
扩展到 K 维。
测试用例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class Polyfit:
@staticmethod
def from_fit_to_forecast(df, forecast_values, dates_forward, x_data, y_data, order=2):
# nice vectorized params estimation
all_params = np.polyfit(x_data, y_data, order)
# terrible fit of data as I loop over them
new_df = pd.DataFrame([np.poly1d(i)(x_data) for i in all_params.T], columns=df.index, index=df.columns).T
forecast_df_second = pd.DataFrame(
[np.poly1d(i)(forecast_values) for i in all_params.T], columns=dates_forward, index=df.columns).T
return new_df, forecast_df_second
@staticmethod
def gen_data(k_steps):
data = 1 + np.random.rand(100, 4) / 300 - (np.random.rand(100, 4) / 10) ** 2
dates = pd.date_range('2010-1-1', freq='D', periods=100)
dates_forward = pd.date_range(max(dates) + pd.Timedelta(1, unit='d'), freq='D', periods=k_steps)
return pd.DataFrame(data, columns=list('ABCD'), index=dates).cumprod(), dates_forward
def __init__(self, k_steps_forward=20):
self.original_data, dates_forward = self.gen_data(k_steps_forward)
x_data = list(range(len(self.original_data.index)))
max_x_data = max(x_data)
forecast_values = list(range(max_x_data + 1, max_x_data + 1 + k_steps_forward, 1))
y_data = self.original_data.values
self.fit_df_2, self.forecast_2 = self.from_fit_to_forecast(
self.original_data, forecast_values, dates_forward, x_data, y_data, order=2)
cls = Polyfit(k_steps_forward=30)
print(cls.fit_df_2)
print(cls.forecast_2)
关键点在 from_fit_to_forecast
我这样做的地方:
[np.poly1d(i)(forecast_values) for i in all_params.T]
这大大减慢了速度。此外,由于我还将使用二阶多项式,因此我尝试使用 np.dot
或其他适用于矩阵但无济于事的东西。
有什么建议吗?
所以你从
得到了一堆多项式系数
all_params = np.polyfit(x_data, y_data, order)
(其中 y_data
是一个二维数组)并且您想在 x_data
点计算所有这些数组。如下所述,执行此操作的矢量化方法是:
(x_data.reshape(-1, 1)**np.arange(order, -1, -1)).dot(all_params)
这是一个完美拟合的小例子(二阶多边形通过三个点),所以你可以看到评估是正确的
x_data = np.array([1, 2, 3])
y_data = np.array([[5, 6,], [9, 8], [7, 4]])
order = 2
all_params = np.polyfit(x_data, y_data, order)
(x_data.reshape(-1, 1)**np.arange(order, -1, -1)).dot(all_params)
输出
array([[ 5., 6.],
[ 9., 8.],
[ 7., 4.]])
说明
x_data.reshape(-1, 1)**np.arange(order, -1, -1)
创建一个 x_data 点的幂矩阵,从最高点开始,例如,
x1**2 x1**1 x1**0
x2**2 x2**1 x2**0
这个矩阵通过矩阵乘法与二次方程ax**2 + bx + c的系数相乘,看起来像
a1 a2
b1 b2
c1 c2
结果就是多项式的值。
基本上想找到最有效的解决方案 (numpy
),基本上允许我将 np.poly1d
扩展到 K 维。
测试用例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class Polyfit:
@staticmethod
def from_fit_to_forecast(df, forecast_values, dates_forward, x_data, y_data, order=2):
# nice vectorized params estimation
all_params = np.polyfit(x_data, y_data, order)
# terrible fit of data as I loop over them
new_df = pd.DataFrame([np.poly1d(i)(x_data) for i in all_params.T], columns=df.index, index=df.columns).T
forecast_df_second = pd.DataFrame(
[np.poly1d(i)(forecast_values) for i in all_params.T], columns=dates_forward, index=df.columns).T
return new_df, forecast_df_second
@staticmethod
def gen_data(k_steps):
data = 1 + np.random.rand(100, 4) / 300 - (np.random.rand(100, 4) / 10) ** 2
dates = pd.date_range('2010-1-1', freq='D', periods=100)
dates_forward = pd.date_range(max(dates) + pd.Timedelta(1, unit='d'), freq='D', periods=k_steps)
return pd.DataFrame(data, columns=list('ABCD'), index=dates).cumprod(), dates_forward
def __init__(self, k_steps_forward=20):
self.original_data, dates_forward = self.gen_data(k_steps_forward)
x_data = list(range(len(self.original_data.index)))
max_x_data = max(x_data)
forecast_values = list(range(max_x_data + 1, max_x_data + 1 + k_steps_forward, 1))
y_data = self.original_data.values
self.fit_df_2, self.forecast_2 = self.from_fit_to_forecast(
self.original_data, forecast_values, dates_forward, x_data, y_data, order=2)
cls = Polyfit(k_steps_forward=30)
print(cls.fit_df_2)
print(cls.forecast_2)
关键点在 from_fit_to_forecast
我这样做的地方:
[np.poly1d(i)(forecast_values) for i in all_params.T]
这大大减慢了速度。此外,由于我还将使用二阶多项式,因此我尝试使用 np.dot
或其他适用于矩阵但无济于事的东西。
有什么建议吗?
所以你从
得到了一堆多项式系数all_params = np.polyfit(x_data, y_data, order)
(其中 y_data
是一个二维数组)并且您想在 x_data
点计算所有这些数组。如下所述,执行此操作的矢量化方法是:
(x_data.reshape(-1, 1)**np.arange(order, -1, -1)).dot(all_params)
这是一个完美拟合的小例子(二阶多边形通过三个点),所以你可以看到评估是正确的
x_data = np.array([1, 2, 3])
y_data = np.array([[5, 6,], [9, 8], [7, 4]])
order = 2
all_params = np.polyfit(x_data, y_data, order)
(x_data.reshape(-1, 1)**np.arange(order, -1, -1)).dot(all_params)
输出
array([[ 5., 6.],
[ 9., 8.],
[ 7., 4.]])
说明
x_data.reshape(-1, 1)**np.arange(order, -1, -1)
创建一个 x_data 点的幂矩阵,从最高点开始,例如,
x1**2 x1**1 x1**0
x2**2 x2**1 x2**0
这个矩阵通过矩阵乘法与二次方程ax**2 + bx + c的系数相乘,看起来像
a1 a2
b1 b2
c1 c2
结果就是多项式的值。