因为比较熟悉java相关工程,所以选用的NLP库是HanLP(其它的NLP库其实也可以用java调用),而现代java的工程基本都用kotlin语言,不仅可以和java类库无缝集成而且具备语言级别的类型安全,是新项目的不二选择。
工程搭建
1. 生成空工程
现代的java工程一般有2种组织方式:gradle和maven。这里选gradle,gradle是以.gradle
文件管理工程的脚本文件,其实是用了一种叫做groovy
的脚本语言写成,.gradle文件之于groovy如同.sh文件之于bash,groovy
是一种编译成JVM字节码的语言,也就是说groovy
也可以和java无缝集成,非常强大也非常方便。
先安装gradle,然后再用gradle的命令生成java工程:
$ wget https://mirrors.cloud.tencent.com/gradle/gradle-7.1-bin.zip
$ unzip gradle-7.1-bin.zip -d /your/gradle/path
$ export PATH=$PATH:/your/gradle/path/gradle-7.1/bin
$ gradle --version
------------------------------------------------------------
Gradle 7.1
------------------------------------------------------------
Build time: 2021-06-14 14:47:26 UTC
Revision: 989ccc9952b140ee6ab88870e8a12f1b2998369e
Kotlin: 1.4.31
Groovy: 3.0.7
Ant: Apache Ant(TM) version 1.10.9 compiled on September 27 2020
JVM: 11.0.10 (JetBrains s.r.o. 11.0.10+0-b96-7249189)
OS: Linux 5.11.22-100.fc32.x86_64 amd64
$ mkdir nlp-demo && cd nlp-demo && gradle init
Select type of project to generate:
复制代码
gradle init
就是生成工程的命令,需要按提示输入工程的类型,我们这里依次选2: application
-> 4: Kotlin
-> 1: no - only one application project
-> 1: Groovy
,最后就可生成工程目录结构了。
1.1 修改下载地址
修改gradle/wrapper/gradle-wrapper.properties
中的distributionUrl
字段:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
复制代码
修改app/build.gradle
中的mavenCentral()
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
}
复制代码
表示我们从国内的maven仓库去下载各种依赖jar包,这样IDE能够比较快的下载各种文件, 最后就可以用JetBrain打开了。
2. 引入nlp的类库包
当前HanLP的最新版本为1.8.3,在app/build.gradle
中:
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
+ implementation 'com.hankcs:hanlp:portable-1.8.3'
复制代码
在app/src/main/kotlin/hanlp/App.kt
中:
package hanlp
+import com.hankcs.hanlp.HanLP
+
class App {
val greeting: String
get() {
@@ -12,4 +11,8 @@ class App {
fun main() {
println(App().greeting)
+ val text = "安装工作"
+ val terms = HanLP.segment(text)
+
+ println(terms)
}
复制代码
HanLP集成完成! 的确非常方便简单了。
3. 运行配置
一般的,在IDE的任务栏有如下的配置显示,点击绿色三角就可以运行并输出结果了,然而我这里不知为何竟然不好使?! 不确定是不是因为我使用的是Android Studio的缘故,但这个问题是好解决的。
点击右边栏的gradle标签,在弹出窗里点击大象图标,再输入gradle run
并确定:
最后任务栏变成如下配置,就可以点击运行了:
以上操作都可以直接在命令行里运行: gradle run
就可以,但是设置好运行配置在开发时方便一点。
工程配置可简单可复杂,有时对刚接触的人来说非常不友好,千万不要在这种地方浪费时间。现在运行基本没有问题了。
一般的nlp任务,如基本分词之类的已经可以直接运行了。如仿照demo_multi_thread.py写的多线程示例:
val sentences = listOf(
"王国强、高峰、汪洋、张朝阳光着头、韩寒、小四",
)
val threadsCount = Runtime.getRuntime().availableProcessors()
val executor = Executors.newFixedThreadPool(threadsCount)
sentences.map {
executor.submit(Callable<List<Term>> {
HanLP.segment(it)
})
}.map {
it.get()
}.forEach {
println(it)
}
executor.shutdown()
复制代码
数据加载
但是运行NLPTokenizer示例会报错,找不到文件,原来这里要用到训练数据,我们没有按照已有的格式配置数据文件的路径。一般地,需要设置一个自定义的HanLP.Config.IOAdapter
,网上有很多示例了,这里演示一个完全自定义的方式:直接向对象的构造函数传入路径参数,看源码非常容易掌握。
val analyzer = PerceptronLexicalAnalyzer("_data/model/perceptron/large/cws.bin",
"_data/model/perceptron/pku1998/pos.bin",
"_data/model/perceptron/pku1998/ner.bin")
val t1 = "我新造一个词叫幻想乡你能识别并正确标注词性吗?"
println(analyzer.segment(t1))
val t2 = "我的希望是希望张晚霞的背影被晚霞映红"
println(analyzer.segment(t2))
val t3 = "公司於1975年由比爾·蓋茲和保羅·艾倫創立。"
println(analyzer.segment(t3))
复制代码
NLPTokenizer
实质是生成了一个PerceptronLexicalAnalyzer
对象,我们只需传入正确的路径即可。
这里有一个需要注意的点:路径不可以data
打头,否则会被库修改成绝对路径。
这样的话就可以在代码中自行传入相对路径,让数据随着代码一起变更,数据文件自行下载即可。程序运行起来的根目录是工程目录下的app
目录,即本地的完整数据文件路径是: $RROJECT_ROOT/app/_data/model/perceptron/large/cws.bin
build.gradle
settings.gradle
gradle/
app/
build.gradle
src/main/kotlin/
_data/
复制代码
大功告成!