言語処理100本ノック-55:固有表現抽出

[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)[「第6章: 英語テキストの処理」](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch6)の[55本目「固有表現抽出」](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec55)記録です。
今回は固有表現の抽出。固有表現の1種類である人名を抜き出します。プログラム上は3ステップできるシンプルなものです。これだけ簡単にできるのはStanford CoreNLP様様ですね。

# 参考リンク

|リンク|備考|
|:--|:--|
|[055.固有表現抽出.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/06.%E8%8B%B1%E8%AA%9E%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E5%87%A6%E7%90%86/055.%E5%9B%BA%E6%9C%89%E8%A1%A8%E7%8F%BE%E6%8A%BD%E5%87%BA.ipynb)|回答プログラムのGitHubリンク|
|[素人の言語処理100本ノック:55](https://qiita.com/segavvy/items/32b3a35825ec32586f33)|多くのソース部分のコピペ元|
|[Stanford Core NLP公式](https://stanfordnlp.github.io/CoreNLP/)|最初に見ておくStanford Core NLPのページ|

# 環境

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|pyenv|1.2.16|複数Python環境を使うことがあるのでpyenv使っています|
|Python|3.8.1|pyenv上でpython3.8.1を使っています<br>パッケージはvenvを使って管理しています|
|Stanford CoreNLP|3.9.2|インストールしたのが1年前で詳しく覚えていないです・・・<br>1年たってもそれが最新だったのでそのまま使いました|
|openJDK|1.8.0_242|他目的でインストールしていたJDKをそのまま使いました|

# [第6章: 英語テキストの処理](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch6)
## 学習内容
> Stanford Core NLPを用いた英語のテキスト処理を通じて，自然言語処理の様々な基盤技術を概観します．
>> [Stanford Core NLP](https://stanfordnlp.github.io/CoreNLP/), ステミング, 品詞タグ付け, 固有表現抽出, 共参照解析, 係り受け解析, 句構造解析, S式

## ノック内容
> 英語のテキスト（[nlp.txt](http://www.cl.ecei.tohoku.ac.jp/nlp100/data/nlp.txt)）に対して，以下の処理を実行せよ．

### [55. 固有表現抽出](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec55)
> 入力文中の人名をすべて抜き出せ．

# 回答
## 回答プログラム [055.固有表現抽出.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/06.%E8%8B%B1%E8%AA%9E%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E5%87%A6%E7%90%86/055.%E5%9B%BA%E6%9C%89%E8%A1%A8%E7%8F%BE%E6%8A%BD%E5%87%BA.ipynb)

```python
import xml.etree.ElementTree as ET

XPATH = './document/sentences/sentence/tokens/token[NER="PERSON"]'
print([ token.findtext('word') for token in ET.parse('./nlp.txt.xml').iterfind(XPATH)])
```

## 回答解説
### XMLファイルのパス
下記の「固有表現」で`<NER>`タグの値が`PERSON`の場合に、同階層の`<word>`タグの値が人名を示します。Stanford CoreNLPの「固有表現」の仕組みは[Stanford Named Entity Recognizer (NER)](https://nlp.stanford.edu/software/CRF-NER.html)に書かれています。

|出力|第1階層|第2階層|第3階層|第4階層|第5階層|第6階層|第7階層|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|単語|root|document|sentences|sentence|tokens|token|word|
|固有表現|root|document|sentences|sentence|tokens|token|NER|

XMLファイルは[GitHub](https://github.com/YoheiFukuhara/nlp100/blob/master/06.%E8%8B%B1%E8%AA%9E%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E5%87%A6%E7%90%86/nlp.txt.xml)に置いています。

```xml:nlp.txt.xml(抜粋)
<root>
  <document>
    <docId>nlp.txt</docId>
    <sentences>
      <sentence id="1">

--中略--

        <tokens>
          <token id="4">
            <word>Alan</word>
            <lemma>Alan</lemma>
            <CharacterOffsetBegin>636</CharacterOffsetBegin>
            <CharacterOffsetEnd>640</CharacterOffsetEnd>
            <POS>NNP</POS>
            <NER>PERSON</NER>
            <Speaker>PER0</Speaker>
```

あとは`xml`パッケージの`iterfind`関数にXPATHを渡してやるだけです。

### 出力結果(実行結果)
プログラム実行すると以下の結果が出力されます。

```bash:出力結果
['Alan', 'Turing', 'Joseph', 'Weizenbaum', 'MARGIE', 'Schank', 'Wilensky', 'Meehan', 'Lehnert', 'Carbonell', 'Lehnert', 'Racter', 'Jabberwacky', 'Moore']
```