본문 바로가기
Machine Learning

[ML] 추천시스템_ 책 추천 알고리즘

by ram_ 2023. 1. 12.

- GoodBooks Data Download

https://www.kaggle.com/datasets/zygmunt/goodbooks-10k

 

import pandas as pd
import numpy as np
import os

os.listdir('./goodBooks')

books = pd.read_csv('./goodBooks/books.csv', encoding='ISO-8859-1')
ratings = pd.read_csv('./goodBooks/ratings.csv', encoding='ISO-8859-1')
book_tags = pd.read_csv('./goodBooks/book_tags.csv', encoding='ISO-8859-1')
tags = pd.read_csv('./goodBooks/tags.csv')
to_read = pd.read_csv('./goodBooks/to_read.csv')

# book_tags와 tags를 merge
tags_join_DF = pd.merge(book_tags, tags, left_on= 'tag_id', right_on='tag_id', how='inner')

# authors로 Tfidf 수행
from sklearn.feature_extraction.text import TfidfVectorizer
tf = TfidfVectorizer(analyzer='word', ngram_range=(1,2), min_df=0, stop_words='english')
tfidf_matrix = tf.fit_transform(books['authors'])

# 유사도 측정. 코사인 유사도 처럼 뽑음
from sklearn.metrics.pairwise import linear_kernel
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)

# the hobbit의 index는?  6
titles = books['title']
indices = pd.Series(books.index, index=books['title'])

# 유사도 값 호출
cosine_sim[indices['The Hobbit']]

# 유사도 결과를 인덱스를 가진 list형으로 
cosine_sim[indices['The Hobbit']].shape

# 가장 유사한 책의 인덱스 찾기
sim_scores = list(enumerate(cosine_sim[indices['The Hobbit']]))
sim_scores = sorted(sim_scores, key=lambda x : x[1], reverse=True)

# 작가로 본 유사 책 검색
sim_scores = sim_scores[1:11]
book_indices = [i[0] for i in sim_scores]
titles.iloc[book_indices]

# book에 tag 포함
books_with_tags = pd.merge(books, tags_join_DF, left_on='book_id', right_on='goodreads_book_id', how='inner')

pd.Series(books[['authors', 'tag_name']].fillna('').values.tolist())

# 저자 이름과 태그를 합친다
# author과 tag_name을 합쳐서 Series(하나의 데이터가 들어가는 개념이기에 value만 빼서 리스트로 만듬)로 corpus라는 칼럼을 만든다. 
# 콤마로 구분되어진 부분은 빈칸으로 대체한다.
books['corpus'] = (pd.Series(books[['authors', 'tag_name']].fillna('').values.tolist()).str.join(' '))

# Tfidf를 수행한다.
tf_corpus = TfidfVectorizer(analyzer='word', ngram_range=(1,2), min_df=0, stop_words='english')
tfidf_matrix_corpus = tf_corpus.fit_transform(books['corpus'])
cosine_sim_corpus = linear_kernel(tfidf_matrix_corpus, tfidf_matrix_corpus)

titles = books['title']
indices = pd.Series(books.index, index=books['title'])

# 추천 함수 
def corpus_recommandation(title):
    idx = indices1[title]
    sim_scores = list(enumerate(cosine_sim_corpus[idx]))
    sim_scores = sorted(sim_scores, key=lambda x : x[1], reverse=True)
    sim_scores = sim_scores[1:11]
    book_indices = [i[0]for i in sim_scores]
    return titles.iloc[book_indices]

 

tags_recommandation함수와 corpus_recommandation함수를 보면 같은 책에 대한 다른 결과값이 보이는 것을 확인 가능하다.

사람은 성향의 차이가 존재하기에 어느것이 더 좋다는 것은 판별할 수 없다.