個人学習-5

20127 ワード

1)コサイン類似度


1.コサイン類似度


2つのベクトル間の余弦角度を用いて求められる2つのベクトルの類似度.
2つのベクトルの方向が完全に同じ場合、1(cos(0)=1)、180度が逆の場合、1(cos(pi)=1)、直交する場合、0(cos(pi/2)=0).2つのベクトルの方向が似ているかどうかを直感的に表す

2つのベクトルの間の余弦の値を求めます!以前の学習の基本内容
from numpy import dot
from numpy.linalg import norm
import numpy as np
def cos_sim(A, B):
    ## norm은 각 벡터의 크기를 뜻함. dot은 두 매트릭스의 dot product
    return dot(A, B) / (norm(A) * norm(B))
    
doc1 = np.array([0, 1, 1, 1])
doc2 = np.array([1, 0, 1, 1])
doc3 = np.array([2, 0, 2, 2])

print(cos_sim(doc1, doc2)) # doc1과 2의 코사인 유사도
print(cos_sim(doc1, doc3)) # 1과 3의 유사도
print(cos_sim(doc2, doc3)) # 2와 3의 유사도
0.6666666666666667
0.6666666666666667
1.0000000000000002
2と3は1で全く同じで、doc 2はdoc 1のtfにスカラーを掛ける.つまり、大きさが違うだけです.
このような1つのドキュメントが別のドキュメントとして表されるtfの積は,すべての単語の頻度が増加しただけである.文の長さが長ければ、すべての単語の頻度が悪くなることが多い.このような場合、1が出てくるとこれがこの書類と非常に似ていると感じるのではなく、増えていることを知らせるものです.すなわち,文書長が異なる場合には比較的公平に行うことができる.
これは,コサイン類似度がベクトルの大きさではなく,方向に焦点を当てるためである.

2.類似度を用いた推奨システムの実現


TF-IDFとコサインの類似度だけで、ストーリーに基づいて映画推薦システムを作成できます.
ムービーファイルのダウンロード
import pandas as pd 
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
data = pd.read_csv('/content/drive/MyDrive/산학협력프로젝트/딥러닝을 이용한 자연어 처리 입문/archive/movies_metadata.csv', low_memory = False)
data.head()

dataは、上記の形状からなり、その形状は(45466,24)である.まず最初に20,000個カットして使います
data = data.head(20000)
data.overview.isna().sum()
135
ストーリーベースの映画がおすすめなので、総覧が重要です.overviewのnullは135です.TF-IDFを生成する場合、Nullがあるとエラーが発生するため、「」に置き換えます.
data.overview.fillna('', inplace = True)
## TF-IDF 수행
## 영어 불용어를 제거하고 TF-IDF 생성
tfidf = TfidfVectorizer(stop_words = 'english')
tfidf_mat = tfidf.fit_transform(data['overview'])
tfidf_mat.shape
(20000, 47487)
20000개의 문서에 대해 47487개의 단어 토큰이 생성되었다!
코사인 유사도를 사용해 문서의 유사도를 파악하자
```py
indices = pd.Series(data.index, index = data['title']).drop_duplicates()
print(indices.head())
title
Toy Story                      0
Jumanji                        1
Grumpier Old Men               2
Waiting to Exhale              3
Father of the Bride Part II    4
dtype: int64
索引を作成する理由は、見出しの入力時に索引を返すためです.
## 코사인 유사도 계산 with linear kernel
cosine_sim = linear_kernel(tfidf_mat, tfidf_mat)
## 추천 함수 작성
def get_recommend(title, cosine_sim = cosine_sim):
    # 선택한 영화의 인덱스 가져오기
    idx = indices[title]
    # 모든 영화에 대해 유사도 구함(TF-IDF 기반)
    sim_scores = list(enumerate(cosine_sim[idx]))
    # 유사도에 따라 정렬
    sim_scores = sorted(sim_scores, key = lambda x: x[1], reverse = True)
    # 가장 유사한 10개의 영화를 받아옴
    sim_scores = sim_scores[1:11]
    # 10개 인덱스 받아옴
    movie_indices = [i[0] for i in sim_scores]
    # 영화 제목 리턴
    return data['title'].iloc[movie_indices]
    
get_recommend('The Dark Knight Rises')
12481                            The Dark Knight
150                               Batman Forever
1328                              Batman Returns
15511                 Batman: Under the Red Hood
585                                       Batman
9230          Batman Beyond: Return of the Joker
18035                           Batman: Year One
19792    Batman: The Dark Knight Returns, Part 1
3095                Batman: Mask of the Phantasm
10122                              Batman Begins
Name: title, dtype: object
  • の暗夜灯と同様に、概要に基づく10大推奨
  • はバットマンに関する映画です!
  • 面白い映画があれば、それを利用して推薦を受けることができます.
  • 団は、そのコパーズ内の映画でこそ可能だ.なければ、
  • を追加して再び戻ることができます.

    2)複数の類似度方法


    1.ユークリッド距離


    多次元空間内の2つの点間の距離と見なすことができます.

    この類似度を計算する際に使用される距離もクラスタ化に使用されます.
    ## 문서간 유클리드 거리 계산으로 유사도 파악
    import numpy as np
    def dist(x, y):
        return np.sqrt(np.sum((x-y) ** 2))
    
    doc1 = np.array([2, 3, 0, 1])
    doc2 = np.array([1, 2, 3 ,1])
    doc3 = np.array([2, 1, 2, 2])
    docQ = np.array([1, 1, 0, 1])
    
    print(dist(doc1, docQ))
    print(dist(doc2, docQ))
    print(dist(doc3, docQ))
    2.23606797749979
    3.1622776601683795
    2.449489742783178
    docqが興味のあるドキュメントで、1~3は既存のドキュメントを表します.ユークリッド距離を基準にQに最も似たドキュメントはdoc 1!!

    2.提花類似度


    2つの集合がある場合,集合から交差への比率は類似度を求める.花の類似度は0から1の間で、同じ場合は1で、要素がなければ0です.
    doc1 = "apple banana everyone like likey watch card holder"
    doc2 = "apple banana coupon passport love you"
    
    # 토큰화를 수행합니다.
    tokenized_doc1 = doc1.split()
    tokenized_doc2 = doc2.split()
    
    # 토큰화 결과 출력
    print(tokenized_doc1)
    print(tokenized_doc2)
    ['apple', 'banana', 'everyone', 'like', 'likey', 'watch', 'card', 'holder']
    ['apple', 'banana', 'coupon', 'passport', 'love', 'you']
    簡単に書き換えに基づいてタグ付けを行い、その結果は以下の通りである.
    ## 문서1과 2의 합집합과 교집합!
    union = set(tokenized_doc1).union(set(tokenized_doc2))
    intersection = set(tokenized_doc1).intersection(set(tokenized_doc2))
    print(union)
    print(intersection)
    {'everyone', 'watch', 'card', 'like', 'holder', 'passport', 'banana', 'you', 'love', 'likey', 'apple', 'coupon'}
    {'banana', 'apple'}
    set演算ではsetしかできないのでdoc 1,2をsetに変換します.これで重複が解消されます.交差と並列の数値抽出係数を計算します.
    ## jaccard
    print(len(intersection) / len(union))
    0.16666666666666666
    2つのドキュメントの重複を除くユニークな要素間の花係数を0.16の値で求めた.花係数は、2つのドキュメント内のユニークな要素の合計に共通する比率です.この割合の高低は主観的で、分析者が基準を制定する必要がある.