機械学習(AI)による単語予測と、法令文を校正するための予測精度の向上についての取組（技術的説明：試行編）

取組の概要については、[機械学習(AI)による単語予測と、法令文を校正するための予測精度の向上についての取組（概要）](https://qiita.com/chuukai/items/3650274c47514c4482a4)を参照されたい。
モデル作成については、[機械学習(AI)による単語予測と、法令文を校正するための予測精度の向上についての取組（技術的説明：モデル作成編）](https://qiita.com/chuukai/items/d4a0e4338de1fb4c01f2)を参照されたい。

##試行を行う目的
　試行を行う目的は、作成したモデルについて、実用に向けた利用ができることを示すことである。

##校正のためのモデルを利用する条件
　以下の2つの条件が満たされていないと、単語の予測ができずに候補単語が出てこないか、または定性的に見れば候補単語が見当外れになる。

1. ドメインに属する文章を使ってモデルが作成されており、校正対象の文章はそのドメインに属していること
1. 上記のドメインに属する文章及び校正対象の文章を分かち書きツールで分かち書きしたときに出力される単語の素性（品詞の名称等）が使えること

　上記の条件について説明する。

1. の条件については、モデルの学習時に登録されていない単語は予測されず、候補単語にならないためである。ただし、ドメインが広ければ広いほど学習時に様々な単語が登録されるが、単語予測の精度（確率）は低くなると推測される。
1. の条件については、単語の誤用においては正しい単語の品詞と誤用される単語の品詞がほとんどの場合は同じであるという関係に基づいて、候補単語の取捨選択を行うことにより、候補単語のS/N比を高めるためである。単語の形態素に関する素性は、これを用いない自然言語処理はあり得るが、この取組では重要な情報となった。

##単語を予測する

###単語を予測するための前処理

####品詞リストを作る
　上記のドメインに属する文章を分かち書きツールで分かち書きしたときに出力される単語の素性（品詞の名称等）のファイルは、以下のスクリプトで作成した。

```publicanbunparse.ipynb
def ommit(linestr):
  line = linestr.rstrip('\n')
  t_lists = line.split('\t')
  term = t_lists[0] + ' '
  if t_lists[0] == 'EOS' or t_lists[0] == '' or t_lists[0] == 'と' or t_lists[0] == 'の':
    term = ''
    return term
  for hinsi in ['記号', '助詞,連体化', '助詞,副詞化', '助詞,係助詞', '助詞,接続助詞', '助詞,並立助詞', '助詞,副助詞／並立助詞／終助詞', '助詞,格助詞,引用', '助詞,格助詞,一般,*,*,*,へ,ヘ,エ', '助詞,格助詞,一般,*,*,*,に,ニ,ニ', '助詞,格助詞,一般,*,*,*,を,ヲ,ヲ', '助詞,格助詞,一般,*,*,*,で,デ,デ', '助詞,格助詞,一般,*,*,*,が,ガ,ガ', '助詞,格助詞,一般,*,*,*,から,カラ,カラ', '助詞,副助詞,*,*,*,*,まで,マデ,マデ', '連体詞', '接頭詞,名詞接続', '特殊', '形容詞,自立,*,*,形容詞・アウオ段,基本形,ない,ナイ,ナイ', '接頭詞,数接続', '名詞,数', '名詞,接尾', '名詞,非自立,副詞可能', '名詞,非自立,助動詞語幹', '名詞,接尾,助数詞', '名詞,代名詞', '助動詞', '名詞,非自立,一般', '動詞,非自立', '動詞,自立,*,*,サ変・スル', '動詞,接尾', '動詞,自立,*,*,一段,基本形,できる,デキル,デキル', '動詞,自立,*,*,五段・ラ行,基本形,係る,カカル,カカル', '助詞,格助詞,連語,*,*,*,に' ]:
    if t_lists[1].find(hinsi) > -1:
      term = ''
      return term
  for stopword in ['ヶ所', 'ヵ所', 'カ所', '箇所', 'ヶ月', 'ヵ月', 'カ月', '箇月', '十', '百', '千', '万', '億', '兆', 'もの', '明治', '大正', '昭和', '平成', '令和']:
    if t_lists[0].find(stopword) > -1:
      term = ''
      return term
  return linestr

for bunrui in range(1,51):
  lssentence = " ".join(['ls','/content/drive/My\ Drive/Colab\ Notebooks/houreibunrui20210510/%02d/*.nml' % bunrui])
  output = subprocess.getoutput(lssentence)
  tolists = output.split('\n')
  for tolist in tolists:
    print(tolist)
    text_data = open(tolist, "rb").read()
    decoded_text = text_data.decode('utf-8')
    text = re.sub('\n\n', '\n', decoded_text)
    with open(tolist[:125] + '.poslist', 'a') as f:
      parses = m.parse(text)
      tolistformecab = re.sub(" ", "\ ", tolist)
      mecabsentence = " ".join(['cat', tolistformecab, '|', 'mecab', path, '>', 'temp.poslist'])
      subprocess.getoutput(mecabsentence)
      with open('temp.poslist', encoding='utf8') as ftemp:
        for linestr in ftemp:
          f.write(ommit(linestr))
      !rm temp.poslist
f.close()
```


###モデルにより予測した単語を取捨選択して、その結果をファイルに書き出すまでの手順
　モデルにより予測した単語を取捨選択して、その結果をファイルに書き出すまでの手順を示すと以下のようになる。

* 原文の単語の場所を空欄にして、その空欄に入る単語をモデルで予測する。
* 予測された単語から、以下に該当する単語を除外する。
 + 原文の単語と同じ
 + 確率が0.99未満
 + 原文の単語との間で共通する品詞がない
 + 確率が高い単語の順に並べて6番目以降になる
* 原文の単語と、除外されずに残った単語、その確率をテキストファイルに追記する。すべての単語が除外された場合は原文の単語のみテキストファイルに追記する。
* 以上を原文のすべての単語に対して、当該分野に属するすべてモデルを使って繰り返す。

####単語除外の条件に関する説明

- 以下の単語除外の条件について、それぞれ説明する。
 + 確率が0.99未満
　確率が高い単語を残して候補単語とすべきである。ここで、どのくらいの数値が高いと言えるのかが問題となる。数値を決めるにあたっては、例えば確率の分布などを見てカットオフポイントとなる数値を求めることが考えられる。しかし、この取組では、出力結果を目で見て、確率が0.99以上であれば校正の検討に値する単語となっていると判断した。

 + 原文の単語との間で共通する品詞がない
　上述のとおり、単語の誤用においては正しい単語の品詞と誤用される単語の品詞がほとんどの場合は同じであるという関係が見られることから、品詞での取捨選択を行った。なお、一つの単語に対して分かち書きツールが複数の種類の品詞を提示する場合があるため、条件を「品詞が異なる」とせずに「共通する品詞がない」とした。

 + 単語を確率が高い順に並べて6番目以降になる
　確率0.99以上という条件を使って、単語の数を制限しても、まだ予測された単語の数が多い場合がある。これはデータセットの量が少ないモデルで単語を予測した場合によくある現象であり、単語を多く残しても予測精度の向上に寄与しないことから、確率が高い順に並べて上位5位までの単語を残している。

####原文の単語と、除外されずに残った単語、その確率を保存したテキストファイルの内容
　原文の単語と、除外されずに残った単語、その確率を保存したテキストファイルの内容のうち1行を以下に例示する。

```323AC0000000025_20210301_501AC0000000071.sentence.nml.wwakati24.pred
政令:内閣府令;0.9999877214431763,	政令:内閣府令;0.9999376535415649,	政令:内閣府令;0.9982808828353882,	政令:内閣府令;0.9998379945755005,	政令:内閣府令;0.9997585415840149,	政令:内閣府令;0.9999784231185913,	政令:,	政令:金融庁長官;0.9992239475250244,	政令:内閣府令;0.9999947547912598,金融庁長官;0.9999576807022095,	政令:	政令:	政令:	政令:
```
　原文は金融商品取引法(323AC0000000025_20210301_501AC0000000071)であり、金融・保険分野の法令(wwakati24)から学習したモデル13個（models24-00w.wwakatiall〜models24-12w.wwakatiall）を使って単語を予測した。
　この行は、原文の中にある「政令」のうち1つについて、その単語の位置に出現するであろう単語を各モデルが予測した結果である。
　行の最初から読み解く。
　原文の単語「政令」に対して、models24-00w.wwakatiallが予測した単語は「内閣府令」であり、その確率は0.9999877214431763である。
　次にmodels24-01w.wwakatiallが予測した単語は「内閣府令」であり、その確率は0.9999376535415649である。
　途中を飛ばして、models24-06w.wwakatiallが予測した単語はなかった。これは0.99以上の確率の単語が、なかったか、あるいは原文の単語である「政令」だったかを意味する。
　次にmodels24-07w.wwakatiallが予測した単語は「金融庁長官」であり、その確率は0.9992239475250244である。
　以降は省略する。

##単語の予測結果に基いて候補単語を原文に埋め込む

（以下、後日更新予定）

<!--
目的達成度合いを測定するための指標
目標である「原文の単語の置き換え候補として提示することで、人のチェックをサポートすること」の達成度を厳密に数値として表そうとすると以下のようになる。
候補となる単語を提示することで、校正者が原文の単語が不適切であることに気づき、単語の置き換えを行った場合を正解と定義し、不適切な単語に対して単語を提示できなかった場合や、提示した単語が適切でなかった場合、提示したが校正者に気づいてもらえなかった場合を不正解と定義したときの、正解となった件数と不正解となった件数の比率

しかし、このような数値は、実験の段階ではなく実務もしくはその試行の段階ではじめて測定できるものであるため、今回は実験の段階での他の数値を用いることとする。

指標を単純化して規定すれば「すべての不適切な単語に対して、適切な置き換え候補の単語を提示できた割合」が「人のチェックへの貢献度」となる。
-->