学习中文分词最好的方法就是边实践边学习,特别是基于统计的分词方法需要较强的数学知识和抽象概念,通过实践可以帮助读者更好地理解统计分词算法。本篇主要讨论了如何利用Java语言构建一个中文分词程序,以及所需要的知识和技能。通过本篇的学习,可以达成如下目标。
● 掌握构建中文分词程序的过程和方法
● 初步认识语料库
1、开发中文分词WEB服务的目的
开发中文分词WEB服务,有这么几个目的:(1)便于读者在学习过程中了解整个分词的开发过程,不仅是学习算法,还要掌握分词的开发流程及架构设计,以及如何对外提供中文分词服务;(2)在学习过程中,利用浏览器可以对算法进行评测,随时切换分词算法,查看不同算法的分词效果及所有时间;(3)有条件的情况下,可以在腾讯云、阿里云等云服务厂商购买有较大优惠的云服务器,将中文分词程序部署到云端,允许他人通过浏览器使用你的中文分词服务,提高自己的学习兴趣。
2、开发中文分词WEB服务所需要的技能和知识
在编程知识方面。中文分词WEB服务基于Java Web开发,读者需要掌握Java编程和Java Web开发知识。对于没有掌握Java Web开发知识的读者来说。需要先学习Java Web的基础知识,包括Spring MVC框架、Tomcat服务的部署、简单的JSP页面编程等相关知识。
在数学知识方面,基于统计的分词算法涉及到概率统计、数学建模、神经网络等相关数学知识。课程会对项目用到的数学知识进行深入讨论。也建议读者提前了解这些数学知识,知识储备更有利于对中文分词算法,特别是基于统计分词算法的了解和掌握。
在语料库方面,需要了解语料库的相关知识。语料库中存放的是在语言的实际使用中真实出现过的语言材料,语料库一般是通过人工借助于计算机整理完成的。中文分词的语料库主要有分词词表和词语频率表。分词词表包含了词名、词类名称、词类标记等属性;词语频率表包含了词在统计的所有文章中出现的次数、出现频率、累计频率等属性。也可以把分词词表和频率表合成一个表。下图是现代汉语语料库字频表,摘自国家语委现代汉语语料库。

图1 现代汉语语料库字频表
3、中文分词WEB服务接口
基于WebService对外提供WEB服务接口,第三方应用系统调用WebService接口可以使用本项目提供的中文分词服务。
接口名称:SegService
接口参数:
① 待分词文本
② 分词模式
接口调用示例
SegService(“中文分词是让机器理解汉语言的重要环节,分词技术被广泛应用到机器翻译、文本相似度分析、搜索引擎等所有与语言处理相关的人工智能系统中。本课程结合基于Java的FNLP自然语言处理库和基于Python的jieba分词库,分别以Java语言和Python语言阐述中文分词的实现原理与技术”,0)
返回处理结果
中文/n 分词/v 是/vl 让/p 机器/n 理解/v 汉/n 语言/n 的/u 重要/a 环节/n ,/w 分词/v 技术/n 被/p 广泛/a 应用/v 到/v 机器翻译/v 、/w 文本/n 相似/v 度/n 分析/v 、/w 搜索引擎/n 等/v 所有/a 与/c 语言/n 处理/v 相关/v 的/u 人工智能/n 系统/n 中/nd 。/w 本/n 课程/n 结合/v 基于/p Java/ws 的/u FNLP/ws 自然/d 语言/n 处理/v 库/n 和/c 基于/p Python/ws 的/u jieba/ws 分词/v 库/n ,/w 分别/v 以/p Java/ws 语言/n 和/c Python/ws 语言/n 阐述/v 中文/n 分词/v 的/u 实现/v 原理/n 与/c 技术/n 。/w
4、分词接口设计

图2 接口设计类图
SegmentInterface接口提供了唯一的分词方法。AbstractDic(基于词典方法分词)是抽象类并实现SegmentInterface接口,同时依赖于Dictionary(词典处理类)读取词典。AbstractStatistics(基于统计方法分词)是抽象类并实现SegmentInterface接口,同时依赖于Model(分词模型处理)。SegService对外提供服务,依赖于DicAlgorithm类和StaAlgorithm类。
5、搭建Spring MVC项目
启动eclipse,建立Java Web项目,项目名称为DaShou(搭手,帮忙的意思)。将Spring框架的Jar包文件文件复制到项目WEB-INFO目录下的lib目录。Spring框架依赖于Apache Commons Logging,因此需要下载Apache Commons Logging库,并将Jar包文件文件复制到项目WEB-INFO目录下的lib目录。
建立相关配置文件,如下图所示。

图3 Spring框架的配置文件
log4j.properties文件
#\u5C06ibatis log4j\u8FD0\u884C\u7EA7\u522B\u8C03\u5230DEBUG\u53EF\u4EE5\u5728\u63A7\u5236\u53F0\u6253\u5370\u51FAibatis\u8FD0\u884C\u7684sql\u8BED\u53E5
log4j.rootLogger=DEBUG,stdout,R
### \u628A\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u5230\u63A7\u5236\u53F0 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
### \u628A\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u5230\u6587\u4EF6\uFF1Ajbit.log ###
#log4j.appender.logfile=org.apache.log4j.FileAppender
#log4j.appender.logfile.File=D:/test.log
#log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
#log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n
#log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:/logs/pm.log
log4j.appender.R.MaxFileSize=1MB
log4j.appender.R.MaxBackupIndex=30
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[HL] %p %t %c - %m%n
log4j.appender.R.DatePattern='.'yyyy-MM-dd'.log'
###\u663E\u793ASQL\u8BED\u53E5\u90E8\u5206
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
###????????°Struts?????ˉ
log4j.logger.com.opensymphony.xwork2=ERROR
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%nconfiguration.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <import resource="spring_ws.xml"/> </beans>
spring_ws.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> </beans>
spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <context:annotation-config /> <context:component-scan base-package="com"></context:component-scan> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=""></bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8"/> <!-- 最大内存大小 --> <property name="maxInMemorySize" value="10240"/> <!-- 最大文件大小,-1为不限制大小 --> <property name="maxUploadSize" value="-1"/> </bean> <mvc:annotation-driven></mvc:annotation-driven> </beans>
修改web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>DaShou</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:/config/properties/log4j.properties</param-value> </context-param> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>6000</param-value> </context-param> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <context-param> <param-name>webAppRootKey</param-name> <param-value>prog.root</param-value> </context-param> <listener> <listener-class> org.springframework.web.util.WebAppRootListener </listener-class> </listener> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:\config\spring_config\spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:\config\spring_config\configuration.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <error-page> <error-code>404</error-code> <location>/jsp/main/error.jsp</location> </error-page> <session-config> <session-timeout>30</session-timeout> </session-config> <context-param> <param-name>spring.profiles.active</param-name> <param-value>dev</param-value> </context-param> <context-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </context-param> <context-param> <param-name>spring.liveBeansView.mbeanDomain</param-name> <param-value>dev</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> </web-app>
6、搭手项目界面

图4 搭手中文分词界面
搭手中文分词可以选择不同分词方法和算法,可以比较算法的优劣。在分词过程中,给出分词所用的时间及分词过程描述。
■ 课程小结
语料库一般是通过人工借助于计算机整理完成的。中文分词的语料库主要有分词词表和词语频率表。分词词表包含了词名、词类名称、词类标记等属性;词语频率表包含了词在统计的所有文章中出现的次数、出现频率、累计频率等属性。
学习中文分词之前需要掌握一定的知识和技能。本课程主要以Java语言为主,仅在算法描述上会讨论Python语言。因此需要读者掌握Java和Web编程技能。同时也需要对概率统计、数学建模、神经网络等相关数学知识提前了解。