Data Engineering/python

EP25 | 고급 Python 활용 #14 | Spark를 활용한 실시간 추천 시스템 구축

ygtoken 2025. 3. 19. 23:17
728x90

이 글에서 다루는 개념

Apache Spark를 활용하면 대용량 데이터를 기반으로 실시간 추천 시스템을 구축할 수 있습니다.
이번 글에서는 다음 내용을 학습합니다.

  • 추천 시스템 개념 및 Spark의 ALS(Alternating Least Squares) 알고리즘
  • PySpark MLlib을 사용한 협업 필터링(Collaborative Filtering)
  • 사용자 기반 및 아이템 기반 추천 모델 구축
  • 실시간 추천 시스템 구현

1️⃣ 추천 시스템 개념

📌 추천 시스템이란?

  • 사용자에게 맞춤형 콘텐츠(영화, 음악, 상품 등)를 추천하는 기술
  • **협업 필터링(Collaborative Filtering)**과 콘텐츠 기반 추천(Content-Based Filtering) 방식이 있음

📌 추천 시스템 유형

추천 방식 설명
협업 필터링 다른 사용자의 행동 패턴을 분석하여 추천 (예: "이 영화를 본 사람은 이 영화도 좋아합니다.")
콘텐츠 기반 필터링 사용자가 본 아이템의 특징을 분석하여 유사한 아이템 추천
하이브리드 방식 협업 필터링 + 콘텐츠 기반 필터링 결합

📌 Spark에서는 협업 필터링을 위한 ALS(Alternating Least Squares) 알고리즘을 지원


2️⃣ PySpark ALS 모델을 활용한 협업 필터링 추천

📌 ALS(Alternating Least Squares) 알고리즘이란?

  • 사용자-아이템 행렬을 행렬 분해하여 추천을 수행
  • 대규모 데이터에서도 효율적인 학습 가능
  • Netflix, Spotify 같은 추천 시스템에서 사용

3️⃣ 데이터 불러오기 및 전처리

📌 사용자-아이템 평점 데이터 로드 (ratings.csv)

userId,movieId,rating
1,101,5.0
1,102,4.0
2,101,4.5
2,103,3.5
3,104,5.0

 

📌 CSV 데이터 불러오기

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("MovieRecommendation").getOrCreate()

df = spark.read.csv("ratings.csv", header=True, inferSchema=True)
df.show()

 

📌 출력 예시

+------+-------+------+
|userId|movieId|rating|
+------+-------+------+
|     1|    101|   5.0|
|     1|    102|   4.0|
|     2|    101|   4.5|
+------+-------+------+

4️⃣ ALS 모델 학습 및 추천 생성

📌 훈련 데이터 분할 (Train/Test Split)

train_data, test_data = df.randomSplit([0.8, 0.2], seed=42)

 

📌 ALS 모델 학습

from pyspark.ml.recommendation import ALS

als = ALS(userCol="userId", itemCol="movieId", ratingCol="rating", coldStartStrategy="drop")
model = als.fit(train_data)
print("ALS 모델 학습 완료!")

 

📌 사용자별 추천 영화 예측

user_recommendations = model.recommendForAllUsers(3)  # 각 사용자에게 3개의 영화 추천
user_recommendations.show(5, truncate=False)

 

📌 출력 예시

+------+--------------------------+
|userId|recommendations           |
+------+--------------------------+
|1     |[[103, 4.8], [104, 4.7]]  |
|2     |[[102, 4.9], [105, 4.6]]  |
+------+--------------------------+

5️⃣ 특정 사용자에게 추천 영화 제공

📌 특정 사용자(userId=1)에게 영화 추천

user_1 = spark.createDataFrame([(1,)], ["userId"])
recommendations = model.recommendForUserSubset(user_1, 3)  # 3개 추천
recommendations.show(truncate=False)

 

📌 출력 예시

+------+----------------------+
|userId|recommendations       |
+------+----------------------+
|1     |[[104, 4.9], [102, 4.8]] |
+------+----------------------+

6️⃣ 특정 영화에 대한 유사한 영화 추천

📌 아이템 기반 추천 (영화 movieId=101와 유사한 영화 추천)

movie_101 = spark.createDataFrame([(101,)], ["movieId"])
movie_recommendations = model.recommendForItemSubset(movie_101, 3)  # 3개 추천
movie_recommendations.show(truncate=False)

 

📌 출력 예시

+-------+----------------------+
|movieId|recommendations       |
+-------+----------------------+
|101    |[[2, 4.8], [3, 4.7]] |
+-------+----------------------+
  • 사용자 2, 3이 해당 영화를 선호할 가능성이 높음

📌 실전 문제: PySpark 추천 시스템 모델 연습하기


문제 1: PySpark로 영화 평점 데이터 불러오기

📌 ratings.csv를 불러와 상위 5개 데이터를 출력하세요.

from pyspark.sql import SparkSession
# 🔽 여기에 코드 작성
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("MovieRecommendation").getOrCreate()
df = spark.read.csv("ratings.csv", header=True, inferSchema=True)
df.show(5)

문제 2: ALS 모델 학습 및 사용자별 추천 영화 예측

📌 ALS 모델을 학습한 후, 사용자별 3개의 추천 영화를 출력하세요.

from pyspark.ml.recommendation import ALS
# 🔽 여기에 코드 작성
als = ALS(userCol="userId", itemCol="movieId", ratingCol="rating", coldStartStrategy="drop")
model = als.fit(train_data)

user_recommendations = model.recommendForAllUsers(3)
user_recommendations.show(5, truncate=False)

문제 3: 특정 사용자(예: userId=2)에게 추천 영화 제공

📌 사용자 2에게 추천 영화를 3개 출력하세요.

# 🔽 여기에 코드 작성
user_2 = spark.createDataFrame([(2,)], ["userId"])
recommendations = model.recommendForUserSubset(user_2, 3)
recommendations.show(truncate=False)

문제 4: 특정 영화(예: movieId=101)와 유사한 영화 추천

📌 movieId=101과 유사한 영화를 3개 출력하세요.

# 🔽 여기에 코드 작성
movie_101 = spark.createDataFrame([(101,)], ["movieId"])
movie_recommendations = model.recommendForItemSubset(movie_101, 3)
movie_recommendations.show(truncate=False)

 

728x90