SVM 每行训练矩阵的长度

Posted

技术标签:

【中文标题】SVM 每行训练矩阵的长度【英文标题】:Length of each row of training matrix for SVM 【发布时间】:2014-04-10 05:30:34 【问题描述】:

我在这里using OpenCV and SVM with images 找到了与此主题相关的出色/全面的帖子/答案。但是,我有一些问题想从链接中的答案中澄清。 (因为我没有足够的声誉来写评论)。

我一直在做什么: 我正在使用 OpenCV SVM 进行培训。用于训练矩阵的特征是通过计算每张图像的归一化平均 R、G 和 B 值来获得的。因此,在训练矩阵中,每行(或每张图像)有 4 列。这些列对应于 labels(1 or 0), **** normalized mean in r channel****, gb 频道。

顺便说一句,我的原始训练文件是一个文本文件,我仍会将其转换为 float[][],并最终转换为 Mat 对象以输入到 opencv 的 SVM。文件如下所示:

1 0.267053 0.321014 0.411933 1 0.262904 0.314294 0.422802 . . 0 0.29101 0.337208 0.371782 0 0.261792 0.314494 0.423714

显然,这与链接中声明每行的大小必须等于图像的大小的声明相矛盾>。它是协议还是某种规则?我只是不明白为什么应该这样做(如果是的话)。

我的问题是,在构建训练矩阵时,每一行的长度是否必须与图像的面积或大小相对应?在我做的训练矩阵中,每行的长度只有4。这是错误的吗?

此外,只有 3 个特征(3 列)用于训练是否足以用于分类/SVM?请引导我走向正确的道路,我怀疑我是否应该继续这样做,或者是否有其他更好的方法来解决这个问题。

我希望我能更多地了解 SVM 步骤背后的概念。文章或相关样本将不胜感激!

【问题讨论】:

【参考方案1】:

如果图像的每个像素都是您要用来训练 SVM 的特征,那么每一行都应列出所有特征,因此也应列出所有像素。在您的情况下,每个图像似乎只有 3 个特征(平均 R、G、B),所以应该没有任何问题。

当然,您可以完美地训练具有 3 个维度的 SVM。但是忽略 SVM,平均颜色是否是您图像的一个合理指标?

【讨论】:

老实说,我不确定这 3 个特征是否足以产生准确的分类结果。我实际上只是基于使用它的研究论文中的 3 个特征的使用,并表明了一个高精度的结果(在叶病的分类中是具体的。)。感谢您提出这一点,@MSalters 除了平均颜色之外,您对我应该包括哪些功能有什么建议吗?我计划添加更多功能,但我不知道有多少功能就足够了。你有什么主意吗?我计划包括尺寸和纹理,但我仍在寻找如何手动计算它的方法。你能建议如何获得这些功能的方法吗? @user3339658:当然,如果您已经建立了感兴趣的区域,那就另当别论了。叶子的颜色是有用的,叶子的平均颜色和它的周围环境没那么有用。 是的,这就是投资回报率的样子。 drive.google.com/file/d/0B1aXcXzD_OADTWFCbGlEYWZVcTg/…。你不觉得这里 ROI 的平均颜色没有用吗?【参考方案2】:

每行的大小不必与图像大小相等。这取决于你有什么功能。使用平均值进行图像分类是不够的。想想看图片时如何对物体进行分类。您不计算平均值,但您可能会查看大脑处理背景中的轮廓、连接区域,有时甚至是单个像素值。

所以要获得更多功能,我有一个建议给你。计算特征提取部分的每一列的平均值。这可能会更有用。

对于另一个特征提取,您可以使用 PCA。通常,您可以连续提供所有像素值来训练 SVM,但即使对于 200*200 的图像,这也会产生 40.000 个特征,哇,这么多。您需要在不丢失太多信息的情况下减少此特征维度,这意味着保留可接受的方差百分比。因此使用 PCA 来降低特征空间维度,并将方差保持在可接受的范围内。

我将尝试向您展示如何使用 PCA 减少特征空间。首先,您需要获取图像,而不是将图像逐行滚动到 Mat 变量:

读取 csv

void read_csv(const string& filename, vector& images, vector& labels, char separator = ';') std::ifstream 文件(filename.c_str(), ifstream::in); 如果(!文件) string error_message = "没有给出有效的输入文件,请检查给定的文件名。"; CV_Error(1, error_message); 字符串行、路径、类标签; 而(getline(文件,行)) 串流线(线); getline(线条,路径,分隔符); getline(线条,类标签); if(!path.empty() && !classlabel.empty()) Mat im = imread(path, 0); images.push_back(im); 标签.push_back(atoi(classlabel.c_str()));

逐行滚动图片:

Mat rollVectortoMat(const vector<Mat> &data) // data is vector of Mat images

   Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32FC1);
   for(unsigned int i = 0; i < data.size(); i++)
   
      Mat image_row = data[i].clone().reshape(1,1);
      Mat row_i = dst.row(i);                                       
      image_row.convertTo(row_i,CV_32FC1, 1/255.);
   
   return dst;
 

主要

int main()


    PCA pca;

    vector<Mat> images_train;
    vector<Mat> images_test;
    vector<int> labels_train;
    vector<int> labels_test;

    read_csv("train1k.txt",images_train,labels_train);
    read_csv("test1k.txt",images_test,labels_test);

    Mat rawTrainData = rollVectortoMat(images_train);                       
    Mat rawTestData  = rollVectortoMat(images_test);                

    Mat trainLabels = getLabels(labels_train);
    Mat testLabels  = getLabels(labels_test);

    int pca_size = 500;

    Mat trainData(rawTrainData.rows, pca_size,rawTrainData.type());
    Mat testData(rawTestData.rows,pca_size,rawTestData.type());


    pca(rawTrainData,Mat(),CV_PCA_DATA_AS_ROW,pca_size);

    for(int i = 0; i < rawTrainData.rows ; i++)
        pca.project(rawTrainData.row(i),trainData.row(i));

    for(int i = 0; i < rawTestData.rows ; i++)
        pca.project(rawTestData.row(i),testData.row(i));


总而言之,您读取了一个类似于 image_path;label 的 csv 文件。比您将图像逐行滚动到 Mat 变量。您应用 pca 以减少到 500 功能。我应用这些 PCA 缩减来将 200*200 图像(40000 个特征)减少到 500 个特征大小。比我应用 MLP 来分类这个。这个 testData 和 trainData 变量也可以与 SVM 一起使用。您还可以在我的 SO 帖子中查看如何使用 MLP 进行训练:

OpenCV Neural Network Sigmoid Output

【讨论】:

感谢您的建议。一定会试试这个。但是我可以问一下您这行“特征提取部分的每一列的平均值”是什么意思。你说的那一列是指每张图片的矩阵表示的那一列吗? 假设您有 100*100 RGB 图像。如果您采用每个通道的列平均值,这将产生 100*3 = 300 个特征。但这只是一个建议,我不希望它代表对对象有意义的东西,但它应该比使用 4 功能更好:) 是的,如果你用矩阵表示它,你将有 3 个 100*100 的 Mat 数组,使用 OpenCV 的 split 方法。

以上是关于SVM 每行训练矩阵的长度的主要内容,如果未能解决你的问题,请参考以下文章

无法理解 SVM 返回的混淆矩阵

在kernlab中的SVM训练之外的内核矩阵计算

如何获得在更大矩阵上训练的 SVM 以对不同大小的矩阵进行分类

使用可变大小的训练图像 hog 描述符训练 SVM (MATLAB)

代码随想录算法训练营第二天 | 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II

代码随想录算法训练营第二天 | 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II