如何将图像(像素)数据训练成libsvm格式以便在Java中用于识别

我想制作一个Java应用程序来识别字符,使用libsvm,但当我开始研究时,我不明白如何将图像数据训练成libsvm可以使用的格式?

最近为了学习,我使用现有数据进行了一次测试:

我还创建了基于32x32的训练图像数据,通过将每个像素转换为0,1,但我不知道这是否可以用来创建libsvm的训练数据格式?另外,libsvm的测试数据是如何创建的?

转换后的图像像素(0,1)示例:

0000000000000111100000000000000000000000000011111110000000000000000000000011111111110000000000000000000111111111111110000000000000000001111111011111100000000000000000111111100000111100000000000000001111111000000011100000000000000011111110000000111100000000000000111111100000000111000000000000001111111000000001110000000000000011111100000000011110000000000000111111000000000011100000000000001111110000000000111000000000000001111110000000000111000000000000011111100000000001110000000000000111111000000000011100000000000001111110000000000111000000000000111111100000000011110000000000001111011000000000111100000000000011110000000000011110000000000000011110000000000011110000000000000111100000000001111100000000000001111000000000111110000000000000011110000000011111000000000000000011100000011111100000000000000000111100011111110000000000000000001111111111111100000000000000000001111111111111000000000000000000011111111111100000000000000000000011111111100000000000000000000000011111000000000000000000000000000011000000000000000000 0000000000000011111111100000000000000000000111111111111100000000000000000011111111111111100000000000000000111111111111111000000000000000001111111111111111000000000000001111111111111111100000000000000011111000001111110000000000000000000000000001111100000000000000000000000000011111000000000000000000000000000111110000000000000000000000000011111000000000000000000000000001111110000000000000000000000000011111100000000000000000000000000111111000000000000000000000000011111100000000000000000001111111111111111100000000000000111111111111111111100000000000001111111111111111111000000000000011111111111111111110000000000001111111111111111110000000000000011111111111100000000000000000000111111111111000000000000000000000111111111110000000000000000000000000111110000000000000000000000000001111100000000000000000000000000011111000000000000000000000000001111110000000000000000000000000011111100000000000000000000000001111110000000000000000000000000111111100000000000000000000000000111110000000000000000000000000001111100000000000000000 7

如何将其转换为libsvm (训练、测试数据)格式?


回答:

libsvm有一个特定的数据格式,每一行是一个训练/测试向量,格式为

LABEL INDEX0:VALUE0 INDEX1:VALUE1 … INDEXN:VALUEN

所以在最“简单”的方法中,你只需将矩阵表示转换为行表示,通过连接连续的行,像这样的图像

010011000

将变成

010011000

在libsvm格式中(假设我们标记为“5”):

5 0:0 1:1 2:0 3:0 4:1 5:1 6:0 7:0 8:0 9:0

由于libsvm支持“稀疏”表示,你可以省略值为“0”的部分

5 1:1 4:1 5:1 

这是一种手动方式,样本数据位于此处: http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/a1a

最简单的“自动”方式是将你的数据表示为.csv格式(再次 – 将数据转换为行状格式,然后转换为.csv),这是一种相当标准的方法:

LABEL,PIXEL_0,PIXEL_1,…,PIXEL_N

然后使用此程序进行转换

/* convert cvs data to libsvm/svm-light format */#include <stdio.h>#include <stdlib.h>#include <string.h>char buf[10000000];float feature[100000];int main(int argc, char **argv){    FILE *fp;    if(argc!=2) { fprintf(stderr,"Usage %s filename\n",argv[0]); }    if((fp=fopen(argv[1],"r"))==NULL)    {        fprintf(stderr,"Can't open input file %s\n",argv[1]);    }    while(fscanf(fp,"%[^\n]\n",buf)==1)    {        int i=0,j;        char *p=strtok(buf,",");        feature[i++]=atof(p);        while((p=strtok(NULL,",")))            feature[i++]=atof(p);        //      --i;        /*        if ((int) feature[i]==1)            printf("-1 ");        else            printf("+1 ");        */        //      printf("%f ", feature[1]);        printf("%d ", (int) feature[0]);        for(j=1;j<i;j++)            printf(" %d:%f",j,feature[j]);        printf("\n");    }    return 0;}

训练和测试文件的结构完全相同,只需按一定比例(如3:1或9:1)随机将数据分成trainingtesting文件,但请记住,在每个文件中包含每个类别的训练向量的平衡数量。

特别是 – 你的数据看起来有点像MNIST数据集,如果是这种情况,这已经为libsvm准备好了:

http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass.html

MNIST训练: http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/mnist.scale.bz2

MNIST测试: http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/mnist.scale.t.bz2

如果你的数据允许的话,将图像转换为[0,1]区间内的实值数据比二进制数据(会丢失很多信息)更有价值。

编辑

例如,如果你的图像是8位灰度图像,那么每个像素实际上是一个介于0到255之间的数字v。你现在所做的,是某种阈值处理,当v > T时设置为1,当v <= T时设置为0,而将这些值映射到实值会为模型提供更多信息。这可以通过简单的压缩v / 255来实现。结果,所有值都在[0,1]区间内,但也包括中间值,如0.25等。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注