質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

88.06%

pythonでコサイン類似度をループで計算する

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,765

score 12

前提・実現したいこと

pythonでテキスト間のcos類似度を求めています。
最終的には膨大なテキストに対して、cos類似度を計算しようと考えています。

cos類似度の分母のループがうまく回りません。

.txtには以下の文が入っています。
私はりんごを食べました。,私はりんごを食べました。,私はみかんを食べました。,私はぶどうを食べました。

4つの文が入っており、4つの文書から2つの文書を組み合わせて計算するので6通りの結果が出るはずですが、うまく出ません。

エラーは出ないので、どこが間違っているかわからない状態です。

御享受、よろしくお願いします。

該当のソースコード

import pprint
import re
import sys
import MeCab
import math
import numpy
from scipy.spatial.distance import pdist, squareform
sentence_data  = open("data2.txt","r")#ファイルのオープン
#行ごとに読み込んでリストデータ
sentence_read = sentence_data.readlines()

sentence_read_str = ','.join(sentence_read)

sentence = sentence_read_str.split(",")

num = len(sentence)

result = []
print("全文書数")
print(num)


a = []


for i in range(num):
    tagger = MeCab.Tagger()
    result.append(tagger.parse(sentence[i]))
    print("形態素解析した結果 result")
    print(result)




#文章を形態素解析して、文章事の単語をリストへ
wordCount = {}#辞書
allCount = {}
sub_tfstore = {}
tfcounter = {}
tfstore = {}
sub_idf = {}
idfstore = {}
merge_idf = {}
tfidf = {}
merge_tfidf = {}
wordList = []

sum = 0

for i in range(num): #resultに形態素解析の結果
    wordList.append(result[i].split()[:-1:2])#wordListにresultを加える
    print("単語のみ")
    print(wordList)

for i in range(num):#iをnum分まわす
    for word in wordList[i]:#wordをwordList分まわす
        allCount[i] = wordCount.setdefault(word,0)#wordCountのwordが0
        wordCount[word]=1
    allCount[i] = wordCount

    wordCount = {}
    print("単語の数")
    print(allCount)

for i in range(num):#tfの分母を計算
    for word in allCount[i]:
        sum = sum + allCount[i][word]
    sub_tfstore[i] = sum
    sum = 0
    print(sub_tfstore)

for i in range(num):
    for word in allCount[i]:
        tfcounter[word] = allCount[i][word]*1.0/sub_tfstore[i]
    tfstore[i] = tfcounter
    print("tfの値")
    print(tfstore)
    tfcounter = {}

for i in range(num):
    for word in wordList[i]:
        wordCount.setdefault(word,0)
    for word in allCount[i]:
        wordCount[word] += 1
    sub_idf = wordCount
    print("単語の文章あたりの出現回数")
    print(sub_idf)

for i in range(num):
    for word in allCount[i]:
        idfstore[word] = math.log(1.0*math.fabs(num)/math.fabs(sub_idf[word]))
    merge_idf[i] = idfstore
    idfstore = {}
    print("idfの値")
    print(merge_idf)


#tfidfの計算
for i in range(num):
    for word in allCount[i]:
        tfidf[word] = tfstore[i][word]*merge_idf[i][word]
    merge_tfidf[i] = tfidf
    tfidf = {}
    print("tfidfの値")
    print(merge_tfidf[0])

print("")
print("tf-idfの値")
for i in range(num):
    for word,count in sorted(merge_tfidf[i].items(),key = lambda x:x[1],reverse = True):
        print('text%d: %-16s %2.3f' % (i+1,word,count))

length = []
sum = 0.0
for x in merge_tfidf:
    for key,value in merge_tfidf[x].items(): #for key,value in merge_tfidf[1].items()
        sum = sum + value*value
    length.append(sum)
    length[x] = math.sqrt(length[x])
    sum = 0.0
print("各テキストのベクトル長 cos類似度の分母")
print(length)

print("")
print("")




#ここがうまくまわりません
#cos類似度 分母 文書の組み合わせ
dotProduct = 0.0
dP = []
result = 0.0
for x in merge_tfidf:
    for Ka,Va in merge_tfidf[x].items() :
        for y in merge_tfidf:
            for Kb,Vb in merge_tfidf[y].items() :
                if Ka == Kb :
                    dotProduct += Va*Vb

        dP.append(dotProduct)
        result += dotProduct
        print(dotProduct)
        dotProduct = 0.0
    print("------------")
    print("文書の組み合わせ cos類似度の分子"+str(x)+":"+str(result))
    print("------------")
    result = 0.0
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

最後のループが文書の組み合わせになっていなくて、
各文書に含まれる単語について全ての文書に対して計算している
って感じになってて多分cos類似度の計算になっていないと思います。

文書の組み合わせを作りたいとしたら、色々ありますが、例えば

for x in range(num-1):
  for y in range(1, num):
    (cos類似度の計算)


みたいになると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る