基于Kubernetes、Docker的机器学习微服务系统设计 | |||||
---|---|---|---|---|---|
实践篇 | (1)概念与构想 | (二)架构与部署 | (三)微服务框架 | (四)中文分词 | (五)预处理 |
(六)特征选择 | (七)分类器微 | (八)部署配置 | (九)应用服务 | (十)数据可视化 | |
研究篇 | RS中文分词 | MP特征选择 | NLV文本分类 | 快速kNN | 文本分类 |
中文分词微服务包括分词方法有:RobinSeg(RS)、IKAnalyzer(IK)、JEAnalysis(JE)、MmSeg4j(MS)、PaoDing(PD)、SmallSeg4j(SS)。其中RS分词实现见我的文章:知更鸟中文分词RS设计实现 ,其他分词方法都采用发布的jar包进行封装装。
设计模式
主要涉及外观模式、适配器模式、工厂模式和单例模式。分词微服务类图如图所示:

设计原则:(1)针对接口编程,不要针对实现;(2)只和最紧密的类交互;(3)封装变化;(4)松耦合设计。
外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。我们采用统一的分词外观类封装各种分词接口,提供一个一致的高层接口。
适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。各种分词的的私有实现接口需要一个提供一个统一的接口调用。
工厂模式:定义一个创建对象的接口,但有子类决定要实例化的类是哪一个。提供统一的分词工厂,创建分类实例对象。
单例模式:确保一个类只有一个实例,并提供了一个全局访问点。由于各种分词对象的创建、加载词典等需要申请大量的内存,耗费大量的时间,所以所分词器实例都通过适配器进行控制只创建一个实例。
代码实现
中文分词接口抽象类
package com.robin.segment;
import com.robin.log.RobinLogger;
import java.util.logging.Logger;
/**
* <DT><B>描述:</B></DT>
* <DD>中文分词接口抽象类</DD>
*
* @version Version1.0
* @author Robin
* @version <I> Date:2018-04-18</I>
* @author <I> E-mail:xsd-jj@163.com</I>
*/
public abstract class AbstractSegmenter {
/** 日志 */
protected static final Logger LOGGER = RobinLogger.getLogger();
/**
* 分词抽象方法
*
* @param text 文本
* @param SEPARATOR 分隔符
* @return 已分词文本
*/
public abstract String segment(String text, String SEPARATOR);
}
统一分词器外观类
package com.robin.segment;
import com.robin.log.RobinLogger;
import com.robin.segment.SegmentFactory.SegmentMethod;
import com.robin.segment.robinseg.RobinSeg;
import com.robin.segment.robinseg.SegmentArgs;
import java.util.logging.Logger;
/**
* <DT><B>描述:</B></DT>
* <DD>统一分词器外观类</DD>
* <DD>外观模式</DD>
*
* @version 1.0
* @author Robin
* @version <I> Date:2018-04-19</I>
* @author <I> E-mail:xsd-jj@163.com</I>
*/
public class SegmentFacade {
// 日志
private static final Logger LOGGER = RobinLogger.getLogger();
/**
* 获取分词器配置参数对象
*
* @param methodName 分词方法
* @return SegmentArgs
*/
public static SegmentArgs getSegmentArgsObj(SegmentMethod methodName) {
AbstractSegmenter segment = SegmentFactory.getSegInstance(methodName);
if (methodName.equals(SegmentMethod.RS)) {
return ((RobinSeg) segment).getSegmentConfInstance();
}
return null;
}
/**
* <DD>根据不同分词算法进行分词,</DD>
* <DD>传入算法名错误或默认情况下用RobinSeg分词。</DD>
*
* @param methodName 分词方法名称,“SegmentMethod.IK”,“.JE”,“.MS”,“.PD”,“.SS”,
* “.RS”
* @param text 待分词文本
* @param separator 分隔符
* @return 使用分隔符分好词文本
*/
public static String split(SegmentMethod methodName, String text, String separator) {
AbstractSegmenter segmenter = SegmentFactory.getSegInstance(methodName);
return segmenter.segment(text, separator);
}
}
分词Action实现类
package com.robin.segment.action;
import com.robin.loader.MircoServiceAction;
import com.robin.log.RobinLogger;
import com.robin.segment.SegmentFacade;
import com.robin.segment.SegmentFactory.SegmentMethod;
import com.robin.segment.robinseg.SegmentArgs;
import com.robin.segment.robinseg.SegmentArgs.SegAlgorithm;
import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
* <DT><B>描述:</B></DT>
* <DD>分词Action实现类</DD>
*
* @version Version1.0
* @author Robin
* @version <I> V1.0 Date:2018-06-05</I>
* @author <I> E-mail:xsd-jj@163.com</I>
*/
public class SegmentAction implements MircoServiceAction {
private static final Logger LOGGER = RobinLogger.getLogger();
public enum StatusCode {
OK,
JSON_ERR,
KIND_ERR,
VERSION_ERR,
SEGMETHOD_ERR,
SEPARATOR_ERR,
SEGMENT_FAILED,
TEXTS_NULL,
}