自然言語文のアノテーションをHackした話

## 概要
[@enullper](https://twitter.com/enullper)です。
YANS2019のアノテーションハッカソンに参加して優勝してきました。
アノテーションといえば地道に一つ一つデータを付与していくイメージがあると思いますが、今回は「**アノテーションをハックする**」ことをチームのテーマとして如何に効率的に大量の良質なデータを用意するかを考えました。

作業の効率化の結果、以下のことを達成しました。

- 与えられた生文データ全て（5519件）に擬似ラベル（後述の手法によって自動的に付与されたラベル）を付与
- そのうち400文を 2人✖️3時間 で修正
- Cross Validation において「全文に擬似ラベルを付与して一部を人手で修正」のデータセットによって訓練されたモデルの性能が「全文に擬似ラベル付与（修正なし）」のデータセットで訓練されたものの性能を上回ることを確認
- 運営側の用意したテストデータで優勝！


## アノテーションとは

[IT用語辞典バイナリ](https://www.weblio.jp/content/アノテーション)でアノテーションは次のように説明されています。

```
アノテーション（英語：annotation）とは、あるデータに対して関連する情報（メタデータ）を注釈として付与すること。
```


今回のタスクでのアノテーションでは有価証券報告書のテキストデータに対してそこに現れている会社（CMP）や時間（TIME）、変化を表す表現（EVL）等に以下のようにラベルの付与を行います。

例として見せている画像は今回のハッカソンで使用したアノテーションツール [doccano](https://github.com/chakki-works/doccano) の画面です。


<img width="651" alt="スクリーンショット 2019-09-17 10.37.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/338fd316-018d-a49a-9a7f-19447599a04f.png">



このように情報を付与したデータを利用することでテキストの量的な分析や機械学習を用いた情報の抽出や構造化が行えるようになります。


## タスクの概要
今回のタスクは**有価証券報告書からの情報抽出**です。  

このハッカソンの大まかな流れは以下の通りです。

- 参加チームに訓練データのもととなる生文データセットとアノテーションガイドライン、アノテーション例が与えられる
- 各チームはアノテーションガイドラインに沿って生文にアノテーションを行い、アノテーション付きデータセットを作る
- 全チームで共通のモデルに作ったデータを読み込ませ訓練
- 評価データのF1値で勝負

つまり、**量・質ともに優れたデータセット**を作ることでモデルの性能が上がり、上位に入ることができます。

なんと、ハッカソンを楽しんでいるといつのまにかデータセットが出来上がっているという全方面に嬉しいイベントです。

## 自動ラベリングによるアノテーション効率化

チームで用いた手法を紹介します。
ここではシステムによって自動で付与されたラベルを **擬似ラベル** と呼びます。

私たちの手法ではつぎの3つのステップでラベルを付与していきました。

- 辞書で擬似ラベルを生成
- 既存の固有表現抽出モデルで擬似ラベルを生成
- 人手で修正

このようにアノテーション付きデータセットを作るときに既存のモデルなどを使って自動ラベリングをし人手で修正することは一般的なようです。（[京大コーパス](http://nlp.ist.i.kyoto-u.ac.jp/index.php?京都大学テキストコーパス)など）

実際にデータセットに含まれていた例で説明していきます。

<img width="817" alt="スクリーンショット 2019-09-14 12.50.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/55fd0644-1af7-44fb-b2c4-1465ebf949d9.png">


### 辞書
テキストにアノテーションをするとき、ラベルの性質によっては単純な辞書マッチで拾えます。
例えば今回はラベルの中に勘定科目（売上原価、減価償却費など）があったのですが、これらは前後の文脈にほとんど影響されずに同じラベルがつけられるため単純な辞書マッチで解くことができます。

もちろん、例外はありえます。そのため人手での修正も必要ですが、修正箇所が少なければ全てを初めからアノテーションするのに比べて格段に少ない労力で行えます。

辞書の構築は運営より提供されたアノテーション例151件からラベル別語彙リストを抽出することで行いました。

以下に辞書マッチによってラベル付けされた例を示します。

<img width="816" alt="スクリーンショット 2019-09-13 19.18.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/55b959ed-67bb-9ebd-59bc-231ae5609b5c.png">


### 既存の固有表現抽出モデル
タスクによっては単純な辞書マッチだけでは難しいこともあります。例えば製品名や会社名は辞書に登録すれば上の方法でも対応可能ですが、実際の文に現れる語は非常に多く、新語も次々と出てくるため全て登録することは非現実的です。また、数値などは正規表現でルールを書くこともできますが、既に対応しているモデルがあるならばそれを使うに越したことはありません。

そのため、擬似ラベルを付与するために既存の固有表現抽出(NER)モデルを使いました。Megagon Labs が開発した [GiNZA] (https://github.com/megagonlabs/ginza) というライブラリです。



このライブラリの固有表現抽出モデルによってラベル付けした結果は以下のようになります。
今回のタスクでつけるラベルと GiNZA のラベルは異なっているため、 GiNZA のラベルを変換する処理を行いました。

```
（例）
  ORG -> CMP
  PRODUCT -> PRD
```
<img width="815" alt="スクリーンショット 2019-09-13 19.18.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/b244d19f-61ca-2e28-5ea4-175f3f4bdeef.png">

### 辞書＋既存のNERモデル

これら２つを合わせると次のようになります。

<img width="814" alt="スクリーンショット 2019-09-13 19.17.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/39118c1f-6ccc-8ca9-abb4-ebaadc1365e9.png">


#### ラベルの優先順位

辞書マッチでは同一のスパンに複数のラベルが貼られることがありますが、最長一致法を用いることで決定的に１つのラベルに決まるようにしました。
例えば、以下の場合、「富士通」と「富士通株式会社」の2つが候補としてありますが、文字列の長さにより「富士通株式会社」が選ばれます。

```
（例文）富士通株式会社が提供するサービス
- 富士通
- 富士通株式会社
```

また、辞書マッチとNERモデルが同じスパンにラベルを貼った場合、ラベリングに対してより一貫性のある辞書マッチを優先しました。

### 人手

ここまでくると人手でつける必要がある部分は少なくなっています。
この例だと以下の部分です。

- **食品卸売事業** の DOM タグ（会社の中の部門）

<img width="818" alt="スクリーンショット 2019-09-13 19.25.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/2206a9a2-8707-21fd-ca63-59bff6f0ed09.png">


## 間違っていてもアノテーションに有効な擬似ラベル

上で出した例だと全てがうまくいっているように見えますが、もちろん自動でのラベリングが失敗したところも数多くあります。
しかし、ラベリングが完全に成功しているわけでなくても部分的には正解している場合はアノテーションの助けになります。

### 部分的にスパンが当てられている例

この例では `ベトナム社会主義共和国` に LOC（地名）ラベルが貼られるべきですが、擬似ラベルはそのスパン（何文字目から何文字目が固有表現にあたるか）の一部の `ベトナム` に貼られています。
長い固有表現はその中に短い固有表現を含むことが多い（国名、会社名等）ため、このような例では短い固有表現が見つかればその周辺を見ることでより長い固有表現を見つけることができます。


<img width="820" alt="スクリーンショット 2019-09-14 13.41.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/6cc9287e-12fd-0cc6-114a-11aaf7dcd400.png">


### スパンがあっていてラベルが間違っている例

次の例では以下のようなラベル付けの間違いが起きています。

- 似たような店名が製品名（PRD）や地名（LOC)とされる
- 兵庫県尼崎市（地名となるべき）が会社名（CMP）とされる

とはいえスパンは当てられています。

そのため、人手での修正の時には予測された固有表現のそれぞれについてスパンに与えられたラベルがあっているか確認すればよいだけになり、アノテーションがかなり楽になります。


<img width="820" alt="スクリーンショット 2019-09-13 17.46.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/95aa21ef-68d5-08e4-5ffd-6932cfcbd09a.png">

## モデルの評価
今回のハッカソンでは2つの評価軸でデータセットを評価しました。


- Cross Validation
    - 提出されたデータセットを分割して訓練データと評価データに分ける。
    - アノテーションの一貫性を評価できる。
- Cross Evaluation
    - 運営が用意したデータも含めて他のチームが作成したアノテーションデータに対するF1値を評価

優勝を決めるための最終的なスコアは運営が用意したデータにおけるF1値が用いられました。

### Cross Validation の結果
今回、運営が各チームのアノテーションしたデータを使って Cross Validation を行うシステムを提供していたため、3種類のパターンを試しました。
これはアノテーションしたデータを分割して Cross Validation を行うため、アノテーションの一貫性を測ることができます。

 1. 全文に擬似ラベルを付与
 1. 擬似ラベルを人手で修正した部分のみ
 1. 全文に擬似ラベルを付与して一部を人手で修正

スコアは以下のようになりました。

コンペティションには上の2つしか間に合わなかったのですが、終了後に3番目のパターンの結果がでました。

また、手法2では人手で修正されたデータの件数が200件、手法3では400件になっていますが、これは手法2を投げた時点で私が200件しかないと勘違いしていたためです。そのため、手法2と3については正当な比較にはなっていません。
いつか機会があれば手法2を400件のデータで試してみたいです。

||訓練データ数|F1|
|---|---|---|
|手法１|5519件|86.86|
|手法２|200件|85.00|
|手法３|5519件(うち400件を人手で修正)|88.53|

興味深いことに、アノテーションの一貫性を評価する指標であるにも関わらず、全て自動でラベリングされた手法１よりも人手での修正を含む手法３の方がスコアが高くなっています。

解析結果の詳細な分析はしていないのですが、この結果から考えるに自動ラベリングで作られたデータであっても人手を加えることでラベリングの一貫性を高めることができると言えそうです。

### Cross Evaluation の結果

Cross Evaluation の結果は以下のようになりました。

`クラウドソーシング` が私たちのチーム名です（手法はクラウドソーシングとは何も関係なかったのですが）。
結果的に対戦相手である `TTY` を超えるF1値を記録し優勝することができました。
今回のハッカソンでは各チームが提出したデータセットのうち Cross Validation で最も高いスコアを出したものを最終的なデータセットとして Cross Evaluation で評価したそうです。

<img width="760" alt="スクリーンショット 2019-09-17 20.56.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293448/cf51e4ec-bd80-b1b0-e12d-3ea96196f5fe.png">


## 自動ラベリングの改善

ハッカソンでは上で紹介したシンプルな方法である程度うまくいくことを示しましたが、
いくつか改善できるポイントがあります。

### 辞書の拡張
まず、辞書マッチでは辞書に登録されていない語はラベル付けすることができません。

そのため、この点に対処するためには以下のような手法で辞書を拡張することが考えられます。

- 既存のリソース（Wikipediaページのタイトルなど）を使って辞書を作る
- 人手によるアノテーションが進んできたところで新たに発見された語を辞書に追加する

### アノテーション途中のデータを用いたモデルの学習

既存のモデルをそのまま使って擬似ラベルを付与することはアノテーションの上で有効ではありますが、
以下で説明するように必ずしも既存のモデルが訓練されたデータセットと解くべきタスクの設定が同じであるとは限りません。
また、テキストのドメインの違いもあります。

そのため、既存のモデルの出力をアノテーションに用いるときは何らかの形で適応しなければならないのですが、
アノテーション途中のデータを使ってモデルを再学習させることで解くべきタスクの設定とドメインにある程度適応させたモデルを作ることができます。

また、データセットの作成が進むに連れて予測性能が上がっていくことが体感できるため、モチベーションの維持にもつながります。

## 既存のモデルを転用するときに気をつけること
既存のモデルによる自動ラベリングによってアノテーションを効率化できますが
転用にあたっては既存のモデルが訓練されたデータセットと扱っているタスクの違いについて考える必要があります。

GiNZA の NER モデルは[京都大学ウェブ文書リードコーパス](http://nlp.ist.i.kyoto-u.ac.jp/index.php?KWDLC)で訓練されています。
このデータセットは約5000件のWeb文書の冒頭3文に各種言語情報を付与したデータセットで、コーパスとしてはそれなりの大きさがあります。

このコーパスの固有表現は[IREXの基準](https://nlp.cs.nyu.edu/irex/NE/df990214.txt)によってアノテーションされています。（注意：リンク先はEUC-JPでエンコーディングされています）

### 同じ固有表現に対するラベルの粒度が違う
本タスクで用いるラベルとの違いはいくつかありますが、ここでは組織に対するラベルの付け方について着目します。

IREXでは組織名（ORGANIZATIONタグが付与される固有表現）を以下のように定義しています。

```
組織名とは、複数の人間で構成され、共通の目的を持った組織等の名称の事である。
```

それに対して、本タスクではより粒度の高いラベルが用意されています。
そのため、既存のモデルによる解析結果とタスクが求めるラベルの粒度を合わせることが必要になります。

```
### 会社（CMP）
会社名を表す表現です。具体的な会社名ではなくても、「当社」のような会社を表す表現も含めます。
- ex) 当社, グループ会社, 日系企業, 親会社
### 部門(DOM)
主に会社内の部門名を表す表現です。
- ex) 物流部門, 情報サービス産業
### 国際機構(UNI)
政治的・安全保障的な意味での集合体です。
- ex) ASEAN, EU, OPEC
```

### 固有表現以外の抽出
IREXの基準は固有表現抽出についてのものですが、本タスクでは固有表現以外も扱っています。
当然ですが、固有表現抽出モデルではこれらに対応することができません。

例えば以下のラベルは一般名詞や一般名詞をヘッドとするフレーズにつけられます

```
### 勘定科目(ACT)
会社の取引による資産・負債・資本の増減、および費用・収益の発生を記録するために必要な分類項目です。
- ex) 売上高, 営業利益
### 状態表現(STA)
会社(CMP)や部門(DOM)、製品(PRD)の状態を表す表現です。
- ex) 業容, 販売状況
- ex) 「当社グループ全体の出店などの状況は〜」では、「当社グループ全体」という会社(CMP)の状態表現(STA)が「出店などの状況」であると考えます。
### 社会情勢(SOC)
地域(LOC)や国際機構(UNI)に帰属する、社会的な情勢です。
- ex) 経済, 雇用, 政策運営, 国内事情
```

次のラベルは名詞だけでなく動詞をヘッドとするフレーズにもつけられます

```
### 変化表現（EVL）
文脈の中での使われ方によって評価表現として抽出する長さが変わります。
- ex) 導入, 進める, 向上している, 上昇傾向にある, 減少した, 増, 損失, 増益
- ex)「一部に改善の遅れが見られる」では「改善」ではなく「改善の遅れ」を評価表現とし、「一部に改善が見られる」では「改善」を評価表現とします。
- ex) 「米国では景気回復が継続し」では「景気回復」ではなく「景気回復が継続」までを評価表現とします。
- ex)「顧客単価の向上を図りました」は、「向上を図る」という表現では上昇が起きたかどうかが不明のため、評価表現には含みません。
```

一般名詞や動詞は種類が固有名詞に比べて少ないため、以下の手法である程度対応できそうです。

- ヘッドとなり得る語を辞書へ登録する
- ヘッドとなり得る語周辺のngramや係り受けを素性としてフレーズを抽出するルールを書く

## 人手でないと難しいこと

本タスクでは、ほとんどの固有表現はラベルがつけられそうなスパンとそのごく近くの表層的な情報をみるだけで当てられそうなものでした。
こういったものは単純な手法であってもかなりの精度でラベリングすることができます。

理想的には、アノテーションにおいても単純な問題はラベリングを完全に自動化してしまい、自動ラベリングが難しいところだけを人手でアノテーションできれば、効率的にアノテーション付きデータを作ることができます。

それでは人手でないと難しいものとしてどのようなものがあるのでしょうか。
例えば今回のアノテーションガイドラインではラベル付けされた表現同士の関係まで踏み込んでいます。


```
- 文脈・文型を最優先してください
    - 変化表現(EVL)があればそれが指し示す勘定項目(ACT)を探す、といったように、情報抽出する際に違和感のないような照応が取れるようにします。
- 入れ子の関係を意識してください
    - ex)「精密機能部品では、安全装置部品が〜」では、「精密機能部品」という部門(DOM)の下に「安全装置部品」という製品(PRD)があると判断できるので、明確に部門という表現がなくても部門(DOM)として抽出します。
- 並列でつながっている場合は別々で抽出します
    - ex)「雇用・所得関係に改善の動きが」では、「雇用」と「所得関係」を別々で社会情勢(SOC)に登録します。
- 例示を含む場合は大元の表現のみを抽出します
    - ex)「家庭用蓄電システムなどの回路製品」では、「家庭用蓄電システム」は「回路製品」の単なる例示であると考えられるのでこちらのみ抽出します。
```

これらを解くためにはそれぞれ以下のことを判断する必要があります。
どれもが今の自然言語処理で難しいとされている問題です。

- 照応
- 意味的な入れ子
- 並列句
- 包含関係

現時点ではどのドメインでも汎用的に高精度でこれらを扱える解析器を作るのはむずかしいですが
個人的には有価証券報告書など狭いところにドメインを絞れば実用に耐える精度が実現できるのではないかと考えています。

アノテーションをするときはこういった現在の自然言語処理技術では難しい問題だけに絞って労力を使うことが理想的だと思います。

## 最後に
今回私たちは「アノテーションをハックする」ことをチームのテーマとして効率的にアノテーション付きデータセットを作成する手法を試しました。
結果としてハッカソンで優勝することができ、そこで得た知見をこの記事という形で共有することができました。
この素晴らしい機会を与えてくださったYANSやハッカソンの運営の方、チームメンバーの方に感謝します。