PCA算法
算法介绍
Principle Component Analysis是主成分分析,简称PCA。它的应用场景是对数据集进行降维,降维后的数据能够最大程度地保留原始数据的特征,同时PCA也可以应用在anomaly detection上。
用PCA进行异常检测的原理是:PCA在做特征值分解之后得到的特征向量反应了原始数据方差变化程度的不同方向,特征值为数据在对应方向上的方差大小。所以,最大特征值对应的特征向量为数据方差最大的方向,最小特征值对应的特征向量为数据方差最小的方向。原始数据在不同方向上的方差变化反应了其内在特点。如果单个数据样本跟整体数据样本表现出的特点不太一致,比如在某些方向上跟其它数据样本偏离较大,可能就表示该数据样本是一个异常点。
也就是说,将样本的协方差矩阵特征值分解以后,特征值就是样本投影到这个轴上后对应的方差,特征值越小,说明投影以后在这个轴上样本点分布集中,而异常点在这种情况下更容易偏移,利用这一点可以作为衡量样本异常的一个指标。
代码实现
使用sklearn中的相关包来实现PCA算法,举一个很简单的小demo:
from sklearn.decomposition import PCA
X = [[0], [0.44], [0.45], [0.46], [1]]
clf = PCA()
clf.fit(X)
# score越小,代表越有可能是离群点
scores = clf.score_samples(X)
"""
输出的结果是:
[-0.76038849 0.11401533 0.11600261 0.11719498 -0.99886226]
"""
print(scores)
其他的内置函数以及介绍在:scikit-learn-PCA
可视化
sklearn上的可视化案例,链接为:scikit-learn
from sklearn.decomposition import PCA
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# #############################################################################
# Create the data
e = np.exp(1)
np.random.seed(4)
def pdf(x):
return 0.5 * (stats.norm(scale=0.25 / e).pdf(x)
+ stats.norm(scale=4 / e).pdf(x))
y = np.random.normal(scale=0.5, size=(30000))
x = np.random.normal(scale=0.5, size=(30000))
z = np.random.normal(scale=0.1, size=len(x))
density = pdf(x) * pdf(y)
pdf_z = pdf(5 * z)
density *= pdf_z
a = x + y
b = 2 * y
c = a - b + z
norm = np.sqrt(a.var() + b.var())
a /= norm
b /= norm
# #############################################################################
# Plot the figures
def plot_figs(fig_num, elev, azim):
fig = plt.figure(fig_num, figsize=(4, 3))
plt.clf()
ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=elev, azim=azim)
ax.scatter(a[::10], b[::10], c[::10], c=density[::10], marker='+', alpha=.4)
Y = np.c_[a, b, c]
# Using SciPy's SVD, this would be:
# _, pca_score, Vt = scipy.linalg.svd(Y, full_matrices=False)
pca = PCA(n_components=3)
pca.fit(Y)
V = pca.components_.T
x_pca_axis, y_pca_axis, z_pca_axis = 3 * V
x_pca_plane = np.r_[x_pca_axis[:2], - x_pca_axis[1::-1]]
y_pca_plane = np.r_[y_pca_axis[:2], - y_pca_axis[1::-1]]
z_pca_plane = np.r_[z_pca_axis[:2], - z_pca_axis[1::-1]]
x_pca_plane.shape = (2, 2)
y_pca_plane.shape = (2, 2)
z_pca_plane.shape = (2, 2)
ax.plot_surface(x_pca_plane, y_pca_plane, z_pca_plane)
ax.w_xaxis.set_ticklabels([])
ax.w_yaxis.set_ticklabels([])
ax.w_zaxis.set_ticklabels([])
elev = -40
azim = -80
plot_figs(1, elev, azim)
elev = 30
azim = 20
plot_figs(2, elev, azim)
plt.show()
显示的结果是:
由上图的超平面可以看出:PCA可以用来选择不平坦方向的地方。