在管道中对有限数量的变量实施 sklearn PCA
Implementing sklearn PCA on limited number of variables in a pipeline
我正在设置机器学习管道来对一些数据进行分类。数据源之一是 PCA 的非常好的候选者,构成了数据集的最后 n
个维度。我想对这些变量而不是前面的变量使用 PCA。通过 stackexchange 搜索,这似乎也是一个普遍面临的问题——人们只想将 PCA 应用于一部分数据。
显然,我可以先进行 PCA,然后连接数据集,然后将其传递给管道,但据我所知,PCA 应该是管道的一部分,否则来自测试样本的信息会渗入训练数据中。
我想使用 sklearn 的 PCA 函数(但我也愿意接受建议)但它不接受任何参数来定义对哪些变量进行 PCA,因此很难将其合并到管道中。
我目前的解决方法是定义一个新的 PCA,它选择所需的特征,看起来像这样:
class new_PCA(PCA):
@staticmethod
def reduce(X):
return X.iloc[:,NUMBER_NONPCA_FEATURES:]
# Define PCA for limited number of columns
def _fit(self, X):
part_X = self.reduce(X)
PCA._fit(self,part_X)
def transform(self, X):
part_X = self.reduce(X)
pca_part = PCA.transform(self, part_X)
X_new = np.concatenate([X.iloc[:,:NUMBER_NONPCA_FEATURES],pca_part],axis=1)
return X_new
def score_samples(self, X):
part_X = self.reduce(X)
PCA.score_samples(self,part_X)
def inverse_transform(self, X):
part_X = self.reduce(X)
PCA.inverse_transform(self,part_X)
所以基础_fit()
方法和transform()
都限制在当前变量。这似乎可行,通过检查源代码,我认为这涵盖了所有将训练数据 (X
) 作为输入的方法。
我只是有点担心我可能忽略了一些东西,这可能会在某处产生一些意想不到的后果。这看起来不错吗?
您的解决方法不是必需的,因为 sklearn 已经涵盖了这个用例。可以通过包含 ColumnTransformer in the pipeline.
来实现针对不同特征的不同转换
考虑下面的例子:
pipe = Pipeline(
[
('ct',
ColumnTransformer(
[("PCA", PCA(), [0, 1, 2]),
("pass", "passthrough", [3, 4, 5])])
),
('svc', SVC())
]
)
管道的 ColumnTransformer 阶段可以看作是一个连接点,将进入的列分成子集,并将指定的转换器应用于传递的列(此处作为索引传递,但也可以是列名)。
在示例中,PCA 仅应用于索引为 0、1 和 2 的列,而列 3、4 和 5 不进行任何转换就传递到管道的下一阶段。
我正在设置机器学习管道来对一些数据进行分类。数据源之一是 PCA 的非常好的候选者,构成了数据集的最后 n
个维度。我想对这些变量而不是前面的变量使用 PCA。通过 stackexchange 搜索,这似乎也是一个普遍面临的问题——人们只想将 PCA 应用于一部分数据。
显然,我可以先进行 PCA,然后连接数据集,然后将其传递给管道,但据我所知,PCA 应该是管道的一部分,否则来自测试样本的信息会渗入训练数据中。
我想使用 sklearn 的 PCA 函数(但我也愿意接受建议)但它不接受任何参数来定义对哪些变量进行 PCA,因此很难将其合并到管道中。
我目前的解决方法是定义一个新的 PCA,它选择所需的特征,看起来像这样:
class new_PCA(PCA):
@staticmethod
def reduce(X):
return X.iloc[:,NUMBER_NONPCA_FEATURES:]
# Define PCA for limited number of columns
def _fit(self, X):
part_X = self.reduce(X)
PCA._fit(self,part_X)
def transform(self, X):
part_X = self.reduce(X)
pca_part = PCA.transform(self, part_X)
X_new = np.concatenate([X.iloc[:,:NUMBER_NONPCA_FEATURES],pca_part],axis=1)
return X_new
def score_samples(self, X):
part_X = self.reduce(X)
PCA.score_samples(self,part_X)
def inverse_transform(self, X):
part_X = self.reduce(X)
PCA.inverse_transform(self,part_X)
所以基础_fit()
方法和transform()
都限制在当前变量。这似乎可行,通过检查源代码,我认为这涵盖了所有将训练数据 (X
) 作为输入的方法。
我只是有点担心我可能忽略了一些东西,这可能会在某处产生一些意想不到的后果。这看起来不错吗?
您的解决方法不是必需的,因为 sklearn 已经涵盖了这个用例。可以通过包含 ColumnTransformer in the pipeline.
来实现针对不同特征的不同转换考虑下面的例子:
pipe = Pipeline(
[
('ct',
ColumnTransformer(
[("PCA", PCA(), [0, 1, 2]),
("pass", "passthrough", [3, 4, 5])])
),
('svc', SVC())
]
)
管道的 ColumnTransformer 阶段可以看作是一个连接点,将进入的列分成子集,并将指定的转换器应用于传递的列(此处作为索引传递,但也可以是列名)。
在示例中,PCA 仅应用于索引为 0、1 和 2 的列,而列 3、4 和 5 不进行任何转换就传递到管道的下一阶段。