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

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

ただいまの
回答率

90.84%

  • Ruby

    6769questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • 自然言語処理

    82questions

    自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。

Rubyで複数値で cos類似度を計算したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 62

abab7200

score 56

自然言語処理の勉強をしています。参考サイトを元に複数値でcos類似度を計算し、値をソートして返したいのですが、やりたい事に対してのコードイメージが沸かず、どなたか指針やヒントをいただければと思い投稿しました。

やりたい事

1:文章を引き渡す(文章はN個)
("Bootstrap","Ruby O Rails","Bootstrapで画像スライダー","Bootstrapでモーダル")

2:下記3つの組み合わせで解析
"Bootstrap"と"Ruby O Rails"  
"Bootstrap"と"Bootstrapで画像スライダー"
"Bootstrap"と,"Bootstrapでモーダル"

4:cos類似度を算出

5:返り値でcos類似度が高い組み合わせをソートして返す

2次元配列や繰り返し処理などを利用するかと思いますが、処理に対しての何の処理が必要かのイメージがついておりません。

どなたかご助力いただけると大変大変助かります。

require 'natto'
require 'matrix'

module CosSimilarity

  def calculate(text1, text2)
    a1 = break_up(text1)
    a2 = break_up(text2)
    uniq_words = (a1 + a2).uniq

    f1 = make_flags(uniq_words, a1)
    f2 = make_flags(uniq_words, a2)

    v1 = Vector.elements(f1, copy = true)
    v2 = Vector.elements(f2, copy = true)

    return v2.inner_product(v1)/(v1.norm() * v2.norm())
  end

  def break_up(text)
    arr = Array.new
    nm = Natto::MeCab.new
    nm.parse(text) do |n|
      surface = n.surface
      feature = n.feature.split(',')

      # 品詞が名刺、かつ記号っぽくなければ採用
      if feature.first == "名詞" && feature.last != '*'
        arr.push(surface)
      end
    end
    arr
  end

  def make_flags(uniq_words, elements)
    frags = []
    uniq_words.each do |word|
      flag = elements.include?(word) == true ? 1 : 0
      frags.push(flag)
    end
    frags
  end

end

CosSimilarity.calculate("Bootstrap","Ruby O Rails")
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

rubyを知らないのでpython風擬似コードで示します。

 とりあえず類似度行列を作る

作ります。

cos_sim_matrix = n*nの二次元配列にしておく
i = 0
for doc1 in docs:
    j = 0
    for doc2 in docs:
        cos_sim_matrix[i][j] = cos_sim(doc1, doc2)  # これだと行列の上下が同じなのに計算してて無駄だから、何か工夫した方が良いです
        j += 1
    i += 1

 ある文書に対して類似度の高い順に並べる

単にその文書に該当する行列の行か列を抜き出してあげるだけです。これだと未知データは取り扱えませんが、未知データの場合は既知の全データとコサイン類似度を計算してソートすれば良いだけなので、もっと簡単です。

def similars(doc):
    index = docs.index(doc)  # これもあまりうまくない処理なので、実際には文書とインデックスの対応を入れた辞書など作られてはどうでしょうか
    row = cos_sim_matrix[index]
    row.pop(index)  # doc自身は落とす
    sorted_lst = sorted(zip(range(len(row)), row), reverse=True)  # 大きい順にソート
    return [docs[i] for i, sim in sorted_lst]  # 文書のリストにして返す

 ちなみに

自然言語処理の記事は、pythonだとググれば幾らでも出てきます。とりあえずいろいろ動かしてみたいなら、そっちを見ると楽できます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/26 13:44

    ありがとうございます。 pythonで一旦確認してみます

    キャンセル

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

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

関連した質問

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

  • Ruby

    6769questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • 自然言語処理

    82questions

    自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。