# 例文
a = "I walk to school"
b = "I walked to school"
c = "Yesterday I walked to school"
d = "I walked to school yesterday"
| 単語 | 文a | 文b | 文c | 文d |
|---|---|---|---|---|
| school | 1 | 1 | 1 | 1 |
| to | 1 | 1 | 1 | 1 |
| walk | 1 | 0 | 0 | 0 |
| walked | 0 | 1 | 1 | 1 |
| yesterday | 0 | 0 | 1 | 1 |
# 対象となる文をリストに格納する。
L = [a,b,c,d]
# sklearnのクラスのインポート
from sklearn.feature_extraction.text import CountVectorizer
# インスタンスの作成
# 引数の"mind_df=1"は「1回以上出現した単語を数える」という意味
# 2回以上出現した単語だけをカウントするには"min_df=2"とする
vectorizer = CountVectorizer(min_df=1)
# カウントする単語を登録(インスタンスにデータを保存している)
vectorizer.fit(L)
# 文のベクトル表現を算出 (Compressed Sparse Row)
X = vectorizer.transform(L)
# 行列の出力(上の表とは行と列が入れ替わっている)
X.toarray()
array([[1, 1, 1, 0, 0],
[1, 1, 0, 1, 0],
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1]])
# 表1と同じにしたかったら
X.toarray().transpose()
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 0, 0, 0],
[0, 1, 1, 1],
[0, 0, 1, 1]])
# 新たな文を同じ方法でベクトル化する
M = ["I yesterday walked to school"]
X2 = vectorizer.transform(M).toarray()
X2
array([[1, 1, 0, 1, 1]])
L = [a,b,c,d]
# "ngram_range=(X,Y)"で求めるN-gramを指定する。
# 「XからY」までという意味
# uni-gram, bi-gram, tri-gramの3つを求めたい場合は"ngram_range=(1,3)とする
bigram_vectorizer = CountVectorizer(min_df=1,ngram_range=(2,2))
bigram_vectorizer.fit(L)
X_b = bigram_vectorizer.transform(L).toarray()
X_b
array([[0, 1, 1, 0, 0],
[0, 1, 0, 1, 0],
[0, 1, 0, 1, 1],
[1, 1, 0, 1, 0]])
# 以下のメソッドでbigramのリストが得られる
bigram_vectorizer.get_feature_names_out()
array(['school yesterday', 'to school', 'walk to', 'walked to',
'yesterday walked'], dtype=object)

点pと点qの距離は以下の式で求められる。 $$ d(p,q) = \sqrt{(q_1-p_1)^2 + (q_2-p_2)^2 + ... + (q_n -p_n)^2} \\ = \sqrt{\sum_{i=1}^n(q_i - p_i)^2} $$
表1の場合、文が5つの単語で表現されているので、
# X.toarray()を代入
X_a = X.toarray()
# numpyのインポート
import numpy as np
# ユークリッド距離を求める
np.linalg.norm(X_a[2] - X_a[3])
np.float64(0.0)
# すべての文間の類似度を求める
X_euc = []
for i in X_a:
x = []
for j in X_a:
x.append(np.linalg.norm(i - j))
X_euc.append(x)
X_euc
[[np.float64(0.0), np.float64(1.4142135623730951), np.float64(1.7320508075688772), np.float64(1.7320508075688772)], [np.float64(1.4142135623730951), np.float64(0.0), np.float64(1.0), np.float64(1.0)], [np.float64(1.7320508075688772), np.float64(1.0), np.float64(0.0), np.float64(0.0)], [np.float64(1.7320508075688772), np.float64(1.0), np.float64(0.0), np.float64(0.0)]]
import pandas as pd
# 2桁のみ表示
pd.options.display.precision = 2
# データフレームで表示
df2 = pd.DataFrame({"a":X_euc[0],
"b":X_euc[1],
"c":X_euc[2],
"d":X_euc[3]},
index=["a","b","c","d"])
df2
| a | b | c | d | |
|---|---|---|---|---|
| a | 0.00 | 1.41 | 1.73 | 1.73 |
| b | 1.41 | 0.00 | 1.00 | 1.00 |
| c | 1.73 | 1.00 | 0.00 | 0.00 |
| d | 1.73 | 1.00 | 0.00 | 0.00 |
# scipyのインポート
import scipy.spatial.distance as dis
# コサイン類似度
dis.cosine(X_a[2],X_a[3])
np.float64(0.0)
# すべての文のコサイン類似度
X_cos = []
for i in X_a:
x = []
for j in X_a:
x.append(dis.cosine(i,j))
X_cos.append(x)
X_cos
[[np.float64(0.0), np.float64(0.33333333333333337), np.float64(0.42264973081037416), np.float64(0.42264973081037416)], [np.float64(0.33333333333333337), np.float64(0.0), np.float64(0.1339745962155613), np.float64(0.1339745962155613)], [np.float64(0.42264973081037416), np.float64(0.1339745962155613), np.float64(0.0), np.float64(0.0)], [np.float64(0.42264973081037416), np.float64(0.1339745962155613), np.float64(0.0), np.float64(0.0)]]
# データフレームにしてみた。
df3 = pd.DataFrame({"a":X_cos[0],"b":X_cos[1],"c":X_cos[2],"d":X_cos[3]},index=["a","b","c","d"])
df3
| a | b | c | d | |
|---|---|---|---|---|
| a | 0.00 | 0.33 | 0.42 | 0.42 |
| b | 0.33 | 0.00 | 0.13 | 0.13 |
| c | 0.42 | 0.13 | 0.00 | 0.00 |
| d | 0.42 | 0.13 | 0.00 | 0.00 |
When you want to break into a conversation and add something, what would you say?