改变 X 和 Y 的 scikit-learn 自定义转换器/管道
scikit-learn custom transformer / pipeline that changes X and Y
我有一组 N 个数据点 X = {x1, ..., xn} 和一组N个目标值/类 Y = {y1, ..., yn}。
给定 yi 的特征向量是在考虑 "window"(缺少更好的术语)数据点的情况下构建的,例如我可能想堆叠 "the last 4 data points",即 xi-4、xi-3、xi- 2, xi-1 用于预测yi.
显然,对于大小为 4 的 window,无法为前三个目标值构建这样的特征向量,我想简单地删除它们。同样对于最后一个数据点 xn.
这不是问题,除非我希望它作为 sklearn 管道的一部分发生。到目前为止,我已经成功地为其他任务编写了一些自定义转换器,但这些不能(据我所知)改变 Y 矩阵。
有没有办法做到这一点,我不知道或者我是否坚持这样做作为管道外的预处理? (这意味着,我将无法使用 GridsearchCV 找到最佳 window 大小和偏移。)
我试过搜索这个,但我得到的只是 this question,它处理从 X 矩阵中删除样本。那里接受的答案让我想,scikit-learn 不支持我想做的事情,但我想确定一下。
你是对的,你不能在 sklearn Pipeline
中调整你的目标。这并不意味着您不能进行网格搜索,但它确实意味着您可能必须以更多的手动方式进行。我建议编写一个函数在 y
上进行转换和过滤,然后手动循环通过 ParameterGrid
创建的调整网格。如果这对您没有意义,请使用您获得进一步帮助的代码编辑 post。
我正在努力解决类似的问题,很遗憾您无法在转换器之间传递 y 值。话虽如此,我以一种有点肮脏的方式绕过了这个问题。
我将 y 值存储为转换器的实例属性。这样我就可以在管道调用 fit_transform
时在 transform
方法中访问它们。然后,transform
方法传递下一个估计器期望的元组 (X, self.y_stored)
。这意味着我必须编写包装器估算器,它非常丑陋,但它有效!
像这样:
class MyWrapperEstimator(RealEstimator):
def fit(X, y=None):
if isinstance(X, tuple):
X, y = X
super().fit(X=X, y=y)
对于堆叠最后 4 个数据点的具体示例,您可以使用 seglearn。
>>> import numpy as np
>>> import seglearn
>>> x = np.arange(10)[None,:]
>>> x
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> y = x
>>> new_x, new_y, _ = seglearn.transform.SegmentXY(width=4, overlap=0.75).fit_transform(x, y)
>>> new_x
array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
[4, 5, 6, 7],
[5, 6, 7, 8],
[6, 7, 8, 9]])
>>> new_y
array([3, 4, 5, 6, 7, 8, 9])
seglearn 声称与 scikit-learn 兼容,因此您应该能够在 scikit-learn 管道的开头安装 SegmentXY。但是,我自己还没有在管道中尝试过。
我有一组 N 个数据点 X = {x1, ..., xn} 和一组N个目标值/类 Y = {y1, ..., yn}。
给定 yi 的特征向量是在考虑 "window"(缺少更好的术语)数据点的情况下构建的,例如我可能想堆叠 "the last 4 data points",即 xi-4、xi-3、xi- 2, xi-1 用于预测yi.
显然,对于大小为 4 的 window,无法为前三个目标值构建这样的特征向量,我想简单地删除它们。同样对于最后一个数据点 xn.
这不是问题,除非我希望它作为 sklearn 管道的一部分发生。到目前为止,我已经成功地为其他任务编写了一些自定义转换器,但这些不能(据我所知)改变 Y 矩阵。
有没有办法做到这一点,我不知道或者我是否坚持这样做作为管道外的预处理? (这意味着,我将无法使用 GridsearchCV 找到最佳 window 大小和偏移。)
我试过搜索这个,但我得到的只是 this question,它处理从 X 矩阵中删除样本。那里接受的答案让我想,scikit-learn 不支持我想做的事情,但我想确定一下。
你是对的,你不能在 sklearn Pipeline
中调整你的目标。这并不意味着您不能进行网格搜索,但它确实意味着您可能必须以更多的手动方式进行。我建议编写一个函数在 y
上进行转换和过滤,然后手动循环通过 ParameterGrid
创建的调整网格。如果这对您没有意义,请使用您获得进一步帮助的代码编辑 post。
我正在努力解决类似的问题,很遗憾您无法在转换器之间传递 y 值。话虽如此,我以一种有点肮脏的方式绕过了这个问题。
我将 y 值存储为转换器的实例属性。这样我就可以在管道调用 fit_transform
时在 transform
方法中访问它们。然后,transform
方法传递下一个估计器期望的元组 (X, self.y_stored)
。这意味着我必须编写包装器估算器,它非常丑陋,但它有效!
像这样:
class MyWrapperEstimator(RealEstimator):
def fit(X, y=None):
if isinstance(X, tuple):
X, y = X
super().fit(X=X, y=y)
对于堆叠最后 4 个数据点的具体示例,您可以使用 seglearn。
>>> import numpy as np
>>> import seglearn
>>> x = np.arange(10)[None,:]
>>> x
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> y = x
>>> new_x, new_y, _ = seglearn.transform.SegmentXY(width=4, overlap=0.75).fit_transform(x, y)
>>> new_x
array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
[4, 5, 6, 7],
[5, 6, 7, 8],
[6, 7, 8, 9]])
>>> new_y
array([3, 4, 5, 6, 7, 8, 9])
seglearn 声称与 scikit-learn 兼容,因此您应该能够在 scikit-learn 管道的开头安装 SegmentXY。但是,我自己还没有在管道中尝试过。