Gunosyデータ分析ブログ

Gunosyで働くデータエンジニアが知見を共有するブログです。

記事ベクトルの定量評価手法の紹介

はじめに

こんにちは、20卒 Gunosy Tech Lab 所属の上村です。 Gunosy Tech Labでは、グノシー・ニュースパス・ルクラなどで用いられる記事配信ロジックのアルゴリズム改善を行っています。 Gunosyではニュース記事をベクトルで表現し、様々なロジックに組み込むことで、ユーザ体験の向上を図っています。

活用事例に興味がある方はこちら data.gunosy.io

今回は、記事ベクトルを定量的に評価する手法を紹介していきます。 性能評価の手法として、単語ベクトル評価用データセットのような、 公開されたデータセットを用いて作成した文章ベクトルの評価を行うことはできますが、 独自のサービスのデータから生成したベクトルをそのサービスレベルで評価することは難しいです。 というのも、ドメイン(この場合はサービス)に特化した文章ベクトルはそれぞれ異なるはずであるため、 オープンなデータセットではなく、独自サービスで扱うデータから生成・評価を行う必要があるからです。 また、文章ベクトルの評価を行うデータセットを作るのは難しく、特に優れたデータセットの作成にはコストがかかります。

そこで、グノシーで配信される記事にはカテゴリが付与されていることを利用し、 カテゴリを一つのクラスタと捉えることで、クラスタリングベースの評価手法を用いベクトルの評価を行います。 これにより、データセット作成にコストをかけることなく、独自データでの評価を行うことができます。 加えて、同時に定性評価を行うことにより、定量評価手法の有効性を検証します。

記事のベクトル化

今回は、ニュース記事を学習したWord2Vecを用いて生成した単語ベクトルを用います。 記事ベクトルは、文章を単語毎に分割し、単語ベクトルの和をノルムで割ったものとします。

実験設定

アプリ「グノシー」で配信された過去の記事を用いて、ベクトルを学習し、評価を行います。 過去記事から200万記事程度をランダムにサンプリングし、学習データと評価データの期間が被らないように分割します。 学習データを用いて Word2Vec (以降、w2v) の学習を行い、単語ベクトルを生成し、文章ベクトルを作成します。 また、w2vはPythonのgensimモジュールを用いて学習を行います。

生成したベクトルの結果を比較するため、以下の検証を行いました。

  • タイトルのみか、本文を使うかどうか
  • 文章の品詞を制限するかどうか(制限なし: raw, 名詞のみ: noun)
  • w2v 出力次元数 (300次元, 100次元, 48次元)

また、記事のカテゴリ(エンタメ、スポーツ、etc...)ごとにクラスタを分割し、紹介する定量評価手法(次のセクションで紹介します)を用いて算出したスコアと、ベクトルの類似度をベースに定性的に評価を行った結果を用いて、モデルの評価を行います。

評価指標

紹介する評価指標は以下の4つです。

  1. Pseudo F (Calinski-Harabasz Index)
  2. DB(Davies-Bouldin) Index
  3. シルエット係数
  4. モデル分離度

Pseudo F*1

クラスタ間の分散の合計と全てのクラスタ間の分散の比をスコアにした精度指標です。クラスタの密度が高く、充分に分離している場合はスコアが高くなります。欠点としては、DBSCANのような密度ベースのクラスタよりも、凸型クラスタの方がスコアが高くなることです。

数式は以下となります。データ数Eのデータをn_Ekはクラスタ数、C_qはクラスタqの集合、c_qはクラスタqの中心、c_Eは全データの中心、n_qはクラスタqに属するデータ数を示し、trは行列のトレース(対角成分の和)です。


\begin{align}
\mathrm{Pseudo\ F} &= \frac{\mathrm{tr}(B_k)}{\mathrm{tr}(W_k)} \times \frac{n_E-k}{k-1} \\
B_k &= \sum^k_{q=1}\sum_{x\in C_q} (x-c_q)(x-c_q)^T \\
W_k &= \sum^k_{q=1}n_q(c_q-c_E)(c_q-c_E)^T
\end{align}

DB Index*2

クラスタ間の類似性を精度指標にしたもので、クラスタ間の距離とクラスタ内の要素数の比から計算されます。 スコアが0に近くほど、妥当な分類であると評価が可能です。 欠点としては、こちらも Pseudo F と同じく、密度ベースのクラスタよりも凸型クラスタの方がスコアが高くなります。

数式は以下となります。s_iはクラスタiのセントロイドと各点の平均距離、d_ijはクラスタijのセントロイド間距離を示しています。


R_{ij} = \frac{s_i + s_j}{d_{ij}}\\
\mathrm{DB} = \frac{1}{k}\sum^k_{i=1}  \max_{i \neq j} R_{ij}

シルエット係数*3

クラスタ内のサンプルの凝縮度の精度指標です。 値が大きければクラスタのサンプルが密集して配置され、値が小さければクラスタのサンプルが乖離して配置されていると評価ができます。

数式は以下となります。aは同クラスタに属するサンプルとの距離の平均、bは異なるクラスタに属するサンプルとの距離の平均を示しています。


\mathrm{Silhouette\ Coefficient} = \frac{b - a}{max(a, b)}

モデル分離度

こちらは、2020年言語処理学会で芝山らにBERT事前学習モデルの定量評価手法*4として提案されたものです。 クラスタ内分散とクラスタ外分散の比をスコアにした精度指標です。 スコアが小さいほど、クラスタ内外での分散比が小さくなり、妥当なクラスタであると評価できます。

数式は以下となります。モデルの分離度をsとし、\sigma_iはクラスタiの分散、gは全クラスタの重心、g_iはクラスタiの重心を示しています。


s = \frac{\sum^N_{i=1}\sigma_i^2}{\sum^N_{i=1} \| g - g_i\|}

実装

Pythonで扱うのであれば、Pseudo F、DB Index、シルエット係数は scikit-learnにて実装されているため、それぞれ以下でimport可能です。

from sklearn.metrics import calinski_harabasz_score  # Pseudo F
from sklearn.metrics import davies_bouldin_score  # DB index
from sklearn.metrics import silhouette_score  # シルエット係数

モデルの分離度はこちらになります。

import numpy as np
import pandas as pd

def m_socre(X, labels):
    df = pd.DataFrame({'vector': X, 'label':labels})
    
    # クラスタ毎の重心の計算
    g = []
    for _, _df in iter(df.groupby(df.label)):
        g.append(np.average(_df.vector.values))
    g = np.array(g)
    
    # クラスタ内重心の計算
    a = 0
    for (_, _df), _g in zip(iter(df.groupby(df.label)), g):
        _tmp = np.sum([(_g - _row) ** 2 for _row in _df.vector])
        A += _tmp

    # クラスタ外重心の計算
    g_all = np.average(g, axis=0)
    b = np.sum([(g_all - _g) ** 2 for _g in g])
    
    # モデルの分離度
    score = a / b
    
    return score

結果と考察

以下に、実験の結果を示します。

本文 品詞制限 w2v_size Pesudo F DB index シルエット係数 モデル分類度
なし raw 300   1.4123 13.1624 -0.0034 7710.84
あり raw 300   3.0065 10.8028 0.0017 3622.14
なし noun 300   1.6342 12.3055 -0.0030 6664.00
あり noun 300   2.8329 10.8661 0.0014 3844.16
あり noun 100   2.7723 11.2574 -0.0040 3928.12
あり noun 48   2.6050 11.5338 -0.0099 4180.38

定量評価においては、本文あり/品詞制限なし/300次元のモデルが、全ての定量評価手法において最も良い精度でした。

定性評価を行った結果として最も良いモデルは、本文あり/品詞制限名詞のみ/300次元のモデルとなりました。 こちらのモデルは、どの指標においても最も良い値とはなっていませんが、他のモデルと比較すると相対的に、良い値であると言えます。 しかし、定性評価と定量評価におけるモデルの評価結果は完全には一致しませんでした。 この理由として、品詞制限なし のモデルでは、「第 n 選」の文字列に類似度が高くなっている傾向がありました。 これより、文章の本質的な内容より特定の表現に強いベクトルとなってしまい、クラスタ内の記事の分布が偏ってしまったと考えられます。

また、定性評価の結果として、本文なしモデルでは記事タイトルに含まれる「♡」や「【】」の記号表現に類似度が高くなってしまうことがありましたが、本文ありモデルではそれを改善することができました。 これは定量評価手法の結果の傾向とも一致していました。 その他に、w2vの出力次元数は大きいほど良いベクトル評価となりました。しかし、定量評価の結果では、Pseudo Fにおいてその順には限らないなど、結果として異なる部分がありました。

今回紹介した定量評価手法は、定性評価は完全には一致しませんでしたが、大まかな傾向の目安としては使えることが分かりました。 これらの定量評価指標は、計ることのできるクラスタの特徴が異なるため、定性評価ともうまく組み合わせ、文章ベクトルの特徴を掴むことが重要になると考えられます。

おわりに

記事ベクトルの定量評価に用いることができる4つの手法とその指標を用いた記事ベクトルの評価を紹介しました。やはり、定量評価と定性評価が完全に一致しないのが難しいところだと感じました。定性評価は、一つ一つ記事を見る必要があるため評価に時間がかかってしまうため、うまく定量評価を活用して様々な実験を回していけると良いかなと思います。今後はこれら定量評価手法や、定性評価を基により良いベクトル表現の作成を目指していきます。また、今回の実験では、w2vを用いてベクトルを生成しましたが、BERTのようなDeepなモデルを用いたベクトル生成も検証していければと思います。