0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

超シンプルな検索エンジンを作ってみたゾ!

Posted at

#はじめに

以下の記事を眺めていたら、自然言語処理を使って、大量データの中から、自分が求めているデータを抽出できるのって素敵だなーって感じていました。

なので、超シンプルな検索エンジンを作りました。

作った検索エンジンの仕組み

①蓄積した文章群から言語モデル(今回はtfidf)、ベクトルを作成。
②入力文章を言語モデルからベクトル化
③入力文章ベクトルと、蓄積した文章群の一つ一つとcos類似度を計算
④cos類似度が高い順にソートして、出力

#ソースコードはこんな感じ
twitterから取得したデータを用いて、言語モデル、ベクトル作成。
※データ取得については、この記事の本質ではないので、今回は割愛します。

#データサイエンティスト、自然言語処理、機械学習を含むtwitterデータを使います。
#search_tweet_listが、取得したデータを保持しているリスト変数です。

#tfidfのために、twitterデータを分かち書きする関数
def wakati_word_list_create(sentences, get_word_class):
    #複数文から、指定の品詞(GET_WORD_CLASS)を抽出した単語リスト
    sentences_word_list = []

    for sentence in sentences:
        #一文から、指定の品詞(GET_WORD_CLASS)を抽出した単語リスト
        one_sentence_word_str = ''
        #形態素解析
        node = mecab.parseToNode(sentence)

        while node:
            
            #語幹
            word = node.feature.split(",")[-3]
            #品詞
            word_class = node.feature.split(",")[0]  
            #(指定の品詞(GET_WORD_CLASS)である) and (語幹が*のもの(つまり未知語))場合は、単語リストに追加
            if word_class in get_word_class and word != '*': 
                one_sentence_word_str = one_sentence_word_str + " " + word

            node = node.next
        sentences_word_list.append(one_sentence_word_str)
    return sentences_word_list

#twitterデータから、指定品詞の分かち分割形式の単語リストを生成
GET_WORD_CLASS = ['名詞', '形容詞']
wakati_word_list = wakati_word_list_create(search_tweet_list, GET_WORD_CLASS)

#tfidfベクトル化
from sklearn.feature_extraction.text import TfidfVectorizer

tfidf = TfidfVectorizer(use_idf=True, token_pattern=u'(?u)\\b\\w+\\b')
#言語モデル作成
tfidf_model = tfidf.fit(wakati_word_list)
#ベクトル空間作成
vectors = tfidf_model.transform(wakati_word_list).toarray()

tfidfとcos類似度で類似度を計算し、降順ソートして、出力する


import numpy as np

#cos類似度を計算する関数
def cos_sim(v1, v2):
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

#検索時に何件を表示させるか
OUTPUT_NUMBER = 5

#検索したい文章、キーワード(入力データ)
search_sentence = ["ここに、なに調べたいかを書いてね"]

#wakati_word_list_createは、上のソースコードに書いている関数です。
wakati_input_texts = wakati_word_list_create(search_sentence, GET_WORD_CLASS)

#作った言語モデルはここで使うよ
tfidf_vectors = tfidf_model.transform(wakati_input_texts).toarray()

similars_map = {}

for sentence_id, sentence_vector in enumerate(vectors):
    similars_map[sentence_id] = cos_sim(tfidf_vectors[0], sentence_vector)
sorted_similars_map = sorted(similars_map.items(), key=lambda x: -x[1])

#任意件数(OUTPUT_NUMBER)を表示
print("入力文章:{}".format(search_sentence[0]))
for break_flag, similar_map in enumerate(sorted_similars_map):
    if break_flag == OUTPUT_NUMBER:
        break
    sentence_id = similar_map[0]
    sentence_similar = similar_map[1]
    if np.isnan(sentence_similar):
        if break_flag == 0:
            print("類似データは1件もなかったよ")
        break
    
    print("==========================================")
    print("類似度 : {}".format(sentence_similar))
    print("{}".format(search_tweet_list[sentence_id]))
    print("")

実行結果

結果①
image.png

結果②
image.png

ええ感じやでー( *´艸`)
特に結果②は、ちゃんとイベント情報をとれてるわ!素敵!!

#もっと良くするには、を考えてみた
これを作ってみて、感じたのは、ベクトル化の手法がかなり大事だなって
ことです。
今回は、tfidfでベクトル化をしましたが、BM25、SCDV、word2vecなどで、全然違うでしょう。さらに、感情評価やネガポジ(極性)を取り込んでベクトル化してみたら、ネガポジの観点を含むような、ちょっと変わった検索エンジンができますね!
なによりも、こういうのには、Bertとか使ってみたいですね!!!どんな精度の検索がされるか、すごく気になります!!!!スペック足りないので、僕の家では作れないですけどね。。。(涙)

#最後に
最後まで読んで頂き、ありがとうございました。
今回のソースコード書いていて、もっと、色々なNLPの手法について勉強してみたいと思いました。
次は、LDAとかやってみて、なにか作ってみようかな~!!('◇')ゞ

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?