[AI] 코사인 유사도를 이용해 추천 프로그램 만들기

Jean·2023년 10월 23일
0

코사인 유사도

  • 벡터와 벡터간의 유사도를 비교할 때 두 벡터간의 사잇각을 구해서 얼마나 유사한지 수치로 나타내는 것

  • 벡터값의 관계
    1. 벡터 방향이 반대가 될수록 반대 관계

    1. 벡터 방향이 90도일 때는 관련성이 없음

    2. 벡터 방향이 비슷할 수록 두 벡터는 유사함

      	나는 수학에서 벡터를 배운적이 없고 코사인은 기억이 안나 잘 모르겠지만 관계성만 익혔다. 아래 코드로 주석을 달아 익혀보도록 하자 

코드로 이해하기

#필요한 라이브러리 가져오기
	#판다스
import pandas as pd
	#TfidfVectorizer - 문자 벡터화
from sklearn.feature_extraction.text import TfidfVectorizer
	#코사인 유사도를 구함
from sklearn.metrics.pairwise import cosine_similarity
# movies_metadata.csv를 읽어서 data에 저장 
data = pd.read_csv('movies_metadata.csv', low_memory=False)
#data에 저장된 데이터 중 두번째 행까지 보여줌 
data.head(2)

출력값으로는 여러 행들이 나왔고 그 중 영화의 'overview'행의 문장들을 사용할 것이다.

# 데이터 양이 많아 상위 200000개만 사용
#data의 0번째부터 20000번째 행을 모두 'df'에 저장
df = data.head(20000) 
# overview 열에 존재하는 모든 결측값을 전부 카운트하여 출력
#df의 'overview'행에 해당하는, null값의, 합을 보여줌
df['overview'].isnull().sum() 

출력 : 135

  • 데이터를 믿고 null값을 확인 안하면 절대 안된다. 사용하는 데이터에 대해서 null 값 확인하기! 
# 결측값을 빈 값으로 대체 ( copy()해서 사용하거나 다음처럼 사용)
#df의 'ovreview' 열에 해당하는 행을 전체 선택해서 df'overview행에 있는 null값을 ''공백으로 채움

df.loc[:, 'overview'] = df['overview'].fillna('')
	왜 '.loc' 메소드를 쓰는 이유에 궁금해서 강사님께 여쭤봤다. 
    df['overview'] = df['overview'].fillna('')도 같은 결과를 가져오는 것 같은데 뭐가 다른걸까? 
    이유는 loc메소드를 쓰지 않아도 결과는 동일하지만 더 정확한 지시를 위해 아래와 같이 코드를 쓰는 것이 권장되는 방법이기 때문이다. 
    
#tfidfvectorizer(불용어 = 'english') : Tfidfvect 에서 정해놓은 불용어 모음을 통해 불용어 설정 완료
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf.fit_transform(df['overview'])

#데이터의 행, 그리고 overview의 결과 값
tfidf_matrix.shape

(20000, 47487)

# 200000개의 문서 벡터와 자기 자신을 포함한 20,000개의 문서 벡터간의 유사도 행렬 (즉, 각 영화의 개요에 대한 TF-IDF 벡터) 간의 코사인 유사도를 계산
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)
print('코사인 유사도 연산 결과 :',cosine_sim.shape)

코사인 유사도 연산 결과 : (20000, 20000)

title_to_index = dict(zip(df['title'], df.index))

# 영화 제목 Father of the Bride Part II의 인덱스를 리턴
idx = title_to_index['Father of the Bride Part II']
print(idx)

출력 : 4

def get_recommendations(title, cosine_sim=cosine_sim):
    # 선택한 영화의 타이틀로부터 해당 영화의 인덱스를 받아온다.
    idx = title_to_index[title]

    # 해당 영화와 모든 영화와의 유사도를 가져온다.
    sim_scores = list(enumerate(cosine_sim[idx]))

    # 유사도에 따라 영화들을 정렬한다.
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)

    # 가장 유사한 10개의 영화를 받아온다. #0번째는 자기 자신 즉, 1값 
    sim_scores = sim_scores[1:11]

    # 가장 유사한 10개의 영화의 인덱스를 얻는다.
    movie_indices = [idx[0] for idx in sim_scores]

    # 가장 유사한 10개의 영화의 제목을 리턴한다.
    return df['title'].iloc[movie_indices]

# 다크 나이트 라이즈와 overview가 유사한 영화 찾기
get_recommendations('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

profile
아 왜 안돼

0개의 댓글