形態素解析ツールTreeTaggerを使って自分が未習得の英単語を抽出する

# はじめに
* 英文を読むときわからない単語が出るたび辞書を引くのではなくてあらかじめ未習得単語のみ抽出したいと思いスクリプトを作成しました。

# 手順概要
　1. すでに習得している英単語のknown_words.lst(既習得リスト)をコーパスを利用して作成する
　2. 対象の英文をTreeTaggerで形態素解析する
　3. 形態素解析結果からknown_words.lst(既習得リスト)を除外し、output_unknown_words.html(未習得リスト辞書リンクhtml)を作成する

```txt:ファイル及びディレクトリ構成
・
├── 01_tree_tagger.sh（TreeTagger形態素解析スクリプト）
├── 02_make_unknown_words_list.sh（未習得単語抽出スクリプト）
├── input_original.txt（input英文ファイル）
├── known_words.lst(既習得リスト)
├── output_tagged.txt（形態素解析済みTAGファイル）
├── output_unknown_words.html(未習得リスト辞書リンクhtml)
├── treetagger（TreeTaggerプログラム格納フォルダ）
```
# 1. 英単語のknown_words.lst(既習得リスト)をコーパスを利用して作成する

すでに習得している英単語の既習得リストをコーパスを利用して作成します。コーパスは、NHK基礎英語3の講師としても有名な投野由紀夫先生の研究室で公開されているリストを使用します。
下記、ページからダウンロードが可能です。
http://www.cefr-j.org/download.html
CEFR-J Wordlist
 Version 1.6をダウンロード (2020.3.24 更新版)

1. Excelのリストファイルをダウンロードしたらシート名「ALL」を選びCEFR列のフィルタを選択します。例えばA2レベルまではマスタしていると思ったらA1とA2を選択してそのレベルの英単語のみを表示します。あとでやり直すことも可能なのでとりあえず適当なレベルを選択してください。
2. フィルタを設定したらExcelのA列を列選択してコピーします。
3. known_words.lst というファイルを作成し、ペーストします。下記のような単語のリストファイルができます。

```txt:known_words.lst
#『CEFR-J Wordlist Version 1.6』
# 東京外国語大学投野由紀夫研究室.（URL: http://www.cefr-j.org/download.html より2020年12月ダウンロード）
a
a.m./A.M./am/AM
ability
about
about
above
above
abroad
accept
acceptable
accident
account
achieve
across
across
・
・
・
```
# 2. 対象の英文をTreeTaggerで形態素解析する
## 2.1. TreeTaggerのインストール 
https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/
のDownloadセクションから以下ファイルをダウンロードします。

* パッケージ（使用しているPC環境に対応しているもの）
* tagging scripts
* インストール用script
* パラメータファイル英語用

```
# treetaggerディレクトリを作成、移動して必要ファイルをダウンロードします。
$ mkdir treetagger
$ cd treetagger

# パッケージ（※使用しているPC環境に対応しているもの）以下は、PC-Linuxの場合
$ wget https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/tree-tagger-linux-3.2.3.tar.gz

# tagging scripts
$ wget https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/tagger-scripts.tar.gz

# TreeTaggerモジュールインストール用script
$ wget https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/install-tagger.sh

# パラメータファイル英語用
$ wget https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/data/english.par.gz

# インストール用scriptの実行
$ sh install-tagger.sh

# インストール後の動作確認（正常時、以下のように形態素解析されます）
$ echo 'Hello world!' | cmd/tree-tagger-english
        reading parameters ...
        tagging ...
         finished.
Hello   UH      hello
world   NN      world
!       SENT    !
```



## 2.2 TreeTagger形態素解析スクリプトを実行して形態素解析済みTAGファイルを作成する
* TreeTaggerを実行し、形態素解析します。出力された結果の内、特定の品詞のみを対象にします。このスクリプトでは形容詞、名詞、動詞、副詞を対象にしています。unknownやbe動詞と解析された単語については除外しています。
TAG SETについては、https://courses.washington.edu/hypertxt/csar-v02/penntable.html が参考になると思います。

こだわりポイント
* 単語の出現順を保持しつつ重複を削除しています。
* 単語が同じでも品詞が違うものは重複と判断しないようにしています。

```bash:01_tree_tagger.sh
#!/bin/bash

# input英文ファイル
original_fname="./input_original.txt"
# output解析済みTAGファイル
tagged_fname="./output_tagged.txt"

cat ${original_fname} | ./treetagger/cmd/tree-tagger-english | \
awk '
  # 特定品詞のみ対象にする。
  $2 ~ /JJ|NN|VB|RB/{
     if( $3 == "<unknown>" ){
       next
     }
     if( $3 == "be" ){
       next
     }
     if( $3 == "%" ){
       next
     }
     str = sprintf("%s %s", $2, $3)
     # 単語の出現順を保持するため、値に行番号をつける
     var = sprintf("%s %s", FNR, $1)
     # 品詞と単語の組み合わせで重複を除外する
     if(!(str in array)){
       array[str] = var
     }
   }
   END{
     for(i in array){
       printf("%s %s\n", array[i], i)
     }
  }' | sort -n -k1,1 > ${tagged_fname}
```

# 3.形態素解析結果から既習得単語を除外し、未習得単語のリストを作成する
* 形態素解析済みTAGファイルから既習得単語を除外し未習得単語のリストを作成します。結果は、オンライン辞書を参照可能なようにリンクをはったhtmlファイルを作成するようにしました。

```bash:02_make_unknown_words_list.sh
#!/bin/bash

tagged_fname="./output_tagged.txt"
unknown_words_fname="./output_unknown_words.html"
# online辞書サイトのURL
URL="https://www.thefreedictionary.com"
known_words_fname="./known_words.lst"
# known_wordsリストをuniq,sortする
sort -u ${known_words_fname} -o ${known_words_fname}

RTN=1
echo "<html>" > ${unknown_words_fname}
cat ${tagged_fname} | while read _num _org _part _word
do
  # known_wordsリストに存在しない単語のみunknown_listに追加する
  grep ^$_word$  ${known_words_fname}
  RTN=$(echo $?)
  if [ $RTN -ne 0 ]; then
    echo "<a href="${URL}/$_word" target="_blank" rel="noopener">$_word</a><BR>" >> ${unknown_words_fname}
  fi
done
echo "</html>" >> ${unknown_words_fname}
```
# 4.使用手順
1. known_words.lst(既習得リスト)を作成します。
* 対象の英文をinput_original.txtに保存します。
* 01_tree_tagger.shを実行します。
* output_tagged.txtが作成されます。
* 02_make_unknown_words_list.shを実行します。
* output_unknown_words.htmlが作成されます。
* known_words.lst(既習得リスト)は必要に応じて単語を追加したり削除したりしてください。

```txt:実行イメージ
# スクリプトに実行権を付与する
$ chmod u+x 01_tree_tagger.sh
$ chmod u+x 02_make_unknown_words_list.sh

# 01_tree_tagger.shを実行
$ ./01_tree_tagger.sh
        reading parameters ...
        tagging ...
         finished.
# output_tagged.txtが作成される
$ ls output_tagged.txt
output_tagged.txt

# 02_make_unknown_words_list.shを実行
$ ./02_make_unknown_words_list.sh
population
grow
small
rate
・
・
・
# output_unknown_words.htmlが作成される
$ ls output_unknown_words.html
output_unknown_words.html
```
```txt:結果ファイルoutput_unknown_words.htmlのイメージ
<html>
<a href=https://www.thefreedictionary.com/demographer target=_blank rel=noopener>demographer</a><BR>
<a href=https://www.thefreedictionary.com/pandemic target=_blank rel=noopener>pandemic</a><BR>
<a href=https://www.thefreedictionary.com/stagnant target=_blank rel=noopener>stagnant</a><BR>
<a href=https://www.thefreedictionary.com/fertility target=_blank rel=noopener>fertility</a><BR>
<a href=https://www.thefreedictionary.com/exacerbate target=_blank rel=noopener>exacerbate</a><BR>
<a href=https://www.thefreedictionary.com/estimated target=_blank rel=noopener>estimated</a><BR>
<a href=https://www.thefreedictionary.com/Spanish target=_blank rel=noopener>Spanish</a><BR>
<a href=https://www.thefreedictionary.com/flu target=_blank rel=noopener>flu</a><BR>
<a href=https://www.thefreedictionary.com/single-year target=_blank rel=noopener>single-year</a><BR>
<a href=https://www.thefreedictionary.com/populous target=_blank rel=noopener>populous</a><BR>
<a href=https://www.thefreedictionary.com/epicenter target=_blank rel=noopener>epicenter</a><BR>
<a href=https://www.thefreedictionary.com/independently target=_blank rel=noopener>independently</a><BR>
<a href=https://www.thefreedictionary.com/census target=_blank rel=noopener>census</a><BR>
<a href=https://www.thefreedictionary.com/crunch target=_blank rel=noopener>crunch</a><BR>
</html>
```
# おわりに
今回の手順で作成した未習得英単語リストはいかがだったでしょうか？
多少思い通りでないものが含まれている場合もありますが、わりと便利に使えるのではないかと思っています。known_words.lst(既習得リスト)のインプットは今回紹介したコーパス以外にもあらゆる単語リストが使用可能です。
今回は出力結果をオンライン辞書のリンクファイルにしましたが、英文記事をスクリプトを自動で取得して英単語リストを作ったり、SpeechToTextを使って発音させたり色々応用が利くのではないかと思います。

この記事が何かのお役にたてれば幸いです。