分类:使用sklearn进行PCA和逻辑回归

时间:2015-09-30 07:59:15

标签: python scikit-learn pca logistic-regression

步骤0:问题描述

我有一个分类问题,即我想基于一组数字特征预测二元目标,使用逻辑回归,以及运行主成分分析(PCA)后。

我有2个数据集:df_traindf_valid(分别是训练集和验证集)作为pandas数据框,包含要素和目标。作为第一步,我使用get_dummies pandas函数将所有分类变量转换为boolean。例如,我会:

n_train = 10
np.random.seed(0)
df_train = pd.DataFrame({"f1":np.random.random(n_train), \
                         "f2": np.random.random(n_train), \
                         "f3":np.random.randint(0,2,n_train).astype(bool),\
                         "target":np.random.randint(0,2,n_train).astype(bool)})

In [36]: df_train
Out[36]: 
         f1        f2     f3 target
0  0.548814  0.791725  False  False
1  0.715189  0.528895   True   True
2  0.602763  0.568045  False   True
3  0.544883  0.925597   True   True
4  0.423655  0.071036   True   True
5  0.645894  0.087129   True  False
6  0.437587  0.020218   True   True
7  0.891773  0.832620   True  False
8  0.963663  0.778157  False  False
9  0.383442  0.870012   True   True

n_valid = 3
np.random.seed(1)
df_valid = pd.DataFrame({"f1":np.random.random(n_valid), \
                         "f2": np.random.random(n_valid), \
                         "f3":np.random.randint(0,2,n_valid).astype(bool),\
                         "target":np.random.randint(0,2,n_valid).astype(bool)})

In [44]: df_valid
Out[44]: 
         f1        f2     f3 target
0  0.417022  0.302333  False  False
1  0.720324  0.146756   True  False
2  0.000114  0.092339   True   True

我现在想要应用PCA来减少问题的维数,然后使用sklearn中的LogisticRegression来训练和预测我的验证集,但我不确定我遵循的程序是否正确。这是我的工作:

第1步:PCA

我的想法是,我需要以与PCA相同的方式转换我的训练和验证设置。换句话说,我可以分别执行PCA。否则,它们将被投射到不同的特征向量上。

from sklearn.decomposition import PCA

pca = PCA(n_components=2) #assume to keep 2 components, but doesn't matter
newdf_train = pca.fit_transform(df_train.drop("target", axis=1))
newdf_valid = pca.transform(df_valid.drop("target", axis=1)) #not sure here if this is right

第二步:逻辑回归

没有必要,但我更喜欢将内容保存为数据框:

features_train = pd.DataFrame(newdf_train)
features_valid = pd.DataFrame(newdf_valid)  

现在我执行逻辑回归

from sklearn.linear_model import LogisticRegression
cls = LogisticRegression() 
cls.fit(features_train, df_train["target"])
predictions = cls.predict(features_valid)

我认为第2步是正确的,但我对第1步有更多疑问:这是我应该链接PCA,然后是分类器的方式吗?

3 个答案:

答案 0 :(得分:5)

为此目的,sklearn中有一个pipeline

from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline

pca = PCA(n_components=2)
cls = LogisticRegression() 

pipe = Pipeline([('pca', pca), ('logistic', clf)])
pipe.fit(features_train, df_train["target"])
predictions = pipe.predict(features_valid)

答案 1 :(得分:1)

PCA 对变量的缩放很敏感。要创建新尺寸,它使用您的特征的标准偏差。由于高/低标准,没有缩放变量重要性是有偏差的。归一化后,当创建减少的空间时,您的所有特征都将具有相同的标准和相同的 PCA 权重。 我建议修改 Alexander Fridman 答案:

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline

pca = PCA(n_components=2)
clf = LogisticRegression() 
scaler = StandardScaler()

pipe = Pipeline([('scaler', scaler), ('pca', pca), ('logistic', clf)])
pipe.fit(features_train, df_train["target"])
predictions = pipe.predict(features_valid)

还有 n_components 是一个应该测试的重要参数。如果您想自动执行此操作,请尝试:

from sklearn.model_selection import GridSearchCV
param_grid = dict(reduce_dim__n_components=[2,3,4,5])
grid_search = GridSearchCV(estimator=pipe, param_grid=param_grid)
grid_search.fit(features_train, df_train.target)

答案 2 :(得分:1)

PCA 的目的是减少数据的维度,以便更容易地分析和理解数据——这是通过将数据映射到不同的维度来实现的 [{{3} }]。现在,另一种方法是找到变量之间的相关性 - 这可以通过了解您的基础数据告诉您什么来完成。

案例研究

让我们通过随机生成的数据(由您提供)来了解您的问题。在继续之前,必须了解以下几点:

  1. PCA 对缩放很敏感 - 所以我使用了 MinMaxScalar 中的 sklearn,你也可以使用 StandardScalar(正如@Mateusz 所指出的)。
  2. 最好将数据可视化并找出数据之间是否存在相关性。我已经提供了相同的热图。
n_train = 10
np.random.seed(0)
df_train = pd.DataFrame({"f1":np.random.random(n_train), \
                         "f2": np.random.random(n_train), \
                         "f3":np.random.randint(0,2,n_train).astype(bool),\
                         "target":np.random.randint(0,2,n_train).astype(bool)})

df_train[df_train.columns] = MinMaxScaler().fit_transform(df_train)

n_valid = 3
np.random.seed(1)
df_valid = pd.DataFrame({"f1":np.random.random(n_valid), \
                         "f2": np.random.random(n_valid), \
                         "f3":np.random.randint(0,2,n_valid).astype(bool),\
                         "target":np.random.randint(0,2,n_valid).astype(bool)})

df_valid[df_valid.columns] = MinMaxScaler().fit_transform(df_valid)

相关性

为了便于理解,使用 seaborn 如下:

sns.heatmap(df_train.corr(), annot = True)

PCA Basics

几乎没有任何相关性,但这是随机生成的数据的预期。

PCA的应用

如前所述,主要目的是对数据进行视觉和统计分析。因此,n_components 建议为 2 或 3。不过,您可以使用 enter image description here 来找到最佳分量数。

PCA 的组成部分

第一个主成分 (PC-1) 最能解释您的数据,其次是第二个主成分,依此类推。考虑所有组件 - 您的数据已 100% 解释 - 这意味着您的输入数据和所有组件的 PCA 结果之间在统计上没有差异。您可以使用以下方法找到解释方差:pca.explained_variance_ratio_

考虑到 n_components = 2 我正在创建 PCA 结果的数据框,并附加目标列,如下所示:

pca = PCA(n_components = 2) # fix components
principalComponents = pca.fit_transform(df_train.drop(columns = ["target"]))

PCAResult = pd.DataFrame(principalComponents, columns = [f"PCA-{i}" for i in range(1, 3)])
PCAResult["target"] = df_train["target"].values # data has no bins-column

Out [21]:
     PCA-1        PCA-2    target
0   0.652797    -0.231204   0.0
1   -0.191555   0.206641    1.0
2   0.566872    -0.393667   1.0
3   -0.084058   0.458183    1.0
4   -0.609251   -0.322991   1.0
5   -0.467040   -0.200436   0.0
6   -0.627764   -0.359079   1.0
7   0.075415    0.549736    0.0
8   0.895179    -0.039265   0.0
9   -0.210595   0.332084    1.0

现在,在继续之前 - 您必须首先检查PCA 解释了多少数据差异。如果值太低 - 那么 PCA 不是训练数据的好选择(在大多数情况下)。

基本上,到目前为止,您已经将维度缩小到2,并且已经丢失了一些信息。

可视化 PCA 结果

现在,让我们使用散点图可视化 PC-1target

sns.scatterplot(y = "target", x = "PCA-1", data = PCAResult, s = 225)

scree plot

嗯,首先,两个变量之间没有逻辑关系

类似地,对于 PC-2target

enter image description here

考虑 PC-1PC-2

enter image description here

数据中有一些聚类模式。

结论

您首先需要了解是否存在任何关系。考虑到我正在处理的一项研究成果,这里是第一个主成分 PC-1 和目标变量(tan delta)之间的图:

enter image description here

显然,数据之间存在某种指数关系。一旦你建立了这种关系 - 你就可以应用任何你想要的逻辑了!!