我有一个分类问题,即我想基于一组数字特征预测二元目标,使用逻辑回归,以及运行主成分分析(PCA)后。
我有2个数据集:df_train
和df_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
来训练和预测我的验证集,但我不确定我遵循的程序是否正确。这是我的工作:
我的想法是,我需要以与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,然后是分类器的方式吗?
答案 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} }]。现在,另一种方法是找到变量之间的相关性 - 这可以通过了解您的基础数据告诉您什么来完成。
让我们通过随机生成的数据(由您提供)来了解您的问题。在继续之前,必须了解以下几点:
MinMaxScalar
中的 sklearn
,你也可以使用 StandardScalar
(正如@Mateusz 所指出的)。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。不过,您可以使用 来找到最佳分量数。
第一个主成分 (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
,并且已经丢失了一些信息。
现在,让我们使用散点图可视化 PC-1
与 target
:
sns.scatterplot(y = "target", x = "PCA-1", data = PCAResult, s = 225)
嗯,首先,两个变量之间没有逻辑关系。
类似地,对于 PC-2
与 target
:
考虑 PC-1
与 PC-2
:
数据中有一些聚类模式。
您首先需要了解是否存在任何关系。考虑到我正在处理的一项研究成果,这里是第一个主成分 PC-1 和目标变量(tan delta)之间的图:
显然,数据之间存在某种指数关系。一旦你建立了这种关系 - 你就可以应用任何你想要的逻辑了!!