輪講：OCR-ed/Post-OCR textの校正correctionについての論文紹介

## 本稿の目的
勉強がてら論文を1本読んだので、理解のためにまとめてみました。

### 対象論文
[Post-OCR Document Correction with large Ensembles of Character Sequence-to-Sequence Models, Ramirez-Orta et al., 2022](https://arxiv.org/abs/2109.06264)


## 動機
> PDFで拾ってきた論文を自動翻訳に放り込んで、センテンスがぶった切られていることに苛立ちながらDELETEキーと↓キーを無心で連打した経験を、皆さまはきっとおありでしょう。PDFなるファイル形式は、それが文書ファイルでありながら文章の復元をまるで考慮していない悪しき技術的負債です……。

という恨み言はさておき、私の個人的な動機として、PDF図書館的なものをつくりたい、というものがあります。大まかな機能要件は以下です。

> 対象ディレクトリに格納したPDF群について、以下のtxtファイルをバッチ処理にて作成する。
> - 整形されたナマのテキストデータ
> - 日本語との対訳テキストデータ

PDFからテキストを抽出するのは既存ライブラリに丸投げすることにして、前者から作ろうとして~~は何度も投げ出して~~いるのが現在です。

ソフトや実装が既にあるよ、とかありましたら知りたいです。~~勉強とか開発なんかはどうでもいいです。~~

改めてちょっと調べてみたところ、このタスクはコンペが開かれるくらいには難しいのでは？と気づいたので、お勉強がてら実装を公開している論文を一つ読んでみました。というのが、本投稿までの運びです。


### 対象論文のお仕事：OCR-ed/Post-OCR textの校正correction
OCR-ed/Post-OCR textとは、光学式文字認識OCR(OPTICAL CHARACTER RECOGNIZE)によってスキャンされたテキストのことです。

文献をスキャンして、その画像データをテキストデータに変換し、そこからゴミ取りをする...というのが本来のOCRの技術領野です。が、今回扱う論文のタスクは、すでに画像データからテキストとして起こしたもののゴミ取り（校正）です。

校正には2段階のタスクがあります。（[コンペ](https://sites.google.com/view/icdar2019-postcorrectionocr/home?authuser=0)参照）

1. OCRエラーの検出：単純な誤字（ex. docm3nt -> document）だけでなく、衍字・脱字や区切り文字（空白）が機能していない場合（ex. d cm3 nt -> document）もある。
2. OCRエラーの修正：システムが生成した修正候補のリストの中から人が正しい修正を選ぶ「半自動システム」が一般的だが、補正候補を1つに絞る「完全自動システム」も（本稿で取り上げる論文はこっち）。


コンペのデータセットを確認したところ、ふだん出くわすものよりだいぶ壊れていたり、よくある改行入りすぎ問題とは無縁そうだったり、はしましたが、そこはデータセット次第でどうとでもなる（んですかね...? 素人の妄想です...）と判断し、実装例を探しました。そうして、ある1つの論文に行き着きました。


---

## 論文紹介
~~前置きが長過ぎましたが~~、本題です。
ダイジェストを[落合式](https://www.slideshare.net/Ochyai/1-ftma15)でお送りしてから、モデルを見ます。
なお、データセットは[コンペのもの](https://sites.google.com/view/icdar2019-postcorrectionocr/dataset?authuser=0)です。

### 1. どういう論文？
2019年のPost-OCR Textの校正コンペにおける9つの言語部門のうち、5つの部門でSOTAをとったモデルについて報告した論文。

### 2. 先行研究と比べてどこがすごい？
コンペは、2017, 2019年と、これまでに2回開催された。
それぞれの回の最優秀手法は以下のとおり。
本論文の手法が↓のCCCより優れているのは、事前に学習した言語モデルに依存しないため、性能を犠牲にすることなく低リソース環境にも適用可能であるという点。

#### 第1回コンペ
最優秀エラー検出手法：WFST-PostOCR ([Nguyen et al. 2019](file:///C:/Users/kammu/Downloads/Post-OCR%20Error%20Detection%20by%20Generating%20Plausible%20Candidates.pdf))
確率的文字誤りモデルを重み付き有限状態編集変換器にコンパイルすることにより、最適なトークン列を見つける。

最優秀エラー修正手法：Char-SMT/NMT（[Amrhein and Clematide 2018](https://www.zora.uzh.ch/id/eprint/162394/1/AmrheinClematide2018.pdf)）
文字ベースの機械翻訳モデルのアンサンブルに基づき、それぞれが異なるperiods of timeのテキストで学習し、先行する2つのトークンと後続する1つのトークンのウィンドウ内で各トークンを翻訳する。

#### 第2回コンペ
最優秀エラー検出・修正手法：Context-based Character Correction (CCC)
多言語BERT（[Devlin et al. 2018](https://arxiv.org/abs/1810.04805)）をファインチューニングしたもの。Attentionメカニズムを持つ文字列モデルに基づく機械翻訳技術が適用されている。

### 3. 技術や方法のポイントはどこ？
character sequence-to-sequenceモデルにより、非常に長い文章を処理することができる。
本手法はシンプルで資源効率に優れ、容易に並列化できるため、様々な長さや難易度の文書に適用可能。

### 4. どうやって有効と検証した？
ハイパーパラメータの違いの影響を調べるために、窓サイズを10〜100まで10刻みで変化させながらGrid Searchを行い、すべての重み付け関数を用いて、disjoint窓またはn-gramで文書を処理し、Greedy SearchとBeam Searchの両方をおこない、CER(文字誤り率)で評価した。

### 5. 議論の内容は？
・本手法は窓サイズの変更に対して安定しているが、窓サイズを大きくすれば必ず性能が向上するわけではない。
・最良の結果は一貫してBeam Searchで得られているが、Greedy SearchのほうがBeam Searchよりも安全。（Beam Searchを使うとGreedy Searchの3倍から10倍遅くなるが、性能が上がる保証はなく、上がったとしてもそこまで差なし）

### 6. 次に読むべき論文は？
わかりません。
とりあえず実装例を探し求めてこの論文に行き着いたので、以下の実装を参考に自分で組んでみます。

[jarobyte91 / post_ocr_correction | Github](https://github.com/jarobyte91/post_ocr_correction/tree/master/notebooks/en)



### モデル
本手法のアイデア：文字列に対して配列モデルを学習し、それを用いて完全な文書を修正する
しかし、文書は数千文字からなる文字列であり、直接用いることは計算上不可能。
そこで以下の三段階を踏む。

> 第1段階：文書をdisjoint窓またはN-gramに分割する
> 第2段階：sequenceモデルを用いて各窓を並列に補正する
> 第3段階：第2段階で得られた部分的な補正を結合し、最終的な出力を得る
>   disjoint窓  -> 単純な結合
>   N-gram      -> 投票方式
> （最終出力を正しいtranscriptionと比較して文字誤り率を算出する。）

#### エラー検出タスク
本システムの核となるのは、文字の並びを修正できる標準的なsequence-to-sequenceモデル。
sequenceモデルとして、Transformerを使用。
入力：修正対象の文書から文字のセグメント
出力：修正されたセグメントとする。

このシーケンスモデルを学習するためには、ナマ文書と、それに対応する正しい転写文の位置合わせが必要だが、これは困難。
↑出力は必ずしも入力と同じ長さではない（文字の挿入や削除があり得る）ため
-> 精度向上のため、デコードメソッドGreedy Search / Beam Searchを適用。

#### エラー修正タスク
2つの方法を試した。

##### Disjoint窓
以下の3ステップから成る。

1. 分割ステップ：修正する文字列を固定長nの分割ウィンドウに分割する
2. 修正ステップ：sequenceモデルを用いて各窓を並列に修正する
3. 結合ステップ：各窓の補正済み出力を連結して最終出力を生成する

この方法では、配列モデルがよく訓練されていれば効果的だが、そうでない場合は、窓の端にある文字が適切な文脈を持たない「境界効果」が起こりやすいことに注意が必要。

##### N-Grams：
以下の3ステップから成る。
この方法では、「境界効果」に対抗するため、入力の全n-gramを利用することで出力に頑健性を持たせることができる。

1. 分割ステップ：補正対象の文字列を文字n-gramに分割する
2. 補正ステップ：各n-gramをsequenceモデルにより並列に補正する
3. 結合ステップ：各n-gramの出力の重なりを利用し、重み付け関数による投票方式により最終出力を生成する

部分出力をどのように結合するか、がこちらでは問題となる。
n-gram の途中で修正された文字は端にある文字よりも多くの文脈を持つため、重みに偏りが生まれる。
-> これに基づいて投票をおこなう。（各位置での重みの合計が最大となる候補の文字が選択される。）

英語での最適なハイパーパラメータは以下とわかった。

> 窓タイプ：n-grams
> 窓サイズ：20
> デコードメソッド：Beam Search
> 重み付け関数：triangle

triangle関数：triangle(p,w) = 1 - |m-p|/2m
（ここで、p: 窓内の当該文字の位置、w: 窓サイズ、m: w/2）


### 学習
・学習過程：モデルがすべてのステップで正しいトークンを生成するようにクロスエントロピ損失を使用した標準的な配列間パイプライン([Cho et al. 2014](https://aclanthology.org/D14-1179/) [Sutskever et al. 2014](https://arxiv.org/abs/1409.3215))
・ハイパーパラメータ調整：[Random Search](https://www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf)


---

## 感想
・Transformerもあやふやな初学者につき、正直なところ、やっていることの（流れはともかく）内容はほぼ理解できていません。
・実装例があるので、学びながらぽちぽち動かしてみようと思います。