日本語テキストを数える手順と、数えても使えなかった話
エンゲージメントサーベイの自由記述を分析したことがあります。結論から書くと、集計も可視化もできたのに、最後まで使えるものになりませんでした。 原因は手法ではなく、その手前にありました。
ひとつは、記述そのものが雑だったこと。設問に対して一行だけ、あるいは「特になし」。読める分量が書かれている回答は、思っていたより少ない。 もうひとつは、頻出語を並べて図にしたところで「それで、何をすればいいのか」に答えられなかったことです。 会議に出したときの空気で分かりました。きれいな図は出せる。でも次の一手に繋がらない。
この章では、その失敗をなぞる形で日本語テキスト分析の手順を書きます。 tidytextの標準的な解説は英語の小説を題材にすることが多いのですが、社内アンケートの日本語はまったく別物です。 途中で何度もつまずくので、つまずく場所を先に示しておきます。
R(tidyverse)と gibasa、tidytext を使って、日本語の自由記述を数えられる形にするところまで。
そのうえで「数えた結果が使えないとき、何を変えるか」を書きます。感情分析ライブラリの紹介で終わらせません。
最初にやるべきは形態素解析ではありません。どれだけの人が、どれだけの分量を書いたかを数えることです。 サーベイの回答率が高くても、自由記述の記入率はまったく別の数字になります。ここを見ないまま分析に入ると、 「全社の声」のつもりで一部の饒舌な人の意見を見ることになります。
中央値と90パーセンタイルを両方見るのが要点です。平均だけだと、長文を書いた数人に引っ張られて実態より豊かに見えます。 中央値が20〜30字なら、それは「文章」ではなく「一言」です。一言の集合から意味を取り出す手法と、 段落の集合から取り出す手法は別なので、ここで方針が決まります。
部署別・在籍年数別に記入率を出すと、それ自体が示唆になることがあります。 書かない層が偏っているなら、そのあとどんな分析をしても、その層の声は最後まで入ってきません。 テキスト分析の結果を読むときに、この偏りを覚えておく必要があります。
tidytextの解説でよく出てくる unnest_tokens() は、空白で区切って単語にします。英語ならそれで足ります。
日本語には空白がないので、そのまま通すと一文がまるごと1トークンになります。形態素解析が要ります。
同じ理由で、AFINN・Bing・NRCといった感情分析辞書も日本語には使えません。あれは英単語の一覧です。 日本語の自由記述に対して感情スコアを出したいなら、日本語の極性辞書を別途用意するか、そもそも感情分析という枠を疑う必要があります。 このあたりを飛ばして「感情分析ができます」と書いてある解説は、日本語データを触っていないと思ったほうが安全です。
RでMeCabを使う方法はいくつかありますが、いま新規に組むなら gibasa が扱いやすいです。
CRANから入り、v0.5.0以降はパッケージ内にMeCabのソースを同梱しているため、MeCab本体を別途インストールしなくてもビルドできます。
返ってくるのが「1行1トークン」の整然データなので、そのまま dplyr と tidytext に繋がります。
prettify() が展開する列名は使う辞書によって変わります。IPA辞書とUniDicでは品詞体系そのものが違うので、
最初に tokens |> count(POS1, POS2, sort = TRUE) で何が返っているかを見てから絞り込んでください。
ここを確認せずに品詞名を決め打ちすると、フィルタが空振りして全部残る、あるいは全部消えます。
ここが実務で最初に効いてきます。一般の辞書には、あなたの会社の部署名も、社内システムの名前も、 社内でだけ通じる略語も入っていません。結果として不自然な位置で切られ、意味のない断片が頻出語の上位に並びます。
対処はユーザー辞書の追加です。手間はかかりますが、追加すべき語はそれほど多くありません。 部署名、システム名、制度名、頻出する略語。この4種類を洗い出すだけで、出力の見え方がかなり変わります。 洗い出しは総務や情シスに聞くより、切られた結果を眺めて拾うほうが早いことが多いです。
自分で辞書を編む前に、まず既存の辞書を替えるだけで解決しないかを見てください。 新語に強い辞書に差し替えると、追加が必要な語がかなり減ります。それでも残るのが本当の社内語です。
切れるようになったら数えます。ここまでは順調に進みます。そして、上位に並ぶのは 「仕事」「会社」「業務」「人」「思う」といった語です。当たり前で、何の情報もありません。
ストップワードを足していけば少しはマシになります。でも、いくら足しても 「その職場を説明する語」は出てきません。全員が同じような言葉を使うからです。 頻度は、共通点を見つける道具であって、違いを見つける道具ではない。ここが構造的な限界です。
違いを見たいなら TF-IDF に切り替えます。「この設問でだけよく出る語」「この部署でだけよく出る語」を出す考え方です。
注意点がひとつ。TF-IDFは珍しい語を高く評価するので、一人しか使っていない語が上位に来ます。 部署の人数が少ないほどこれが起きます。そのまま部署別の一覧にすると、実質的に個人の発言を晒すことになりかねません。 最低出現人数のしきい値を入れてから見てください。
ここまでで、頻出語のランキングも、部署別の特徴語も、ワードクラウドも出せます。図としては成立します。 私が止まったのはこの先でした。その図を見て、次に何をするかが決まらない。
理由を後から整理すると、こうなります。
「評価」という語が多く出たとして、評価制度に不満なのか、評価されて嬉しいのか、区別がつきません。 単語を数えた時点で、肯定と否定が同じ袋に入ります。
全体で集計すると、辞めそうな人の一言も、満足している人の一言も、同じ1カウントになります。 人事が知りたいのは「誰が何に困っているか」なのに、そこが平されます。
打てる手は「制度を変える」「マネージャーに介入する」「配置を見直す」といった単位です。 単語の頻度は、その単位に翻訳できません。ここが一番大きい。
見栄えがするので報告資料に入れたくなりますが、面積が頻度に対応しているだけで、順位も差も正確には読めません。 人に見せる図としては、上位語の棒グラフのほうが誠実です。ワードクラウドを出すなら、 それは分析結果ではなく雰囲気の共有だと割り切ったほうがいいと思います。
手法を高度にしても解決しませんでした。変えたのは、何を数えるかのほうです。
全体で数えるのをやめて、エンゲージメントスコアの高い層と低い層に分け、両者で出現の偏る語を見る。 「両方でよく出る語」は捨てて、「片方にだけ寄っている語」だけを見ます。 これだけで、当たり前の語が自動的に落ちます。
出現数の少ない語で比率が暴れるので、頻度のしきい値は必ず入れてください。
より丁寧にやるなら、頻度で重みづけした対数オッズを使う方法があります(tidylo パッケージなど)。
ただ、最初の当たりを付けるだけならこの単純な比で十分でした。
いちばん効いたのは、実はこれです。テキスト分析を結論を出す道具として使うのをやめました。 代わりに、全部は読めない量の自由記述から、読むべき数十件を選ぶための道具として使いました。
低スコア層に偏っていた語を含むコメントだけを抽出して、原文を人間が読む。 そうすると、単語の集計では絶対に出てこなかった具体的な状況が書かれています。 数十件なら読めます。読んだ内容は、そのまま施策の議論に持っていける形をしています。
テキストマイニングの解説としては地味な着地です。けれど、実務で報告に耐えたのはこの形でした。 「機械が要約した結果」ではなく「機械が選んだ40件を人が読んだ結果」のほうが、聞く側も判断しやすい。
人事データ全般に言えることですが、自由記述はとくに危険です。書いた本人の言い回しがそのまま残るので、 部署と組み合わせただけで誰の発言か分かってしまうことがあります。 匿名で回収したはずのサーベイが、分析の過程で実質的に記名になる。これが起きると、次回から誰も書かなくなります。
サーベイの案内文で「個人が特定される形では利用しません」と伝えているなら、それは分析側の制約でもあります。 技術的にできることと、やっていいことは別だという当たり前の話ですが、コードを書いていると忘れがちです。
gibasa でトークン化し、品詞と原形で絞る。英語の感情辞書は使えないテキストを特徴量として予測モデルに入れる話は、モデルの評価とセットで考える必要があります。 とくに退職予測のような不均衡データでは、精度の見方を間違えると「何も予測していないモデル」が高精度に見えます。 そのあたりは第18章で扱います。
※ 当サイトはAmazonアソシエイトプログラムに参加しています