PCA算法实现

前言

PCA算法是数据降维中最常用的算法之一,利用PCA算法实现的数据降维能够有效减少算法运行时间和算法对硬件的消耗。本篇文章将使用python实现PCA算法,并将其应用于图像处理。

使用PCA算法实现降维

数据可视化

在算法实现之前,首先加载初始数据,并对初始数据进行可视化。这将有利于我们更好的了解PCA算法是如何将2D数据降维至1D数据的。在实际问题中,遇到的数据可能远远超过三维,为了能够实现数据可视化,常常将其降维至三维以下。二维原始数据的可视化实现代码及可视化图像如下所示:

plt.ion()
np.set_printoptions(formatter={'float': '{: 0.6f}'.format})
print('Visualizing example dataset for PCA.')
data = scio.loadmat('ex7data1.mat')
X = data['X']
plt.figure()
plt.scatter(X[:, 0], X[:, 1], facecolors='none', edgecolors='b', s=20)
plt.axis('equal')
plt.axis([0.5, 6.5, 2, 8])
input('Program paused. Press ENTER to continue')

算法实现

  • 数据标准化
    为了减少算法实现的复杂度,需要对训练样本进行标准化处理其标准化处理的公式为:
    x_{norm} = \frac{x-\mu}{\sigma}
    其中 \mu代表x的均值,\sigma代表x的标准差,其实现代码如下所示:
def feature_normalize(X):
    mu = np.mean(X, 0)
    sigma = np.std(X, 0, ddof=1)
    X_norm = (X - mu) / sigma
    return X_norm, mu, sigma
  • 算法实现
    PCA算法的实现可以调用库函数中的算法实现,其中U就是主要成分,而S是一个对角矩阵。具体实现代码如下所示:
def pca(X):
    
    U = np.zeros(n)
    S = np.zeros(n)
    #协方差矩阵
    sigma = np.dot(X.T, X) / m
    #full_matrices的取值是为0或者1,默认值为1,这时u的大小为(M,M),v的大小为(N,N) 。
    #否则u的大小为(M,K),v的大小为(K,N) ,K=min(M,N)。
    #compute_uv的取值是为0或者1,默认值为1,表示计算u,s,v。为0的时候只计算s。
    U, S, V = scipy.linalg.svd(sigma, full_matrices=True, compute_uv=True) 
    return U, S

如下代码所示,通过调用以上算法,我们已经找到了矩阵的特征向量并且绘制出该数据的主成分部分

X_norm, mu, sigma = feature_normalize(X)
# Run PCA
U,S = pca(X_norm)
draw_line(mu, mu + 1.5 * S[0] * U[:, 0])
draw_line(mu, mu + 1.5 * S[1] * U[:, 1])
# 特征向量
print('Top eigenvector: \nU[:, 0] = {}'.format(U[:, 0]))

PCA算法实现降维

以上,利用python实现了PCA算法,得到了其数据集的特征向量,现在可以使用PCA算法将高维数据投影到更低维的向量空间实现降维。以下代码通过PCA算法将数据集投影到特征向量所在的空间实现降维

  • 数据投影
    n维矩阵X降维至k维矩阵的计算公式如下所示,
    Z = U_k^{T}*X,其中U_k表示矩阵U的前k列向量。具体实现
    代码如下所示:
def project_data(X, U, K): 
    Z = np.zeros((X.shape[0], K))
    Ureduce = U[:, np.arange(K)]
    Z = np.dot(X, Ureduce)
    return Z
  • 压缩重现
    实现数据降维之后,通过将其投影至原数据所在的高维空间,可以实现数据的压缩重现,数据压缩重现的公式如下所示:
    X_{approx} = U_k*Z,其实现代码如下所示:
def recover_data(Z, U, K):
       X_approx = np.zeros((Z.shape[0], U.shape[0]))   
    Ureduce = U[:, np.arange(K)]
    X_approx = np.dot(Z, Ureduce.T)
    return X_approx

  • 数据可视化
    通过图像可视化展示数据降维和压缩重现,可以清楚的展示数据降维和数据压缩重现之间的关系,蓝色圆圈代表原来的数据,红色圆圈代表降维后的数据,实现代码和效果如下所示:
plt.figure()
plt.scatter(X_norm[:, 0], X_norm[:, 1], facecolors='none', edgecolors='b', s=20)
plt.axis('equal')
plt.axis([-4, 3, -4, 3])
K = 1
Z = project_data(X_norm, U, K)
print('Projection of the first example: {}'.format(Z[0]))
print('(this value should be about 1.481274)')
X_rec = recover_data(Z, U, K)
print('Approximation of the first example: {}'.format(X_rec[0]))
print('(this value should be about [-1.047419 -1.047419])')
plt.scatter(X_rec[:, 0], X_rec[:, 1], facecolors='none', edgecolors='r', s=20)
for i in range(X_norm.shape[0]):
    draw_line(X_norm[i], X_rec[i])

PCA算法的应用

PCA算法在图像处理上的应用

  • 图像显示
    以上,通过python实现了PCA算法,并利用PCA算法实现了数据降维和数据恢复。在这部分内容中会将PCA算法应用于人脸的图像数据集,人脸图像的矩阵共都包含着1024幅图像,32×32的显示在一个二维图像中,一共有5000个数据集,显示其中的前一百个数据如下所示:
def display_data(x):
    (m, n) = x.shape # m =5000,n=1024

    # 每幅图像都是32×32的灰度级
    example_width = np.round(np.sqrt(n)).astype(int) #width = 32
    example_height = (n / example_width).astype(int) #width = 32

    #计算显示的大小 dsiplay_rows = 70 display_cols = 72
    display_rows = np.floor(np.sqrt(m)).astype(int)
    display_cols = np.ceil(m / display_rows).astype(int)

    # 每幅图像之间的间隔
    pad = 1

    #设置显示矩阵大小 display_array = 2311*2311
    display_array = - np.ones((pad + display_rows * (example_height + pad),
                              pad + display_rows * (example_height + pad)))

    #用每一幅图像逐个替换显示矩阵的每个初始元素
    curr_ex = 0
    for j in range(display_rows):
        for i in range(display_cols):
            if curr_ex > m:
                break

           
            max_val = np.max(np.abs(x[curr_ex]))
            display_array[pad + j * (example_height + pad) + np.arange(example_height),
                          pad + i * (example_width + pad) + np.arange(example_width)[:, np.newaxis]] = \
                          x[curr_ex].reshape((example_height, example_width)) / max_val
            curr_ex += 1

        if curr_ex > m:
            break

    plt.figure()
    plt.imshow(display_array, cmap='gray', extent=[-1, 1, -1, 1])
    plt.axis('off')
data = scio.loadmat('ex7faces.mat')
X = data['X']
display_data(X[0:100])

运行结果如下所示:


  • PCA算法处理图像
    在图像数据中使用PCA算法降维数据,首先要进行数据标准化,运行完PCA算法之后,注意到每一个矩阵U主成份都是长度为n的向量(n = 1024),可以将U中向量重新设置为32×32的图像矩阵,实现图像数据的可视化,具体实现代码如下所示:
print('Running PCA on face dataset.\n(this might take a minute or two ...)')

# 标准化处理
X_norm, mu, sigma = feature_normalize(X)
U, S = pca(X_norm)
display_data(U[:, 0:36].T)

input('Program paused. Press ENTER to continue')

运行结果如下所示:


  • 数据恢复
    对降维后的数据可以利用投影向量进行恢复,对比原来的图像,发现,图像的大小基本保持不变,但一些细节明显缺失。
print('Visualizing the projected (reduced dimension) faces.')
K = 100
X_rec = recover_data(Z, U, K)
# Display normalized data
display_data(X_norm[0:100])
plt.title('Original faces')
plt.axis('equal')
# Display reconstructed data from only k eigenfaces
display_data(X_rec[0:100])
plt.title('Recovered faces')
plt.axis('equal')
input('Program paused. Press ENTER to continue')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 本文先简要明了地介绍了特征向量和其与矩阵的关系,然后再以其为基础解释协方差矩阵和主成分分析法的基本概念,最后我们结...
    xiao_dong_zi阅读 3,753评论 0 10
  • 很多机器学习的问题都会涉及到有着几千甚至数百万维的特征的训练实例。这不仅让训练过程变得非常缓慢,同时还很难找到一个...
    城市中迷途小书童阅读 3,735评论 0 2
  • 转载: PCA的数学原理 PCA(Principal Component Analysis)是一种常用的数据分析方...
    ruizuo007阅读 463评论 0 5
  • 前言 在之前的学习中,已经学习了无监督学习中的K均值算法。除此算法之外,无监督学习还有另外一种新的算法,该算法被称...
    此间不留白阅读 1,349评论 0 4
  • PCA(Principal Component Analysis)是一种常用的数据分析方法。PCA通过线性变换将原...
    0_f75b阅读 1,233评论 0 4