【问题标题】:classification: PCA and logistic regression using sklearn分类:使用 sklearn 的 PCA 和逻辑回归
【发布时间】:2015-12-27 22:18:58
【问题描述】:

步骤0:问题描述

我有一个分类问题,即我想根据一组数字特征、使用逻辑回归并在运行主成分分析 (PCA) 之后预测二元目标。

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

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。否则,它们将被投影到不同的特征向量上。

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 的方式,然后是分类器吗?

【问题讨论】:

  • 我认为该程序没有任何问题。你的结果呢?你得到预期的输出了吗?
  • 我的数据上的一个意外行为(与此处显示的示例不同)是,当我增加 PCA 函数中的组件数量时,我的混淆矩阵变得更糟!另外,我想知道“虚拟化”过多的分类变量是否对结果没有任何影响?我应该在 PCA 期间排除“目标”列吗?
  • 目标不是您数据的一部分。所以在使用 PCA 时排除目标标签。对于分类数据,您应该使用 sklearn 中实现的一种热表示。
  • @Riyaz 谢谢!是的,这就是我在 pandas 中使用 get_dummies 所做的,这相当于一种热编码。
  • 如果您增加 PCA 中的组件数量(因此有很多您正在使用的功能),则可能会过度拟合您的训练集并且无法正确泛化,因此会产生混淆矩阵。

标签: python scikit-learn classification logistic-regression pca


【解决方案1】:

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

案例研究

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

  1. PCA 对缩放很敏感 - 所以我使用了 MinMaxScalarsklearn,您也可以使用 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)

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

主成分分析的应用

如上所述,主要目的是对数据进行直观和统计分析。所以n_components 推荐为 2 或 3。但是,您可以使用 scree plot 来找到最佳的组件数。

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)

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

同样,PC-2target

考虑PC-1PC-2

数据中有一些聚类模式。

结论

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

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

【讨论】:

    【解决方案2】:

    为此目的,sklearn 中有一个pipeline

    from sklearn.decomposition import PCA
    from sklearn.linear_model import LogisticRegression
    from sklearn.pipeline import Pipeline
    
    pca = PCA(n_components=2)
    clf = LogisticRegression() 
    
    pipe = Pipeline([('pca', pca), ('logistic', clf)])
    pipe.fit(features_train, df_train["target"])
    predictions = pipe.predict(features_valid)
    

    【讨论】:

    • clf 是什么?是错字吗?
    • 是的,应该是cls
    • @guy - clf 是“分类器”的缩写,一种常见的缩写。
    【解决方案3】:

    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)
    

    【讨论】:

    • 只是补充一点,如果您只将变量居中,保持方差不变,这通常称为“基于协方差的 PCA”。如果您还将变量标准化为方差 = 1,这通常称为“基于相关性的 PCA”,它可能与前者有很大不同(参见线程 here
    猜你喜欢
    • 1970-01-01
    • 2016-03-06
    • 2022-01-12
    • 2020-09-16
    • 2021-03-11
    • 2015-12-19
    • 2018-10-09
    • 2020-11-09
    • 2015-05-04
    相关资源
    最近更新 更多