はじめに
新しいパターン抽出手法を開発したので、応用先の探索をしています。
ちょっと変わり種で、自然言語処理で用いられる分散表現でも、パターン抽出できないかと探ってみた結果、全く向かない事がわかったのでその報告をします。
パターン抽出の手法に関しては、この記事を参照してください。
また、パターン抽出の実装は、この記事を参照してください。
試した事
word2vecで学習済みの単語ベクトルを抽出し、そのベクトルをパターン抽出技法で類似度の比較をしました。
うまくいけば包括関係なんか出るかなとか考えたりもしたので、包括関係にある言葉、似ている言葉、似ていない言葉のペアに分け、類似度の代表的な評価指標のcosineと比較しました。
cosine similarity は、分散表現における最も一般的な類似度指標であり、比較の基準として採用しました。
使用したデータは、Google が公開している Google News word2vec 事前学習モデルを使用しました。
コード
from gensim.models import KeyedVectors
import bedcmm.pattern as bedcmm
import numpy as np
wv = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin.gz', binary=True)
def cosine_sim(w1, w2):
return np.dot(wv[w1], wv[w2]) / (
np.linalg.norm(wv[w1]) * np.linalg.norm(wv[w2])
)
# 語ペア定義
inclusion_pairs = [
("animal", "dog"),
("vehicle", "car"),
("fruit", "apple"),
("instrument", "piano"),
("profession", "doctor"),
]
similarity_pairs = [
("dog", "cat"),
("car", "truck"),
("apple", "orange"),
("piano", "violin"),
("doctor", "nurse"),
]
not_similarity_pairs = [
("dog", "orange"),
("car", "violin"),
("apple", "cat"),
("piano", "truck"),
]
# 計算
print("=== Inclusion (is-a) ===")
for w1, w2 in inclusion_pairs:
if w1 in wv and w2 in wv:
bedcmm_value1 = bedcmm.pattern_1d(np.array(wv[w1],dtype=np.float64), np.array(wv[w2],dtype=np.float64))
bedcmm_value2 = bedcmm.pattern_1d(np.array(wv[w2],dtype=np.float64), np.array(wv[w1],dtype=np.float64))
print(f"cosine_sim = {w1:12s} - {w2:12s}: {cosine_sim(w1, w2):.8f}")
print(f"bedcmm(w1/w2) = {w1:12s} - {w2:12s}: {bedcmm_value1[0]:.8f}")
print(f"bedcmm(w2/w1) = {w1:12s} - {w2:12s}: {bedcmm_value2[0]:.8f}")
print("\n=== Similarity (peer) ===")
for w1, w2 in similarity_pairs:
if w1 in wv and w2 in wv:
bedcmm_value1 = bedcmm.pattern_1d(np.array(wv[w1],dtype=np.float64), np.array(wv[w2],dtype=np.float64))
bedcmm_value2 = bedcmm.pattern_1d(np.array(wv[w2],dtype=np.float64), np.array(wv[w1],dtype=np.float64))
print(f"cosine_sim = {w1:12s} - {w2:12s}: {cosine_sim(w1, w2):.8f}")
print(f"bedcmm(w1/w2) = {w1:12s} - {w2:12s}: {bedcmm_value1[0]:.8f}")
print(f"bedcmm(w2/w1) = {w1:12s} - {w2:12s}: {bedcmm_value2[0]:.8f}")
print("\n=== Not Similarity (not peer) ===")
for w1, w2 in not_similarity_pairs:
if w1 in wv and w2 in wv:
bedcmm_value1 = bedcmm.pattern_1d(np.array(wv[w1],dtype=np.float64), np.array(wv[w2],dtype=np.float64))
bedcmm_value2 = bedcmm.pattern_1d(np.array(wv[w2],dtype=np.float64), np.array(wv[w1],dtype=np.float64))
print(f"cosine_sim = {w1:12s} - {w2:12s}: {cosine_sim(w1, w2):.8f}")
print(f"bedcmm(w1/w2) = {w1:12s} - {w2:12s}: {bedcmm_value1[0]:.8f}")
print(f"bedcmm(w2/w1) = {w1:12s} - {w2:12s}: {bedcmm_value2[0]:.8f}")
結果
=== Inclusion (is-a) ===
cosine_sim = animal - dog : 0.64380127
bedcmm(w1/w2) = animal - dog : 0.00000000
bedcmm(w2/w1) = animal - dog : 0.00000000
cosine_sim = vehicle - car : 0.78210968
bedcmm(w1/w2) = vehicle - car : 0.00000000
bedcmm(w2/w1) = vehicle - car : 0.00000000
cosine_sim = fruit - apple : 0.64101464
bedcmm(w1/w2) = fruit - apple : 0.00000000
bedcmm(w2/w1) = fruit - apple : 0.00000000
cosine_sim = instrument - piano : 0.46876317
bedcmm(w1/w2) = instrument - piano : 0.00000000
bedcmm(w2/w1) = instrument - piano : 0.00000000
cosine_sim = profession - doctor : 0.23653139
bedcmm(w1/w2) = profession - doctor : 0.00000000
bedcmm(w2/w1) = profession - doctor : 0.00000000
=== Similarity (peer) ===
cosine_sim = dog - cat : 0.76094568
bedcmm(w1/w2) = dog - cat : 0.00000000
bedcmm(w2/w1) = dog - cat : 0.00000000
cosine_sim = car - truck : 0.67357898
bedcmm(w1/w2) = car - truck : 0.00000000
bedcmm(w2/w1) = car - truck : 0.00000000
cosine_sim = apple - orange : 0.39203459
bedcmm(w1/w2) = apple - orange : 0.00000000
bedcmm(w2/w1) = apple - orange : 0.00000000
cosine_sim = piano - violin : 0.82281864
bedcmm(w1/w2) = piano - violin : 0.00000000
bedcmm(w2/w1) = piano - violin : 0.00000000
cosine_sim = doctor - nurse : 0.63195235
bedcmm(w1/w2) = doctor - nurse : 0.00000000
bedcmm(w2/w1) = doctor - nurse : 0.00000000
=== Not Similarity (not peer) ===
cosine_sim = dog - orange : 0.11858451
bedcmm(w1/w2) = dog - orange : 0.00000000
bedcmm(w2/w1) = dog - orange : 0.00000000
cosine_sim = car - violin : 0.22449902
bedcmm(w1/w2) = car - violin : 0.00000000
bedcmm(w2/w1) = car - violin : 0.00000000
cosine_sim = apple - cat : 0.20749082
bedcmm(w1/w2) = apple - cat : 0.00000000
bedcmm(w2/w1) = apple - cat : 0.00000000
cosine_sim = piano - truck : 0.13954961
bedcmm(w1/w2) = piano - truck : 0.00000000
bedcmm(w2/w1) = piano - truck : 0.00000000
いやぁ、提案しているパターン抽出は、清々しく0が並びます。
うまくいかない理由
そもそもword2vecは、次元と値に相対的な意味しかありません。
パターン抽出として計算するには、無理があります。
絶対的な意味を持つ指標を使ってもうまくかないとおもいます。
例えば「King」と「Queen」を比較する際に、分散表現を用いると、「性別」という次元が出てくると思います。すべての次元を比較して、最小値を取得する手法なので、1か所真逆の違う意味になると、類似度の一番低い値が選択されるため、似ていても全く似ていないと判断されてしまいます。
よって、自然言語処理のように、意味を分散させて広く表現した形式のデータには、パターン抽出方法は、向かないです。
まとめ
新しいパターン抽出方法を分散表現で試したら、類似度や包括関係を評価できなかった。
その理由は、意味を分散させるので、少しでも類似度が、低い次元があるとそれを反映してしまうからと考えられる。
手法の失敗というより、表現設計の前提不一致が原因である。
つぎに
パターン抽出をどのような形で活かしていくかは、次にまとめたいと思います。
記事を書いたのでリンクを貼っておきます。
提案するパターン抽出手法は、ECサイト再訪行動を捉えられるか:シミュレーションによる検討
使用データ・ライセンス
本記事では、Google が公開している Google News word2vec 事前学習モデルを使用しています。
© Google
Licensed under the Apache License, Version 2.0.