Content-Based Filtering & Popularity
- Content-Based Filtering 은 이전 성능을 비교했던 추천 알고리즘과 다소 목적이 다릅니다.
- 새로운 유저, 아이템에 대해 추천할 내용이 없는 경우 Cold Start 문제라고 하며 이는 추천시스템에서 반드시 다루어야할 과제입니다.
- Cold Start 문제를 사용자/아이템 프로파일링, 군집화를 이용해 해결할 수 있으나, 이를 위해 정교한 추가 데이터 분석이 필요합니다.
- 이번 강의에서는 Content-Based Filtering과 Popularity-based 추천을 통해 해결하는 과정을 진행합니다.
Content-based filtering
- 유저 과거에 혹은 최근에 선호했던 아이템의 특성을 기반으로 비슷한 특성의 새로운 아이템을 추천하는 방법입니다.
- 유저가 선호하는 아이템을 정의하고,
- 해당 아이템과 유사한 다른 아이템을 찾아서 추천합니다(유사도가 높은 순서대로)
- 아이템 별로 임베딩을 진행하고 모든 아이템 x 아이템 쌍별로 코사인 유사도를 이용해 유사도 기준으로 유사 아이템을 찾아낼수 있습니다.
- 개인화된 추천 아이템을 제공하나, 유사한 아이템이 중복적으로 추천되므로 새로운 아이템(Novelty, Serendipity)이 부족할수 있습니다.
- 따라서 단독 모델로 쓰이기 보다, 보완용 혹은 하이브리드용으로 주로 쓰입니다.
Popularity-based 추천
- 비개인화된 추천, 가장 많이 팔린 아이템, 평점이 높은 아이템 순으로 정렬하여 누구에게나 동일하게 추천하는 단순한 방식
- 개인화가 반영되지 않아 성능이나 사용자 피드백이 좋지 않은 경향이 있어, 사용하지 않는 추세
# book selection
book_rec = book_info[(book_info['rating_count'] >= 3) & (book_info['rating_mean'] >= 4)]
# summary added
book_rec = book_rec.merge(df[['isbn', 'summary']].drop_duplicates(), on='isbn', how='left').fillna("")
# Function to clean and extract meaningful keywords
def clean_text(summary):
# Remove punctuation, numbers, and special characters using regex
cleaned_summary = re.sub(r'[^a-zA-Z\s]', '', summary)
# Tokenize the summary by splitting on whitespace
words = cleaned_summary.lower().split()
# Filter out stopwords and short words (less than 3 characters)
meaningful_words = [word for word in words if word not in stop_words and len(word) > 2]
return ' '.join(meaningful_words) # Return as a single string
# Apply the cleaning function to the 'summary' column
book_rec['cleaned_summary'] = book_rec['summary'].apply(clean_text)
book_rec['keywords'] = book_rec['book_title']+' '+book_rec['book_author']+' '+book_rec['cleaned_summary']+' '+book_rec['category']
book_rec = book_rec[['isbn', 'book_title', 'keywords']]
book_rec['keywords'] = book_rec['keywords'].apply(clean_text)
book_rec.shape # (27772, 3)
tfidf = TfidfVectorizer(stop_words='english', max_features=1000, min_df=10)
tfidf_matrix = tfidf.fit_transform(book_rec['keywords'])
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)
#3426600218, 0385504209, 059035342X, 0345370775, 0345337662, 0345339681
my_isbn = '3426600218'
top_n = 10
def get_recom_items(my_isbn, top_n, cosine_sim, book_rec, std_book_include=True):
idx = book_rec[book_rec['isbn'] == my_isbn].index[0]
sim_scores = list(enumerate(cosine_sim[idx]))
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
if std_book_include:
sim_scores = sim_scores[:top_n+1]
else:
sim_scores = sim_scores[1:top_n+1]
book_indices = [i[0] for i in sim_scores]
return book_rec.iloc[book_indices]
recom_result = get_recom_items(my_isbn, top_n, cosine_sim, book_rec, std_book_include=False)
보통 유저별 최근 구매 아이템중에 빈도가 많거나 평가 좋은 아이템을 기준으로 이용없는 경우,
자주 클릭한 아이템을 이용하거나 세그먼트별 대표아이템을 대안으로 이용그래도 없으면
회원가입시 간단한 설문조사로 파악(e.g. Netflix)
# Popularity Recommendation, but NON-personalized
category_list = book_info.groupby(['category']).size()
category_list.sort_values(ascending=False)[:10]
#my_cate = 'Business & Economics'
my_cate = 'Business & Economics'
book_info.query("category == @my_cate").sort_values("rating_count", ascending=False)[:10]
# Content-based & Populiarty Hybrid
user_id = 219008
top_n = 10
def get_recommended_items_content(user_id, top_n):
# the previous book that the user liked the most
most_liked_isbn = df_mf[df_mf['user_id'] == user_id].sort_values("rating", ascending=False)['isbn']
if most_liked_isbn.empty:
return pd.DataFrame()
most_liked_isbn = most_liked_isbn.values[0] # get the isbm
# popularity-based if none
if most_liked_isbn not in book_rec['isbn'].values:
predictions = book_info.sort_values("rating_count", ascending=False)[:top_n]
predictions['user_id'] = user_id
predictions = predictions[['user_id', 'isbn', 'book_title', 'book_author']]
# using content-based
else:
idx = book_rec[book_rec['isbn'] == most_liked_isbn].index[0]
sim_scores = list(enumerate(cosine_sim[idx]))
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)[1:top_n+1]
book_indices = [i[0] for i in sim_scores]
recommend_books = book_rec.iloc[book_indices]['isbn']
predictions = book_info[book_info['isbn'].isin(recommend_books)]
predictions['user_id'] = user_id
predictions = predictions[['user_id', 'isbn', 'book_title', 'book_author']]
return predictions
get_recommended_items_content(user_id, top_n)
'코드 및 쿼리문 > 강의 - 메타코드M' 카테고리의 다른 글
Kaggle 데이터를 활용한 개인화 추천시스템(7) (0) | 2024.12.10 |
---|---|
Kaggle 데이터를 활용한 개인화 추천시스템(6) (0) | 2024.12.10 |
Kaggle 데이터를 활용한 개인화 추천시스템(4) (1) | 2024.12.05 |
Kaggle 데이터를 활용한 개인화 추천시스템(3) (2) | 2024.12.05 |
Kaggle 데이터를 활용한 개인화 추천시스템(2) (2) | 2024.12.05 |