[알고리즘] 영화 추천 시스템 코드
2020. 4. 6. 22:36ㆍ노트/Python : 프로그래밍
추천시스템의 분류
1. 컨텐츠 기반 추천 시스템
2. 협업 기반 추천 시스템
2-1. 메모리 기반(KNN)
2-1-1. 사용자 기반 : 비슷한 유형의 사용자를 찾음
2-1-2. 아이템 기반 : 어떤 영화를 본 관객들이 다른 영화를 본다. (영향도)
2-2. 잠재요인 기반(Latent factor)
- 컨텐츠 기반 추천시스템
사용자가 선호하는 아이템을 같은 장르( 컨텐츠 ) 에 기반하여 추천하는 시스템
- 협업 기반 추천 시스템
- 메모리 기반
- 메모리 기반
영화1 | 영화2 | 영화3 | 영화4 | |
사용자1 | 4 | ? | 3 | ? |
사용자2 | 3 | 2 | ? | 5 |
사용자3 | ? | 3 | 2 | 2 |
다음과 같은 사용자 - 아이템 평점 행렬(Matrix)를 구성하여 구현해야한다.
사용자 기반 협업 필터링과 아이템 기반 협업 필터링이 있다.
- 사용자 기반 협업 필터링
User1과 User2는 itemA 부터 itemC까지 평점이 비슷하다.
그래서 비슷한 유형의 사람이라고 보고,
User1에게 itemD를 주면 User2의 3점과 비슷하게 줄 것이고,
User2에게 itemE를 주면 User1의 1점과 비슷하게 줄 것이다.
- 아이템 기반 협업 필터링
itemA와 itemB는 평점 분포가 유사하기 때문에 유사한 아이템으로 보고,
User4에게는 itemA를 추천하고 ,
User5에게는 itemB를 추천한다.
데이터
코드
# 실무 적용하기 좋음
데이터 준비
#데이터 불러오기
moviedata=pd.read_excel("영화평점.xlsx",header=1, index_col=0, dtypes=float)
#영화X이름 행렬로 만들기위해 Transpose
moviedata=pd.DataFrame(data=moviedata.T)
#데이터 프레임 딕셔너리 구조로 변경
moviedata_dic=moviedata.to_dict()
moviedata_dic
딕셔너리 nan 값 제거
# dictionary에 nan값 함수
def dropna(data): # name : i , movie : j
for i in data:
for j in data[i]:
name=i
movie=j
value=data[i][j]
data[i]={movie: value for movie, value in data[i].items() if pd.isnull(value)==False}
return data
# 딕셔너리 nan 값 제거
moviedata_dic_drop=dropna(moviedata_dic)
moviedata_dic_drop
피어슨 상관계수 함수 구현
-
왼쪽의 식을 오른쪽 식으로 변형하여 함수를 구현함
* 주의사항: 분모에 0을 나누지 않도록 임의 상수값 0.00001 정도를 추가함
cnt 값도 누적한 값으로 나눌 수 있도록 식 들여쓰기 주의
#피어슨 상관계수
def sim_pearson(data, n1, n2):
#구현
sumX=0
sumY=0
sumSqX=0 # x 제곱합
sumSqY=0 # y 제곱합
sumXY=0 #XY 합
global cnt # 영화 갯수
cnt =0
for i in data[n1]:
if i in data[n2]:
sumX+=data[n1][i]
sumY+=data[n2][i]
sumSqX+=pow(data[n1][i],2)
sumSqY+=pow(data[n2][i],2)
sumXY+=(data[n1][i])*(data[n2][i])
cnt+=1
global num # 전역변수 선언
global den # 전역변수 선언
num=sumXY-((sumX*sumY)/cnt)
den= (sumSqX-(pow(sumX,2)/cnt))*(sumSqY-(pow(sumY,2)/cnt))
return num/sqrt(den+0.00001) # 분모=0방지
나와 상관계수가 높게 나온 사람 출력 함수 구현
def top_match(data, name, rank=3, simf=sim_pearson):
#sim_pearson함수를 simf라는 이름으로 사용하겠다.
#구현부분
simList=[] #유사한 영화들이 저장될 리스트
for i in data:
if name!=i: #자기 자신을 제외
simList.append((simf(data, name, i),i))
simList.sort() #오름차순
simList.reverse() #역순(내림차순)
return simList[:rank]
# 1.나와 가장 상관계수가 높게 나온 사람? 5명출력
print(top_match(moviedata_dic_drop,"엄다연",5))
내가 보지 않은 영화에 대해 예상 평점이 높은 순으로 추천 함수 구현
def recommendation(data,person,simf=sim_pearson ):
res=top_match(data, person, len(data))
# print(res)
simSum=0 #상관계수(유사도)의 합
score_dic={} #예상평점 총합을 저장하기 위한 dic
sim_dic={} # 유사도 합을 저장하기 위한 dic
myList=[]
for sim, name in res:
if sim<0 : continue # 유사도가 양수인 경우만 처리를 하도록 하겠음
for movie in data[name]:
if movie not in data[person]:
# name이 본 movie를 person이 보지 않았다면... => 추천해야하는 영화 대상이 됌
simSum+=sim*data[name][movie]
score_dic.setdefault(movie,0) #key가 없으면 초기화하지만 key가 있으면 냅둔다.
score_dic[movie]+=simSum
sim_dic.setdefault(movie,0)
sim_dic[movie]+=sim
simSum=0 # 영화변경 -> 0으로 초기화
for key in score_dic: #기준이 안본 영화의 제목들이 들어감
score_dic[key]=score_dic[key]/sim_dic[key] # 평점총합 / 유사도 총합
myList.append((score_dic[key],key))
myList.sort()
myList.reverse()
return myList
# 2.내가 안본 영화 중에서 추천 점수가 가장 높은 순으로 영화제목과 예상평점을 출력
recommendation(moviedata_dic_drop, "엄다연")
'노트 > Python : 프로그래밍' 카테고리의 다른 글
[추천시스템] 넷플릭스 영화 추천 시스템 구현 파이썬 코드 (13) | 2020.04.08 |
---|---|
[파이썬기초] 데이터전처리 중복값 처리 (0) | 2020.04.07 |
[파이썬기초] 데이터전처리 결측값 (NaN) 처리 (0) | 2020.04.06 |
[파이썬기초] 한글 깨짐 방지코드 (0) | 2020.04.06 |
[파이썬] 데이터 변형 | 원핫인코딩 (0) | 2020.04.04 |