自编码器用于高维数据

3
我正在进行一个项目,需要减少观察数据的维度,同时仍然具有显著的表示。由于许多原因,强烈建议使用Autoencoders,但我不确定这是否是最佳方法。
我有1400个样本,每个样本的维度约为60,000,这太高了,我正在尝试将它们的维数降低到原始值的10%。我正在使用theano autoencoders [Link],看起来成本一直在30,000左右(这非常高)。我尝试增加epochs的数量或降低学习率,但都没有成功。我对autoencoders不是很了解,所以我不确定该如何继续或何时停止尝试。
在继续进行任何其他测试之前,我想听听您的意见。
  • 你认为数据集太小了吗(我可以再添加600个样本,总共约2000个)?

  • 你认为使用堆叠自编码器有帮助吗?

  • 我应该继续调整参数(epochs和learning rate)吗?

由于数据集是图片的合奏,我试图从自编码器中可视化重建,但我得到的都是相同的输出。这意味着,给定输入时,自编码器尝试重新构建输入,但我得到的却是任何输入的相同(几乎完全一样)的图像(看起来像数据集中所有图像的平均值)。这意味着内部表示不够好,因为自编码器无法从中重构图像。

数据集:大约1400-2000张扫描书籍的图片(包括封面),每张图片大约有60,000个像素(转化为一个具有60,000个元素的特征向量)。每个特征向量已归一化为[0,1],最初的值在[0,255]之间。

问题: 使用自编码器将其降维(如果可能)。

如果您需要任何额外的信息,或者我遗漏了一些有助于更好地理解问题的内容,请添加评论,我将非常乐意帮助您帮助我 =)。
注意:我目前正在对整个数据集运行更多轮次的测试,并将根据结果更新我的帖子,这可能需要一些时间。

4
你有没有考虑过其他的降维技术,比如主成分分析? - Daniel Renshaw
我绝对会考虑这个问题,但我仍然想了解为什么自编码器不起作用。 - G4bri3l
1
所以我之前有一个句子说“Daniel说什么”,因为你应该先尝试简单的事情,而PCA对你来说就像一个单层自编码器一样有效(你也无法训练更多)。另一个建议是使用预训练的卷积神经网络,例如在sklearn-theano中可以找到的,选择最新的层并在空间上折叠通道,从而给出每个书籍封面大小为(n_channels,)的签名。这将捕获一些视觉信息。 - eickenberg
3个回答

3

自编码器之所以有用,是因为它们可以学习非线性降维。然而,还有其他降维技术比自编码器快得多。扩散映射是一种流行的技术;局部线性嵌入是另一种。我已经在超过2000个60k维数据(包括图像)上使用了扩散映射,并且它在不到一分钟的时间内工作。

下面是一个简单的Python实现,使用了numpy等:

def diffusion_maps(data, d, eps=-1, t=1):
    """
    data is organized such that columns are points. so it's 60k x 2k for you
    d is the target dimension
    eps is the kernel bandwidth, estimated automatically if == -1
    t is the diffusion time, 1 is usually fine
    """

    from scipy.spatial import pdist, squareform
    from scipy import linalg as la
    import numpy as np

    distances = squareform(pdist(data.T))

    if eps == -1:
        # if a kernel bandwidth was not supplied,
        # just use the distance to the tenth-nearest neighbor
        k = 10
        nn = np.sort(distances)
        eps = np.mean(nn[:, k + 1])

    kernel = np.exp(-distances ** 2 / eps ** 2)
    one = np.ones(n_samples)
    p_a = np.dot(kernel, one)
    kernel_p = walk / np.outer(p_a, p_a)
    dd = np.dot(kernel_p, one) ** 0.5
    walk = kernel_p / np.outer(dd, dd)

    vecs, eigs, _ = la.svd(walk, full_matrices=False)
    vecs = vecs / vecs[:, 0][:, None]
    diffusion_coordinates = vecs[:, 1:d + 1].T * (eigs[1:d + 1][:, None] ** t)

    return diffusion_coordinates

扩散映射的要点在于,你可以在数据上形成一个随机游走,这样你更容易访问附近的点而不是远离的点。然后你可以定义两点之间的距离(扩散距离),它实质上是所有可能路径上移动两个点的平均概率。诀窍在于计算这个非常容易;你只需要对一个矩阵进行对角化,然后使用其特征向量将你的数据嵌入到低维空间中即可。在这种嵌入中,欧几里得距离即为扩散距离,只有一个近似误差。

2
请问“n_samples”是什么意思?此外,代码在赋值之前使用了变量“walk”。您能否澄清一下?谢谢。 - user823743
请问您能解释一下 "n_samples和walk" 这两个变量的含义吗? - javac

3

除非了解问题描述的情况,否则没有必要认为成本为30,000是“高”的。如果例如隐藏层的大小特别小,并且数据中很少有冗余,则全局最小成本实际上可能在30,000左右。

如果成本在训练之前(即在具有随机编码器和解码器权重的情况下)为30,000,并且即使经过一些培训后仍然保持在该水平,则可能存在问题。

您应该期望第一次更新后成本会降低(如果您正在使用小批量随机梯度下降法,则每个周期会有多个更新)。您还应该期望随着隐藏层的大小增加,收敛成本会降低。

在这种情况下可能有所帮助的其他技术包括去噪音自动编码器(可以通过反复应用随机噪声来人工增加训练数据集的大小)和压缩自动编码器,后者将正则化功率集中在您关心的编码器部分。两者都可以在Theano中实现,第一个是本教程的主题带代码)。


1

先从简单的开始...请注意,如果您在60,000维空间中只有1400个点,则可以不损失地将维度降低到<=1400。这是一个简单的数学事实:您的数据矩阵为1400x60,000,因此其秩(维度)最多为1400。因此,在考虑其他任何事情之前,我强烈建议使用主成分分析(PCA)来减少数据的维度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接