我试图通过 ml.linalg 方法使用 PCA 来减少广泛的数据集(51 个特征,约 1300 个个体),如下所示:
1)将我的列命名为一个列表:
features = indi_prep_df.select([c for c in indi_prep_df.columns if c not in{'indi_nbr','label'}]).columns
2)导入必要的库
from pyspark.ml.feature import PCA as PCAML
from pyspark.ml.linalg import Vector
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.linalg import DenseVector
3)将特征折叠为 DenseVector
indi_feat = indi_prep_df.rdd.map(lambda x: (x[0], x[-1], DenseVector(x[1:-2]))).toDF(['indi_nbr','label','features'])
4)删除除了保留索引的功能之外的所有内容:
dftest = indi_feat.drop('indi_nbr','label')
5)实例化PCA对象
dfPCA = PCAML(k=3, inputCol="features", outputCol="pcafeats")
6)并尝试拟合模型
PCAout = dfPCA.fit(dftest)
但我的模型无法收敛(错误如下)。
我尝试过的事情:
- 均值填充或零填充 NA 和 Null 值(视情况而定)
- 减少特征数量(减少到25个,然后我改用SKlearn的PCA)
Py4JJavaError: An error occurred while calling o2242.fit.
: breeze.linalg.NotConvergedException:
at breeze.linalg.svd$.breeze$linalg$svd$$doSVD_Double(svd.scala:110)
at breeze.linalg.svd$Svd_DM_Impl$.apply(svd.scala:40)
at breeze.linalg.svd$Svd_DM_Impl$.apply(svd.scala:39)
at breeze.generic.UFunc$class.apply(UFunc.scala:48)
at breeze.linalg.svd$.apply(svd.scala:23)
at org.apache.spark.mllib.linalg.distributed.RowMatrix.computePrincipalComponentsAndExplainedVariance(RowMatrix.scala:389)
at org.apache.spark.mllib.feature.PCA.fit(PCA.scala:48)
at org.apache.spark.ml.feature.PCA.fit(PCA.scala:99)
at org.apache.spark.ml.feature.PCA.fit(PCA.scala:70)
我的配置是 50 个执行器,每个执行器 6GB,所以我不认为这是资源不足的问题(而且我在这里没有看到任何有关资源的信息)。
我的输入因子是百分比、整数和 2 位小数浮点数的混合,全部为正数和序数。这会导致收敛困难吗?
当我将 PySpark DF 转换为 Pandas DF 后,SKLearn 方法的收敛速度很快,没有遇到任何问题。