反向Box-Cox变换

时间:2014-10-15 20:23:54

标签: python statistics scipy transformation inverse

我正在使用SciPy's boxcox function对连续变量执行Box-Cox transformation

from scipy.stats import boxcox
import numpy as np
y = np.random.random(100)
y_box, lambda_ = ss.boxcox(y + 1) # Add 1 to be able to transform 0 values

然后,我拟合一个统计模型来预测这个Box-Cox变换变量的值。模型预测采用Box-Cox量表,我想将它们转换为变量的原始比例。

from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor()
X = np.random.random((100, 100))
rf.fit(X, y_box)
pred_box = rf.predict(X)

但是,在找到转换后的数据和lambda时,我找不到执行反向Box-Cox变换的SciPy函数。有这样的功能吗?我现在编码了一个逆变换。

pred_y = np.power((y_box * lambda_) + 1, 1 / lambda_) - 1

5 个答案:

答案 0 :(得分:12)

  1. 这是代码。它正在工作,只是测试。 Scipy使用了neperian对数,我检查了BoxCox转换文件,并且看到他们使用了log10。我与neperian保持联系,因为它适用于scipy
  2. 请遵循以下代码:

    #Function
    def invboxcox(y,ld):
       if ld == 0:
          return(np.exp(y))
       else:
          return(np.exp(np.log(ld*y+1)/ld))
    
    # Test the code
    x=[100]
    ld = 0
    y = stats.boxcox(x,ld)
    print invboxcox(y[0],ld)
    

答案 1 :(得分:7)

SciPy添加了逆Box-Cox转换。

https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.inv_boxcox.html

scipy.special.inv_boxcox scipy.special.inv_boxcox(y,lmbda)=

计算Box-Cox变换的倒数。

找到x:

y = (x**lmbda - 1) / lmbda  if lmbda != 0
    log(x)                  if lmbda == 0

参数: y:array_like

要转换的数据。

lmbda:array_like

Box-Cox变换的功率参数。

返回:
x:数组

转化数据。

注释

0.16.0版中的新功能。

示例:

from scipy.special import boxcox, inv_boxcox
y = boxcox([1, 4, 10], 2.5)
inv_boxcox(y, 2.5)

output: array([1., 4., 10.])

答案 2 :(得分:4)

感谢@Warren Weckesser,我了解到目前SciPy的实现没有扭转Box-Cox转换的功能。但是,未来的SciPy版本可能具有此功能。目前,我在我的问题中提供的代码可能会为其他人提供反转Box-Cox转换的代码。

答案 3 :(得分:0)

为了使用scipy.special.inv_boxcox从scipy.stats.boxcox反转boxcox转换,您必须识别生成的lambda。

首先应用转换并打印lambda(即参数)。

df[feature_boxcox], param = stats.boxcox(df[feature])
print('Optimal lambda', param)

然后,为了反转变换,请输入生成的lambda。

inv_boxcox(df[feature_boxcox], param)

答案 4 :(得分:0)

我建议看一下 Yeo-Johnson 变换,它是 Box-Cox 模拟,但可以处理负值,并且是一个很好的 implemented in scikit-learn 库,可以轻松进行逆变换。

我将它与 fbprophet 库一起使用(预测):

from sklearn.preprocessing import PowerTransformer

from fbprophet import Prophet
from fbprophet.plot import plot_cross_validation_metric
from fbprophet.diagnostics import cross_validation
from fbprophet.diagnostics import performance_metrics
import numpy as np
import pandas as pd

def inverse_transform(df, pt_instance, features):
    for feature in features:
        df[feature] = pt_instance.inverse_transform(np.array(df[feature]).reshape(-1,1))
    return df

pt = PowerTransformer(method='yeo-johnson')

train_df_transformed = train_df.copy()
train_df_transformed['y'] = pt.fit_transform(np.array(train_df['y']).reshape(-1,1))

model = Prophet(**hyperparams)
model.fit(train_df_transformed)
df_cv = cross_validation(model, initial='14 days', period='3 days', horizon='1 day', parallel="processes")
df_cv = inverse_transform(df_cv, pt, ['yhat','yhat_lower','yhat_upper'])
df_cv = pd.merge(df_cv.drop(columns=['y']),train_df, left_on='ds', right_on='ds')
df_p = performance_metrics(df_cv, metrics=['mae','mape'], rolling_window=1)
fig1 = plot_cross_validation_metric(df_cv, metric='mape')
fig2 = plot_cross_validation_metric(df_cv, metric='mae')