Leverages データ戦略ブログ

インハウスデータ組織のあたまのなか

形態素解析の精度向上を頑張った話

はじめに

こんにちは。データ戦略室データエンジニアリンググループの森下です。
普段はデータエンジニアとして、主にデータ活用基盤の保守運用や機能追加、ツール開発やデータ抽出・可視化といった業務を行っています。もともと機械学習への興味はありましたが、本記事の内容以前では、業務で使用したことはありませんでした。今回、初めて機械学習の業務を経験する事ができ、非常に多くのことを学ぶことができました。本記事は未経験者の奮闘記となりますので、これから機械学習を学ぶ方・業務に活かす方にとって参考になれば幸いです。

経緯について

データエンジニアとしてデータ活用基盤の構築や保守運用をしていく中で、機械学習へのデータ活用は自然と考える部分です。しかし、書籍やチームの勉強会で機械学習について少しずつ学んではいるものの、業務で機械学習を使用したことはありませんでした。
そのような状況の中で、機械学習の業務に携わりたいという思いが少しずつ芽生え、次第に大きくなっていきました。そのため、チームのデータサイエンティスト(以下、「先輩」)に日頃から「初心者がチャレンジできる仕事があれば自分に担当させてほしい」という話をしていたところ、今回の記事となる自然言語処理を使用した社内ツールの改修案件を任せていただけることになりました。やりたいことを普段から周囲の人間に話しておくことは重要です

改修したツールと使用されている自然言語処理について

今回の案件は既存ツールの改修です。SEO対策のツールとして、サイトを1つの文書とみなし、自社サイトと他社サイトの文書を比較することで、SEO対策に活かせそうな単語を自動で抽出するものになります。
使用されている自然言語処理の分析手法は以下になります。

TF-IDFについては、前回のブログ記事で解説されていますので、興味がある方はそちらをご確認ください。
https://analytics.leverages.jp/entry/2021/06/17/150000

今回の案件で行ったこと

ここからは、今回の業務で行ったことを詳細に記載していきます。他の業務と並行して進めていたこともあり、2ヶ月ほどこの業務を行っていました。

1:業務説明と進め方の確認

まずはじめに、ツールを開発した先輩からもともとのツール導入の目的やツールの概要を説明していただきました。また、ツールのどの部分に手を加える必要がありそうか、ということも説明していただきました。当時は説明を理解できていたつもりですが、
「〜〜ということで、形態素解析に使用しているユーザー辞書の登録単語を増やします」という理由の部分をほとんど理解していなかった、ということが後々判明します。

業務を進めるにあたり、まずは自然言語処理について理解を深めるところから始めます。当時の知識は、「TF-IDF とか word2vec ってどこかで聞いたことあるな……」程度でした。そのため、いきなり既存ツールのソースコードを読むより、使用されている機械学習の理論について、ある程度の理解が進んだところで実装方法を確認したほうがよいと考えました。
手を加えるところはツールの一部分ですが、ツール全体の仕様やソースコードの挙動を理解していないと改修する意味があまりありません。

2:本を読む

まずは、体系的にまとまった本を読んで概要を理解しようと思いました。先輩から『Pythonによるテキストマイニング入門』という本をお借りし、時間を見つけては読み進めていきます。読んでいる最中の気持ちとしては、「TF-IDFとかデータ戦略室内の勉強会でやったな……全然覚えてないや……」とか「単語が半角スペースで区切られている英語と違って、日本語の分析って面倒なんだな……」といったものでした。数式もあまりなく、平易な日本語で記載されているので、概要を把握するには良い本です。ソースコードの記載もありますが、時間の関係で目を通すだけで写経は行いませんでした。

3:ツール動作検証のための環境構築

本を読み終えた後は、動作と仕様を理解するため、既存ソースコードを使用してツールを動かしていきます。形態素解析には MeCab というライブラリを使用するのですが、ローカルの MacBook に入れようとしたらエラーで入りません。エラー内容を先輩にお見せしたところ、「あ、面倒なやつだ」とのこと。諦めてチームで運用している共用サーバーのLinux環境に入れることとします。
なんとかいろいろ調べて Linux 環境で MeCab が動くようになりました。1日中この作業をしていたわけでは無いですが、環境構築だけで2日ほどかかったと思います。

4:ソースコードを読んで動作検証

無事に実行環境を構築できたので、ツールを動かしつつソースコードを読み進めていきます。先に本を読んで事前知識を身につけておいたおかげで、全体の仕様は早めに理解できました。しかしながら、詳細に確認していくと、やはり機械学習周りでつまずくことが増えていきます。

TF-IDFを例に説明します。
この時点でのTF-IDFに対する知識は、「文書内の単語について、単語のTF-IDF値を計算することで重要度を算出することができる」というものです。TF-IDF値の計算に用いるTF(Term Frequency: 単語の出現頻度)とIDF(Inverse Document Frequency: 逆文書頻度)の計算方法は、書籍に記載されていますので、机上では理解できています。
ソースコードで計算する場合は、scikit-learnの TfidfVectorizer を使用して以下のようになります。

from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer()
a = vectorizer.fit_transform(document) 
b = vectorizer.get_feature_names()

この4行だけでも、以下のような確認が発生しました。

  • scikit-learn の TfidfVectorizer を確認する
  • fit_transform の定義を確認する
  • fit_transform の 返却値である a の中身を確認する
  • get_feature_names の定義を確認する
  • get_feature_names の 返却値である b の中身を確認する
  • TF-IDF値を計算している関数を確認する

このように詳細に確認していくと、ライブラリを使用して数行で完結するソースコードについて、その動作や裏側の計算処理を理解するのに30分ほどかかることもありました。

5:改修箇所を特定

既存ツールのソースコードを全て読み、どのような処理を行っているかを全体像から詳細まで把握できました。
把握した結果、最初に業務説明を受けた時と同じく、「形態素解析に使用しているユーザー辞書の登録単語を増やす」という結論に自分でも至ります。ツール全体を見通したことで、「辞書の登録単語を増やす」という作業をする意味が、説明を受けた当初よりも理解を深めることができました。同時に、この作業がどれだけ地道で地味なものかということも理解できました。

6:辞書の単語を追加

ユーザー辞書の登録単語を増やす目的は、業界独自の用語を正しく形態素解析し、1つの単語として認識させることです。今回対象となる業界は、看護・介護業界です。以下のような用語は、本来であれば1つの用語としてカウントするべきですが、通常のシステム辞書を用いた形態素解析では複数単語に分割されてしまいます。

本来の用語 分割されてしまった結果
特別養護老人ホーム 特別 養護 老人 ホーム
社会福祉法人 社会 福祉 法人
介護福祉士 介護 福祉士
訪問看護ステーション 訪問 看護 ステーション

ここでの問題は、「分割されるべきでない単語が分割されている」ことです。そのため、登録するべき単語候補を抽出するために、「前後の数単語を結合し、結合された単語の出現数をカウント、出現頻度の高い単語について辞書登録可否を確認する」というアプローチを取りました。(ちなみにこのアイディアは先輩のアイディアです。)

2つの単語を結合する場合を例に説明します。
形態素解析済みの文書の中に、「特別 養護 老人 ホーム」という連なりがあった場合、直後の単語を結合し、「特別養護」「養護老人」「老人ホーム」という3つの単語を新規に作成します。その後、結合した単語一覧の中で、「特別養護」「養護老人」「老人ホーム」の出現頻度をカウントします。最後に、出現頻度の高い順番でソートし、登録するべき単語かどうかを確認していきます。形態素解析済みの文書に出現する全ての単語の対して上記の処理を行うため、候補の単語は何万も出現しますが、出現頻度順にソートすることで効率よく精査をすることができます。しかし、単に出現頻度が高いというだけで、単語として成立していないものも多く出現します。例えば、以下のような単語は、出現頻度が高いものの単語の登録はしません。

  • 看護師看護師
  • 交通支給
  • 東京神奈川

この作業を3単語結合と4単語結合のパターンで実施し、登録する単語を増やしていきました。結果的に名詞だけで700単語ほどを追加することになります。

7:辞書を追加して精度向上を検証

新しく用語を追加した辞書を使って形態素解析をかけていきます。
精度の向上は、AUCやAICといった統計量を用いて数字で判断できるものではなく、「ツールを使用して抽出できた単語に対して、ユーザーが精度向上したと感じることができたか」によって判断します。数値で判断できるものではないので、辞書追加前と比較して何%向上した、といった形で比較検討することができません。辞書追加→形態素解析→分割後の文書を確認→辞書追加……というサイクルを何回か回して精度を向上させていきます。

まとめ

既存ソースコードを読み、動作検証をしている段階で痛感しましたが、機械学習をプロダクト実装する際には、「機械学習の理論の理解」と「ソースコードとしてどのように書くかの理解」の2つが必要です。書いていることは当たり前のことですが、通常のアプリケーション開発では、やりたいことに対して「ソースコードとしてどのように書くか」という部分さえ押さえれば実装可能であることが多いと思います。
今回の業務で最も時間がかかった部分は、既存ツールのソースコード理解であり、ソースコードでは数行で終わってしまう「機械学習の計算を理解する」部分でした。今回の案件の前から、チームの勉強会や書籍からある程度は理解できていた部分ではありましたが、業務として機械学習に触れたことで、以前より格段に理解が深まりました。
また、日頃からやりたいことを発信していたため、初めてながら機械学習の仕事を任せていただきました。今後もチャンスがあればエンジニアとしての立場から機械学習を活用した業務に挑戦し、スキルの幅を広げていこうと思っています。