SVM类库研究(牛mm精简版)

俺的SVM,牛mm说太口语化,另外加的都是句号,说我语文没有学好。于是她给我改写了一下。我发现我真的很喜欢句号,句号表示一句话终结了。很显然,我喜欢把每件事情都终结了。

不多说了,因为牛mm可能不希望别人知道她真名,所以我只好先用牛mm代替了。因为她很牛,而且又是mm,所以就叫牛mm。原文:http://blog.csdn.net/cctt_1/archive/2008/11/17/3321185.aspx废话完毕,下面粘贴改进后的版本:

第一步,资料和代码查找。在Google上搜索各种SVM相关代码和使用方法,经过可行性试验和筛选,选定了libsvmc版本,使用vs2005编译生成svm-train.exe ,svm-predict.exe,svm-scale.exe。关于这些类库文件的使用方法,可以参照http://www.csie.ntu.edu.tw/~piaip/ docs/svm/

第二步,确定文件存储格式。通过下载和阅读heart.scale了解到,其文件格式是<class> <A>:<B>,对应于我的文件存储就是<类号> <词号><词个数> <词号><词个数>....但是这里有一点要注意:最后一行数据必须敲一个回车。就是说以空行做结束。否则程序就不会终止。另外偶然发现svm可以直接处理字符串,文件格式是: 类号 字符串。我心想这个不正适合我的文本分类吗?而且我根本就不需要做分词就可将整个content当作一个字符串。我试了下作者给的其他的svm版本都不支持。我看了下这个作者给的svm的源代码libsvm-2.88-string中其实是含有这段代码的,但是没有使用宏进行编译,所以要使用这个libsvm来处理字符串,需要对代码进行宏编译。

第三步,宏编译?-D ...后面还有一大堆看不懂的参数。作者给了makefile文件,可以选择两种编译环境:一是windows环境;二是linux等操作系统。考虑到数据文件大小在3G左右,linux下并没有足够大的空间来存放这些文件,所以只有在windows下了。下载一个windows下的g++,安装后,打开作者所给的makefile文件,去掉CXX?=g++中的?.然后生成成功。

第四步,研究java如何调用libsvmexe文件。找了几段网上的代码,发现均不满足要求;于是写了http://blog.csdn.net/cctt_1/archive/2008/11/14/3300789.aspx。不过这篇文章里只是说exe运行正确的情况下可以正常退出;如果exe抛出异常,那么程序就会终止。所以你还有在得到一个类似error的输入输出流,这个也是Process的函数。然后反复试验就知道是把error流放在前面还是正常输入输出放在前面了。

第五步,初步测试。使用十几个content做测试,发现效果不错;然后用了26000多个content再做测试,发现运行了几个小时依旧没有结果。其实之前就不抱有什么期望,因为libsvm对字符串的处理是采用子串匹配算法,效率比较低。

第六步,重新使用正常的libsvm,采用类号 词号:词个数...作为文件存储方式。这时看到了libsvm-2.88java的代码,于是采用之;但是在libsvm中抛了Outofmemory异常。我按网上的做法,将eclipseeclipse.ini文件中的xmx的大小改为1024m,重启之,还是不行。于是再搜索,结果还是没有啥新发现,于是还是使用了调用exe的方式。(后来才知道这里的1024m是对于eclipse来说的。如果eclipse运行程序的话,要在Run...这个选项中的jvm参数中设置-xmx1024m才可以。)

第七步,一切ok,进行测试,发现正确率偏低达到28%。后来看到有scaleexe,想着可以找到训练的最好参数。但是我看着我的硬盘一点点的被吃掉,那个生成scale的程序还没有终止。一个30M的小文件耗费了我6G左右的硬盘..而且还没有将scale生成完毕,scale方法就此作罢。如果只有几百个content使用-c的参数竟然达到了100%;但是交叉训练还是25%左右。

第八步,检查了自己的程序,发现竟然词号那里有错误。每统计一个文件,重新生成了一个词号..这怎么可能是对的,重新改正,生成新的数据文件。再跑一遍,发现这次svm-train.exe抛异常了,竟然是status_access_valid。查了下是共享内存出了问题,但是我这个是单线程的,于是把几乎所有能关的程序全部关闭再跑,依旧同样的错误。给作者发信,作者竟然很快给我回信了,说libsvm可以跑出结果呀,又把他的log给了我。

第九步,和同组成员一起分析原因。为啥人家就能跑出来,自己却跑不出来呢?再看libsvm的异常信息,上面有stack的信息,再分析了下作者给的log,发现我没有跑出来的那个log,其迭代次数达到了3000多次;而之前的最高次数也就是1000次。难道是stack溢出?于是使用vs打开源代码,将工程中的properties->system->stack commit size 调为10,意为10M,再各个编译、运行,果然成功。

第十步,训练26000content需要1个小时,但是需要训练的content数量是26000*7以上的。以实际经验来看svm的训练不是线性的,而是指数或多项式级的;所以训练如此大的文件,我的机器我的时间是根本不允许的。

SVM虽然部署完毕,但是在运行过程仍然存在着种种问题,下面是一些想法:

1)如何解决正确率不高,训练时间长的问题。因为没有时间这样去跑,所以得另想它法,能不能将几篇文档整合?于是将全部的文档按照doc个数为n进行整合,然后最后再除以n.所以现在维数据不是词个数(整数),而是浮点数,然后将测试文档放入预测,发现全为0了,根本预测不出。可能是因为这样除n不具有一般意义,比如一个词只出现1次,但是再除以n,那就是0.0001或者更小;而预测文档中此词就是1,所以根本不可能匹配。另外一种方法:如果n个文档不匹配,那么如果是全部的文档,是否符合统计的规律?结果测试说明,还是不匹配,原因相同。这里其实还有一个想法,就是将这个统计得到的训练文档中维数据整理成整数,如果此时维数据是0.0001,还有的维数据是0.002,那么如果真实测试文档中有这两个词,那么必定至少是1。如果每个维数据都乘以一个代价常数,变为一个大于等于1的维数据,这样做就有可能得到正确的预测。另外还要考虑到有些词是偶尔出现在此类中,也就是基本与此类无关。那么的它的维数据中可能有更小的例如0.000001.那么这样的数据怎么考虑?还有如果全部的维数据都乘以一个相同的代价常数。那么当维数据0.0001变为1时,(假设)维数据1(表示这个词与此类有极大的关联),将变为10000,在一篇文档中不可能有一个词个数是10000的。即使这个词在每个文档中都出现,所以我们还是不能这样直接乘以一个相同代价的常数。这里因为时间关系,并没有做一个代价函数。

2)试图采用所有的数据进行训练。26000doc不一定能说明什么问题,当数据量极大的时候,或许能产生一个好结果;但是这是我们希望发生的事情。借用了别人实验室中的机器,发现虽然他的机器是44G的,但是跑svm依旧很慢。原因在于svm是一个单线程单进程的程序,所以和一个核去跑本质上没有啥区别。另外也发现一个问题,就是libsvm在测试2.57G的数据时,crash了,这真的不是内存或者是其他的错误,因为产生的向量维数太大,以至于申请一个向量空间时访问到了操作系统的保护段数据,被操作系统拒绝了,所以可能要进行缩水

我这里说的“缩水”是一种自己的算法,我认为每个文档在训练集中的地位不是一样的。那么可能有些文档没有必要存在于训练集中,或者说每个文档存在于训练集中的概率是不同的,所以我这里做一个“缩水”,将大文档尽可能的排除,设为20%概率保留;小文档尽可能的保留,设为80%;中等大小的文档50%保留。这样做完后,只剩下500M左右的数据。我希望这些数据可能保持原来的特性,并且训练速度要提高,可惜结果还是一样的差。

3)想到可以查询相关论文资料。(这一步感觉应该提前去做。竟然因为时间关系忘记了,因为一直以为这是一个工程的活,和研究没有太多的关联。谁知道在数据量如此大时候,这些工程的方法都不起作用。)找到很多论文,发现论文之间的一致性:降维,找特征值。可是这个矩阵太大了。另外还有一种方法,就是在这个类中找出很多感觉上一定相关的词(人肉的方法),然后用这些词进行筛选。当然这个方法是可行的,可惜没有时间和精力去每个类找这么多相关的词。

我觉得svm不得不暂时放弃了。毕竟数据量太大的时候,效果很不好,这也是各个svm论文中提到的一点;而且至今没有很好的解决方案。另外即使是降维,最后还是要调节参数,看了各个文献,发现调参数也是很有讲究的(使用人工智能等等方法)

最后的总结:svm的确是可以运行了,但是训练时间太长;另外数据集太大,svm显得太笨重;还有正确率必须用参数调优,而调优的前提是必须生成scale文件。大数据量所生成的scale文件太大了,所以就不可能去调优(对于我的机器而言)。这样比较起来还是朴素贝叶斯较好,简单、而且速度快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值