Goodな生活

INTPの好奇心の受け皿

潜在意味解析(LSA)における特異値分解【Python】

LSA(Latent semantic analysis)とは

  • LSAは教師なし文書分類種類の一つで、Latent semantic analysis;潜在意味解析の略称。文書中に明示的に現れないトピックやカテゴリーを「潜在的な意味」だと考える。
  • やっていることは単語空間の行列に対して特異値分解という線形代数の操作を行うことで、低ランク近似行列を作成し、単語空間よりも次元の小さなトピック空間で文書を表現する。ちなみに単語空間の生成はBoWでもtf-idfでも良い。単語空間よりもトピック空間の次元が小さいため、文書の類似性に基づいて文書を集約する(次元を削減している)と言うことができる。
  • 同じく次元削減の手法として主成分分析(PCA)があり、これは共分散行列を固有値分解することで主成分(固有ベクトル)を得る。PCAは正方行列にのみ適用できる一方、特異値分解は正方行列に限らない。(基本的には文書の数よりも単語空間の次元の方が大きくなる)
  • 特異値分解で得られた潜在トピックのベクトルは違いに直交する、つまり独立であるという強い制約を置かれる。これだと文書とトピックが1対1対応することになり、複数のトピックの要素を異なる割合で含む文書の違いを捉えることができない。ハードクラスタリングになってしまう

特異値分解の実行

奥村(2015)に従って特異値分解を実施します。drive, automobile, car, play, musicという単語を含む4つ文章を用意します。

import numpy as np

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import TruncatedSVD
import pandas as pd

# 文書の準備
documents = [
    "In the bustling city, people drive their automobiles with ease. The automobile industry has seen significant advancements, making the drive smoother and more enjoyable. Every new model of the automobile is more efficient. As they drive through the city, the sight of different automobiles is common.",
    "Every morning, they drive their cars to work. The drive through the traffic is often long, but their cars make it bearable. On weekends, they drive to scenic spots, enjoying the comfort of their cars.",
    "In the park, children play with enthusiasm. They do various games, creating a joyful atmosphere. Nearby, musicians practice their music, adding a harmonious backdrop. The sound of music blends with the children's play.",
    "At the community center, children eagerly participate in various play activities. They play games and explore new things. The instructors encourage them to play creatively. There is also a music session where they can experience different instruments."
]


次にCount Vectorizerを使って文書-単語行列を作成します。ここではベクトル化する単語を5つに絞っているため、出力される文書-単語行列の次元は4 x 5になります。

# CountVectorizerを使用して文書-単語行列を作成
vectorizer = CountVectorizer(vocabulary=['drive', 'automobile', 'car', 'play', 'music'])
X = vectorizer.fit_transform(documents)

# 行列をDataFrameに変換して表示
df = pd.DataFrame(X.toarray(), columns=vectorizer.get_feature_names_out())

この行列に特異値分解を行い、U(文書-トピック)、Sigma(トピック-トピック)、V(トピック-単語)の3つの行列に分解します。n_components=2なのでトピックの数を2に指定しています。

# SVDの実行
svd = TruncatedSVD(n_components=2)
U = svd.fit_transform(X)
Sigma = np.diag(svd.singular_values_)
VT = svd.components_

# DataFrameに変換して表示
U_df = pd.DataFrame(U, columns=[f'Topic {i+1}' for i in range(U.shape[1])])
Sigma_df = pd.DataFrame(Sigma, columns=[f'Topic {i+1}' for i in range(Sigma.shape[1])])
VT_df = pd.DataFrame(VT, columns=vectorizer.get_feature_names_out(), index=[f'Topic {i+1}' for i in range(VT.shape[0])])

# 閾値を設定
threshold = 1e-10

# DataFrameの全ての値に対して閾値以下のものを0に置き換える
U_df = U_df.applymap(lambda x: 0 if np.abs(x) < threshold else x)
Sigma_df = Sigma_df.applymap(lambda x: 0 if np.abs(x) < threshold else x)
VT_df = VT_df.applymap(lambda x: 0 if np.abs(x) < threshold else x)

まずUは文書-トピック行列なので4 x 2次元です。Indexの0,1,2,3は文書1,2,3,4を表していて、文書1,2はトピック1, 文書3,4はトピック2に割り振られました。

続いてSigmaはトピック-トピック行列なので4 x 2次元です。Indexの0と1はトピック1とトピック2を表していて、トピック同士が独立しています。

最後にVはトピック-単語行列なので、2 x 5次元です。これを使ってトピックの意味を解釈します。トピック1 は自動車に関するもの、トピック2は音楽に関するもの。

これらを掛け合わせると低ランク近似行列が得られます。

# 低ランク近似行列の作成
X_approx = np.dot(np.dot(U, Sigma), VT)

# DataFrameに変換して表示
X_approx_df = pd.DataFrame(X_approx, columns=vectorizer.get_feature_names_out())

X_approx_df = X_approx_df.applymap(lambda x: 0 if np.abs(x) < threshold else x)


ここでは4つの文書がトピック1(自動車)か2(音楽)のどちらか一方に割り振られているが、例えば「車のオーディオシステム」に関する文書だった場合、両方のトピックに関係することになる。例えばトピック1(自動車)は40%、トピック2(音楽)には30%、それ以外(30%)など、割り振られるトピックへの割合を考えられると、より実態に即した潜在的意味を抽出できるのではないか。

その他の文書分類手法

PLSA(probablistic Latent semantic analysis)

  • 上記の問題があるために、確率モデルとして定式化されたのがPLSA(probabilistic LSA)。これだと確率分布間に直交性を仮定しなくても良い。ソフトなクラスタリングができる。
  • トピックベクトルの値が全て確率であるため、各単語が複数のトピックに属する(LSAではこれは起こらない)

LDA(Latent Dirichlet Allocation)

  • LDAでは単語の出現頻度をディリクレ分布を用いて近似する。ディリクレ分布は座標の総和が1で定義される単体(simplex)。単語の出現頻度は偏った分布として点在することを表すためにディリクレ分布が用いられる。多次元だと可視化できないため、3次元のユークリッド空間内の正三角形(2次元)で表される。次元が一つ落ちるのは確率の総和が1になる制約のため。確率密度が三角形上の濃淡や色合いで表される。
  • 単語とトピックがディリクレ分布から生成されると仮定する。θが文書kにおけるトピックの出現確率、φはトピックkにおける単語の出現確率。単語とトピックの生成過程を図示したのがグラフィカルモデル。トピックは単語ごとに存在し、その割合が文書ごとに異なる。
  • 潜在トピックベクトルの基底ベクトルが単語ベクトルとなっている。つまり単語ベクトルの線形結合によって潜在トピックベクトルが作られる。
  • 文書が与えられた時に単語の生起する確率をトピックを介して表すことができる。つまり文書内に現れていない(=観察されない)単語であってもそれが出現する確率を算出できる、その裏にあるトピックを抽出できる点がポイント。
  • ただしトピックは単語で表現されるベクトルであることに違いはため、そのトピックが何を表すかは分析者が解釈して決める。これはLSAもpLSAも同じ。