質問: テキストから情報抽出をしたい(非構造データからJSONなどに出力)場合には、どのようなアプローチの方法が良いでしょうか。 ライブラリやAPIがあれば、教えていただければと思います。 言語としては、主にJava、Python考えています。 下記に示している例の表では列の数が、7列ですがこの数を増減できるような作りにもしたいと考えています。 (情報抽出する際のカテゴリを増やしたい) よろしくお願いいたします。 --- 例). メールの場合 株式会社○○の山田太郎です。 仕事情報をご案内いたします。 【案件名】 XXフォーラム 【勤務地】 東京 【要因】 30名 【作業内容】 ・チケット管理 ・会場内案内 ・会場設置(椅子運び等) 肉体労働もあるので男性の方が好ましいです。 基本的に日中業務ですが、深夜できる方も募集しています。 以上よろしくお願いいたします。 --- ↓↓情報抽出して構造化データにする↓↓ | 案件名 | 勤務地 | 要員 | 性別 | 作業内容 | 勤務時間帯 | その他 | | --- | --- | --- | --- | --- | --- | --- | | XXフォーラムイベントスタッフ | 東京 | 30名 | 男性が好ましい | チケット管理, 会場案内, 会場設置(椅子運び等) | 日中 | 深夜できる方も募集中 |
回答: > > テキストから情報抽出をしたい > > どのようなアプローチの方法が良いでしょうか > > > 先に断っておくと、**固有表現抽出**を含めた**自然言語処理**は、 AIなどと同じ最先端の分野なので、希望通りにできる保証はありません。 もし簡単に汎用化できたら、安価なソフトが商品化されて、とっくに普及してるはずです。 では、どういうアプローチをしたら良いか。概要から言いますと、 情報抽出は部分的には可能なので、**ドメイン**を絞るやり方が良いです。 逆に、汎用的にやろうとするほど、高確率で失敗します。限定してください。 自然言語処理は、人工知能と文字列処理のあいだにありますが、 **ドメインを絞ることで、文字列処理に近づける**と、実現可能性が高まります。 具体的にどういうことか、ご質問のサンプルで考えてみましょう。 > > 【勤務地】 > > 東京 > > > 【要員】 > > 30名 > > > 「東京」などの地名の前に、必ず「【勤務地】」が来るなら、 「30名」などの人数の前に、必ず「【要員】」が来るなら、 たんなる文字列処理の問題です。しかし、実務的にはそうではない。 たとえば、【】でくくってくれないかもしれない。 「要員」の代わりに「人数」と表現するかもしれない。 それくらいならまだ、**正規表現**など文字列処理で対応できます。 さらに、「勤務先は東京になります」になると難しい。 まあこれは一文から勤務先の表現と地名を抜き出せばいいでしょう。 しかし、「東京から送迎バスを出すので、別働隊の埼玉**ではなく**、 千葉行きに乗って向かってください」の勤務先をどうするかは難しい。 **意味や文脈**が関係してくるからです。 この一文を抜き出すのに、前後の文も判断する必要があるかもしれません。 こうして、正規表現の単純な抽出では、すぐに限界を迎えます。 そもそも、勤務先を「東京、千葉」と並列にして良いのかとか、 集合場所と勤務先は別なのかとか、**要件**が決まっている必要があります。 そういうわけで、抽出する先の文章の書式が**統一**されているほど、 文字列処理に近づき、実装しやすくなります。 たとえば、表から表なら位置を変えるだけなので簡単でしょう。 まとめると、**決め打ちできる書式をいかに増やすか**が重要です。 情報収集するサイトを絞るとか、データの出所が社内なら、 フォーマットを統一するようにしておくとか。 抽出の処理自体にも触れておきましょう。 分類が文字列を入力して、分類基準を出力するのに対して、 抽出は**文字列を入力して、部分文字列を出力する**のが特徴です。 質問文に処理対象と欲しい処理結果は書いてありますが、 その**中間の部分文字列をどう定義するか**が処理のポイントです。 「対象の文書(全体文字列) → 部分文字列 → 表などに構造化」という流れ。 この部分文字列とは、たとえば「東京」とか「30名」とかです。 しかしこれは、「神奈川」や「100人」も抜き取りたいので、 「地名」とか「人数」とか**抽象化**された概念になります。 また、「東京」とか都道府県限定なのか、それとも、 「秋葉原」「新宿」とかでも良いのかなど、要件と関係してきます。 それに、「30名」は「30人」も、「三十名」「三十人」も抜き出したいでしょう。 こういうのを正規表現だけで表現すると、 規模が大きくなるにつれ、非常に複雑になりやすい。 だから、せっかくJavaを使うなら(Pythonなら関数型のやり方でもいいかも)、 **オブジェクト**で表現したいです。DDDなどでいう**ドメイン**モデルです。 私なら、まず「人数」をクラスにして、 さらに、数字部分と単位部分も別のクラスに分けて、 合成して人数にして......と、徹底的に分解していきます。 自然言語処理は非常に複雑で難解になりやすいので、 クラスが増えても、それだけ実装コストを掛ける意味があると思います。 ネストしたIF文と正規表現の嵐だと、結局メンテ不能になっていきます。 一方、**部分文字列をオブジェクトの集合で表現する**と、それぞれ独立しているので、 変更の対象が分かりやすくなり、変更容易になるのでメンテしやすいです。 まとめると、全体の文書を部分文字列(オブジェクト)の集合に分解して、 後は正規化(30か三十か単位をそろえるなど)し、表などに構造化して出力します。 なお今回、長く難しい話になるので、**パース(構文解析)**の話題を省略しましたが、 単語単位だけでなく、文法にそって文単位で解析すると、 難度は一気に上がりますが、より本格的な自然言語処理が可能になります。 そして、このパースを視野に入れているから、オブジェクトにしたいのです。 パースでは構文木を作りますが、正規表現では階層構造の表現が難しい。 しかし、**クラスは階層構造を表現**できます。そのためのクラスです。 > > ライブラリやAPIがあれば、教えていただければと思います。 > > > 形態素解析なら「MeCab」、みたいに定番のライブラリもありますが、 全部APIを叩くだけで済むようなことはまずなく、 普通は泥くさく書く部分が出てくるはずです。