通过叠加PCA和t-SNE对机器学习的降维

渣渣 2018-05-01

通过叠加PCA和t-SNE对机器学习的降维

我们必须在任何机器学习任务中几乎总是执行的一个常见步骤是:维度降低以及用于实现以下目的的两种常用技术:

  • 主成分分析(PCA)

  • t分布随机相邻嵌入(t-SNE)

两者都有它们的小众用途,但在这篇文章中,我们将看到我们如何将它们结合起来,以实现更好的输出以满足我们的需求。

获取并设置数据

我们将使用数据库(http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)来完成这项任务:

!wget http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip -O att_faces.zip

!unzip att_faces.zip

数据集有10个图像,每个图像有40个不同的个体,上面给出了400个图像中的每个图像的图像路径。

收集所有图像路径:

import glob

imagepaths = glob.glob('**/*.pgm', recursive=True)

print(len(imagepaths))

创建我们需要的数据集:

import numpy as np

import pandas as pd

from scipy.misc import imread

faces = pd.DataFrame([])

individual_id = 0

for i, path in enumerate(imagepaths):

print("===== loading image", i+1)

img = imread(path)

img = img.astype(np.uint8)

img = img / 255

img = img.flatten()

data_entry = pd.DataFrame([img])

data_entry['individual_id'] = individual_id

if ((i+1)%10 == 0):

individual_id+=1

faces = faces.append(data_entry)

图像是112x92,上面的代码使图像变平整以将每个像素作为一个特征 - 为每个图像提供一组10304个特征 - 这意味着我们的数据集现在具有10304个维度。

拔出individual_id以识别个人:

individuals = faces['individual_id']

faces = faces.drop(['individual_id'], axis=1)

individuals.unique()

让我们绘制上面的数据并快速查看这些图像的外观:

import matplotlib.pyplot as plt

from scipy.misc import imread

def plot_faces(data):

fig, axes = plt.subplots(40, 10, figsize=(9, 41),

subplot_kw={'xticks':[], 'yticks':[]},

gridspec_kw=dict(hspace=0.01,

wspace=0.01))

for i, ax in enumerate(axes.flat):

ax.imshow(data.iloc[i].values.reshape(112, 92), cmap="gray")

使用上面的功能,plot_faces(faces) :

通过叠加PCA和t-SNE对机器学习的降维

我们脸部数据集的前5行

为40个人中的每一个创建一种颜色:

import random

r = lambda: random.randint(0,255)

random_colors = []

for i in range(0, len(individuals.unique())):

random_colors.append('#%02X%02X%02X' % (r(),r(),r()))

colors = np.array(random_colors)[individuals]

PCA

定义一个带有run_pca2个参数的函数:data&dimensions,并返回结果数据:

from sklearn.decomposition import PCA

def pca(data, dimensions):

pca = PCA(n_components=dimensions)

pca.fit(data)

pca_results = pca.transform(data)

return pca_results

如果我们使用上面的faces数据集并通过dimensions=3,我们得到的是来自我们拥有的10304维数据集的三维数据集。

pca_results = run_pca(faces, 3)

我们来看一下3D图:

from mpl_toolkits.mplot3d import Axes3D

def plot_3d(data, colors):

x, y, z = data.T

fig = plt.figure(figsize=(10, 5.5/8*10))

ax = fig.add_subplot(111, projection='3d')

ax.scatter(x, y, z, color=colors);

plot_3d(pca_results, colors)

通过叠加PCA和t-SNE对机器学习的降维

plot after PCA

上面的每一种颜色都对应着一个独特的个体,并且看上面的情节,很难看出它们之间的清晰分离。

T-SNE

考虑到它们是如何实现的,当您有非常多的维度时,PCA是推荐的技术,当维度的数量很小(例如- 50)时,就会发光。

现在,我们确实有大量的维度(10304),但这并没有限制我们只使用PCA——如何使用PCA将维数降低到50,然后用t-SNE来在三维空间中出最好的结果?

让我们试一试。

与run_pca()上面的函数类似,定义一个run_tsne():

from sklearn.manifold import TSNE

def run_tsne(data, components):

tsne = TSNE(n_components=components,

verbose=1,

perplexity=15,

learning_rate=75.0)

tsne_results = tsne.fit_transform(data)

return tsne_results

我们首先使用run_pca()降至50,然后run_tsne()进一步使用它将其降至3维数据集 - 我们最终绘制该数据集。

pca_results = run_pca(faces, 50)

results = run_tsne(pca_results, 3)

plot_3d(results, colors)

通过叠加PCA和t-SNE对机器学习的降维

plot after PCA followed by t-SNE

相关推荐