Professional Documents
Culture Documents
【技術解説】集合の類似度 (Jaccard係数,Dice係数,Simpson係数) - ミエルカAI は、自然言語処理技術を中心とした、RPA開発・サイト改善・流入改善レコメンドエンジンを開発
【技術解説】集合の類似度 (Jaccard係数,Dice係数,Simpson係数) - ミエルカAI は、自然言語処理技術を中心とした、RPA開発・サイト改善・流入改善レコメンドエンジンを開発
ai.com/ai/)
ミエルカTOP (https://mieru-ca.com) > メディア (https://mieruca-ai.com/ai) > 技術解説 (https://mieruca-
ai.com/ai/category/%e6%8a%80%e8%a1%93%e8%a7%a3%e8%aa%ac/) > ⾃然⾔語処理 (https://mieruca-
ai.com/ai/category/%e6%8a%80%e8%a1%93%e8%a7%a3%e8%aa%ac/%e8%87%aa%e7%84%b6%e8%a8%80%e8%
> 【技術解説】集合の類似度(Jaccard係数,Dice係数,Simpson係数)
2018-05-11
【技術解説】集合の類似度(Jaccard係数,Dice係数,Simp-
son係数)
いいね︕ 15
(https://www.f (https://twitter (https://b.hate
acebook.com/s .com/share? na.ne.jp/add?
(https://slackb
harer/sharer.p url=https://mi mode=confirm
(https://getpo utton.herokuap
hp? eruca- &url=https://
p com/post/ne
執筆︓⾦⼦冴
前回の記事(【技術解説】似ている⽂字列がわかる︕レーベンシュタイン距離とジャロ・ウィ
ンクラー距離の計算⽅法とは (https://mieruca-ai.com/ai/levenshtein_jaro-
winkler_distance/))では,⽂字列同⼠の類似度(距離)が計算できる⼿法を紹介した.また,
その記事の中で,⾃然⾔語処理分野では主に⽂書,⽂字列,集合等について類似度を計算する
場⾯が多いことについても触れた.今回は集合同⼠の類似度を表現する以下の3つの係数と計
算⽅法について解説する.
●Jaccard係数
●Dice係数
●Simpson係数
その前に,⾃然⾔語処理で類似度を表す指標について確認しよう.
⾃然⾔語処理で使⽤される類似度(距離)
⾃然⾔語処理の分野では,類似度を測る対象によって⼿法を使い分ける.
ここでは事前に,主に使⽤される⼿法について確認しておこう.
ベクトル同⼠の類似度
●コサイン類似度
●ピアソンの相関係数
●偏差パターン類似度
集合同⼠の類似度(今回の解説対象)
●Jaccard係数
●Dice係数
●Simpson係数
⽂字列同⼠の類似度
●ハミング距離
●レーベンシュタイン距離
●ジャロ・ウィンクラー距離
※レーベンシュタイン距離,ジャロ・ウィンクラー距離については,以下の記事で解説済
み.
⽂字列の類似度(Levenshtein距離,jaro-winkler距離) (https://mieruca-
ai.com/ai/levenshtein_jaro-winkler_distance/)
それでは本題の集合同⼠の類似度について,Jaccard係数から確認していこう.
Jaccard係数(Jaccard index)とは
Jaccard係数の定義と意味
Jaccard係数は,「Jaccard index」や「Jaccard similarity coefficient」と呼ばれる.
ある集合Aと別の集合BについてのJaccard係数J(A,B)は,以下の式で定義される.
(集合Aと集合Bがどちらも空集合ϕの時,J(A,B)=1とする)
|A ∩ B|
J(A, B) =
|A ∪ B|
わかりやすく,図を⽤いると以下のようになる.
上記の定義より,Jaccard係数は2つの集合に含まれている要素のうち共通要素が占める割合
を表しており,係数は0から1の間の値となることがわかる.Jaccard係数が⼤きいほど2つの
集合の類似度は⾼い(よく似ている)といえる.
Jaccard係数の計算アルゴリズムおよびpython実装⽅法
今回は例として,以下の集合Aと集合Bを⽤いてJaccard係数の計算アルゴリズムと実装⽅法を
確認しよう.
集合A=[“リンゴ”,”ブドウ”,”イチゴ”,”パイン”,”キウイ”,”メロン”]
集合B=[“メロン”,”イチゴ”,”リンゴ”,”パインアップル”]
実装したソースコードは以下のようになる.計算の結果,集合Aと集合BのJaccard係数は約
0.429となった.
1 #Jaccard係数(overlap coefficiant)の計算アルゴリズム
2 def jaccard_similarity_coefficient(list_a,list_b):
3 #集合Aと集合Bの積集合(set型)を作成
4 set_intersection = set.intersection(set(list_a), set(list_b))
5 #集合Aと集合Bの積集合の要素数を取得
6 num_intersection = len(set_intersection)
7
8 #集合Aと集合Bの和集合(set型)を作成
9 set_union = set.union(set(list_a), set(list_b))
10 #集合Aと集合Bの和集合の要素数を取得
11 num_union = len(set_union)
12
13 #積集合の要素数を和集合の要素数で割って
14 #Jaccard係数を算出
15 try:
16 return float(num_intersection) / num_union
17 except ZeroDivisionError:
18 return 1.0
19
20 if __name__== '__main__':
21 list_a = ["リンゴ","ブドウ","イチゴ","パイン","キウイ","メロン"] #集合A
22 list_b = ["メロン","イチゴ","リンゴ","パインアップル"] #集合B
23
24 jaccard = jaccard_similarity_coefficient(list_a,list_b) #Jaccard係数を計算
25 print(jaccard) #計算結果を出力 ⇒ 0.42857142857142855
念のため,定義式から⼿計算してみよう.
以下の図が計算の過程と結果であり,プログラムの結果と⼀致することがわかる.
Jaccard係数の⽋点
Jaccard係数では分⺟に2つの集合の和集合を採⽤することで値を標準化し,他の集合同⼠の
類似度に対する絶対評価を可能にしている.しかし,Jaccard係数は2つの集合の差集合の要
素数に⼤きく依存するため,差集合の要素数が多いほどJaccard係数は⼩さくなる.これは,
⼈の⽬から判断した際の「共通要素が多いほど類似度が⾼い」という感覚と異なっている.
そこで,差集合の要素数の影響を抑え,共通要素の要素数の影響に重みをおくDice係数が提案
された.
では次に,Dice係数の解説にうつろう.また,残り2つの係数(Dice係数,Simpson係数)につ
いては,Jaccard係数との関連も含めて解説していく.
Dice係数(Sørensen–Dice coefficient)とは
Dice係数の定義と意味
ある集合Aと別の集合BについてのDice係数DSC(A,B)は,以下の式で定義される.
2|A ∩ B|
DSC(A, B) =
|A| + |B|
わかりやすく,図を⽤いると以下のようになる.
分⺟を「和集合の要素数」から「2集合の平均要素数」とすることで,⼀⽅の集合だけ要素数
が膨⼤である場合などに類似度が著しく下がる問題を防ぎ,共通要素数を重視した類似度計算
を実現している.
Dice係数の計算アルゴリズムおよびpython実装⽅法
Jaccard係数の例を⽤いて,同様にDice係数の計算アルゴリズムと実装⽅法を確認しよう.
集合A=[“リンゴ”,”ブドウ”,”イチゴ”,”パイン”,”キウイ”,”メロン”]
集合B=[“メロン”,”イチゴ”,”リンゴ”,”パインアップル”]
実装したソースコードは以下のようになる.今回は集合Aと集合Bがどちらも空集合ϕの時,
DSC(A,B)=1.0とした.
計算の結果,集合Aと集合BのDice係数は0.6となり,Jaccard係数の計算値(約0.429)より⾼
い結果となった.
1 #Dice係数の計算アルゴリズム
2 def dice_similarity_coefficient(list_a,list_b):
3 #集合Aと集合Bの積集合(set型)を作成
4 set_intersection = set.intersection(set(list_a), set(list_b))
5 #集合Aと集合Bの積集合の要素数を取得
6 num_intersection = len(set_intersection)
7
8 #集合Aの要素数を取得
9 num_listA = len(list_a)
10 #集合Bの要素数を取得
11 num_listB = len(list_b)
12
13 #定義式に従い,Dice係数を算出
14 try:
15 return float(2.0 * num_intersection) / (num_listA + num_listB)
16 except ZeroDivisionError:
17 return 1.0
18
19 if __name__== '__main__':
20 list_a = ["リンゴ","ブドウ","イチゴ","パイン","キウイ","メロン"] #集合A
21 list_b = ["メロン","イチゴ","リンゴ","パインアップル"] #集合B
22
23 dsc = dice_similarity_coefficient(list_a,list_b) #Dice係数を計算
24 print(dsc) #計算結果を出力 ⇒ 0.6
念のため,定義式から⼿計算してみよう.
以下の図が計算の過程と結果であり,プログラムの結果と⼀致することがわかる.
Dice係数の⽋点
『Jaccard係数とDice係数の関連』の項でも説明した通り,Dice係数の定義式は,Jaccard係
数の定義式の分⺟を「和集合の要素数」から「2集合の平均要素数」とすることで,差集合の
要素数が膨⼤になった場合に類似度への影響を緩和している.しかし,緩和しているとはいっ
ても,2集合の要素数に⼤きな差があり差集合の要素数が膨⼤になった場合(例えば,⼀⽅の集
合が別の集合を内包している等の場合)に,Dice係数は低下してしまう.
そこで,差集合の要素数の影響を極限まで抑えたSimpson係数が提案された.
次は,Simpson係数について,Jaccard係数との関連も含めて解説していく.
Simpson係数(Overlap coefficient)とは
Simpson係数の定義と意味
|A ∩ B|
overlap(A, B) =
min{|A|, |B|}
わかりやすく,図を⽤いると以下のようになる.
上記の定義より,Simpson係数は2つの集合のうち要素数が少ない⽅の要素数と共通要素数の
割合を表しており,Jaccard係数やDice係数と同様に0から1の間の値となることがわかる.ま
た,Simpson係数が⼤きいほど2つの集合の類似度は⾼い(よく似ている)といえる.
Jaccard係数とDice係数,Simpsonの関連
Simpson係数の計算アルゴリズムおよびpython実装⽅法
Jaccard係数,Dice係数の例を⽤いて,同様にSimpson係数の計算アルゴリズムと実装⽅法を
確認しよう.
集合A=[“リンゴ”,”ブドウ”,”イチゴ”,”パイン”,”キウイ”,”メロン”]
集合B=[“メロン”,”イチゴ”,”リンゴ”,”パインアップル”]
実装したソースコードは以下のようになる.今回は集合Aと集合Bがどちらも空集合ϕの時,
overlap(A,B)=1.0とした.計算の結果,集合Aと集合BのSimpson係数は約0.75となった.
1 #Simpson係数(overlap coefficiant)の計算アルゴリズム
2 def overlap_coefficient(list_a,list_b):
3 #集合Aと集合Bの積集合(set型)を作成
4 set_intersection = set.intersection(set(list_a), set(list_b))
5 #集合Aと集合Bの積集合の要素数を取得
6 num_intersection = len(set_intersection)
7
8 #集合Aの要素数を取得
9 num_listA = len(list_a)
10 #集合Bの要素数を取得
11 num_listB = len(list_b)
12
13 #定義式に従い,Simpson係数を算出
14 try:
15 return float(num_intersection) / min([num_listA,num_listB])
16 except ZeroDivisionError:
17 return 1.0
18
19 if __name__== '__main__':
20 list_a = ["リンゴ","ブドウ","イチゴ","パイン","キウイ","メロン"] #集合A
21 list_b = ["メロン","イチゴ","リンゴ","パインアップル"] #集合B
22
23 overlap = overlap_coefficient(list_a,list_b) #Simpson係数を計算
24 print(overlap) #計算結果を出力 ⇒ 0.75
念のため,定義式から⼿計算してみよう.
以下の図が計算の過程と結果であり,プログラムの結果と⼀致することがわかる.
Simpson係数の⽋点
『Jaccard係数とDice係数,Simpsonの関連』の項でも説明した通り,Simpson係数の定義式
は,Dice係数の定義式の分⺟を「2集合の平均要素数」から「2集合のうち少ない⽅の要素
数」とすることで,Dice係数よりも差集合の要素数による影響を下げ,相対的に共通要素数を
重視した類似度計算を実現している.しかし,Simpson係数では要素数が少ない⽅の要素数を
分⺟としているため,⼀⽅の集合の要素数が少ない場合に,差集合の要素数がどれだけ多くて
も類似度がほぼ1となってしまう.
この問題を解決するためには,2つの集合の要素数に条件(閾値を設定する,2集合間の要素数
の差が範囲内である等)を付加するとよい.
また,⼀⽅の集合が別の集合の真部分集合の場合に,Jaccard係数(もしくはDice係数)と
Simpson係数では値が異なるため,使⽤する場⾯に応じて使い分ける必要がある.次の項で
は,Jaccard係数,Dice係数,Simpson係数の使い分けについて,例を⽤いて確認しよう.
Jaccard係数,Dice係数,Simpson係数の使い分けと判断基準
ここまでの説明で,Jaccard係数を拡張したものがDice係数,Dice係数を拡張したものが
Simpson係数であることはご理解いただけただろう.この説明では,Simpson係数が最も優
れているようにとらえることもできるが,使⽤する場⾯によってはそうとは限らない.ここで
は,いくつかのパターンを⽤いてそれぞれの係数を使い分ける⽅法を確認する.
パターン1︓2集合の⼀部が共通要素
初めに,各係数の解説でも使⽤したような,2集合の⼀部が共通要素である場合を考えよう.
図で表すと,以下のようになる.
この場合,Jaccard係数よりDice係数の⽅が,さらにDice係数よりSimpson係数の⽅が差集合
の影響を抑えているため,各係数の値はJaccard係数 < Dice係数 < Simpson係数となる.
パターン2︓2集合に共通要素がない
次に,2集合に共通要素がない,つまりA ∩ B = ϕの場合を考える.
図で表すと,以下のようになる.
各係数の分⼦には,共通要素の数を表す|A ∩ B|の項がある.共通要素がない場合は当然
|A ∩ B| = 0のため,Jaccard係数 = Dice係数 = Simpson係数 = 0となる.
パターン3︓⼀⽅の集合が別の集合の真部分集合
最後に,⼀⽅の集合が別の集合の真部分集合である場合を考えよう.
実は,各係数の使い分けにおいて最も重要となるのがこのパターンである.
図で表すと,以下のようになる.
この場合のJaccard係数とDice係数の値は1にはならない.Jaccard係数とDice係数では差集
合の影響を受けるため,真部分集合の場合でも完全に⼀致しているとは判断されない.しか
し,Simpson係数では値が1になる.真部分集合の場合,「要素数の少ない⽅(集合B)の要素
数=共通要素の要素数」が成り⽴つためである.
このように,⼀⽅の集合が別の集合の部分集合である場合に,Jaccard係数およびDice係数と
Simpson係数では考え⽅に⼤きな違いが⽣まれる.⾃分が使⽤する際には真部分集合をどのよ
うに考慮するのかをベースに,どの係数計算を採⽤すべきかを考える必要がある.
最後に,Jaccard係数,Dice係数,Simpson係数の応⽤可能性について確認しよう.
Jaccard係数,Dice係数,Simpson係数の応⽤可能性
今回解説した3つの係数は,最初に確認した通り,いずれも集合同⼠の類似度を表す指標であ
る.
集合同⼠の類似度がわかると以下のようなことに応⽤できる.
●⽂書同⼠の類似度計算
⇒⽂書を「単語の集合」ととらえることで,集合の類似度=⽂書の類似度と置き換えること
ができる.
●トピック同⼠の関連推定
⇒トピック毎の単語の集合を作成して類似度を計算すると,その値はトピック同⼠の類似度
と⾔い換えることができるだろう.これにより,あるトピックの話題が出現したときに別のト
ピックと関連付けるべきかどうかを判断する⽬安が得られる.
●⽂字列同⼠の共起推定
⇒トピック同⼠の関連推定に関係して,「あるトピックの単語が出現した際に,類似度の⾼
いトピックの単語も出現するかもしれない」という推定ができるようになる.
参考
関連記事はこちら
【⾃然⾔語処理⼊⾨】⽇本語ストップワードの考察【品詞別】 (https://mieruca-ai.com/ai/nlp-
stopwords/)
記事内容に関するお詫び (https://mieruca-ai.com/ai/fisherian-bayesian/)
【技術解説】確率的潜在意味解析(PLSA)のアルゴリズムと応⽤ (https://mieruca-ai.com/ai/plsa/)
【論⽂解説】A Generalized Language Model as the Combination of Skipped n-grams and Modified
Kneser-Ney Smoothing (https://mieruca-ai.com/ai/a-generalized-language-model/)
いいね︕ 15
(https://www.facebook.com/sharer/sharer.php?
(https://twitter.com/share?
(https://b.hatena
u=https://mieruca-
url=https://mieruca-
mode=confirm&u
(https://slackbutton.herokuapp.com/post/new?
ai.com/ai/jaccard_dice_simpson/)
ai.com/ai/jaccard_dice_simpson/;
ai.com/ai/jaccard
(https://getpocket.com/edit? url=https://mieruca-
【技術解説】集合
ai com/ai/jaccard dice simpson/)