Weka在Eclipse下使用IKAnalyzer进行分类预测

程序使用IKAnalyzerV2012_U6中文分词器,因此要在Java的工作目录下添加IKAnalyzer2012_u6.jar,因为这个分词器依赖于Lucene,所以也要添加lucene-core-3.6.2.jar,当然,weka.jar也是必须的。我这有已经下载好的资源

链接:https://pan.baidu.com/s/1F0EOyF4VxH4bRh6tFb0gXA 密码:n2m9

把IKAnalyzer的stopword.dic和IKAnalyzer.cfg.xml复制到项目src根目录下

这里使用复旦大学李荣陆提供的文本分类语料库测试语料,下载网址为http://www.nlpir.org/?action-viewnews-itemid-103(可能有时候进不去,刷新一下就好了)

我把下载好的测试包解压到F盘进行测试,读者可自行解压,在输入命令时更改相应路径即可,下面是源程序代码(代码来自袁梅宇的《数据挖掘与机器学习WEKA应用技术与实践》,进行了小部分修改)

package wekalearning.classifiers;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.wltea.analyzer.lucene.IKAnalyzer;

import weka.classifiers.Classifier;
import weka.classifiers.trees.J48;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Utils;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.StringToWordVector;

public class MessageClassifier implements Serializable {

	private static final long serialVersionUID = -6705084686587638940L;
	private Instances m_Data = null;// 迄今收集到的训练数据
	private StringToWordVector m_Filter = new StringToWordVector();// 用于生成单词计数的过滤器
	private Classifier m_Classifier = new J48();// 实际的分类器
	private boolean m_UpToData;// 模型是否为最新
	
	/**
	 * 构建空训练集
	 * @throws Exception
	 */
	public MessageClassifier() throws Exception {
		String nameOfDataset = "MessageClassificationProblem";
		
		List<Attribute> attributes = new ArrayList<Attribute>();// 创建的属性列表
		
		attributes.add(new Attribute("Message", (List<String>) null));// 添加属性以保存文本信息
		
		List<String> classValues = new ArrayList<String>();// 添加类别属性
		classValues.add("miss");
		classValues.add("hit");
		attributes.add(new Attribute("Class", classValues));
		
		m_Data = new Instances(nameOfDataset, (ArrayList<Attribute>) attributes, 100);// 创建初始容量为100的数据集
		
		m_Data.setClassIndex(m_Data.numAttributes() - 1);// 设置类别索引
	}
	
	/**
	 * 使用给定的训练文本信息更新模型
	 * @param message
	 * @param classValue
	 * @throws Exception
	 */
	public void updateData(String message, String classValue) throws Exception {
		Instance instance = makeInstance(message, m_Data);// 把文本信息转换为实例
		
		instance.setClassValue(classValue);// 为实例设置类别值
		
		m_Data.add(instance);// 添加实例到训练数据
		m_UpToData = false;
		
		System.err.println("更新模型成功!");
	}
	
	/**
	 * 分类给定的文本消息
	 * @param message
	 * @throws Exception
	 */
	public void classifyMessage(String message) throws Exception {
		if (m_Data.numInstances() == 0) {// 检查是否已构建分类器
			throw new Exception("无可用分类器!");
		}
		
		if (!m_UpToData) {// 检查分类器和过滤器是否为最新
			m_Filter.setInputFormat(m_Data);// 初始化过滤器,并告知输入格式
			
			Instances filteredData = Filter.useFilter(m_Data, m_Filter);// 从训练数据生成单词计数
			
			m_Classifier.buildClassifier(filteredData);// 重建分类器
			m_UpToData = true;
		}
		
		Instances testset = m_Data.stringFreeStructure();// 形成单独的小测试集,该文本信息不会添加到m_Data的字符串属性当中
		
		Instance instance = makeInstance(message, testset);// 使文本信息成为实例
		
		m_Filter.input(instance);// 过滤实例
		Instance filteredInstance = m_Filter.output();
		
		double predicted = m_Classifier.classifyInstance(filteredInstance);// 获取预测类别值的索引
		
		System.err.println("文本信息分类为:" + m_Data.classAttribute().value((int) predicted));
	}
	
	/**
	 * 将文本信息转换为实例的方法
	 * @param text
	 * @param data
	 * @return
	 */
	private Instance makeInstance(String text, Instances data) {
		Instance instance = new DenseInstance(2);// 创建一个属性数量为2,权重为1,全部值都为缺失的实例
		
		Attribute messageAtt = data.attribute("Message");// 设置文本信息属性的值
		instance.setValue(messageAtt, messageAtt.addStringValue(text));
		
		instance.setDataset(data);// 让实例能够访问数据集中的属性信息
		
		return instance;
	}
	
	/**
	 * 主方法
	 * 可以识别以下参数
	 * -E
	 * 文本是否为英文。默认为中文,省略该参数
	 * -m 文本信息文件
	 * 指向一个文件,其中包含待分类的文本信息,或用于更新模型的文本信息
	 * -c 类别标签
	 * 如果要更新模型,使用本参数输入文本信息的类别标签。省略表示需要对该文本进行分类
	 * -t 模型文件
	 * 包含模型的文件。如果不存在则自动创建。
	 * @param options 命令行选项
	 */
	public static void main(String[] options) {
		try {
			String messageName = Utils.getOption('m', options);// 读入文本信息文件,存储为字符串
			if (messageName.length() == 0) {
				throw new Exception("必须提供文本信息文件的名称!");
			}
			FileReader m = new FileReader(messageName);
			StringBuffer message = new StringBuffer();
			int l;
			while ((l = m.read()) != -1) {
				message.append((char) l);
			}
			m.close();
			
			boolean isEnglish = Utils.getFlag('E', options);// 检查文本是否为英文
			if (!isEnglish) {// 只有汉字需要进行中午分词
				Analyzer ikAnalyzer = new IKAnalyzer();
				Reader reader = new StringReader(message.toString());
				TokenStream stream = (TokenStream) ikAnalyzer.tokenStream("", reader);
				CharTermAttribute termAtt = (CharTermAttribute) stream.addAttribute(CharTermAttribute.class);
				message = new StringBuffer();
				while (stream.incrementToken()) {
					message.append(termAtt.toString() + " ");
				}
			}
			
			String classValue = Utils.getOption('c', options);// 检查是否已给定类别值
			
			String modelName = Utils.getOption('t', options);// 如果模型文件存在,则读入,否则创建新的模型文件
			if (modelName.length() == 0) {
				throw new Exception("必须提供模型文件的名称!");
			}
			MessageClassifier messageCl;
			try {
				ObjectInputStream modelInObjectFile = new ObjectInputStream(new FileInputStream(modelName));
				messageCl = (MessageClassifier) modelInObjectFile.readObject();
				modelInObjectFile.close();
			} catch (FileNotFoundException e) {
				messageCl = new MessageClassifier();
			}
			
			if (classValue.length() != 0) {
				messageCl.updateData(message.toString(), classValue);
			} else {
				messageCl.classifyMessage(message.toString());
			}
			
			ObjectOutputStream modelOutObjectFile = new ObjectOutputStream(new FileOutputStream(modelName));
			modelOutObjectFile.writeObject(messageCl);
			modelOutObjectFile.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 代码编译无错误

接下来就是运行的时候啦~~

在Run Configuration下对Arguement进行设置,填入MessageClassifier -m F:\tc-corpus-answer\answer\C5-Education\C5-Education001.txt -c miss -t messageclassifier.model,手工修改目录对模型进行训练(也可以采用自动化训练,这里为了节省时间只使用了几个文档进行训练),成功后有红色的“更新模型成功!”

完成对模型的训练后,接下来进行测试,在上述位置填入MessageClassifier -m F:\tc-corpus-answer\answer\C5-Education\C5-Education016.txt -t messageclassifier.model,我们可以看到成功分类为miss

程序的效率并不高,仅做练习使用,不建议在大的工程项目当中使用~ 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值