Dee*_*mar 6 python pca apache-spark pyspark apache-spark-ml
我在Spark ML中尝试PCA(主成分分析).
data = [(Vectors.dense([1.0, 1.0]),),
(Vectors.dense([1.0, 2.0]),),
(Vectors.dense([4.0, 4.0]),),
(Vectors.dense([5.0, 4.0]),)]
df = spark.createDataFrame(data, ["features"])
pca = PCA(k=1, inputCol="features", outputCol="pcaFeatures")
model = pca.fit(df)
transformed_feature = model.transform(df)
transformed_feature.show()
Run Code Online (Sandbox Code Playgroud)
输出:
+---------+--------------------+
| features| pcaFeatures|
+---------+--------------------+
|[1.0,1.0]|[-1.3949716649258...|
|[1.0,2.0]|[-1.976209858644928]|
|[4.0,4.0]|[-5.579886659703326]|
|[5.0,4.0]|[-6.393620130910061]|
+---------+--------------------+
Run Code Online (Sandbox Code Playgroud)
当我在scikit上尝试使用相同数据的PCA时 - 如下所示,给出了不同的结果
X = np.array([[1.0, 1.0], [1.0, 2.0], [4.0, 4.0], [5.0, 4.0]])
pca = PCA(n_components=1)
pca.fit(X)
X_transformed = pca.transform(X)
for x,y in zip(X ,X_transformed):
print(x,y)
Run Code Online (Sandbox Code Playgroud)
输出:
[ 1. 1.] [-2.44120041]
[ 1. 2.] [-1.85996222]
[ 4. 4.] [ 1.74371458]
[ 5. 4.] [ 2.55744805]
Run Code Online (Sandbox Code Playgroud)
如您所见,输出存在差异.
为了验证结果,我在数学上计算了相同数据的PCA.我得到了与scikit-learn相同的结果.下面的片段是第一个数据点(1.0,1.0)的pca变换计算:

你可以看到它与scikit学习结果匹配.
看起来火花ML不会从数据向量X中减去平均向量MX,即它用来Y = A*(X) 代替 Y = A*(X-MX).
对于点(1.0,1.0):
Y = (0.814*1.0)+(0.581*1.0)) = 1.395
Run Code Online (Sandbox Code Playgroud)
这与火花ML得到的结果相同.
Spark ML是错误的结果还是我错过了什么?
在 Spark 中,PCA 转换不会自动为您缩放输入数据。在应用该方法之前,您需要自己处理好这一点。要标准化数据的平均值,StandardScaler可以按以下方式使用:
scaler = StandardScaler(inputCol="features", outputCol="scaledFeatures",
withStd=False, withMean=True)
scaled_df = scaler.fit(df).transform(df)
Run Code Online (Sandbox Code Playgroud)
scaled_df然后可以按照与之前相同的方式应用 PCA 方法,结果将与 scikit-learn 给出的结果相匹配。
我建议使用 Spark ML 管道来简化流程。要同时使用标准化和 PCA,它可能如下所示:
scaler = StandardScaler(inputCol="features", outputCol="scaledFeatures",
withStd=False, withMean=True)
pca = PCA(k=1, inputCol=scaler.getOutputCol(), outputCol="pcaFeatures")
pipeline = Pipeline(stages=[scaler , pca])
model = pipeline.fit(df)
transformed_feature = model.transform(df)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
700 次 |
| 最近记录: |