Julia 中的探索性 PCA

Phi*_*lis 3 pca julia

我尝试了解如何使用 MultivariateStats.jl 包在 Julia 中执行简单的探索性 PCA。

\n

例如,在 R 中,可以执行以下操作:

\n
library(FactoMineR)\ndata(iris)\n\n## PCA model:\nres_pca <- PCA(iris, quali.sup = 5, graph = FALSE)\n## Retrieve coordinates of individuals on all 4 PCs:\nres_pca$ind$coord\n## Simple plots:\nplot(res_pca, choix = "ind", habillage = 5)\nplot(res_pca, choix = "var")\n
Run Code Online (Sandbox Code Playgroud)\n

我没有设法在 Julia 中获得这些非常基本的操作的任何等效项(我的意思是使用 MultivariateStats.jl 中的“本机”函数)。让我们从以下开始:

\n
using MultivariateStats\nusing RDatasets\n\niris = dataset("datasets", "iris")\n\n## PCA model:\nM = fit(PCA, Array(iris[:, 1:4]); pratio=1, maxoutdim=4)\n
Run Code Online (Sandbox Code Playgroud)\n

一旦我获得了 PCA“模型” M,我如何轻松检索个人坐标?如何轻松显示相关圈等?

\n

据我了解,从准机器学习的角度来看,PCA 在 Julia 中作为一种“模型”实现,并且基本上无法提供轻松显示探索性 PCA 中通常需要的所有常用图表、统计数据和见解的方法?(我的意思是,cos\xc2\xb2、贡献等)

\n

是否还有其他更面向探索性多变量分析的 Julia 包,可以提供与 FactoMineR 或 ade4 等著名 R 包大致相同的功能?

\n

谢谢!

\n

cbk*_*cbk 14

好的,首先您将数据放入错误的方向。正如您从文档中看到的

\n
\n

fit(PCA, X; ...)
\n对矩阵 X 中给定的数据执行 PCA。X 的每一列都是一个观察值。

\n
\n

您需要将观察值作为列,将变量作为行。考虑到我们通常将变量视为列,这可能看起来令人困惑,但在底层线性代数的背景下,它更有意义。因此,为了做到这一点,让我们从以下开始:

\n
using MultivariateStats, Statistics\nusing RDatasets: dataset\n\niris = dataset("datasets", "iris")\niris_matrix = Array(iris[:, 1:4])\'\n\n## PCA model:\nM = fit(PCA, iris_matrix; pratio=1, maxoutdim=4)\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所注意到的,这将返回一个类型的对象PCA。事实证明,文档中详细描述了这种类型的可用方法:

\n
\n

特性

\n

设M是PCA的实例,d是观测值的维度,p是输出维度(即主子空间的维度)

\n

indim(M)
\n获取输入维度d,即观察空间的维度。

\n

outdim(M)
\n获取输出维度 p,即主子空间的维度。

\n

Mean(M)
\n获取平均向量(长度为 d)。

\n

投影(M)
\n获取投影矩阵(大小为 (d, p))。投影矩阵的每一列对应一个主成分。

\n

主成分按相应方差的降序排列。

\n

principalvars(M)
\n主成分的方差。

\n

tprincipalvar(M)
\n主成分的总方差,等于 sum(principalvars(M))。

\n

tresidualvar(M)
\n总残差方差。

\n

tvar(M)
\n总观测方差,等于 tprincipalvar(M) + tresidualvar(M)。

\n

principalratio(M)
\n主子空间中保留的方差之比,等于 tprincipalvar(M) / tvar(M)。

\n
\n

但如果您不知道这一点或者在查找文档时遇到困难,您可以通过使用该函数获得所有可用方法(对于 Julia 中的任何methodswith类型)的完整列表- 在本例中具体为methodswith(PCA)

\n

其中的关键是projection,它为我们提供了实际的投影矩阵:

\n
julia> proj = projection(M)\n4\xc3\x974 Matrix{Float64}:\n -0.361387    0.656589  -0.58203     0.315487\n  0.0845225   0.730161   0.597911   -0.319723\n -0.856671   -0.173373   0.0762361  -0.479839\n -0.358289   -0.075481   0.545831    0.753657\n
Run Code Online (Sandbox Code Playgroud)\n

正如文档告诉我们的

\n
\n

投影矩阵的每一列对应一个主成分

\n
\n

因此proj[:,1]包含 PC1 的权重/“载荷”,proj[:,2]包含 PC2 的载荷等。

\n

既然您询问了贡献,我猜您的意思是每个主成分对解释总方差的贡献,文档告诉我们您可以通过以下方式获得principalvars

\n
julia> principalvars(M)\n4-element Vector{Float64}:\n 4.2282417060348605\n 0.24267074792863352\n 0.07820950004291898\n 0.023835092973449976\n
Run Code Online (Sandbox Code Playgroud)\n

所以 PC1 确实承担了这里的大部分繁重工作。或者,如果您更喜欢用每个分量解释的总方差的百分比来表示,那么:

\n
julia> principalvars(M) ./ tvar(M) * 100\n4-element Vector{Float64}:\n 92.46187232017269\n  5.306648311706788\n  1.7102609807929683\n  0.5212183873275495\n
Run Code Online (Sandbox Code Playgroud)\n

展望同一文档的“转换”部分

\n
\n

改造建设

\n

给定一个 PCA 模型 M,我们可以用它来将观测值转换为主成分,如下所示

\n

= \xe1\xb5\x80 ( - )

\n

或用它来重建(近似)主成分的观察结果,如

\n

\xcc\x83 = +

\n

这里, 是投影矩阵。

\n

该包提供了执行此操作的方法:

\n

变换(M, x)
\n将观测值 x 转换为主成分。

\n

这里,x 可以是长度为 d 的向量,也可以是每列都是观测值的矩阵。

\n

reconstruct(M, y)
\n根据 y 中给出的主成分近似重建观测值。

\n

这里,y 可以是长度为 p 的向量,也可以是每列给出观测值的主成分的矩阵。

\n
\n

我们可以看到将这种转换应用于我们的数据的方法是

\n
iris_transformed = transform(M, iris_matrix)\n
Run Code Online (Sandbox Code Playgroud)\n

或者如果你想自己做线性代数

\n
iris_transformed = projection(M)\' * (iris_matrix .- mean(M))\n
Run Code Online (Sandbox Code Playgroud)\n

然后,一旦我们有了转换后的数据,我们就可以将前两个主成分相互绘制出来:

\n
using Plots\nh = plot(iris_transformed[1,:], iris_transformed[2,:], seriestype=:scatter, label="")\nplot!(xlabel="PC1", ylabel="PC2", framestyle=:box) # A few formatting options\n
Run Code Online (Sandbox Code Playgroud)\n

Iris 数据集的 PCA,绘制 PC1 与 PC2

\n

最后,如果你想为不同的变量添加箭头,事实证明我们已经拥有了我们需要的一切projection(M),我们已经将其存储为proj

\n
for i=1:4; plot!([0,proj[i,1]], [0,proj[i,2]], arrow=true, label=names(iris)[i], legend=:bottomleft); end\ndisplay(h)\n
Run Code Online (Sandbox Code Playgroud)\n

显示每个变量向量的 PCA 图

\n

编辑:我可能还应该提到,虽然(还)没有用于 PCA 类型的 StatsPlots 配方,但有一个用于 MDS 的配方,因此在这种情况下,您可以通过简单地编写来获得与上述等效的图

\n
M = fit(MDS, iris_matrix; distances=false)\nusing StatsPlots\nplot(M)\n
Run Code Online (Sandbox Code Playgroud)\n

(对于此处距离度量是原始(即高维)向量空间中的欧氏距离的情况,PCA 和 MDS 是等效的)

\n