我想创建自己的变压器,用于sklearn Pipeline
。
我正在创建一个类,它同时实现fit和transform方法。transformer的作用是从矩阵中删除NaN超过指定数量的行。
我面临的问题是如何更改传递给转换器的X和y矩阵?
我认为这必须在fit方法中完成,因为它可以访问X和y。由于python通过赋值传递参数,一旦我将X重新分配给一个行数更少的新矩阵,对原始X的引用就会丢失(当然对y也是如此)。有可能维护这个引用吗?
我使用pandas DataFrame来轻松地删除NaN过多的行,这可能不是我的用例的正确方法。当前代码如下所示:
class Dropna():
# thresh is max number of NaNs allowed in a row
def __init__(self, thresh=0):
self.thresh = thresh
def fit(self, X, y):
total = X.shape[1]
# +1 to account for 'y' being added to the dframe
new_thresh = total + 1 - self.thresh
df = pd.DataFrame(X)
df['y'] = y
df.dropna(thresh=new_thresh, inplace=True)
X = df.drop('y', axis=1).values
y = df['y'].values
return self
def transform(self, X):
return X
8条答案
按热度按时间ygya80vv1#
修改样本轴,例如删除样本,不符合scikit-learn transformer API。所以如果你需要这样做,你应该在scikit learn的任何调用之外做,作为预处理。
现在,转换器API用于将给定样本的特性转换为新的特性,这可以隐式地包含来自其他样本的信息,但样本永远不会被删除。
另一种选择是尝试插补缺失值,但是同样,如果你需要删除样本,在使用scikit learn之前将其视为预处理。
8e2ybdfx2#
构建在
sklearn
之上的包imblearn
包含一个估计器FunctionSampler,它允许在流水线步骤中操作特征数组X
和目标数组y
。请注意,在管道步骤中使用
Pipeline
需要使用imblearn
中的Pipeline
类,该类继承自sklearn
中的Pipeline
类。此外,默认情况下,在Pipeline
的上下文中,如果方法resample
不是在fit
之后立即调用(如fit_resample
),则它不执行任何操作。因此,请提前阅读文档。8fq7wneg3#
您必须修改sklearn
Pipeline
的内部代码。我们定义了一个转换器,它在拟合(
fit_transform
)期间移除至少一个特征或目标值为NaN的样本。而在推理(transform
)期间移除至少一个特征值为NaN的样本。需要注意的是,我们的转换器在fit_transform
中返回X和y,因此我们需要在sklearnPipeline
中处理此行为。我们只需要在
fit
和_fit
方法中的两个特定点修改原始sklearnPipeline
,其余保持不变。为了在新的
X
和y
中解压缩Dropna().fit_transform(X, y)
生成的值,需要执行此操作。以下是整个渠道的运作情况:
另一项试验,进一步进行中间预处理步骤:
更复杂的行为可以根据需要通过其他简单的修改来实现。如果您对
Pipeline().fit_transform
或Pipeline().fit_predict
也感兴趣,您需要进行相同的修改。falq053o4#
添加到@João Matias回复:
下面是一个使用imblearn定义管道步骤的示例,该步骤删除包含缺失值的行:
注意,您必须使用imblearn管道。
eqoofvh95#
您可以使用sklearn.preprocessing.FunctionTransformer方法(http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.FunctionTransformer.html)轻松地解决这个问题
你只需要把你对X的替换放到一个函数中
你就可以通过调用
可以在管道中使用。阈值可以在drop_nans函数之外设置。
4ngedf3f6#
@eickenberg是正确和干净的答案。尽管如此,我喜欢把所有东西都放在一个管道中,所以如果你感兴趣,我创建了一个库(还没有部署在pypi上),允许对Y:
https://gitlab.com/thibaultB/transformers/
用法如下:
使用这段代码,如果你把所有修改行数的转换器放在“SplitXY”转换器之前,你就可以改变行数。SplitXY转换器之前的转换器应该保留列名,这就是为什么我还添加了一个SklearnPandasWrapper,它 Package sklearn转换器(通常返回numpy数组)来保留列名。
cunj1qz17#
您可以使用
function transformer
l7wslrjt8#
继续使用“deep-copies”,沿着管道向下,
X
、**y
**仍然受到保护**
.fit()
**可以在每次调用时首先将 deep-copy 赋值给新的类变量然后减少/变换这些以使
NaN
-s不多于按self.treshold
排序的NaN
-s