最近期末事儿比较多,没什么大东西,最近在使用libsvm做文本分类,虽然感受到了LIBSVM的便捷之处,但是也感受到了Libsvm的调参的复杂性,写下来Mark一下
文本分类,使用的是路透社的语料最为训练和测试数据集,原始的语料有91类大概十几万篇文章,由于以一些类的数量太少(本次实验室将一个类别下的文本数量少于100篇的过滤)而不具备训练价值(对于有监督的学习而言),最后我们得到的是8个类别,包括训练数据集合测试数据集
文本分类的处理主要包括三个方面,第一,特征抽取;第二,特征选择;第三,机器学习方法训练模型【1】,特征抽取可以看做是文本的预处理,包括去停用词、去标点符号、同义词合并(如compute和computing),本次实验没有考虑到同义词合并,当然也有现成的算法来做处理。
特征选择是选出能代表文本内容和能和其他文档有区分度的token(token不太好翻译,可以把它想象成单词,汉字之类的),主要的方法有:
1,词频法TF,也就是选取一个类别的频率比较高的若干个词
2,信息增益法Information Gain,信息增益法是文本处理中比较常用的预处理方法的一种,计算公式是
说明:公式中的东西看上去很多,其实也都很好计算。比如P(Ci),表示类别Ci出现的概率,其实只要用1除以类别总数就得到了(这是说你平等的看待每个类别而忽略它们的大小时这样算,如果考虑了大小就要把大小的影响加进去)。再比如P(t),就是特征T出现的概率,只要用出现过T的文档数除以总文档数就可以了,再比如P(Ci|t)表示出现T的时候,类别Ci出现的概率,只要用出现了T并且属于类别Ci的文档数除以出现了T的文档数就可以了。【2】
得到每个词的信息增益值之后,就可以把这些词从大到小的顺序呢排列,选取前面指定数量的词作为特征词(数量的多少需要根据文本数量和单词总数自己调节得到最优化)
3.卡法检测法
卡法检测法也是一种比较简单常用的方法,公式如下【3】
最后运用机器学习的方法对训练集进行模型训练即可
落实到本实验上,本实验主要使用LIBSVM,特征选择的方法主要是使用了信息增益和词频的方法
第一步,预处理文档:
预处理文档主要包括去除停用词,去除标点数字等无效token,主要的处理方法代码如下:
private void processTextString(String str){ str=str.replaceAll("[().,<>'\":-]", " ").replaceAll("[\\\\/]", " ").replaceAll("[0-9]"," ").toLowerCase().replaceAll("(author.*author)", "");//1 String []words=str.split(" "); String newStr=""; String line=""; for(String word:words){ word=word.trim().toLowerCase(); if(!stopwords.contains(word) ){ //2 if(line.length()>100){ newStr+=line+"\r\n"+" "; line=""; }else{ line+=word+" "; } } } fh.writeToFileNonRandom(newStr); }
其中,1是为了去除数字和一些符号,2是为了去除停用词
第二步,特征抽取与选择,这里我尝试了两种方法,词频和信息增益的方法
词频的方法比较简单,就是选取每个类的前几个词频比较高的词语,然后将每个类的这些词合并到一起作为最后的特征词
信息增益的计算方法是根据上文提到的计算公式计算每个不重复单词的信息增益值,然后根据其信息增益值按照从大到小的顺序排列
主要代码如下:前者是词频方法,后者是信息增益方法
public void getFeatureVector() throws IOException{ //选择特征词 feature_words=new ArrayList<String>(); for(Map.Entry<Integer, Map<String,Integer>> entry:cwf.entrySet()){ Map<String,Integer> wf=entry.getValue(); int cat=entry.getKey(); int count=0; int val=0; /*if(wf.size()<80){ val=200; }else{ val=100; }*/ //二分类给个25就行了 for(Map.Entry<String, Integer> nEntry: wf.entrySet()){ if(count<=200){ //说明,每类提取前200个词频最高的词语作为特征词 String word=nEntry.getKey(); if(!feature_words.contains(word)){ feature_words.add(word); System.out.println(word); }else{ feature_words.remove(word); } count++; } } } System.out.println("feature: "+feature_words.size()); //抽取文档词向量 File rootFile=new File(Constants.ROOT_PATH); File testFile=new File(Constants.TEST_PATH); processFileVector(rootFile); fHelper=new FileHelper(Constants.TEST_FEATURE_PATH); processFileVector(testFile); }
public void getFeatureVector() throws IOException{ //选择特征词 Map<String,Double> sortMap=MapSort.sortMapByValue(wordScore); feature_words=new ArrayList<>(); int count=0; System.out.println("sortMap size: "+sortMap.size()); for (Entry<String, Double> entry : sortMap.entrySet()){ //before 16500 if(count<16500){ //选取信息增益值前16500的词语作为特征词 String feature_word=entry.getKey(); feature_words.add(feature_word); } count++; } //抽取文档词向量 File rootFile=new File(Constants.ROOT_PATH); File testFile=new File(Constants.TEST_PATH); processFileVector(rootFile); fHelper=new FileHelper(Constants.TEST_FEATURE_PATH); processFileVector(testFile); }
选取到特征词之后,就可以对训练集和测试集计算得到词向量,注意这里采用的是词袋模型,词语之间没有顺序关系。
得到词向量之后就可以使用LIBSVM进行训练了,训练的代码不多,就几行
/*ExtractFeatureVector3 ef=new ExtractFeatureVector3(); ef.loadDataSet(); ef.sortCWF(); ef.getFeatureVector();*/ //词频 ExtractFeatureVector2 ef=new ExtractFeatureVector2(); ef.loadDataSet(); //采用IG ef.calcWordScore(); ef.getFeatureVector(); String[] trainArgs = {Constants.TRAIN_FEATURE_PATH};//directory of training file String modelFile = svm_train.main(trainArgs); String[] testArgs = {Constants.TEST_FEATURE_PATH, modelFile, Constants.TEST_FEATURE_RESULT};//directory of test file, model file, result file svm_predict.main(testArgs);
上面代码中,第一个注释的是采用词频的特征选择方法。
最后来比较一下结果:
对于二分类:
使用词频分类的参数是,每类选取前25个词频最高的词作为特征词,整个的特征向量也就40多维,测试数据集是目录下面的tmp1文件夹,但是结果惊人,达到了94%
使用信息增益的方法是选取前13500维度的词作为特征词,结果为:
然后我们比较了一下八分类:
对于词频的方法,每类选取前200个最高频的词,然后八个类一起作为特征向量。结果如下:
对于信息增益的方法:我们选取信息增益值前16500个词作为特征词,结果如下
可见LIBSVM对于多类的分类准确性明显没有二分类准确,当然这里也存在着一个问题,就是分类数据的均匀问题,在测试数据集里有两个类的训练数据比其他类都要多,而对于数据比较多的类,SVM往往在计算函数间隔的时候会将线性空间的划分倾向这些数据比较多的类,这样也会造成一些准确率损失,因此尽量选择的语料是均匀的,如果不均匀的话就需要考虑额外的优化算法,现在也有不少的研究,谷歌学术一查一大把。
最后,我说一下LIBSVM的优化情况,
我也是刚开始使用LIBSVM,对这个优化不是很了解,但是也是看了一些资料,可以参考下【3--5】
其实LIBSVM主要的步骤有5:
1)按照LIBSVM软件包所要求的格式准备数据集;
2)对数据进行简单的缩放操作;
3)首要考虑选用RBF 核函数;
4)采用交叉验证选择最佳参数C与g ;
5)采用最佳参数C与g 对整个训练集进行训练获取支持向量机模型;
6)利用获取的模型进行测试与预测。
其中2-4是LIBSVM的优化,第二部的缩放也叫归一化操作,归一化的命令式:svm-scale.exe -l 0 -u 1 train.txt > train-scale.txt,其中-l表示归一化的下界 -u表示归一化的上界,train.txt是原始特征值,trainscale.txt是归一化后的特征值,需要说明的是归一化并不一定会带来准确度提升,而且有可能造成特征值文本大小骤增
对于第三步,从实验结果上看,对于大数据(特征值远大于文档词数)的训练还是采用线性模型比较好,因为特征向量的维度已经很多了,不需要再映射到一个更高的维度
对于第四步骤,现在可以使用grid.py或者easy.py进行调优,调优步骤详见【4】,很遗憾,这个实验没有调出来,一直在报:RuntimeError: get no rate 错误,调了半天也没调成功
LAST BUT NOT LEAST
综合这个实验来看,信息增益的方法对于数据集不均匀的训练集,往往不会有好的效果,因为对于比较大的一类数据,其中的与其他类不一致的token可能过多,导致最终的得到的特征词向量中包含在该类的token数量过多,达不到很好的效果,而使用词频可以避免该问题,但是词频的分类效果不是很好,当然还有很多其他的特征选择方法,这里我没有一一尝试。
还有一点,不知道是不是我的特征向量训练的不是很好,LIBSVM对于多分类的问题支持并不是很给力,这点还有待日后研究
相应的程序和数据集都在下面给出来了.
参考文献:
【1】Aurangzeb Khan, Baharum Baharudin, Lam Hong Lee*, Khairullah khan "A Review of Machine Learning Algorithms for Text-Documents Classification"
【2】文本分类入门(十一)特征选择方法之信息增益 http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html
【3】使用libsvm实现文本分类 http://shiyanjun.cn/archives/548.html
【4】LibSVM学习(六)——easy.py和grid.py的使用 http://blog.csdn.net/flydreamgg/article/details/4470477
【5】java libsvm使用说明 http://renhongchao.iteye.com/blog/2061664
相关推荐
例如,在文本分类中,我们可以将文本特征转换为向量,然后用SVM进行训练和预测;在回归问题中,SVM可以用于预测连续数值,如股票价格或天气预报。此外,libsvm也常用于特征选择和降维,帮助我们找到最有影响力的特征...
6. **应用案例**:展示LibSVM和LibLinear在不同领域的应用,如文本分类、图像识别等。 7. **性能比较**:与其他机器学习库的性能对比,帮助用户选择合适的工具。 **总结** LibSVM和LibLinear是强大的机器学习工具...
支持向量机因其在处理高维非线性问题上的优秀表现,常常被用于处理这类问题,例如在模式识别、文本分类、生物信息学等领域。 在libsvm-3.20的压缩包中,只有一个文件名"libsvm-3.20",这通常包括了libsvm的核心库...
**SVM工具包详解——以libsvm-3.24为例** SVM(Support Vector Machine,支持向量机)是一种广泛应用于机器学习领域的监督学习算法,尤其在分类和回归问题中表现出色。它通过构建一个最大边距超平面来划分数据,...
6. **应用示例**:可能还包括在文本分类、图像识别、生物信息学等领域中的实际应用示例,展示如何将训练好的SVM模型应用于实际问题。 总之,LibSVM是一个强大的工具,它提供了实现和支持向量机算法的高效接口。通过...
本文将深入探讨libsvm的原始版本——libsvm-1.0,旨在帮助读者理解和掌握这一强大的库。 libsvm,全称Library for Support Vector Machines,是由台湾大学林智仁教授及其团队精心打造的一款开源软件包。这个软件的...
《支持向量机权重编码详解——以libsvm-weights-3.20为例》 在机器学习领域,支持向量机(Support Vector Machine,简称SVM)是一种广泛应用的分类和回归算法。它通过构建最大边距超平面来实现对数据的高效分类。在...
在libsvm-2.88-string.zip中,"string"表示该版本特别针对字符串特征进行了优化,这对于处理文本分类或其他涉及字符串数据的任务尤其有用。libsvm通过将字符串转化为数值向量来适应SVM模型,这通常涉及到词袋模型...
在实际应用中,LibSVM被广泛应用于文本分类、图像识别、生物信息学等领域。通过调用LibSVM库,开发者可以快速构建起强大的机器学习模型,进行数据预处理、模型训练、验证和预测等一系列工作。对于初学者,LibSVM的...
在许多现实世界的问题中,如文本分类、生物信息学等,数据往往以字符串的形式存在。这个版本的libsvm引入了字符串核函数,如Jaccard相似度或Tanimoto系数,它们能够有效地度量字符串之间的相似性。这些核函数使得SVM...
例如,在文本分类任务中,可以使用TF-IDF或其他方法提取特征,然后使用libsvm训练一个SVM模型,对新的文本进行分类。通过调整C和γ,找到最优模型,以提高分类效果。 总之,libsvm-2.82作为SVM的优秀实现,具有广泛...
支持向量机(Support Vector Machine,SVM)是一种广泛应用的监督学习模型,尤其在分类和回归...通过熟练掌握libsvm和其核函数的使用,我们可以解决许多实际问题,例如图像识别、文本分类、生物信息学等领域的问题。
本示例"svm demo.zip"将展示如何利用SVM进行文本分类,通过两种不同的实现方式——Python的sklearn库和libsvm库,来深入理解SVM的工作原理及其在实际问题中的应用。 首先,我们要了解sklearn库中的SVM。sklearn是...
在本文中,我们将深入探讨一个特定的工具——“20130416090323_Win-64bit-JNI-lib分词包”,特别是其中的NLPIR_JNI.dll文档,它是如何在Windows 64位环境下支持libsvm实现文本分类的。 NLPIR(Natural Language ...
实验中采用了中文分词系统ICTCLAS进行数据预处理,使用libsvm、Bagging和AdaBoost方法进行文本分类,并对实验结果进行了精确度、召回率和F值的评价。 5. 实验环境的搭建 为了进行有效的实验,研究者搭建了一个适合...
该实验报告涉及的是北京邮电大学的一门课程——数据仓库与数据挖掘,其中的一个实验是使用SVM(Support Vector Machine)进行文本分类。实验的主要目的是让学生熟悉网络爬虫的运用,掌握中文分词软件的使用,理解...
在文本分类、图像识别、生物信息学等领域都有显著成果。 通过电子科技大学的这门实验课程,学生不仅能掌握理论知识,还能在实践中深化理解,提升解决问题的能力。K-means和libsvm是人工智能领域的重要工具,对于...