過去の記事の空気を読んでみた

こんにちは。昨年クウジットに入社した木村です。

はじめてTokyoZの記事を書くことになりました。

「内容は自由」と聞きましたが、暗黙の許容範囲があるかもしれません。空気を読みたいと思います。そこで、過去の記事ではどんな話題があったのかを調べることにしました。調査の対象は過去に日本語で書かれた記事です。50個あります。

というわけでこれから自然言語処理の話を展開しますが、傾向をつかむ目的のため、細部にはこだわらない方針でいきます。自然言語の例外にすべて付き合っていたら、いくら時間があっても足りません。また、記事の中にあるソースコードおよび図表の中の文字は対象外とします。pythonで一般的なライブラリを用いて計算、可視化を行います。

ブログの空気を読む!その1(ワードクラウドの作成)

最初の段階として、全体の傾向をざっくりつかむために対象記事に登場する名詞でワードクラウドを作成しました。ワードクラウドは出現頻度に応じて単語を大きく図示する方法です。しかし、今回は単純な頻度ではなく、TF-IDF(Term Frequency-Inverse Document Frequency)という一種の重要度を使います。TF-IDFは単語の出現頻度に加え、全文書中数に対するその単語の出現文書数の割合も考慮することで多くの文書に出現する一般的な語の重要度を抑えます。例えば、ある文書群の中で「私」が全部の記事に登場し、かつ頻度も全部の記事で一番だからといって、この文書群で最も重要な単語は「私」とは言えないですね。

今回行った主な手順

  • 形態素解析で名詞を抽出
    • 形態素解析エンジンにはmecabを使用
    • 辞書はmecab-ipadic-NEologdを使用。他には辞書を用意していません。
  • 各記事のTF-IDF値の算出
  • TF-IDFの合計値でワードクラウドの作成

以下ができたワードクラウドです。

だいたいのイメージとあっているようです。弊社は笑顔溢れる会社です。

ブログの空気を読む!その2(トピックの抽出)

もう少し細かく話題の傾向をつかみたいのですが、個別の単語の頻度やTF-IDFを追ってもそれは細か過ぎますし、数が膨大です。値が上位の単語に絞っても、類似語や表記揺れがあった場合は本来上位に来る単語や概念を見逃してしまう可能性があります。

そこで、トピックモデルを使ってトピックを抽出することにしました。ここで言うトピックとは「音楽」や「スポーツ」のような大きな話題と思ってください。トピックモデルは、文書の生成過程についての確率モデルです。より大きな枠組みでは潜在意味解析の一種です(名前からも「空気を読む」っぽい方法ですね)。今回は基本的なトピックモデルであるLDA(Latent Dirichlet Allocation) を用います。文書とトピックが一対一で対応するのではなく、1つの文書に複数のトピックが潜在的に存在すると考え、以下のような流れが繰り返えされることで文書が生成させると仮定します。

トピックの分布をディリクレ分布(多項分布の確率分布の一種)から生成
(例:仮に、音楽10%、スポーツ20%、天気30%、食べ物40%が生成された)

トピックの分布に従ってトピックを選択
(例:仮に、「食べ物」が選択された)

トピック内の単語の分布に従って単語を生成
(例:仮に、「食べ物」トピック内の単語の分布が、仮にアイス40%、ケーキ30%、うどん20%、パン10%とする。その中から「アイス」が選ばれた)

そして、上記で仮置きしたパラメータについて、実際のデータに対して尤もらしい値を推定することでモデルが完成します。

今回行った主な手順

  • 記事のコーパスをTF-IDFで作成(引き続き、話題を知りたいため名詞のみ)
  • 上記コーパスでLDAモデルを作成
    • gensimを使用
    • トピック数はPerplexityとCoherenceから決定
  • トピック内の頻出名詞をワードクラウドで可視化

トピック数はドメイン知識が十分あれば決めてしまっても良いのですが、そうでない場合、いくつかの決定方法があります。今回はPerplexityとCoherenceという2つの指標を使いました。Perplexityは選択肢の数のようなものです。文書中のある単語が不明として、LDAによって絞り込まれた選択肢(ここでは単語)が少なければPerplexityが低い=モデルの性能が良いことになります。Coherenceは単語間の類似度の平均です。意味の近い単語が集まっているトピックを抽出できるのが良いモデルであるという観点で、トピック全体のCoherenceが高ければモデルの性能が良いことになります。今回の記事数から見てトピックは多くても10以下にしたいため、この2つの指標を2から10のトピック数で探索したところ以下の結果になりました。

比較的Perplexityが低くCoherenceは高いのはトピック数が6の時でした。

トピック数6のLDAモデルを作成し、それぞれのトピック内で生成確率ベスト5の名詞とベスト30の名詞によるワードクラウドを以下に掲載します。大胆にトピックに名前を付けてみました。

Topic1 ワイワイ系
笑顔 0.008034
グループ 0.007171
太陽風 0.005199
空実 0.00462
最高 0.004152

Topic2 太陽系
太陽風 0.00697
エントリ 0.005713
激辛 0.005516
API 0.005478
笑顔 0.004531

Topic3 幸福系
因子 0.00618
接続 0.004857
指標 0.004828
カラフル 0.00435
世界 0.004341

Topic4 ハードウェア系
意識 0.005091
MACHINE 0.004821
状態 0.004699
GoPro 0.004472
公開 0.00422

Topic5 炊き出し系
おにぎり 0.008714
味噌汁 0.008703
笑顔 0.006758
健康経営 0.005559
炊き出し 0.005496

Topic6 イベント系
動画 0.005364
距離 0.004607
ロゴ 0.004198
祈祷 0.004068
動作 0.003764

入社以来の弊社についてのドメイン知識を総動員し、自分の中で消化しやすいトピック名を付けることができました。あいかわらず笑顔の強さが際立っています。弊社は笑顔溢れる会社です。

ブログの流れを読む!(トピックの時系列での可視化)

過去の記事のトピックの傾向はわかりました。しかし、この後に新しい記事を書く前提として、これらのトピックの推移(厳密にはトピックに属する確率の推移)を知りたいです。そのために時系列のグラフを描きます。すでにモデルもデータもありますので、少々pandasでデータをこねて表示するだけです。表示にはplotlyを使いました。記事とトピックに属する確率は以下のようになりました。記事番号は記事の登場順です。0番が最初の記事です。

最初の頃は1つの記事が1つのトピックに属する確率が100%に近く、話題が今回のトピックで解釈しやすいことがわかります。しかし、個別のトピックの推移はこのままではわかりにくいです。そこで、記事5本分の移動平均を計算して可視化します。

これである程度流れがわかりそうです。さらに理解しやすいように個別のトピックの推移とワードクラウドを並べて見ていきます。

ワイワイ系

太陽系

太陽風鍋が過去にしばしば話題になっていたようです。

幸福系

ハードウェア系

炊き出し系

コロナの影響でテレワークが推進され、最近炊き出しが開催されていない影響が出ているかもしれません。

イベント系

イベント系は比較的高く推移してきましたが、コロナの影響が出ているかもしれません。

ブログの空気と流れを読んで次の一手を考える!

空気も流れも読めたので、これらを参考に次の記事の話題を考えます。比較的安定しているワイワイ系とイベント系は伝統と解釈してみます。太陽系と炊き出し系はそれぞれピークがずれていますが、食事関連としてまとめて考えると、それは定期的に話題になってきたとも考えられます。

  • ワイワイ系 → 継続
  • イベント系 → 継続
  • 太陽鍋、炊き出し → 食事関連は姿を変えて復活?

と考えると、イベント系の「距離」、「動画」が目についたこともあり、次は「リモート飲み会」の記事が良いかもしれません。

ん?

リモート飲み会はほぼやっていないのでは私にはこの話題では厳しいです!

ここまでで、この記事は3000文字くらいあります。過去の記事の平均文字数は2400文字なので超えていますね。しかも中央値は1971文字です。(文字数だけは)標準的な記事のおよそ1.5倍頑張ったので、ここで筆を置きたいと思います。

最後までお読みいただきありがとうございました。

The following two tabs change content below.

kimura

2019年にクウジットに入社。データ解析およびAI開発のプロジェクトに従事。