自然语言处理与Java语言实现
上QQ阅读APP看书,第一时间看更新

1.1 开发环境准备

由于Java语言可读性好,所以本书采用Java来介绍自然语言处理的开发。Java的开发环境Eclipse也是使用Java语言开发的,所以需要先准备基本的JDK,然后准备运行在JDK上的Eclipse。

当前可以使用的最新版本是JDK 12。JDK 12可以从Java的官方网站上下载得到,使用默认方式安装即可,然后导入Eclipse中。本书中的程序通过本书给出的下载方法都可以找到。Eclipse支持多种操作系统,例如,如果使用的是苹果电脑Mac系统,就下载Eclipse for Mac OS X。

如果需要用Web界面做演示,还要下载Tomcat,可以从Tomcat官网上下载,推荐使用Tomcat 7以上的版本。

如果要构建源代码工程,可以使用工具Ant和Maven。Ant与Maven都和项目管理软件make类似。虽然Maven正在逐步替代Ant,但当前仍然有很多开源项目在继续使用Ant。从Ant官网上可以下载到Ant的最新版本。

在Windows下ant.bat和3个环境变量相关:ANT_HOME、CLASSPATH和JAVA_HOME。ANT_HOME和JAVA_HOME环境变量需要用路径设置,并且路径不要以“\”或“/”结束;不要设置CLASSPATH。

使用echo命令检查ANT_HOME环境变量:

>echo %ANT_HOME%
D:\apache-ant-1.7.1

如果把Ant解压到C:\apache-ant-1.7.1,则修改环境变量PATH,增加当前路径C:\apache-ant-1.7.1\bin。

如果一个项目源代码的根路径包括一个build.xml文件,则说明这个项目可能是用Ant构建的。大部分用Ant构建的项目只需要如下命令:

#ant

在Eclipse中,可以根据项目源代码自动生成build.xml文件,方法是:选定指定Java项目,右键单击菜单的“导出”选项,选择导出“Ant Build文件”。

可以从Maven官网上下载最新版本的Maven,当前版本是maven-3.3.9。解压下载的Maven压缩文件到C:根路径,将创建一个路径C:\apache-maven-3.3.9。修改Windows系统环境变量PATH,增加当前路径C:\apache-maven-3.3.9\bin。如果一个项目源代码的根路径包括一个pom.xml文件,则说明这个项目可能是用Maven构建的。大部分用Maven构建的项目只需要如下命令:

#mvn clean install

盖大楼的时候需要搭建最终不会交付使用的脚手架。与此类似,很多单元测试代码也不会在正式环境中运行,但是必须要有。通常可以使用JUnit做单元测试。

1.1.1 Windows命令行cmd

假设有一个标准件工厂,在车间生产产品,在工地使用这些产品。在集成开发环境中开发软件与此类似。如果在Windows操作系统中运行开发的软件,则往往通过Windows命令行来运行。

在图形化用户界面出现之前,人们就是用命令行来操作计算机的。Windows命令行是通过Windows系统目录下的cmd.exe执行的。执行这个程序最直接的方式是找到这个程序,然后双击。但cmd.exe并没有一个桌面快捷方式,所以这样使用太麻烦。

还可以在开始菜单的运行窗口直接输入程序名,回车后运行这个程序。具体步骤为单击“开始”→“运行”按钮,这样就会打开资源管理器中的运行程序窗口;或者使用窗口键+R组合键,打开运行程序窗口。然后,输入程序名cmd后单击“确定”按钮,就会出现命令提示窗口。因为能够通过这个黑色的窗口直接输入命令来控制计算机,所以这个窗口也称为控制台窗口。在计算机里,把那套直接连接在计算机上的键盘和显示器叫作控制台(Console)。

通常用扩展名表示文件的类别,例如,exe表示可执行文件。完整的文件名称由文件名和扩展名组成。文件名和扩展名之间由点分隔,例如,java.exe。

当我们建立或修改一个文件时,必须向Windows指明这个文件的位置。文件的位置由3部分组成:驱动器、文件所在路径和文件名。路径是由一系列路径名组成的,这些路径名之间用“\”分开,例如,C:\Program Files\Java\jdk1.8.0_03\bin\java.exe。

开始的路径往往是C:\Users\Administrator。正如公园的地图上往往会标出游客的当前位置,Windows命令行也有个当前目录的概念,这个C:\Users\Administrator就是当前路径。

可以用cd命令改变当前路径,例如将路径改变为C:\Program Files\Java\ jdk1.8.0_03路径:

C:\Users\Administrator>cd C:\Program Files\Java\jdk1.8.0_03

切换盘符不能使用cd命令,而是直接输入盘符的名称。例如想要切换到D盘,可以使用如下命令:

C:\Users\Administrator>d:

系统约定从指定的路径找可执行文件,这个路径通过PATH环境变量指定。环境变量是一个“变量名=变量值”的对应关系,每一个变量都有一个或者多个值与之对应。如果是多个值,则这些值之间用分号分开。例如PATH环境变量可能对应这样的值:“C:\Windows\system32;C:\Windows”,这表示Windows会从C:\Windows\system32和C:\Windows两个路径找可执行文件。

设置或者修改环境变量的具体操作步骤是:首先在资源管理器中右键单击“这台电脑”,在弹出的快捷菜单中选择“属性”菜单项,在弹出的窗口中选择“高级”→“环境变量”选项;然后在弹出的环境变量设置窗口中设置用户变量,或者系统变量;再设置环境变量PATH的值。

需要重新启动命令行才能让环境变量设置生效。为了检查环境变量是否设置正确,可以在命令行中显示指定环境变量的值,这需要用到echo命令。echo命令用来显示一段文字:

C:\Users\Administrator>echo Hello

执行上面的命令将在命令行输出:Hello。

如果要引用环境变量的值,可以前后各用一个“%”把变量名包围起来,如“%变量名%”。使用echo命令来显示环境变量PATH中的值:

C:\Users\Administrator>echo %PATH%

1.1.2 在Windows下使用Java

本小节首先介绍安装JDK,然后介绍如何在命令行中开发Java程序。Java开发环境简称JDK(Java Development Kit)。JDK包括Java运行环境(Java Runtime Envirnment)、Java工具和Java基础类库。可以从Java官方网站上下载得到JDK,注意不是JVM(Java Virtual Machine,Java虚拟机)。

进入官网后,选择下载Java SE,也就是Java标准版本。Latest Release就是最新发布的安装程序。完整的JDK版本号中包括大版本号和小版本号。例如1.7.0的大版本号是7,小版本号是0;而1.8.22的大版本号是8,小版本号是22。因为可以在Windows或Linux等多种操作系统环境下开发Java程序,所以有多个操作系统的JDK版本可供选择。

因为JDK是有版权的,所以需要接受许可协议(Accept License Agreement)后才能下载。如果在Windows下开发,就选择Windows x86。这样会下载类似jdk-8u121-windows-i586.exe这样的文件。下载完毕后,使用默认方式安装JDK即可。

JDK相关的文件都放在一个叫作JAVA_HOME的根目录下。JDK根目录的命名格式是C:\Program Files\Java\jdk1.8.0_<version>。最后以一个数字类型的版本号结尾,如10或者21等。

因为在一台计算机上可以安装多个JDK和JVM,为了避免混乱,可以新增环境变量JAVA_HOME,指定一个默认使用的JDK。

使用echo命令检查环境变量JAVA_HOME:

>echo %JAVA_HOME%
C:\Program Files\Java\jdk1.8.0_10

Eclipse这样的集成开发环境只需要JAVA_HOME这一个环境变量。为了检查JAVA_HOME是否正确设置,使用如下命令,如果能显示虚拟机的版本号就表示可以了。

>"%JAVA_HOME%"\bin\java -version
java version "1.8.0_10-rc"
Java(TM) SE Runtime Environment (build 1.8.0_10-rc-b28)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)

如果还需要在Windows控制台下执行Java程序,则需要访问编译源代码的javac.exe或者执行class文件字节码的java.exe。环境变量PATH指定了从哪里找java.exe这样的可执行文件。可以通过多个路径查找可执行文件,这些路径以分号隔开。如果想在命令行运行Java程序,还可以修改已有的环境变量PATH,增加Java程序所在的路径。例如,C:\Program Files\Java\jdk1.8.0_10\bin。

然后检查环境变量PATH:

>echo %PATH%

如果在任何路径下输入javac命令都能显示javac的用法,则说明PATH已经设置正确。也可以用一个Java程序试验一下。

新建一个Java项目后,在这个项目的src路径下新建一个叫作NLP的Java类,代码如下:

public class NLP {
      public static void main (String args[]) {
                System.out.println("Hello nlp!");
      }
}

运行下述代码:

>javac NLP.java
>java NLP

看运行结果是否显示“Hello nlp!”。

最简单的,可以使用javac构建出class文件。对于复杂的项目,往往使用工具构建项目源代码。Gradle就是一个可用于构建Java项目的工具。例如,自然语言处理软件包CoreNLP就支持使用Gradle构建。可以在Gradle官网下载二进制文件来安装Gradle。

Windows上自动设置Gradle环境变量的脚本如下:

set input=F:\soft\gradle-3.5
echo gradle 路径为%input%
set gradlePath=%input%
::创建GRADLE _HOME
wmic   ENVIRONMENT     create
name="GRADLE_HOME",username="<system>",VariableValue="%javaPath%"
call set xx=%Path%;%gradlePath%\bin
::echo %xx%
::将环境变量中的字符串重新赋值到path中
wmic ENVIRONMENT where "name='Path' and username='<system>'" set VariableValue="%xx%"
pause

打开控制台并运行gradle -v命令显示版本来验证安装,例如:

C:\Users\Administrator>gradle -v

显示类似如下的输出则表示安装正确:

------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Build time:   2017-04-10 13:37:25 UTC
Revision:     b762622a185d59ce0cfc9cbc6ab5dd22469e18a6
Groovy:       2.4.10
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_121 (Oracle Corporation 25.121-b13)
OS:           Windows Server 2008 6.0 x86

可以在Gradle构建中使用标准和定制的Ant任务,就像在Ant本身中使用的那样。另外,可以导入现有的Ant脚本。就像这样简单:

ant.importBuild 'build.xml'

Gradle本地存储库(Gradle Cache Location)是Gradle维护其缓存的位置,其中包括Gradle在构建任何项目时从存储库下载的所有依赖项,以便在下次重新运行构建时重用。

在Windows下,Gradle本地存储库的默认路径是C:/Users/Administrator/.gradle。可以通过设置环境变量GRADLE_USER_HOME将Gradle本地存储库更改为其他目录。

1.1.3 Linux终端

虽然使用Linux操作系统办公并不多见,但是很多自然语言处理应用是运行在Linux操作系统下的。往往通过SSH客户端软件连接到远程的Linux服务器。SSH通常作为大多数Linux发行版上易于安装的软件包提供,可以尝试使用ssh localhost来测试它是否正在运行。

如果有现成的Linux服务器可用,可以使用支持SSH协议的终端仿真程序SecureCRT来连接远程Linux服务器,因为可以保存登录信息,保证登录安全,所以比较方便。除了SecureCRT,还可以使用开源软件PuTTY,或者保存登录密码的KiTTY。如果用root账户登录,则终端提示符是#,否则终端提示符是$。

就像小袋鼠在袋鼠妈妈的袋子里长大,使用VMware,则Linux可以运行在Windows系统下。VMware让Linux运行在虚拟机中,而且不会破坏原来的Windows操作系统。

首先要准备好VMware,当然仍然需要Linux光盘文件。Linux也有很多种版本,例如RedHat、Ubuntu和SUSE等。这里选择CentOS。

也可以在Windows系统下安装Cygwin,使用它来练习Linux常用命令。

如果需要安装软件,可以下载RPM安装包,然后使用RPM安装。但找到操作系统对应的RPM安装包往往比较麻烦。一个软件包可能依赖其他软件包。为了安装一个软件,可能需要下载它所依赖的软件包。

为了简化安装操作,可以使用黄狗升级管理器(Yellow dog Updater Modified,Yum)。Yum会自动计算出程序之间的关联性,并且计算出完成软件包的安装需要哪些步骤。这样在安装软件时,就不会再被那些关联性问题所困扰了。

Yum软件包管理器会自动从网络下载并安装软件。Yum有点类似360软件管家,但是不会有商业倾向的推销软件。例如安装支持wget和rzsz命令的软件:

#yum install wget
#yum install lrzsz

可以使用Nodepad++自带的插件NppFTP编辑Linux系统下的文件。为了方便在服务器端管理和开发自然语言处理相关的应用,可以采用Micro这样的终端文本编辑器。

可以使用DNF安装Micro。为了安装DNF,必须先安装并启用epel-release依赖。使用Yum安装epel-release的命令如下:

# yum install epel-release

如果没有DNF安装工具软件,也可以直接安装Micro的预编译版本。使用wget下载Micro:

#wget https://github.com/zyedidia/micro/releases/download/nightly/micro-1.3.4-67-
linux64.tar.gz

和Windows不同,Linux操作系统下的路径名之间用“/”分开。./micro-1.3.4-67-linux64.tar.gz表示当前路径下的micro-1.3.4-67-linux64.tar.gz文件。使用如下命令解压缩当前路径下的micro-1.3.467-linux64.tar.gz文件:

#tar -xf./micro-1.3.4-67-linux64.tar.gz

编辑/etc/profile配置文件,增加micro所在的路径到PATH环境变量/home/soft/micro-1.3.4-67:

#./micro /etc/profile

增加如下行:

export PATH=/home/soft/micro-1.3.4-67:$PATH

可以使用Micro编辑配置文件:

#micro /etc/security/limits.conf

保存文件后,按Ctrl+Q组合键退出。

1.1.4 在Linux下使用Java

首先安装JDK,然后来看如何在Linux终端开发Java程序。使用wget下载JDK安装包:

#wget -c --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.
oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.
rpm

使用RPM安装,命令如下:

# rpm -i./jdk-8u131-linux-x64.rpm

验证Java安装,输入如下命令:

#java –version

如果安装成功,则输出如下:

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

为了自动构建Java源代码,需要安装Maven,首先下载Maven安装文件:

# wget
 http://mirrors.shuosc.org/apache/maven/maven-3/3.5.2/binaries/apache-maven-
3.5.2-bin.tar.gz

然后解压缩安装文件:

# tar -xzf apache-maven-3.5.2-bin.tar.gz

把安装路径改成/usr/local/apache-maven:

# mv apache-maven-3.5.2 /usr/local/apache-maven

修改配置文件/etc/profile设定变量MAVEN_HOME的值,并把Maven所在的路径加入PATH变量,也就是增加如下行:

export MAVEN_HOME=/usr/local/apache-maven
export PATH=$MAVEN_HOME/bin:$PATH

安装Gradle,首先下载安装文件gradle-3.5-bin.zip:

# wget https://services.gradle.org/distributions/gradle-3.5-bin.zip

创建Gradle软件存放的路径:

# mkdir /opt/gradle

解压缩gradle-3.5-bin.zip到/opt/gradle目录:

# unzip -d /opt/gradle gradle-3.5-bin.zip

检查解压缩出来的文件:

# ls /opt/gradle/gradle-3.5
LICENSE NOTICE bin getting-started.html init.d lib media

把Gradle所在的路径加入PATH变量:

export PATH=$PATH:/opt/gradle/gradle-3.5/bin

在Linux终端输入命令验证安装:

# gradle –v

在Linux下也可以使用Bazel构建Java项目,首先,在Linux下安装Bazel:

yum install -y bazel

BUILD文件包含Bazel的几种不同类型的指令。最重要的类型是构建规则,它告诉Bazel如何构建所需的输出,例如可执行的二进制文件或库。BUILD文件中构建规则的每个实例都称为目标,并指向一组特定的源文件和依赖项。目标也可以指向其他目标。

看看java-tutorial / BUILD文件:

java_binary(
     name = "ProjectRunner",
     srcs = glob(["src/main/java/com/example.java"]),
)

在上面的示例中,ProjectRunner目标实例化Bazel的内置java_binary规则。规则告诉Bazel构建一个.jar文件和一个包装器shell脚本(都以目标命名)。

目标中的属性显式声明其依赖项和选项。虽然name属性是必需的,但许多选项是可选的。例如,在ProjectRunner规则目标中,name是目标的名称,srcs指定Bazel用于构建目标的源文件,main_class指定包含main方法的类。(读者可能已经注意到我们的示例使用glob将一组源文件传递给Bazel,而不是逐个列出它们。)

下面我们构建示例项目,转到java-tutorial目录并运行以下命令:

bazel build //:ProjectRunner

注意目标标签 -//部分是我们的BUILD文件相对于工作区根目录的位置(在本例中是根目录本身),而ProjectRunner是我们在BUILD文件中给目标起的名字。

Bazel产生的输出类似于以下内容:

INFO: Analysed target //:ProjectRunner (15 packages loaded, 476 targets configured).
INFO: Found 1 target...

Target //:ProjectRunner up-to-date:
   bazel-bin/ProjectRunner.jar
   bazel-bin/ProjectRunner
INFO: Elapsed time: 230.242s, Critical Path: 89.34s, Remote (0.00% of the time):
 [queue: 0.00%, setup: 0.00%, process: 0.00%]
INFO: 3 processes: 2 processwrapper-sandbox, 1 worker.
INFO: Build completed successfully, 7 total actions

恭喜你,你刚刚建立了你的第一个Bazel目标!Bazel将构建输出放在工作区根部的bazel-bin目录中。浏览其内容以了解Bazel的输出结构。

现在测试新构建的二进制文件:

# bazel-bin/ProjectRunner
Hi!

1.1.5 Eclipse集成开发环境

就好像做实验有专门的试验台,开发软件也有专门的集成开发环境。开发Java程序最流行的开发环境叫作Eclipse。

Eclipse也有很多版本,可以选择最简单的一个版本Eclipse IDE for Java Developers。Eclipse是绿色软件,无须安装,解压后就可以直接使用。在Windows下,双击后就可以解压文件。如果需要专门的解压软件,推荐使用7z。

Eclipse默认是英文界面,如果习惯用中文界面,可以从Eclipse官网上下载支持中文的语言包。

Eclipse按项目管理软件,每个项目都有自己的.classpath文件,这个文件指定了源代码路径、编译后输出文件的路径以及这个项目引用的jar包的路径。一个简单的.classpath文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.
ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="lib/fastjson-1.2.7.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

为了方便在其他机器上正常开发,classpathentry中的路径往往用相对路径而不是绝对路径。如果是绝对路径,也可以手动修改文件为相对路径。