본문 바로가기메뉴 바로가기


카카오 AI추천 : 카카오의 콘텐츠 기반 필터링 (Content-based Filtering in Kakao)

카카오 서비스 사용자들의 아이템(콘텐츠 또는 상품) 소비 패턴을 살펴보면, 기존에 소비한 아이템과 유사한 아이템을 소비하는 경우를 쉽게 찾아볼 수 있습니다. 예를 들면, 브런치의 특정 작가의 글을 연속해서 보거나, 멜론에서 한 장르의 음악을 많이 듣는다거나, 카카오웹툰, 카카오페이지에서 같은 장르의 작품을 많이 감상한다거나, 선물하기 서비스에서 특정 브랜드의 상품을 자주 구매하는 경우가 여기에 해당됩니다.

이렇게 소비 패턴이 뚜렷하다면 아이템의 정보를 활용해 추천하는 콘텐츠 기반 필터링(Content-based filtering) 방식이 효과적일 수 있습니다. 이번 글에서는 콘텐츠 기반 필터링에 대해서 알아보고, 카카오의 서비스에서 어떻게 적용이 되어 있는지 소개하고자 합니다.


콘텐츠 기반 필터링

콘텐츠 기반 필터링은 아래 그림에 표현된 것과 같이, 사용자가 소비한 아이템에 대해 아이템의 내용(content)이 비슷하거나 특별한 관계가 있는 다른 아이템을 추천하는 방법을 말합니다. 아이템의 내용은 아이템을 표현할 수 있는 데이터를 지칭하는데, 아이템 카테고리, 아이템 이름과 같은 텍스트 데이터, 이미지 데이터가 주로 사용됩니다. 다른 사용자의 아이템 소비 이력을 활용하는 협업 필터링(Collaborative filtering) 과는 주로 사용하는 데이터가 다르다는 차이점이 있습니다.

아이템이 유사한지 확인하려면 아이템의 비슷한 정도(유사도, similarity)를 수치로 계산할 수 있어야 합니다. 유사도 계산을 위해서 일반적으로 아이템을 벡터 형태로 표현하고 이들 벡터 간의 유사도 계산 방법을 많이 활용합니다.

아이템을 잘 표현할 수 있는 벡터를 만드는 데 널리 사용되는 방법으로는 (1) 원 핫 인코딩(One-hot encoding), (2) 임베딩(Embedding)이 있습니다. 

원 핫 인코딩(One-hot encoding)은 아이템의 카테고리와 같은 범주형 데이터(categorical feature)를 표현하는 간단한 방법으로, 표현해야 하는 범주의 개수를 크기로 갖는 벡터를 만들어 데이터를 1과 0으로 표현하는 방법입니다. 아래 그림처럼 4가지의 아이템의 색상 데이터를 표현하고자 한다면, 그림 오른쪽처럼 특정 색상만 1의 값을 갖고 나머지는 0의 값을 갖는 벡터를 만들 수 있습니다.

표현하는 범주형 데이터의 종류에 따라 0과 1 대신 다양한 실숫값을 사용하기도 합니다. 예를 들어, 텍스트 데이터의 경우는 등장하는 단어를 각각의 범주로 생각하고 각 단어의 중요도나 빈도를 반영하기 위해 TF-IDF 가중치(weight)를 계산해 1 대신 넣기도 합니다.

카테고리와 같은 간단한 범주형 데이터의 경우 원 핫 인코딩(One-hot encoding)으로 표현이 가능하지만, 표현해야 하는 데이터 범주의 영역이 넓거나 이미지와 같이 복잡한 데이터인 경우는 데이터를 고정된 크기의 벡터로 표현하는 임베딩(Embedding) 방법을 많이 사용합니다. 벡터의 크기가 고정되어 있어 다루어야 하는 데이터의 크기가 늘어나더라도 상대적으로 적은 크기의 데이터를 통해 표현이 가능하고 딥러닝을 활용한 텍스트, 이미지 모델을 적용해 좋은 품질의 벡터를 얻을 수 있습니다.

텍스트 데이터의 경우는 Word2Vec 모델이 제일 널리 알려지고 사용되는 텍스트 임베딩 모델입니다. Word2Vec으로 각 단어의 임베딩 벡터를 학습하고, 텍스트에 등장하는 단어의 벡터를 합하거나 TF-IDF 가중 합산을 하는 방식으로 많이 활용되고 있습니다. 이후에 텍스트에 등장하는 단어 사이의 순서를 고려하기 위한 CNN, RNN 모델들이 제안되었고, 최근에는 BERT와 같은 대규모 텍스트 모델을 임베딩 모델로 활용하기 위한 다양한 연구가 등장했습니다.

이미지 데이터의 경우는 ImageNet 데이터의 카테고리 분류를 위해 미리 학습된 모델을 바탕으로 실제 사용할 데이터에 대해 파라미터 미세 조정(Fine-tuning)을 수행한 다음, 분류 레이어(classification layer)의 입력으로 들어가는 보틀넥 피처(Bottleneck feature)를 이미지 임베딩으로 사용하는 방법이 일반적입니다. 인물 사진이나 쇼핑과 같은 일부 도메인에서는 레이어 구조를 수정해 카테고리 분류 대신 유사, 동일성 여부를 직접 판별하는 샴 네트워크(Siamese network), 삼중항 네트워크(Triplet network)를 적용하는 방법도 있습니다.

이렇게 표현된 아이템 벡터는 내적(Dot product), 코사인 유사도(Cosine similarity), 피어슨 상관 계수(Pearson correlation coefficient)와 같은 다양한 벡터 유사도 측정 방식을 통해 아이템 유사도를 측정하는 용도로 사용됩니다. 측정된 유사도를 바탕으로 사용자가 최근 소비한 아이템과 유사한 아이템을 추천하면 콘텐츠 기반 필터링을 통한 추천이 됩니다.

콘텐츠 기반 필터링은 아이템 정보만 있으면 추천이 가능하기 때문에 소비 이력이 없는 새로운 아이템에 대한 추천이 바로 가능하다는 장점이 있습니다. 하지만 충분한 소비 이력이 쌓인 아이템에 대해서는 협업 필터링에 비해 추천 성능이 밀린다는 인식이 보편적입니다. 이런 이유로, 콘텐츠 기반 필터링은 추천 대상 아이템이 빠르게 바뀌는 상황이나 소비 이력이 적은 아이템에 대해, 협업 필터링을 보완하는 용도로 많이 활용됩니다.

카카오웹툰에서의 콘텐츠 기반 필터링

콘텐츠 기반 필터링을 통한 추천 로직은 카카오의 많은 서비스에 이미 적용이 되어 있습니다. 이번 단락에서는 카카오웹툰의 연관 작품 추천 영역에 적용된 콘텐츠 기반 필터링 로직을 소개하겠습니다. 

아래 화면은 카카오웹툰에서 작품을 열람하기 위해 작품 리스트에서 작품을 클릭하면 진입하게 되는 작품 홈 영역입니다. 작품 홈 영역 상단에는 해당 작품을 본 사용자가 볼 만한 다른 작품을 추천해 주는 연관 추천 영역(“A 작품과 비슷한 작품들” 영역)이 있습니다. 사용자는 좌우로 추천 리스트를 스와이프 해 다른 작품을 탐색하고 열람할 수 있습니다. 여기에 제공되는 추천에 콘텐츠 기반 필터링을 활용하고 있습니다.

새로운 작품이 추가되면, 콘텐츠 기반 필터링을 위해 아래와 같은 데이터 준비 작업을 실시간으로 진행합니다.

  • 작품 줄거리 텍스트 데이터를 바탕으로 작품 텍스트 임베딩을 생성합니다. 텍스트 임베딩에는 카카오가 보유한 다양한 텍스트 데이터로 사전에 학습한 한국어 임베딩 모델을 사용합니다.
  • 사전에 다양한 이미지를 사용해 학습 시켜 둔 이미지 모델을 사용해 작품 대표 이미지의 임베딩을 생성합니다.
  • 카카오브레인에서 개발한 웹툰 그림체 추출 모델을 사용해 작품 대표 이미지의 그림체 임베딩을 생성합니다.

특정 작품에 대한 연관 추천 결과를 계산할 때, 미리 준비해둔 콘텐츠 기반 필터링을 위한 데이터를 사용합니다. 앞서 얘기했듯이 콘텐츠 기반 필터링의 장점과 단점이 있기 때문에 이것만으로 추천 결과를 계산하지는 않고 다양한 모델로 얻은 추천 결과를 함께 사용합니다. 

먼저, 앞서 알아본 3가지 임베딩을 통해 찾은 유사한 작품들 이외에도 협업 필터링과 같이 다른 방법으로 학습한 임베딩을 사용해 각각 유사한 작품 상위 K개를 추출합니다.

예를 들어, 위의 그림과 같이 “슬” 작가님의 <슬프게도 이게 내 인생>이라는 작품 대상으로 추천 결과를 계산한다면, 협업 필터링, 텍스트, 그림체, 이미지 임베딩을 가지고 각각 유사도가 높은 작품을 추려내고 이 유사한 작품들을 <슬프게도 이게 내 인생> 작품의 연관 추천 대상으로 선정합니다.

이후에는 선정한 유사 작품들을 멀티암드 밴딧(multi-armed bandit) 알고리즘을 통해 사용자가 추천받은 작품을 열람할 확률을 최대로 만들 수 있도록 순서를 조정해 사용자에게 노출합니다. 멀티암드 밴딧(multi-armed bandit) 알고리즘은 사용자가 열람하는 이벤트를 실시간으로 받아 열람 확률 최대화를 계속해서 진행합니다. 이로 인해 사용자는 항상 최근 인기도와 작품 내용 모두를 반영한 최신 추천 결과를 받을 수 있습니다.

마치며

이번 글에서는 다양한 추천 영역에서 활용되고 있는 콘텐츠 기반 필터링의 기본적인 아이디어와 카카오웹툰 연관 추천 영역에 적용된 사례를 살펴봤습니다. 

카카오웹툰에서는 텍스트, 이미지와 같은 기본적인 임베딩 모델은 물론, 웹툰 도메인에 맞게 만든 그림체 추출 모델을 만들어 추천 대상을 다양하게 준비해두고 콘텐츠 기반 필터링, 협업 필터링, 멀티암드 밴딧 등 여러 알고리즘을 결합시킨 로직으로 추천 결과를 만들고 있습니다. 이 글이 콘텐츠 기반 필터링의 실제 적용 사례를 이해하는 데 도움이 되었길 바랍니다.


함께 하면 좋은 글 🔍

bell.park
bell.park 카카오 추천팀에서 추천 모델 고도화를 위한 연구와 개발을 하고 있습니다.
Top Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
CF
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codegame
codereview
coding
coding test
Collaborative Filtering
communication
competition
Compliance
component
conference
consul
container
Content-based filtering
contents
contest
contribution
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
culture
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
Embedding
employeecard
emscripten
eslint
etcd
event
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
GHC
github
globalpollution
go
Grace Hopper Celebration
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
ICPC Sinchon
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
KnowledgeGraph
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Message Streaming Platform
Messaging
microservice
Microsoft TypeScript
mm
mobil
mobile
mocking
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
One-hot encoding
open
open source
opensource
openstack
OpenWork
OSS
page
pair programming
parallel
PBA
performance
planning poker
Platform
polyfill
preview
programming-contest
project
project-structure
pycon
python
quagga
RabbitMQ
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
retrospective
Rome
RSM
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
service worker
session
sharding
shopping
Shuffle Partition
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
Women Technologists
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업
All Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
CF
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codegame
codereview
coding
coding test
Collaborative Filtering
communication
competition
Compliance
component
conference
consul
container
Content-based filtering
contents
contest
contribution
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
culture
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
Embedding
employeecard
emscripten
eslint
etcd
event
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
GHC
github
globalpollution
go
Grace Hopper Celebration
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
ICPC Sinchon
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
KnowledgeGraph
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Message Streaming Platform
Messaging
microservice
Microsoft TypeScript
mm
mobil
mobile
mocking
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
One-hot encoding
open
open source
opensource
openstack
OpenWork
OSS
page
pair programming
parallel
PBA
performance
planning poker
Platform
polyfill
preview
programming-contest
project
project-structure
pycon
python
quagga
RabbitMQ
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
retrospective
Rome
RSM
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
service worker
session
sharding
shopping
Shuffle Partition
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
Women Technologists
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업

위로