减少数据集的大小

数据挖掘 分类 scikit-学习 计算机视觉 预处理 降维
2021-09-20 15:59:05

我正在尝试对手势进行分类。为此,我正在使用 Python 的 scikit 学习库分类算法。为此,我收集了深度图像。每个手势收集 200 个样本。每个手势由 25 个帧组成,每个帧的大小为 240x420。我尝试了 PCA 的逐帧维度,以减小每个手势的大小(每个 200 个样本),使其易于在机器上运行。当要分类的手势数量大于 4 时,数据量仍然很大,很难在我的机器上运行。我正在寻找让它在我的机器上运行的方法。

3个回答

有很多方法可以解决这个问题,我将专注于特征选择/提取,因为你提到了 PCA。

Sklearn 本身已经提供了一些特征选择/提取算法,请参见此处,例如 SelectKBest。这意味着您可能会选择特定的帧、样本,甚至像素(不太可能)。

此外,它不仅有 PCA,还有更多,请参见此处我将提到 PCA、NMF、ICA。虽然您显然已经尝试过,但重要的是要注意这些算法也必须正确调整。

现在,另一方面,像 Graph4Me 已经提到你可以使用 CNN。为此,您可以使用 AutoEncoder 的结构,它尝试学习输入的最小表示,以正确地将输入恢复为输出。可以训练解码器-编码器结构,然后仅使用编码器作为一种方式来获得降维的训练样本。这里有一个教程(用于 pytorch),虽然它是针对文本的,但同样的原理可以应用于图像和视频。

最后一点,您显然可以尝试一些简单的预处理,例如裁剪视频、降低帧速率、转换为灰度(如果尚未完成),甚至只是黑白。如果一次加载所有内容是一个问题,我还希望您已经在各个方面按顺序处理数据。

您的问题缺少有关您的方法的一些细节。因此,我将尝试使用所提供的信息来回答问题,并向您展示缺少的信息。

数据集

你有深度图像记录不同的手势。每个图像的分辨率为 240x420,每个手势有 200 个图像。我假设每个图像都有一个通道(深度)。一个手势由 25 个图像组成。

你有>4类,但由于计算问题,您仅限于 4 个类。

现在您是要基于单个图像还是基于形成手势的 25 个图像进行分类?我假设你想要后者。

下一个问题:超过 4 节课的时间太长了?训练还是推理?我假设 PCA,正如我稍后讨论的那样。

如果对 25 幅图像进行分类,则输入尺寸 240x420x25 小于取 RGB Full-HD 图像(假设量化类似于 RGB-Camera),所以这仍然是可行的。

因此,根据输入大小,如果在强大的 GPU 上运行,至少可以使用神经网络。

您希望机器学习系统可运行的机器是什么?

机器学习管道

您没有准确解释您应用 PCA 的数据矩阵以及您使用的分类算法。

我假设如下:当您指出计算复杂度随着类的数量而增加时,您将 PCA 直接应用于输入图像,并且类的数量越多,数据矩阵越大,您计算的特征向量就越多,两者都会导致计算成本高。

您应该考虑 PCA 是否真的是正确的工具。

首先,数据矩阵的大小是多少?如果我正确理解你的方法,用k课程,你有k×25×200×240×420像素。所以随着k=5你有关于2.5×109数据矩阵中的条目。这确实很大!

此外,PCA 确实是某种数据缩减。但是,即使 PCA 足够快,您也应该注意一些限制。

PCA 会在你的数据所在的地方找到一些线性嵌入空间。使用第一个ķ 特征向量为您的数据提供最重要的主要成分。

这样做有两个大问题:

1.) PCA 直接应用于噪声很大的深度测量。此外,测量空间非常大,因此 ML 很难解释每一个可能的图像。相反,您应该减少输入的“复杂性”。

这是通过在类似于等价类的图像描述符上应用 PCA/ML 来完成的。它们将不同的输入组合在一起,这些输入被认为是相等的,例如,您只查看图像中的边缘而不关心实际强度。然后将具有相同边缘的图像组合在一起。有许多图像描述符(例如 HOG、SIFT、SURF)可能需要根据目的进行调整。另一个例子是您可能不关心手势在图像中的确切位置。所以你想要翻译不变性。因此,您应该使用也具有平移不变性的图像描述符(向量)。

2.) 由于 PCA 假设一个线性嵌入空间,这可能是错误的,具体取决于您的数据。

您可以使用自动编码器(这是一个 CNN),它概括了 PCA。它可以用作降维工具,但它允许非线性嵌入空间。

备择方案

总之,我怀疑 PCA 是否是正确使用的工具。我看到了几种选择:

1.) 你可以从一个 CNN 开始(你可以直接输入 25 帧),然后简单地为不同的类训练它。这可能会给你一个普通的 CNN 已经令人满意的结果。它隐含地学习有用的图像描述符,因此您不必关心这些。您还可以使用循环网络,它允许您一次输入一张图像。您可以使用自动编码器进行降维。

2.) 有很多作品专注于视频中的动作识别,基于 CNN,这正是您想要的 ( https://towardsdatascience.com/deep-learning-architectures-for-action-recognition-83e5061ddf90 )。

3.) 如果设置非常受限,您应该使用先验知识,例如对于手势,您可以首先尝试获取手的姿势。这为您提供了手的描述符,然后将其用于对手势进行分类(例如,使用 CNN)。这种方法比我迄今为止提到的所有替代方法都要好得多。如果做得好,它将不太容易过度拟合,并且可能不依赖于太大的数据集。

4.) 使用适当的、手工制作的图像描述符并在其上应用一些 ML 分类工具。图像描述符将大大减小尺寸并消除噪声和冗余。

5.) 替代方案 1.) 和 2.) 是一种黑盒解决方案,虽然可行,但容易过度拟合。备选方案 3.) 和 4.) 是稳健的,但难以设计。如果这个项目是针对一家公司的,并且您需要一个稳健可靠的结果,您可以联系我,因为我已经为大公司处理过此类问题。

我希望你知道 NumPy 的默认类型是float64,即使它不是必需的。

在这种情况下,您可以轻松地将其更改为 “float16” 而不会丢失信息它可以为 10 个手势减少 30GB 的大小。

import numpy as np
image_1 = np.ones((240,420))   
image_2 = np.ones((240,420))
image_1 = image_1.astype('float16')

import sys
diff_bytes = sys.getsizeof(image_2)-sys.getsizeof(image_1)
total_diff = diff_bytes*200*25*10 #Assuming 10 gestures
total_diff_GB = total_diff/(10**9)
print('Memory saved in GB - ', total_diff_GB,' GB')

以 GB 为单位保存的内存 - 30.24 GB


下面的代码片段显示了针对此类要求的一种非常通用的方法,
它会自动检查最大值并相应地调整大小

dataset = pd.read_csv("/content/train.csv.zip")
init_mem = dataset.memory_usage().sum() / 1024**2
print('Initial memory size '+str(init_mem)+' MB')
for col in dataset.columns:
    col_type = dataset[col].dtype
    col_max_val = dataset[col].max()
    
    if str(col_type)[:3] == 'int':
        for dtype in list([np.int8,np.int16,np.int32,np.int64]):
            if col_max_val/np.iinfo(dtype).max < 1:
                dataset[col] = dataset[col].astype(dtype)
                break
    elif str(col_type)[:3] == 'flo':
        for dtype in list([np.float16,np.float32,np.float64]):
            if col_max_val/np.finfo(dtype).max < 1:
                dataset[col] = dataset[col].astype(dtype)
                break    
    else:
        dataset[col] = dataset[col].astype('category')

fin_mem = dataset.memory_usage().sum() / 1024**2
print('Final memory size '+str(fin_mem)+' MB')