cabochaで行う自然言語処理の基礎

### はじめに
本記事では日本語の係り受け解析器であるcabochaをJavaで呼び出し、形態素解析及び係り受け解析を行います。

### 自然言語処理とは
自然言語処理とは、文字通り自然言語(日本語や英語などの人がコミュニケーションを行う為に使用する言語)をコンピュータに処理させるための技術になります。
こちらの技術は機械翻訳やAIチャットサービスなど、自然言語を扱う様々な分野で使用されています。
自然言語はあやふやでそのままだとコンピュータに処理させるのは難しいため、形態素解析や構文解析などを行うことで自然言語をコンピュータで処理しやすくします。


### 形態素解析とは
形態素解析とは、文章を形態素（意味を持つ最小の単位）ごとに分解し、品詞や変化などを判断することです。
例えば『私は勉強をする』という文章で考えると、『私』『は』『勉強』『を』『する』といったように形態素ごとに分け、『私』は代名詞であり変化はしていないといったことなどを判断します。



### 係り受け解析とは
係り受け解析とは、主語と述語など、同士の関係性を判断することです。
例えば『私は勉強をする』という文章で考えると『私は』が主語で、『する』が述語のため、『私は』が『する』に係っているといったことなどを判断します。


### cabochaを使用したJavaでの形態素解析、係り受け解析
以下の手順でJavaでかかり受け解析を行うオープンソースのcabochaを呼び出し、形態素解析及び係り受け解析を行います。
cabochaはjavaの公式ライブラリが存在しないため、「java.lang.Runtime」クラスであらかじめインストールしたcabochaを実行する方法で実施します。

#### 1. mecabのインストール
mecabとは、日本語の形態素解析を行うオープンソースの一つです。
今回はcabochaを使用してかかり受け解析を行うのですが、cabochaを実行するためには本オープンソースのインストールが必要になります。
以下サイトからmecabのインストーラをダウンロードし、インストーラを実行することでmecabのインストールを行います。
https://taku910.github.io/mecab/#download

#### 2. cabochaのインストール
cabochaとは、日本語のかかり受け解析を行うオープンソースの一つです。
以下サイトからcabochaのインストーラをダウンロードし、インストーラを実行することでcabochaのインストールを行います。
https://taku910.github.io/cabocha/

#### 3. Javaでcabochaの実行
以下プログラムでcabochaを実行し、引数の係り受け解析を行った結果をコンソールに出力します。

```
package com.example.demo;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import java.io.OutputStreamWriter;
import java.io.BufferedReader;

public class NplApplication {

	public static void main(String[] args) throws Exception {
		//解析を行う単語の設定
		String sentence = args[0];
		//cabocha実行ファイルの格納先
		String cabochaPath = "C:\\Program Files (x86)\\CaboCha\\bin\\cabocha.exe -f1";

        try {
            //cabochaの実行
        	Process process = Runtime.getRuntime().exec(cabochaPath);
         
            OutputStream out= process.getOutputStream();
            OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
            writer.write(sentence);
            writer.close();
            InputStream is = process.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line;
            while ((line = br.readLine()) != null) {
            実行結果をコンソールに出力
                System.out.println(line);
            }
            process.destroy();
            process.waitFor();
        } catch( Exception e ) {
            System.out.println(e);
        }  
	}
}

```
引数に『私は勉強をする』を与えて上記プログラムを実行すると以下の内容がコンソールに出力されます。
```
* 0 2D 0/1 -2.725394
私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 2D 0/1 -2.725394
勉強	名詞,サ変接続,*,*,*,*,勉強,ベンキョウ,ベンキョー
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 2 -1D 0/0 0.000000
する	動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
EOS
```
コンソールに出力された内容は、先頭がアスタリスクの行が文節ごとの係り受け解析の譲歩、先頭がアスタリスクでない行が形態素ごとの形態素解析の情報です。

まず、形態素解析の情報についてみていきます。各形態素ごとに以下の内容を出力しています。
その為、例えば上記出力内容の2行目を見ると、『私』という形態素は品詞が名詞であることや、活用型や活用形はない事、読みや発音が『ワタシ』であることなどが確認できます。
```
表層形	品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音
```

次に、係り受け解析の情報についてみていきます。各分節ごとに以下の内容を出力しています。
```
* 文節番号 かかり先番号 主辞/機能語の位置 係り関係のスコア
```
それぞれの出力内容の詳細は以下です。
* 文節番号：各文節ごとに割り振った番号。以降のかかり先番号などを表すために使用する。
* かかり先番号：本文節が、どの文節にかかっているかを表す番号。かかり先が存在しない場合は-1Dと表示される。
* 主辞/機能語の位置：文節の中の何番目の形態素が主辞（句や分の主要語）で、何番目の形態素が機能語(助詞などの意味を持たない単語)かを、主辞の位置/機能語の位置の順で表している。
* 係り関係のスコア：文節同士がどの程度係りやすいかを表す数値。数値が大きいほど係りやすい。

その為、例えば上記出力内容の１行目を見ると、『私は』という文節は文節番号2の『する』という文節に係っていることなどが確認できます。
### 終わりに
自分は以前Perlでの自然言語処理を行った事がありますが、今回の記事を書くにあたり久しぶりに勉強し直してみました。
最近だと自然言語処理を使用している有名なものとしてChatGptなどがあるのでこちらについてもまた触ってみようと思います。