管道中的 Scikit-Learn FunctionTransformer 没有其他功能 - 不返回原始数据?
Posted
技术标签:
【中文标题】管道中的 Scikit-Learn FunctionTransformer 没有其他功能 - 不返回原始数据?【英文标题】:Scikit-Learn FunctionTransformer in pipeline with no other functionality - not returning original data? 【发布时间】:2016-09-11 18:31:21 【问题描述】:我正在尝试在 Python 2.7 的 Scikit-Learn 管道中运行自定义转换器 FunctionTransformer()
。我使用了文档here 中的示例。此示例执行 PCA,然后仅选择第二个转换的组件。即转换一个 NumPy 数组 X 并提取转换后的 NumPy 数组的第二列。
我对官方文档中的代码所做的更改如下:
-
从管道中删除 PCA()
添加 2 个打印语句以查看管道之前的 X 和管道之后的 X
删除了训练测试拆分 - 这样我使用 X 进行训练,然后转换 X
注释掉所有绘图代码
这是完整的工作代码:
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cross_validation import train_test_split
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import FunctionTransformer
def _generate_vector(shift=0.5, noise=15):
return np.arange(1000) + (np.random.rand(1000) - shift) * noise
def generate_dataset():
"""
This dataset is two lines with a slope ~ 1, where one has
a y offset of ~100
"""
return np.vstack((
np.vstack((
_generate_vector(),
_generate_vector() + 100,
)).T,
np.vstack((
_generate_vector(),
_generate_vector(),
)).T,
)), np.hstack((np.zeros(1000), np.ones(1000)))
def all_but_first_column(X):
return X[:, 1:]
def drop_first_component(X, y):
"""
Create a pipeline with PCA and the column selector and use it to
transform the dataset.
"""
pipeline = make_pipeline(
FunctionTransformer(all_but_first_column),
)
pipeline.fit(X,y)
return pipeline.transform(X), y
if __name__ == '__main__':
X, y = generate_dataset()
print X[:20,:]
X_transformed, y_transformed = drop_first_component(*generate_dataset())
print X_transformed[:20,:]
当我运行这段代码时,我得到以下输出:
流水线前:
[[ -9.54109780e-01 1.00849257e+02]
[ -6.44868525e+00 9.89713451e+01]
[ 6.00611903e+00 9.86368545e+01]
[ -1.02307489e-01 9.91617270e+01]
[ 1.12423836e+01 1.04240711e+02]
[ 6.94957296e+00 1.09557543e+02]
[ 5.41042855e+00 1.09859950e+02]
[ 9.54984210e-01 1.03636786e+02]
[ 1.11194327e+01 1.06942524e+02]
[ 1.32146748e+01 1.16489221e+02]
[ 1.72316993e+01 1.16995924e+02]
[ 1.22797187e+01 1.08568249e+02]
[ 1.14360695e+01 1.06799741e+02]
[ 1.75291161e+01 1.13610682e+02]
[ 1.38768685e+01 1.07815267e+02]
[ 1.29773817e+01 1.12404830e+02]
[ 1.54218007e+01 1.11786074e+02]
[ 1.73923980e+01 1.19284226e+02]
[ 1.97373775e+01 1.16807048e+02]
[ 1.26896716e+01 1.26467393e+02]]
流水线后:
[[ 94.35392453]
[ 107.08036958]
[ 96.42404642]
[ 96.07304368]
[ 109.33207232]
[ 102.67435761]
[ 106.34131846]
[ 108.45857447]
[ 105.33376831]
[ 107.79576699]
[ 110.71367112]
[ 116.73589447]
[ 117.74629814]
[ 112.48947773]
[ 109.7573836 ]
[ 121.95472733]
[ 119.62476775]
[ 120.0264124 ]
[ 115.00315794]
[ 120.60368954]]
来自这个 Github post,它提到FunctionTransformer()
可以用来做一些简单的事情。我希望只在管道中放置一列。
流水线前后的 X 不同。如果我只想让管道删除 X 的最后一列,那么该管道是否应该在管道之前和之后返回相同的 X?
其他信息(如有必要):
在我的最终应用程序中,我需要使用转换器作为管道的第一步,然后在第二站使用PCA()
。因此,我首先在这篇文章中测试管道,仅第一步 - FunctionTransformer()
。
【问题讨论】:
【参考方案1】:您对generate_dataset()
进行了两次调用,因此您的drop_first_component
函数正在处理的矩阵不是X
、y
,而是一些新生成的数据。
将相同的(X, y)
直接传递给generate_dataset
可以解决问题:
if __name__ == '__main__':
X, y = generate_dataset()
print X[:20, :]
X_transformed, y_transformed = drop_first_component(X, y)
print X_transformed[:20, :]
也就是说,我认为在这里使用管道阶段完全是矫枉过正。您正在导入一些额外的库,包括几个额外的配置和逻辑行,这些行分布在三个函数中——所有这些都是为了一个除了简单的列 select X[:, 1:]
之外什么都不做的计算。
【讨论】:
非常感谢。这对我解释了很多!对于管道部分,正如我在 OP 的附加信息中提到的那样,接下来我将在流程中添加一个 PCA 步骤,以便管道在那里会有所帮助。就目前而言,你是对的,我不需要它。再次感谢。以上是关于管道中的 Scikit-Learn FunctionTransformer 没有其他功能 - 不返回原始数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 scikit-learn 管道中的 CountVectorizer 之前包含 SimpleImputer?
管道中的 Scikit-Learn FunctionTransformer 没有其他功能 - 不返回原始数据?
使用 GridSearchCV scikit-learn 在管道中的 KMeans