🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3456閲覧

python上でのコサイン類似度の求め方

shin_godzilla

総合スコア1

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/02/08 08:00

前提・実現したいこと

初めて質問させていただきます。
現在、pythonにてベクトルのコサイン類似度を求める作業をしています。

その際、データフレームを2つ用意し、それぞれ上から一行ずつ取り出してコサイン類似度を求めようとしています。(以下のようなデータフレームが2つあるイメージです)
これらをリスト化し、以下の処理を実行しましたがうまくいきませんでした。

インデックス名 1   2   3   4…
名前      数字  数字  数字  数字…
名前      …
名前      …

発生している問題・エラーメッセージ

ValueError: shapes (682,768) and (682,768) not aligned: 768 (dim 1) != 682 (dim 0)

該当のソースコード

import numpy as np

def cos_similarity(v1, v2):
return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

print(cos_similarity(リスト名, リスト名))

試したこと

上記のエラーメッセージから、データフレームの方に瑕疵があるかと思い調べましたが、特に問題はないように思われました。
解決方法が分かる方がいらっしゃいましたら、教えていただけないでしょうか。
何卒宜しくお願い致します。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ppaul

2021/02/08 09:03

求めたいのは、v1のindexである名前とv2のindexである名前のコサイン類似度だと考えていいですか?
shin_godzilla

2021/02/08 09:33

返信ありがとうございます! 仰る通りです。
jbpb0

2021/02/08 21:34

二つのデータフレームをdf1, df2とします 計算したい組み合わせは、 df1の1行目とdf2の1行目 df1の2行目とdf2の2行目 みたいに、同じ行どうしだけですか? それとも、全ての組み合わせ(総当たり)ですか? たとえば、 df1の1行目とdf2の2行目 みたいな、別の行との組み合わせも計算するのですか?
jbpb0

2021/02/09 00:14 編集

総当たりなら、下記でできます ppaulさんの回答のコードと、同じ結果になります from sklearn.metrics.pairwise import cosine_similarity print(cosine_similarity(df1, df2)) df1, df2の同じ行どうしの組み合わせの結果だけ欲しければ、対角要素を取り出せばいいです print(np.diag(cosine_similarity(df1, df2)))
guest

回答2

0

主旨にあっているかどうか自信はありませんが、なにか、こういう類のことを求めているように思いました。

python

1import pandas as pd 2import numpy as np 3 4df_dot=df1.dot(df2.T) 5df1_norm = pd.DataFrame(np.linalg.norm(df1.values, axis=1), index = df1.index) 6df2_norm = pd.DataFrame(np.linalg.norm(df2.values, axis=1), index = df2.index) 7df_norm = df1_norm.dot(df2_norm.T) 8df_cos = df_dot/df_norm 9print(df_cos)

実行してみた結果は以下です。

python

1>>> print(df1) 2 1 2 3 4 3名前1 0.679578 0.951728 0.624343 0.834700 4名前2 0.987034 0.847858 0.129869 0.309054 5名前3 0.207578 0.449786 0.862022 0.656207 6名前4 0.928108 0.370134 0.124086 0.597354 7名前5 0.295989 0.108466 0.148657 0.316404 8名前6 0.511950 0.394687 0.185698 0.759663 9名前7 0.573310 0.742546 0.136020 0.533240 10>>> print(df2) 11 1 2 3 4 12名前A 0.005137 0.774268 0.434078 0.753827 13名前B 0.166590 0.772086 0.400457 0.031152 14名前C 0.439442 0.402212 0.295230 0.913475 15名前D 0.816473 0.162942 0.701697 0.959829 16名前E 0.076024 0.213447 0.883743 0.475083 17名前F 0.015643 0.798376 0.905344 0.201227 18名前G 0.681353 0.338289 0.644906 0.368703 19>>> 20>>> df_dot = df1.dot(df2.T) 21>>> print(df_dot) 22 名前A 名前B 名前C 名前D 名前E 名前F 名前G 23名前1 1.640616 1.124052 1.628234 1.949203 1.203119 1.503676 1.495391 24名前2 0.950886 0.880684 1.095417 1.331806 0.517609 0.872115 1.157042 25名前3 1.218172 0.747499 1.126052 1.477496 1.185345 1.274818 1.091460 26名前4 0.795515 0.508689 1.139024 1.478513 0.543016 0.542568 1.057851 27名前5 0.388545 0.202441 0.506612 0.667346 0.327347 0.289481 0.450894 28名前6 0.961485 0.488047 1.132477 1.341755 0.648178 0.644102 0.882185 29名前7 1.038889 0.739899 1.077857 1.196348 0.575620 0.832246 0.926149 30>>> df1_norm = pd.DataFrame(np.linalg.norm(df1.values, axis=1), index = df1.index) 31>>> df2_norm = pd.DataFrame(np.linalg.norm(df2.values, axis=1), index = df2.index) 32>>> df_norm = df1_norm.dot(df2_norm.T) 33>>> print(df_norm) 34 名前A 名前B 名前C 名前D 名前E 名前F 名前G 35名前1 1.824362 1.388166 1.769934 2.273863 1.611394 1.917234 1.665674 36名前2 1.564795 1.190661 1.518111 1.950342 1.382129 1.644454 1.428686 37名前3 1.387284 1.055592 1.345896 1.729095 1.225339 1.457906 1.266615 38名前4 1.363385 1.037407 1.322710 1.699307 1.204230 1.432790 1.244795 39名前5 0.548190 0.417121 0.531835 0.683258 0.484197 0.576096 0.500507 40名前6 1.181577 0.899068 1.146326 1.472704 1.043646 1.241727 1.078801 41名前7 1.266591 0.963756 1.228803 1.578664 1.118735 1.331069 1.156420 42>>> df_cos = df_dot/df_norm 43>>> print(df_cos) 44 名前A 名前B 名前C 名前D 名前E 名前F 名前G 45名前1 0.899282 0.809739 0.919941 0.857221 0.746632 0.784295 0.897769 46名前2 0.607675 0.739660 0.721566 0.682858 0.374501 0.530338 0.809865 47名前3 0.878099 0.708133 0.836656 0.854491 0.967361 0.874417 0.861714 48名前4 0.583485 0.490347 0.861129 0.870068 0.450924 0.378680 0.849820 49名前5 0.708777 0.485329 0.952572 0.976713 0.676061 0.502487 0.900875 50名前6 0.813730 0.542836 0.987919 0.911082 0.621071 0.518715 0.817746 51名前7 0.820225 0.767725 0.877160 0.757823 0.514527 0.625247 0.800876

投稿2021/02/08 12:39

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shin_godzilla

2021/02/09 00:53

ありがとうございますm(__)m
guest

0

ベストアンサー

二つのデータフレームをdf1, df2とします

計算したい組み合わせは、
df1の1行目とdf2の1行目
df1の2行目とdf2の2行目
みたいに、同じ行どうしだけですか?

それとも、全ての組み合わせ(総当たり)ですか?
たとえば、
df1の1行目とdf2の2行目
みたいな、別の行との組み合わせも計算するのですか?

総当たりなら、下記でできます

python

1from sklearn.metrics.pairwise import cosine_similarity 2print(cosine_similarity(df1, df2))

df1, df2の同じ行どうしの組み合わせの結果だけ欲しければ、対角要素を取り出します

python

1print(np.diag(cosine_similarity(df1, df2)))

投稿2021/02/09 00:18

jbpb0

総合スコア7653

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shin_godzilla

2021/02/09 00:56

同じ行同士の組合せの方がなぜかうまくいかなかったのですが、解決できました! ありがとうございますm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問