在上篇文章中对libsvm的流程和简单的java代码测试做了说明,本篇简单对libsvm如何在工程中实践进行简短说明,不当的地方欢迎大家指正。
第一步是对libsvm的预测函数进行调整,我是从svm_predict类中抽取部分代码组成预测防范,代码如下:
/** * 对传入的文本特征根据训练好的分类模型进行分类 * @param model 已经训练好的模型 * @param contentFeature 传入的计算好的文本分词后的特征 * @return */ public static int libSvmPredict(svm_model model, String contentFeature){ //默认分类类别为-1 int label = -1; //判断传入的文本特征是否为空 if (contentFeature == null) return label; //对传入的特征进行切分 StringTokenizer st = new StringTokenizer(contentFeature," f:"); //这里target用不到,测试中会用到,即我们测试语料的类别标签 // double target = atof(st.nextToken()); int m = st.countTokens()/2; svm_node[] x = new svm_node[m]; for(int j=0;j<m;j++) { x[j] = new svm_node(); x[j].index = atoi(st.nextToken()); x[j].value = atof(st.nextToken()); } double v = svm.svm_predict(model,x); label = (int) v; return label; }
第二步对待分类的文本按照上篇文章中讲到的方法根据terms词表生成libsvm需要的格式,注意我这里为了方便仅做了词的tf,idf默认都为1,代码如下:
/** * 获取模型分词用的term词表 * @param termsPath * @return */ public static Map<String, Integer> getModelTerms(String termsPath){ Map<String, Integer> termsMap = new HashMap<String, Integer>( ); try { String termsStr = FileOptionUtil.readFile( termsPath, "UTF-8" ); if (termsStr != null){ String[] terms = termsStr.split( " " ); if (terms!=null && terms.length>0){ for (int i=0; i<terms.length; i++){ String term = terms[i]; String[] termM = term.split( " " ); if (termM!=null && termM.length==2){ termsMap.put( termM[0], Integer.parseInt(termM[1]) ); } } } } } catch (IOException e) { e.printStackTrace(); } return termsMap; } public static String getContentFeature(String content, Map<String, Integer> terms){ String contentFature = ""; //对传入的文本进行分词 Map<String, Integer> contentTermsMap = HanLPAnalyser.segString( content ); Map<Integer, Double> contentTfIdf = new TreeMap<Integer, Double>( new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo( o2 ); } } ); //计算tf-idf,这里我们就用单存的tf代替tf-idf,idf值均为1 for (String word : contentTermsMap.keySet()){ if (terms.containsKey( word )){ contentTfIdf.put( terms.get( word ), getWordTF( word, contentTermsMap ) ); } } for (Integer key : contentTfIdf.keySet()){ contentFature += key + ":" + contentTfIdf.get( key ) + " "; } return contentFature.trim(); }
第三步根据上述方法进行分类计算,main方法代码如下:
public static void main(String[] args){ String s = "    依照上海证券交易所发布的《关于证券公司创设白云机场权证有关事项的 " + "通知》,光大证券股份有限公司向上海证券交易所申请注销白云机场认沽权证并 " + "已获核准,中国证券登记结算有限责任公司上海分公司已办理相应登记手续。本 " + "公司此次获准注销的白云机场认沽权证数量为1,500万份,该权证的条款与原白 " + "云机场认沽权证(交易简称机场JTP1、交易代码580998、行权代码582998)的条 " + "款完全相同。 " + "     "; Map<String, Integer> terms = LibSvmDataProcess.getModelTerms( "/Users/zhouyh/work/yanfa/xunlianji/UTF8/heji/terms.txt" ); String contentFeature = LibSvmDataProcess.getContentFeature( s, terms); svm_model model = GetSvmModel.getSvmModelInstance().getModel( "/Users/zhouyh/work/yanfa/xunlianji/UTF8/heji/model.txt" ); int label = libSvmPredict(model, contentFeature); System.out.println(label); }
测试结果如图,财经类和我们选择的语料类别也一致,如下图所示:
最后,此代码仅为将libsvm如何在工程中实践做了下流程走通,后续要在工程中使用,还需要做很多的调整。