降维——PCA解释
Dimensionality Reduction – PCA explanation
我认为我对 PCA 没有很好的理解,有人可以帮助我解决下面的困惑吗?
以鸢尾花数据集为例,我有4个协变量,x1:sepal长度; x2:sepal宽度; x3:petal长度; x4:petal 宽度。公式如下所示,a1,a2,a3,a4 是协变量的权重。 PCA 将尝试使用不同的线性变换来最大化方差。同时也遵循a1^2 + a2^2 + a3^2 + a4^2=1的规则。我想知道 a1,a2,a3,a4 的值。
a1*x1 + a2*x2 + a3*x3 + a4*x4
我在 python 上有以下代码,我认为哪个是正确的?
# load libraries
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import seaborn as sns
import pandas as pd
import numpy as np
iris = load_iris()
X = iris.data
df = pd.DataFrame(X,columns=iris.feature_names)
pca = decomposition.PCA(n_components = 4)
digits_pca_4 = pca.fit(X)
digits_pca_4.explained_variance_ratio_
结果是
array([0.92461872, 0.05306648, 0.01710261, 0.00521218])
我的问题是:
我假设 a1=sqrt(0.92)、a2=sqrt(0.05)、a3=sqrt(0.02)、a4=sqrt(0.005) 是否正确?
第二个问题:
如果我选择 a1=a2=a3=a4=0.5 的线性组合,与 PCA 的方差相比,它的方差是多少(我假设它小于 PCA 结果,因为 PCA最大化方差?)?如何获得 python 中 a1=a2=a3=a4=0.5 时的方差? PCA 的方差是下面的代码吗?
pca.explained_variance_.sum()
非常感谢!
直接回答你的问题:不,你的初步解释不正确。
说明
PCA 完成的实际投影是一个矩阵乘法 Y = (X - u) W
,其中 u
是 X 的平均值 (u = X.mean(axis=0)
),W
是找到的投影矩阵PCA:n x p
正交矩阵,其中 n
是原始数据维度,p
是所需的输出维度。您给出的表达式 (a1*x1 + a2*x2 + a3*x3 + a4*x4
) 并不意味着所有值都是标量。充其量,它可能意味着计算单个组件,使用下面 W
的一列 j
作为 a_k
: Y[i, j] == sum(W[k, j] * (X[i, k] - u[k]) for k in range(n))
.
无论如何,您可以用vars(pca)
检查pca = PCA.fit(...)
结果的所有变量。特别地,可以发现上述投影矩阵为W = pca.components_.T
。可以验证以下语句:
# projection
>>> u = pca.mean_
... W = pca.components_.T
... Y = (X - u).dot(W)
... np.allclose(Y, pca.transform(X))
True
>>> np.allclose(X.mean(axis=0), u)
True
# orthonormality
>>> np.allclose(W.T.dot(W), np.eye(W.shape[1]))
True
# explained variance is the sample variation (not population variance)
# of the projection (i.e. the variance along the proj axes)
>>> np.allclose(Y.var(axis=0, ddof=1), pca. explained_variance_)
True
图形演示
理解 PCA 的最简单方法是,它纯粹是 n 维(去除均值后)的 旋转 ,同时仅保留第一个 p 维。旋转使得数据的最大方差方向与投影中的自然轴对齐。
这里有一个小的演示代码,可以帮助您直观地了解正在发生的事情。请同时阅读 Wikipedia page on PCA.
def pca_plot(V, W, idx, ax):
# plot only first 2 dimensions of W along with axes W
colors = ['k', 'r', 'b', 'g', 'c', 'm', 'y']
u = V.mean(axis=0) # n
axes_lengths = 1.5*(V - u).dot(W).std(axis=0)
axes = W * axes_lengths # n x p
axes = axes[:2].T # p x 2
ax.set_aspect('equal')
ax.scatter(V[:, 0], V[:, 1], alpha=.2)
ax.scatter(V[idx, 0], V[idx, 1], color='r')
hlen = np.max(np.linalg.norm((V - u)[:, :2], axis=1)) / 25
for k in range(axes.shape[0]):
ax.arrow(*u[:2], *axes[k], head_width=hlen/2, head_length=hlen, fc=colors[k], ec=colors[k])
def pca_demo(X, p):
n = X.shape[1] # input dimension
pca = PCA(n_components=p).fit(X)
u = pca.mean_
v = pca.explained_variance_
W = pca.components_.T
Y = pca.transform(X)
assert np.allclose((X - u).dot(W), Y)
# plot first 2D of both input space and output space
# for visual identification: select a point that's as far as possible
# in the direction of the diagonal of the axes cube, after normalization
# Z: variance-1 projection
Z = (X - u).dot(W/np.sqrt(v))
idx = np.argmax(Z.sum(axis=1) / np.sqrt(np.linalg.norm(Z, axis=1)))
fig, ax = plt.subplots(ncols=2, figsize=(12, 6))
# input space
pca_plot(X, W, idx, ax[0])
ax[0].set_title('input data (first 2D)')
# output space
pca_plot(Y, np.eye(p), idx, ax[1])
ax[1].set_title('projection (first 2D)')
return Y, W, u, pca
示例
虹膜数据
# to better understand the shape of W, we project onto
# a space of dimension p=3
X = load_iris().data
Y, W, u, pca = pca_demo(X, 3)
请注意,投影实际上只是 (X - u) W
:
>>> np.allclose((X - u).dot(W), Y)
True
合成椭球体数据
A = np.array([
[20, 10, 7],
[-1, 3, 7],
[5, 1, 2],
])
X = np.random.normal(size=(1000, A.shape[0])).dot(A)
Y, W, u, pca = pca_demo(X, 3)
我认为我对 PCA 没有很好的理解,有人可以帮助我解决下面的困惑吗?
以鸢尾花数据集为例,我有4个协变量,x1:sepal长度; x2:sepal宽度; x3:petal长度; x4:petal 宽度。公式如下所示,a1,a2,a3,a4 是协变量的权重。 PCA 将尝试使用不同的线性变换来最大化方差。同时也遵循a1^2 + a2^2 + a3^2 + a4^2=1的规则。我想知道 a1,a2,a3,a4 的值。
a1*x1 + a2*x2 + a3*x3 + a4*x4
我在 python 上有以下代码,我认为哪个是正确的?
# load libraries
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import seaborn as sns
import pandas as pd
import numpy as np
iris = load_iris()
X = iris.data
df = pd.DataFrame(X,columns=iris.feature_names)
pca = decomposition.PCA(n_components = 4)
digits_pca_4 = pca.fit(X)
digits_pca_4.explained_variance_ratio_
结果是
array([0.92461872, 0.05306648, 0.01710261, 0.00521218])
我的问题是:
我假设 a1=sqrt(0.92)、a2=sqrt(0.05)、a3=sqrt(0.02)、a4=sqrt(0.005) 是否正确?
第二个问题:
如果我选择 a1=a2=a3=a4=0.5 的线性组合,与 PCA 的方差相比,它的方差是多少(我假设它小于 PCA 结果,因为 PCA最大化方差?)?如何获得 python 中 a1=a2=a3=a4=0.5 时的方差? PCA 的方差是下面的代码吗?
pca.explained_variance_.sum()
非常感谢!
直接回答你的问题:不,你的初步解释不正确。
说明
PCA 完成的实际投影是一个矩阵乘法 Y = (X - u) W
,其中 u
是 X 的平均值 (u = X.mean(axis=0)
),W
是找到的投影矩阵PCA:n x p
正交矩阵,其中 n
是原始数据维度,p
是所需的输出维度。您给出的表达式 (a1*x1 + a2*x2 + a3*x3 + a4*x4
) 并不意味着所有值都是标量。充其量,它可能意味着计算单个组件,使用下面 W
的一列 j
作为 a_k
: Y[i, j] == sum(W[k, j] * (X[i, k] - u[k]) for k in range(n))
.
无论如何,您可以用vars(pca)
检查pca = PCA.fit(...)
结果的所有变量。特别地,可以发现上述投影矩阵为W = pca.components_.T
。可以验证以下语句:
# projection
>>> u = pca.mean_
... W = pca.components_.T
... Y = (X - u).dot(W)
... np.allclose(Y, pca.transform(X))
True
>>> np.allclose(X.mean(axis=0), u)
True
# orthonormality
>>> np.allclose(W.T.dot(W), np.eye(W.shape[1]))
True
# explained variance is the sample variation (not population variance)
# of the projection (i.e. the variance along the proj axes)
>>> np.allclose(Y.var(axis=0, ddof=1), pca. explained_variance_)
True
图形演示
理解 PCA 的最简单方法是,它纯粹是 n 维(去除均值后)的 旋转 ,同时仅保留第一个 p 维。旋转使得数据的最大方差方向与投影中的自然轴对齐。
这里有一个小的演示代码,可以帮助您直观地了解正在发生的事情。请同时阅读 Wikipedia page on PCA.
def pca_plot(V, W, idx, ax):
# plot only first 2 dimensions of W along with axes W
colors = ['k', 'r', 'b', 'g', 'c', 'm', 'y']
u = V.mean(axis=0) # n
axes_lengths = 1.5*(V - u).dot(W).std(axis=0)
axes = W * axes_lengths # n x p
axes = axes[:2].T # p x 2
ax.set_aspect('equal')
ax.scatter(V[:, 0], V[:, 1], alpha=.2)
ax.scatter(V[idx, 0], V[idx, 1], color='r')
hlen = np.max(np.linalg.norm((V - u)[:, :2], axis=1)) / 25
for k in range(axes.shape[0]):
ax.arrow(*u[:2], *axes[k], head_width=hlen/2, head_length=hlen, fc=colors[k], ec=colors[k])
def pca_demo(X, p):
n = X.shape[1] # input dimension
pca = PCA(n_components=p).fit(X)
u = pca.mean_
v = pca.explained_variance_
W = pca.components_.T
Y = pca.transform(X)
assert np.allclose((X - u).dot(W), Y)
# plot first 2D of both input space and output space
# for visual identification: select a point that's as far as possible
# in the direction of the diagonal of the axes cube, after normalization
# Z: variance-1 projection
Z = (X - u).dot(W/np.sqrt(v))
idx = np.argmax(Z.sum(axis=1) / np.sqrt(np.linalg.norm(Z, axis=1)))
fig, ax = plt.subplots(ncols=2, figsize=(12, 6))
# input space
pca_plot(X, W, idx, ax[0])
ax[0].set_title('input data (first 2D)')
# output space
pca_plot(Y, np.eye(p), idx, ax[1])
ax[1].set_title('projection (first 2D)')
return Y, W, u, pca
示例
虹膜数据
# to better understand the shape of W, we project onto
# a space of dimension p=3
X = load_iris().data
Y, W, u, pca = pca_demo(X, 3)
请注意,投影实际上只是 (X - u) W
:
>>> np.allclose((X - u).dot(W), Y)
True
合成椭球体数据
A = np.array([
[20, 10, 7],
[-1, 3, 7],
[5, 1, 2],
])
X = np.random.normal(size=(1000, A.shape[0])).dot(A)
Y, W, u, pca = pca_demo(X, 3)