- PDFファイルからのテキスト抽出は予想以上に難しく、PDFは本質的にグラフィックベースのファイルフォーマットである
- PDF内にはグリフの位置情報しかなく、意味論的なシグナルはほとんど存在しないため、テキストの識別と再構成が難しい
- 検索エンジンではHTML形式のクリーンな入力が求められるが、既存のオープンソースツールには見出しや段落などの構造情報抽出に限界がある
- 機械学習ベースのビジョン方式が最も正確だが、リソースと性能の問題から大規模適用は難しい
- 主な改善策として、フォントサイズと統計に基づく見出し・段落識別アルゴリズムを導入し、抽出精度を高めている
PDFからのテキスト抽出の課題
- 最新の検索エンジンはPDFファイルフォーマットをインデックス化する機能を備えている
- PDFからの情報抽出が容易でないのは、PDFがもともとテキストフォーマットではなくグラフィックフォーマットだからである
- 実際のテキストの代わりに、グリフが座標上に配置された形になっているため、回転、重なり、順序の乱れ、意味情報の欠如などが発生する
- 私たちが通常思い描くテキストとしての情報は、ファイル内に直接存在していない
- PDFビューアでctrl+fによるテキスト検索ができること自体、実は驚くべきことである
検索エンジンの要件と基本アプローチの限界
- 検索エンジンが最も好む入力はきれいなHTML形式である
- 最新の機械学習ベースのコンピュータビジョンモデルが最も良い性能を示すが、
- 大容量(数百GB)のPDFファイルをGPUなしで1台のサーバーで処理するのは非効率的である
- 幸い、この分野は完全な未知の領域ではないため、
- PDFBoxのPDFTextStripperクラスを活用し、出発点として使うことができる
- ただし、見出しなどの意味論的構造はほとんど把握できない—文字列が抽出されるだけである
見出し識別アルゴリズム
見出し識別の基本原理
- 通常、見出しはセミボールドまたはそれ以上に太い文字が孤立していることを利用できる
- 太字ではない見出しもよくあるため、この方法だけでは限界がある
- 多くの場合、フォントサイズが見出しを区別する基準になる
- しかしフォントサイズは文書ごとに大きく異なり、グローバルなしきい値は使えない
フォントサイズ統計の活用
- 各ページにはたいてい**支配的なフォントサイズ(本文)**が存在する
- 1ページ目(表紙)には説明的な内容や著者情報があるため、フォントサイズ分布が異なる
- ページごとにフォントサイズ分布が異なるため、文書全体ではなくページ単位の統計を使うのが効果的である
- 各ページの中央値フォントサイズに20%ほど上乗せすると、見出しをかなり正確に識別できる
複数行の見出しの結合問題
- スタイル上の理由で、見出しが複数行に分かれることもある
- 見出しを結合するタイミングの判断は簡単ではなく、2行以上の見出しや著者名、別の強調テキストが混在する場合がある
- 結合ルール:
- 同じフォントサイズと太さを持つ連続行を結合する方法はかなりうまく機能する
- ただし例外は多く、無差別に結合するとおかしな結果を招きうる
段落識別の改善
- PDFTextStripperは行間とインデントに基づいて段落を識別する
- 行ごとの区切りしきい値に固定値を使っているため、文書ごとに異なる行間への対応には限界がある
- とくに論文草稿やプレプリントでは1.5〜2倍の行間も珍しくない
- しきい値が大きすぎると、見出しが本文に含まれてしまう誤りが起きる
統計ベースの段落区切り
- フォントサイズと同様に、行間についても統計処理を適用する
- 行同士の距離の中央値を活用することで、どのような行間でも堅牢な段落区切りが可能になる
結論
- PDFからテキストを抽出することは、本質的に完全にはなりえない
- PDFフォーマット自体がその用途向けに設計されていないためである
- 実装では妥協が不可欠であり、「十分によい」程度の結果を得る戦略が重要である
- 検索エンジンでは、見出し、要約、主要な構造的手がかりといった意味のあるシグナルの抽出に集中するのが効率的である
参考サンプルテキスト
- Can Education be Standardized? Evidence from Kenya (2022) - Working Paper
: Guthrie Gray-Lobe, Anthony Keats, Michael Kremer, Isaac Mbiti, Owen W. Ozier
- The theory of ideas and Plato’s philosophy of mathematics (2019)
: Dembiński, B.
- The role of phronesis in Knowledge-Based Economy (2024)
: Anna Ceglarska, Cymbranowicz Katarzyna
1件のコメント
Hacker Newsのコメント
人生で何か新しくて面白いものに出会ったと思っていたら、昔それについて何カ月も、あるいは何年もかけて専門家になっていた記憶がぼんやり蘇る、という経験をしたことがある。すごくクールなことをやっていた時期ですら、頭の中からすっかり消えてしまっていて、また最初からやり直しているような気分になる。6〜7年前にPDFとOCRでかなりすごいことをやっていたという曖昧な記憶がある。Googleで検索してみたら、「tesseract」という名前に聞き覚えがあった
2006年ごろ、初期のハック可能なe-readerだったiRexで、多段組みの科学論文からテキストをコピーできないことにいら立っていた。当時のPDFビューアにはpopplerが使われていたので、多段組み文書の読み順を推定するようにpopplerを改造した。そのために、tesseractの作者であるThomas BreuelのOCRアルゴリズムを参考にした。これは一種のヒューリスティックなハックで、アクセシビリティAPIとの相性はよくなかった。マルチカラム選択機能は導入されたが、メンテナを説得するのに苦労した。ともあれ、こうしてkpdfにマルチカラム選択機能が入った。最近では、こういう用途ならtesseractを直接使うほうがずっと理にかなっていると思う
PDFというフォーマットのせいで無駄になった人類の何十年分もの時間は取り戻せない。この狂った状況がいつ終わるのか気になる
Tesseractは長いあいだ最高のオープンソースOCRだった。でも最近は、精度とGPUアクセラレーションの面ではdocTRのほうが優れていると思う。docTRは、さまざまなテキスト検出・認識モデルを組み合わせられるパイプライン構造になっている。PyTorchやTensorFlowで学習やチューニングもできるので、特定ドメインにより適した性能を引き出せる
人生とはそういうものだ。プロジェクトを終えるたびに「これでこの分野の専門家になった。でもたぶん二度とこれをやることはないだろう」と思う。なぜなら次は、まったく新しいテーマをまたゼロから始めることになるからだ
この前、誰かにC++について聞かれたとき、「真面目に仕事でやったことはない」と答えた。ところが後になって、20年ほど前にBorland C++で作ったプライベートなインスタントメッセンジャーのクライアントコードを書いていて、何千人も使っていたことを思い出した。こういうことはよくある
君の頭の中のことまではわからないけど、たぶん本当にtesseractだったんだと思う。自分にも似た経験があって、私の場合は12年くらい前のことだった
HQが流行っていた頃、tesseractでHQのクイズを自動で解くツールを作ったことがある。アプリの問題画面をスクリーンショットして小さなAPIに送信し、Googleで問題文を検索して、それぞれの答えが何回出てくるかを数えて確率順にランキングする仕組みだった。正確ではない単純な方法だったけれど、作っていてとても楽しかった
風で葉っぱが飛んでいったら、ただ別の葉っぱを探すヒアリと大差ない現象だ
7〜8年前、20代の頃のことなら今でもかなり鮮明に覚えている。少し年齢差があるのかもしれないし、健康診断を受けてみるのも勧める
PDFのコンテンツストリーム——テキストを囲むBT…ETや、フォントや座標を指定する各種オペレータなど——を、ブラウザの開発者ツールの「要素を検証」のようにソースレベルで“見て”、レンダリング結果と並べて比較・分析できるツールがあればいいのにと思う。今のビジョンモデルがPDFを「見る」ように処理してテキストを読む流れとは別に、実際にPDF内部にどんな情報が入っているのかを深く理解したい。いくつかツールはあるが、オブジェクト単位までしか見せず、コンテンツストリームの中までは掘り下げてくれない。サンプルPDFの実際のストリームソースとレンダリング結果をHTMLのように並べて比較・分析し、どの部分がどう表現されているのか確認できる環境が欲しい
MozillaのPDF.jsでPDFをDOMにレンダリングすれば、ほぼ近い体験はできると思う。たとえばTjやTJのような演算子は、それぞれ<span>やその集合に変換される。おそらく元文書に忠実である必要があるからだろう
cpdfツールを試してみるといい(自作です)。cpdfの
-output-jsonおよび-output-json-parse-content-streamsオプションでPDFをJSONに変換して、いろいろ実験できる。逆にJSONからPDFへ戻すこともできる。ただしリアルタイムのインタラクションはない無料またはオープンソースのツールを探しているのだと思うが、昔のAcrobat Proを使っていたとき、かなり近い機能があった。ただしページを検査するというより、コンテンツツリーをたどる方式で、オブジェクト/ストリームまでは見せても個々の命令までは降りていかなかった
「ビジョンモデルでPDFを“人のように見る”こと」と「実際にPDFにどんなデータが入っているかを知ること」の両方を、私たちはTensorlakeで作っている(そこで働いている)。単にテキストを読むだけでなく、表、画像、数式、手書き文字なども本当に理解して、Markdown/JSONとしてデータ抽出できるようにし、AIやLLMなどのアプリに適用できるようにしている」 https://tensorlake.ai
完全に望みどおりのレベルではないが、PDF内部のさまざまな描画演算を“ライブ”で見せるインスペクタを備えたノートブックがあるので、参考になるかもしれない https://observablehq.com/@player1537/pdf-utilities
何年もAppleでこの問題に取り組んでいた。要点は「すべては幾何学だ」と受け入れて、単語間隔と文字間隔をクラスタリングして区別するアルゴリズムにある。多くのPDFには有効だが、近くで見ると種類があまりに多くて、一部はがっかりする。今やり直すなら、OCRは完全に外して幾何情報ベースで進めつつ、機械学習を組み合わせると思う。事前に既知のテキストでPDFを作って機械学習に使えば、学習データ構築も自動化できる。(WWDC 2009のBertrand Serletの発表動画がある)
これは「PDF to Text」という単一の問題ではなく、実際には3つのカテゴリに分けられると思う。(1)信頼できるOCR(検索、ベクトルDBへの投入など)、(2)構造化データ抽出(特定の値だけ抜き出す)、(3)文書全体のパイプライン自動化(例: モーゲージ処理の自動化)。Marginaliaの目的は(1)で、最近はGemini FlashなどのおかげでOCRは低コスト化・汎用化している。しかし(2)と(3)はもっと難しく、完全自動化には今なおデータセット構築、パイプライン設計、不確実性の検知と人手介入、ファインチューニングなど、多くの人間の努力が必要だ。未来はこの方向にある。(LLM文書処理会社を経営している) https://extend.ai
(4)として、さまざまな形式の文書に対する信頼できるOCRと意味抽出、つまりアクセシビリティのためのソリューションも必要だと思う。これが難しい理由は、一般的なワークフローと違ってユーザー文書の種類を予測できないこと、表・ヘッダー/フッター/注釈/数式などテキスト以外の要素も抽出しなければならないこと、エラー最小化が求められるので必要以上にOCRを使えないこと、埋め込みテキストとレンダリング内容が一致しない場合があること(隠しテキストや非定型な組み合わせなど)、ローカルアプリ中心で動くためサーバー活用が難しいこと、インプリンター用途の文書に対するForm対応が必要なことなど、複合的な難題が山積しているからだ。現時点でこれらを完全に解決したソリューションは存在しない
VLMでOCRパイプラインを簡素化したと言っても、実際の複雑な文書では非常に難しい、という警告だ。単純な画像ラベルには優れていて、ごく単純な文書には使えるが、表・ヘッダー・整理要約などが入った文書ではひどくhallucinateする。したがって実運用ではほとんど使えないレベルだ
Markdownへの変換の途中で、ヘッダー検出などさまざまな問題に直面している。最近のOCRは素晴らしいが、文書全体の構造を保つことのほうがはるかに難しい。LLMを何度も通して構造を抽出し、ページごとにコンテキストを入れる方式で、ようやくそこそこの結果を得ている
より良い解決策は、PDF内部に編集可能なソース文書を添付することだ。LibreOfficeなら簡単にできる。通常、容量もそれほど増えず、テキストの意味も明確にわかる。既存のPDFリーダーでも問題なく使える
既存のPDFからのテキスト抽出が問題になっているときに、PDFの作り方への助言が本当にどれだけ役立つのかは疑問だ。こういう解決法が本格的に効果を発揮するのはいつになるのだろう
そのとおりだが、ソース文書とレンダリングされたPDFの内容がまったく違ってしまう危険もある
正しい意見だが、PDFを作る側とPDFを使う側の利害が一致していないと有効ではない。電子証拠開示(e-Discovery)の分野では、相手方弁護士が資料を使いにくくするため、わざとPDFに変換して提出する慣行がよくある。その結果、リソースの乏しい公選弁護人は資料処理により多くの時間を取られ、実質的な不利益を受ける。これを防ぐには、各種データを標準的な機械可読フォーマットで提出することを法的に義務づけるべきだと思う
もしソース文書にアクセスできるなら、PDF内部に添付するのはとても良い。しかし大半の場合、こちらにはそうしたコントロール権がない
本当の問題の大部分はレガシーPDFだ。うちの会社にも何千件と溜まっていて、一部はひどいスキャンだ。Adobe OCRが埋め込まれているものもあるが、大多数にはまったくない
下のPDFは、実際には.txtファイルだ。拡張子を.pdfに変えてPDFビューアで開けるし、テキストエディタで直接編集して、画面に表示される内容、フォント、フォントサイズ、行間、1ページ当たりの文字数や行数、用紙サイズなど、さまざまな部分をコントロールできる。(実際のPDFテキスト例を含む)
PDFにはバイナリストリームも埋め込める。PDFはテキストではなく、レイアウトとグラフィックのために作られたフォーマットだ。例のように各行がまとめて現れることもあるが、実際には文字ごと、単語ごと、あるいは無秩序に表現されることすらある
PDFは「Portable Document Format」の略だ。7-bit ASCIIファイルとしてエンコードされていて、さまざまな機器やOS環境で高い移植性を誇る。(参考: Adobe公式文書リンク)
この例はPDFの“Hello World”だ。最近のPDFはほとんどがオブジェクト(obj)をdeflateで圧縮し、それらのオブジェクトをストリーム内にグループ化しているので、より複雑になっている。だから単純なテキストとして
6 0 Objを検索しながら解析するのは非常に難しいPDFからテキスト、特に構造化テキストを取り出すのは決して簡単ではない。HTMLテーブルなら比較的簡単に抽出できることが多いが、PDFでは表のように見えても、実際にはレンダリングされた座標ベースでテキストやグラフィックが散在しているだけだ。私もPoppler PDF utilsでPDFをHTMLに変換してから、テーブルヘッダーを見つけ、各値のx座標を基準に列を判定して、行ごとのデータを抽出する方法を使っている。見た目は粗いが、整形済みtxtを使うよりは信頼できる結果になる
WebページとBeautifulSoupのようにPDFからデータ抽出できないのが不満で、そういうインターフェースを持つライブラリを自作した。(
page.find形式の例)PDFごとにケースが地獄のように多様なので、抽出ノウハウや奇怪なPDFの例を集めてライブラリ化している https://jsoma.github.io/natural-pdf/ , https://badpdfs.com/いつかPDFから表データを自分のデータ処理ソフトウェアに取り込みたい。C++アプリに組み込めて、無料か非常に安価なライブラリをご存じの方がいたら教えてほしい
(国家機関の文書のように)表示可能なテキストと、実際に抽出されるテキストがまったく違う文書がある。こういうケースは時々ある
PDFは本質的にマークアップ/XMLフォーマットだ。同じPDFでも本当に無数の作り方がある。グラフィックツールから書き出せばグラフィックとテキストが混在したPDFになり、ワープロから書き出せばテキスト中心のPDFになるなど、多次元的な結果が生まれる。作成アプリが情報をどう扱うかが、PDF出力のされ方に大きく影響する。既製ユーティリティとしては、cisdemなどさまざまな製品群がある程度は構造化データの抽出に使える。ただし、作業ごとに適した道具が必要だ
私の気に入っている例の1つが、この論文PDFだ(リンク付き)。1ページ目には典型的な2段組みテキストと中央ヘッダーがあり、両段のあいだに割り込むテキストや、行長やインデントが変化する要素まである。ページヘッダーも奇数ページと偶数ページで異なり、セクションヘッダーのルールもばらばらだ。段落も常にインデントされるわけではなく、行間にも変動がある。さまざまな問題の総合セットだ
自分で簡単なPDFパーサを書いてみたとき、このフォーマットのやり方に驚いたことがある。だからこそ、なぜこのフォーマットがテキスト中心の用途でこれほど多く使われるのか、いつも不思議に思っている。たとえば請求書なら、デジタルシステムにとってはデータ抽出が容易で、人間にとっては整形された形で見やすいのが望ましい。だから業界全体が、より良いフォーマットへ段階的に移行してほしいと思う
PDFから「有用な情報」を抽出するのがまさにTensorlakeの仕事だ(https://tensorlake.ai)。PDFにはテキストだけでなく、表、画像、数式、手書き、取り消し線など多様な情報が含まれているので、開発者として私たちはテキストを単に「読む」だけでなく「理解」できなければならない。(社員であることを明示)