Skip to main content Link Menu Expand (external link) Document Search Copy Copied

TITLE : [토크ON세미나] 추천시스템 분석 입문하기 2강 - 컨텐츠 기반 모델 (유사도 함수, TF-IDF)

YOUTUBE LINK : https://youtu.be/g2-z0saMteA PRESENTER : SKplanet Tacademy DURATION : 00:50:15 PUBLISHED : 2021-01-25

Table of contents

  1. TITLE : [토크ON세미나] 추천시스템 분석 입문하기 2강 - 컨텐츠 기반 모델 (유사도 함수, TF-IDF)
  2. FULL SCRIPT
  3. SUMMARY

FULL SCRIPT

인테리어의 인간과 인간의 관계를 알아볼 수 있는 인테리어의 인간과 인간의 관계를 알아볼 수 있는 인테리어의 인간과 인간의 관계를 알아볼 수 있는 인테리어의 인간과 인간의 관계를 알아볼 수 있는 그래서 첫 번째 챕터로 아까는 추천 시스템의 과거에 어떤 알고리즘을 사용하는지 APRE 알고리즘과 FP-GROSS 봤고요.

그리고 기업에서는 알고리즘 어떤 걸 사용하는지 해당 내용 살펴봤습니다.

그리고 이제부터는 본격적으로 실제 현업에서 많이 사용하는 컨텐츠 기반의 추천 시스템과 그리고 협업 필터링 기반의 추천 시스템을 살펴보도록 하겠습니다.

일단 컨텐츠 기반의 추천 시스템이라고 하면 사용자가 이전에 구매한 상품 목록을 살펴보고 이 중에서 사용자가 좋아하는 상품들과 유사한 상품들을 찾아서 그 유사한 상품을 추천해주겠다는 알고리즘입니다.

근데 이제 그러면 내가 구매한 상품과 유사한 상품을 찾아야 되는데요.

이걸 어떻게 찾냐?

보통은 아이템을 벡터 형태로 표현을 해가지고 이 유사한 벡터를 찾음으로써 추천을 진행해주게 됩니다.

그래서 이런 걸 텍스트 같은 경우에는 사람마다 다 다르겠지만 자연어처리 모델 중에 요새 핫한 BUST도 있고 WORD2VEC도 있고 TF-IDF 빈도수 기반의 카운터 벡터라이저 등의 자연어처리 모델을 통해서 얘를 벡터로 바꿔줄 수 있고 이미지 같은 경우에는 딥러닝 하는 분들이라면 한 번쯤 들어봤을 법한 CNN도 있고 레즈넷, VGG 같은 딥러닝 기반의 모델로 이미지를 벡터로 만들어주는 것부터 출발하게 됩니다.

그럼 이렇게 아이템들을 벡터 형태로 바꾸게 된 다음에 이 벡터들 간의 유사도를 계산하게 되면 만약 벡터 1을 기준으로 하면 벡터 1은 벡터 2부터 n까지 중에서 자신과 유사한 순서가 정해졌을 거 아니에요?

그래서 자신과 유사한 벡터를 추출하게 되면 얘가 곧 바로 추천을 하게 되는 아이템이 되는 거죠.

그래서 일단은 벡터 간의 유사도를 어떻게 계산하는지 그러니까 유사도 계산 방법에 대해서 먼저 살펴보고 그 다음에 아이템을 벡터로 변경하는 방법론들에 대해서 살펴보도록 하겠습니다.

일단 유사도 함수 같은 경우는 종류가 정말 다양해요.

제가 여기서 소개해드릴 것은 방법론 4개인데 실제 이 4개뿐만 아니라 제가 공부하려고 찾아봤을 때만 해도 한 10몇 개 가까이 되는 것 같고 조금 상황마다 다르게 사용하는 게 필요한 게 유사도 함수인 것 같아요.

그리고 실제 유사도 함수를 다르게 적용했을 때마다 추천 결과라든지 비슷하게 나오는 유사 상품의 경우도 많이 다르고요.

그래서 일단은 가장 쉬운 유클리디안 유사도에 대해서 먼저 살펴보도록 하겠습니다.

여러분들 대부분 유클리디안 거리라는 걸 많이 들어봤을 텐데 유클리디안 유사도 같은 경우는 유클리디안 거리의 역을 취한 값입니다.

그리고 참고로 분모가 0이 되는 걸 방지하기 위해서 어떤 특정 소수값, 작은 값을 더해주고요.

그래서 유클리디안 거리는 간단하게 p라는 벡터와 q라는 벡터가 있을 때 둘 간의 벡터 간의 거리를 그냥 계산하면 되는 알고리즘입니다.

그래가지고 p-q와 p-q를 내적하게 돼서 그 값을 계산하게 되는 거죠.

그래서 한번 만약에 아래와 같이 문서 4개가 있고 과일이 길고 노란 먹고 바나나 사과 10분 저는 좋아요라는 하나하나의 단어 토큰을 가진 벡터 4개가 있다고 한번 생각해보도록 하겠습니다.

여기는 1번 문서와 2번 문서에 대해서 유사도를 계산하는 부분인데요.

일단 계산은 간단하게 둘 간의 거리를 계산하면 되는데 0과 0 같은 경우는 계산했을 때 거리 차이가 0이잖아요.

그래서 이 부분 0의 제곱 0의 제곱 0의 제곱 0의 제곱 마찬가지로 여기 세 부분도 0의 제곱 실제 두 부분이 바나나랑 사과 이 부분에 대해서만 차이가 나게 되는데 그래서 둘 문서 1과 문서 2 간의 거리 계산을 했을 때 바나나 사과 부분에서 1의 제곱 더하기 1의 제곱에 루트를 씌운 값에다가 분모가 0이 되는 걸 방지해주기 위한 2의 마이너스 5승 값만 이렇게 더해주고 역수를 취하게 되면 이 유사도 값을 계산할 수가 있습니다.

그런 유쿨리잔 유사도 같은 경우 장점이 계산하기가 쉽고 그리고 각각의 벡터의 요소 요소 컬럼 하나 하나가 어떤 크기에 조금 민감하거나 중요했을 때 그런 경우에 조금 효과를 볼 수가 있죠.

하지만 이게 분포가 다르거나 스케일 그런 게 다를 때 보통 문제가 생길 수가 있고 상관성을 놓칠 수가 있어서 그런 쪽에 조금 한계가 있습니다.

그리고 그 다음 볼 거는 사실 유사도 함수하면 대부분이 많이 사용하는 게 코사인 유사도라고 할 수 있습니다.

그래서 코사인 유사도 같은 경우는 둘을 a와 b의 그런 크기에다가 a, b의 내적 값을 통해서 계산을 할 수가 있는데 실제 코사인 세타를 계산한다고 생각하면 됩니다.

그래가지고 어떤 문서 1과 문서 2에 대한 벡터가 존재했을 때 둘이 얼마나 비슷한 방향을 가지고 있는지 그 방향을 의미하는, 둘이 얼마나 비슷한 방향을 의미하고 있는지 그 방향에 대한 각도인 세타를 중심으로 얼마만큼의 코사인 세타를 가지냐가 시뮬러티가 되는 거죠.

그래서 세타가 0으로 둘이 동일한 방향을 가지고 있으면 시뮬러티가 1이 되는 거고 만일 세타가 90도 방향을 가지면 시뮬러티가 0 그리고 세타가 마이너스 180도 아니면 180도처럼 정반대 방향을 가지고 있으면 시뮬러티가 마이너스 1로 가장 최소의 값을 가지게 됩니다.

그래서 문서 1과 문서 2에 대해서 한번 계산 진행해보자면 일단 위에 알고리즈처럼 a의 제곱에다가 제곱의 합에 대하다가 루트를 씌우고 마찬가지로 b의 제곱에 대한 루트를 합에 씌우고 얘를 분모로 두고 문자 같은 경우는 2를 곱한 거에 대한 서메이션을 취하게 되는데 a 같은 경우 1값을 가지고 있는 부분이 3개잖아요?

그래서 총 1의 제곱이 3개를 더한 다음에 루트를 씌우고 두 번째 문서 2 같은 경우도 똑같이 1을 3구 공간에 대해서만 가지고 있으니까 1을 제곱을 3번 더하면 됩니다.

그리고 분자 같은 경우는 둘 다 1을 가지고 있는 게 2개밖에 없으니까 1 플러스 1이 되고요.

그래서 루트 3 곱하기 루트 3분의 2를 하게 되면 3분의 2가 되어서 0.6667이라는 유사도를 가지는 걸 볼 수가 있습니다.

그래서 이런 유사도 함수에서 코사인을 사용했을 때는 벡터의 크기가 중요하지 않은 경우에 즉 거리를 측정하기 위한 매트릭으로 사용하게 되는데 예를 들어서 문서내에서 단어의 빈도수 같이 문서들의 길이가 고르지 않더라도 문서내에 얼마나 나왔는지 그러니까 크기 그러니까 얼마만큼의 단어 빈도수라는 크기를 보기 싫지만 그냥 얼마만큼 얘가 있냐 없냐는 비율 같은 걸 확인하고 싶을 때 사용하게 되는 거죠.

근데 아까 유쿨리디안과는 반대로 유쿨리디안 벡터 간의 하나하나의 요소가 크기가 중요한 경우에 대해서는 유쿨리디안이 좋지만 벡터의 크기 같은 게 중요한 경우에 대해서는 잘 작동하지 않는 단점이 있습니다.

세 번째로 보기 전에 유쿨리디안 유사도와 코사인 유사도 간에 어떤 차이가 있는지에 대해서 한번 살펴보도록 하겠습니다.

아래의 예시 같은 경우는 이런 0이라는 벡터와 mid라는 벡터, adult라는 파란색깔, 노란색깔, 빨간색깔이라는 세 가지 벡터가 x축과 y축에서 이렇게 존재한다고 한번 상상을 해보겠습니다.

그리고 이 회색의 점이 들어왔을 때 어떤 벡터와 유사한지에 대해서 유쿨리디안 유사도와 코사인 유사도에 대한 결과를 한번 살펴보도록 하겠습니다.

아까 말했듯이 유쿨리디안 유사도 같은 경우는 가장 가까운 그런 벡터를 찾기 때문에 이 회색 점이 들어오면 자연스럽게 이 세 개에 대한 거리를 측정하게 되고 거리가 가장 낮은, 가장 작은 이 0이라는 벡터와 회색 물음표가 비슷하겠다고 판단할 수 있는 것은 당연한데요.

한번 그러면 코사인 유사도로 반경됐을 때 이게 어떻게 되는지 살펴보면 코사인 유사도 같은 경우는 벡터 간의 방향을 살펴본다 했었잖아요.

그래서 회색 같은 점 같은 경우는 방향이 이런 식으로 가지게 되는데 파란색 같은 경우는 이런 식으로 코사인이 이렇게 형성이 되니까 둘 같은 경우 세타가 생각보다 90도보다는 작기만 어느 정도 값을 가지게 됩니다.

근데 만약 노란색하고 빨간색 간의 세타를 비교해보면 회색 같은 경우는 이렇게 점 노란색 같은 경우는 이렇게 점을 가지게 되고 둘 간의 간격을 살펴보면 이 정도, 되게 짧은 것을 볼 수 있습니다.

마찬가지로 빨간색 점에 대해서도 회색 간 이루고 있는 간격의 세타가 파란색 보다는 훨씬 적은 것을 알 수가 있고요.

그래서 분명히 유클리디한 유사도로 계산했을 때는 파란색 점이 회색 점하고 가장 비슷하다고 결과가 나왔지만 그러면 코사인 유사도로 변경해서 문서 간의 유사도를 계산했을 때는 회색 점이 노랑하고 빨간과 가장 유사하다는 것으로 결론 지을 수가 있습니다.

그래서 유사도 함수 간의 차이점을 잘 이해하고 사용하는 게 되게 중요하고요.

그리고 다음으로 살펴본 유사도는 피어슨 유사도인데 피어슨 유사도 같은 경우는 보통 상관관계를 분석할 때 많이 사용하는 알고리즘으로 다음과 같이 계산할 수가 있습니다.

그래서 그런 자기 값에 대해서 그리고 평균을 뺀 값 보통 분산이라고 많이 하죠.

그럼 거기에 대해서 실제 계산을 문서 1과 2에 대해서 진행하게 되면 얘 같은 경우는 평균이 총 값 하나, 둘, 셋, 넷, 다섯, 여섯, 일곱, 여덟 아홉 개 중에 세 가지를 가지고 있으니까 평균은 3분의 1이잖아요.

그래서 3분의 1에 대해서 0-1 3분의 1이 되는 구간이 총 여섯 개가 되고 1-1 3분의 1을 통해서 2 3분의 2가 나온 게 총 세 개가 되니까 6 곱하기 1 3분의 1의 제곱 더하기 3 곱하기 2 3분의 2의 제곱에 루트를 씌워준 값과 마찬가지로 동일하게 두 번째 문서 2에 대해서도 분산을 계산한 값 편차가 되니까 편차죠.

편차를 계산한 값에 대해서 곱을 한 다음에 분자도 동일하게 계산해서 나온 값을 통해서 유사도를 계산할 수가 있습니다.

그리고 그 다음으로 많이 사용하는 유사도 중에 자카드라는 유사도가 있는데 자카드 같은 경우는 집합해서 얼마만큼의 결합된 부분이 있는지로 계산을 합니다.

그래서 문서 1과 문서 2에 대해서 분모 같은 경우는 합집합의 길이가 되고요 분자 같은 경우는 교집합의 그런 크기, 길이로 생각할 수가 있습니다.

그래서 교집합 같은 경우는 1이 얼마만큼 겹치는지에 대한 것으로 계산할 수가 있는데 1이 지금 두 개가 겹치잖아요.

그래서 교집합의 크기는 2가 되고 집합은 1이 얼마만큼 가지고 있는지.

총 문서 1은 3개, 문서 2도 3개여서 3 더하기 3에다가 둘이 겹치는 부분이 두 개니까 3 더하기 3에 2를 뺀 4분의 1을 통해서 유사도가 0.5가 나오는 것을 알 수가 있습니다.

그리고 지금 얘기한 건 코사인, 자카드, 유클리디안, 그리고 아까 피어슨까지 이렇게 네 개를 살펴봤는데 사이킬런하고 스시파이의 디스턴스 항목 보면 정말 많고요.

그리고 이런 걸 조금 적절하게 쓰는 게 중요한 것 같습니다.

다이버전스 같은 경우는 분포의 유사도 계산할 때도 솔직히 많이 사용하고 다이스 유사도 같은 경우도 많이 사용하고 실제로 소렌센 같은 경우도 현업에서 조금씩 사용해서 비교하는 것 같더라고요.

그래서 실제로는 저는 회사에서 일할 때는 여러 가지 많이 비교해서 사용했고요.

그리고 다른 분들 그런 거 발표 같은 거 들었을 때도 그런 코사인만 사용하는 게 아니라 조금 상황에 적절하게 맞게 조금 여러 가지 평가 지표 해가지고 그런 여러 가지 추천 시스템 유사도 해가지고 그래서 조합을 한다 하더라고요.

네 맞습니다.

그래서 여러 가지 추천 시스템에 대해서 가중치를 두고 그리고 고객 집단에 따라서 다른 추천 시스템 모델을 적용할 수도 있는 거고 그거는 이제 도메인에 따라서 다르게 하는 거죠.

그래서 예전에 나갔던 그런 카카오 브런치 추천 시스템 대회 같은 경우 나가서 제가 4등 했던 그런 대회가 있었는데 저는 그거 같은 경우는 추천 시스템 모델 자체를 10가지 정도 만든 다음에 조금 정확도 기준으로 추천한다든지 그런 정확도라든지 평가 지표가 좋은 순서대로 이렇게 10가지 적용한다든지 아니면 콜드 스타트나 아예 구매를 적게 한 사람한테는 다른 모델을 쓰고 그리고 구매를 많이 한 사람한테는 또 다른 모델을 쓰고 이렇게 좀 상황에 맞게 여러 가지 적용을 했어요.

그래서 모델마다 조금씩 가중치가 다르도록 서로 다른 유사도는 어떻게 조합하나요?

이딴 말 다른 유사도를 정하는 건가요?

라고 했는데 일단 여기서 문서 간에 유클리에 대한 유사도 계산했을 때 문서 1부터 문서 4에 대한 유사도 매트릭스가 나올 거잖아요.

여기서 보면 4x4로 문서 1과 문서 1, 문서 1과 문서 2, 문서 1과 문서 3, 문서 1과 문서 4에 대한 유사도 마찬가지로 2에 대해서도 각 1, 2, 3, 4에 대한 유사도가 나올 거고 이렇게 한 결과를 해서 추천 시스템 각각 만든 다음에 조합을 해도 되는 거고 이 유사도 값을 적규럽게 가중치 줘서 더한 다음에 그걸로 유사도를 만들어도 되는 거고 그럼 이제 지금처럼 더했을 때 0부터 1까지 가중치 줘서 만들면 똑같이 유사도 매트릭스가 그대로 유지되니까 그걸 통해서 추천해줄 수도 있는 거고 각각의 유사도 다르게 해서 모델, 코사인 모델, 유클리에 대한 모델 해서 두 모델의 추천 결과를 그냥 순서대로 추천해줄 수도 있는 거죠.

유사도 매트릭스를 더해도 되고요.

각각의 유사도 매트릭스마다 모델을 만들어서 추천 결과를 결합해도 되는 것 같습니다.

정답은 없는 것 같아요.

여기서 이제 레프레젠트 아이템을 통해서 벡터 간의 어떤 아이템을 벡터로 바꿨을 때 벡터 간의 유사도를 통해서 벡터 1부터 n까지의 자신과 유사한 벡터를 추출하는 부분에 대해서 를 지금 유사도 함수 여러 가지 적용해서 만들어야 된다는 이야기를 했었잖아요.

그럼 이제는 어떤 식으로 아이템을 벡터로 바꾸는지 그 레프레젠트 아이템을 벡터라이저 하는 부분에 대해서 살펴보도록 하겠습니다.

그리고 원래 이 아이템이 글처럼 자연화로 된 경우도 있고 텍스트 형태로 된 경우도 있고 이미지처럼 이미지로 된 경우도 있고 태블러 데이터도 있고 사실 도메인마다 너무 달라가지고 오늘 예시에서는 뒤에 실습 예제에서 좀 맞게 텍스트 형태의 데이터를 가지고 있다는 상황을 가정한 채 발표를 진행하도록 하겠습니다.

그래서 첫 번째로 제어 처리 알고리즘을 살펴볼 것은 TF-IDF라는 방법론입니다.

실제 조금 꽤 사용하는 방법이고요.

되게 가장 기본적인 알고리즘인 것 같아서 준비해 왔습니다.

그래서 TF-IDF에 대해서 간단하게 소개해 드리자면 얘 같은 경우는 세 가지 지표인 TF라는 단어 빈도와 그리고 영문서 빈도 TF 그리고 그거에 대해서 가정치를 주는 IDF라는 세 가지 지표를 통해서 계산하는 방법인데 정의를 이야기해 드리자면 특정 문서 내에서 특정 단어가 얼마나 자주 등장하는지를 의미하는 단어 빈도수 TF와 전체 문서에서 특정 단어가 얼마나 등장하는지 영문서 빈도 TF를 통해서 다른 문서에서는 등장하지 않지만 특정 문서에서만 자주 등장하는 단어를 찾아내가지고 이 단어를 통해서 유사도를 계산하는 방법입니다.

그래가지고 얘 같은 경우는 문서의 핵심어 추출이라든지 문서들의 유사도 그리고 검색 결과의 중요도를 정하는 작업 등에 많이 활용되는데요.

조금 더 간단하게 설명드리자면 TF 같은 경우는 특정 문서 D에서 특정 단어 T에 등장했어.

그러니까 문서마다의 단어의 등장 횟수를 모두 기록해야 되는 거죠.

근데 DF 같은 경우는 특정 단어가 등장한 문서가 몇 개인지를 계산한 거예요.

그래서 특정 문서가 기준이 아니라 전체 문서가 10개 있으면 이 만일 I라는 단어가 등장한 문서의 개수를 세우고 싶을 때 문서 10개에서 모두 나왔으면 10개, 문서 9개에서 나왔으면 9개 이런 식으로 DF 값이 계산을 해주게 되고요.

DF가 반비례하는 어떤 의미의 함수를 만드는 게 IDF인데 이 반비례 함수는 소프트웨어마다 조금 다른 게 있어서 보통 이론책에서는 log의 1플러스 DF의 T분의 N값을 많이 사용합니다.

그래서 이제 TF와 IDF를 곱해서 TF, IDF라는 표현을 사용하고요.

이렇게만 보면 실제 어떻게 되는지 잘 모르겠으니까 조금 더 예제와 방법론에 대해서 자세히 설명드리도록 하겠습니다.

TF, IDF를 사용하는 이유에 대해서 먼저 설명을 드릴게요.

예제 블로그에 되게 설명이 잘 나와 있어서 조금 인용이 왔는데 예를 들어서 I like this movie, I love this movie, it was the best movie I have ever seen 이런 문장들이 있다고 생각해볼게요.

그리고 이게 문서 1, 문서 2라고 생각했을 때 저희는 TF, IDF를 통해서 이런 아이템, 문서를 벡터로 표현해주는 과정을 거치는 거잖아요.

그리고 TF가 의미하는 것처럼 단어내에서 많이 등장하는 빈도수를 기반으로 그런 중요한 단어를 찾고 싶은 거예요.

그러니까 like, love, best, movie 이런 식으로 많이 나오는 단어일수록 중요하겠거니라고 생각해서 하는 건데 이렇게 중요한 단어를 빈도수만을 기반으로 하는 거를 카운터 벡터라이저라고 표현을 해요.

그래서 이런 하나의 단어를 하나의 토큰으로 봐서 이 토큰이 얼마나 나왔는지, 그러니까 카운트, 수를 계산한다는 거죠.

하지만 이런 카운터 벡터라이저의 가장 큰 문제가 조사나 관사처럼 의미 없는 데 많이 나오는 단어들이 있다는 거예요.

예를 들어서 여기만 봐도 I, I, I, I, I, this, this, this, this, movie, movie, movie, movie.

이렇게 실제 여기서 I like this movie에서는 like라는 단어가 제일 핵심적인 표현인데 like, love, best처럼 많이 나와도 다른 단어가 의미 없이 많이 나오는 게 있어서 뜻이 묻힌다.

그래서 이러한 단어들에는 페널티를 적절하게 줘서 중요한 단어만은 잡아내자 하는 게 지금 IDF를 통해서 특정 단어가 뭐 여기서는 T가 I, movie 이런 게 되겠죠.

그게 등장한 게 문서가 많으면 많을수록 얘는 많이 등장했지만 중요하지 않은 단어다.

그래서 그만큼 페널티를 주자 해가지고 둘을 결합한 게 TF-IDF입니다.

그래서 실제 다음과 같은 문서 네 가지를 가지고 있는 예시를 통해서 어떻게 유사도를 계산하고 추천을 하는지 한번 살펴보도록 하겠습니다.

그래서 문서는 총 네 개가 있고요.

그리고 문서 내용은 먹고 싶은 사과, 먹고 싶은 바나나, 길고 노란 바나나, 바나나, 저는 과일이 좋아요라는 예시가 있다고 한번 생각해보도록 하겠습니다.

그래서 먼저 TF 값을 계산할 건데 TF 값이 아까 뭐라고 했네요?

제가 아까 말했듯이 TF는 문서 D에서 특정 단어 T가 얼마만큼 등장하는 횟수거든요.

그래서 문서마다 단어를 세는 거예요.

먹고는 한 번 나왔고 사과는 한 번 나왔고 식프는 한 번 나왔으니까 1, 1, 1.

반대로 문서 3에서는 바나나는 두 번 나오고 길고와 노란은 한 번씩 나왔으니까 바나나는 2, 길고와 노란은 1, 1.

이렇게 TF를 계산한 다음에 DF 값도 계산할 수가 있겠죠.

DF는 아까 말했듯이 특정 단어 T가 얼마만큼 문서에 등장했는지를 의미하는데 과일이라는 표현은 총 문서 4개에서 과일이 지금 한 번밖에 안 나왔잖아요?

그래서 값이 1이 되는 거고 바나나 같은 경우는 총 문서 아 이거 제가 실수를 했네요.

문서 4개 중에서 문서 1과 문서 2에서만 나와가지고 바나나 값은 문서 2가 되는 게 맞습니다.

그리고 식픈 같은 경우도 문서 0과 1에서 2번밖에 안 나왔으니까 값이 2가 되는 게 맞고요.

이렇게 DF 값을 계산하고 이 DF에 대해서 IDF 영문서 빈도를 이런 식의 이미 정해진 함수에 따라서 생성할 수 있습니다.

이 N 같은 경우는 문서의 개수를 의미하고요.

1 플러스 DF는 아까 설정한 과일이 길고 노란 각각에 맞춰서 이 값을 적용해서 계산하게 되면 됩니다.

그래서 이렇게 IDF 값을 계산한 다음에 TF와 이 문서 TF와 그리고 이 IDF 값을 곱해서 이 매트릭스를 만들어주면 이게 TF, IDF의 최종 그런 매트릭스가 되고요.

그리고 이제 문서 간에 벡터가 하나씩 생긴 거잖아요.

그래서 이 벡터 간의 유사도를 계산하게 되면 문서 어떤 게 유사한지를 알 수가 있는 거죠.

그래서 여기에서는 간단하게 코사인 유사도를 통해서 유사도를 계산했을 때 문서 1과 문서 2 간의 유사도만 0.5061로 어느 정도 관련이 있다고 나왔습니다.

실제 결과 봤을 때 먹고 싶은 이 부분이 겹치니까 둘 간의 유사도가 높게 나온 것을 확인할 수가 있겠죠.

그리고 아마 IDF 값이 바나나가 여러 번 나와가지고 어느 정도 페널티를 받아서 생각보다 0.5보다 더 클 것 같은데 낮게 나온 것 같습니다.

그래서 조금 한번 다시 헷갈린 분들을 위해서 정리를 드리자면 지금 하려고 하는 작업은 아이템, 그러니까 문서 0부터 문서 3에 대해서 얘를 벡터로 표현해 주려고 하고 싶고요.

여기서 사용한 알고리즘으로 TF, IDF를 적용한 거예요.

그래서 TF, IDF가 뭐냐면 특정 D에서의 특정 단어를 등장한 거를 많이 등장한 순서대로 중요도를 부여하고 싶은데 관사나 조사처럼 좀 쓸데없이 의미가 없는 데 많이 나오는 게 있으니까 걔네한테는 페널티를 주고 그 페널티를 주는 방법을 로그에 로그를 씌운 다음에 DF 값을 분무해 듬으로써 페널티를 주겠다.

그리고 이 두 값을 곱함으로써 벡터라이저를 진행하겠다라고 하는 겁니다.

그리고 이렇게 벡터를 만들었으니까 아까 배웠던 유사도 알고리즘을 통해서 문서 간의 유사도를 계산할 수 있고 문서 0 먹고 싶은 사과라는 문서를 본 사용자에 대해서 가장 유사한 문서인 먹고 싶은 바나나를 본 문서를 추천해 줄 수가 있게 된 거죠.

그 유저한테.

실제 코드는 이렇고요.

TF, IDF 장점을 얘기하면 되게 해석이 직관적이에요.

많이 나왔는데 쓸데없이 의미가 없는 거는 제외하고 조금 특정 문서에서만 많이 나온 거를 가중치를 둬서 벡터라이저를 하겠다.

되게 해석이 직관적이고 사용하기 쉬운 것 같아요.

내가 쓰기도 편하고 코드 같은 경우는 이렇게 세 줄로 처리되거든요.

유사도 함수까지 계산했을 때는 네 줄이고.

단점이 되게 메모리 문제가 커요.

아까 그런 룰 기반의 에이프리오리나 FP-Gross에서도 언급했지만 추천 시스템 가장 큰 문제점이 메모리를 어떻게 효과적으로 다룰까인데 사실 지금 같은 경우는 문서 4개고 말뭉치 해봤자 9개여서 되게 별로 없었는데 사실 실제 문서 같은 경우 한 것만 해도 단어가 몇십 개가 아니죠.

몇천 개, 몇 만 개가 나올 텐데 그렇게만 해도 지금 문서 100 매트릭스 사이즈가 문서 하나에 대해서 그런 컬럼이 5만 개고 그러면 유사도 계산할 때 이제 곱사잉 계산하다가 메모리 펑 터지고 컴퓨터.

그런 문제점이 있기 때문에 되게 높은 차원을 가지고 스팔스한 형태겠죠.

문서 합쳤을 때 이 책에는 나왔는데 다른 책에는 안 나오는 단어들이 굉장히 많을 테니까.

그래서 그런 문제점을 가지고 있고 이런 거를 조금 해결하고자 했던 아이디어가 다음에 나오는 Word2vec입니다.

그리고 Word2vec 이야기하기 전에 잠시 TF-IDF 코드 한번 살펴보고 진행하도록 할게요.

실제 코드 아까 봤던 사이트에서 TF-IDF를 이용한 추천시템 샵1 부분 들어오시면 됩니다.

저 같은 경우는 이게 Edit인데 아마 다른 분들 같은 경우는 Edit 말고 Copy?

그런 거 있을 거예요.

그거 클릭하셔서 들어오시면 됩니다.

그래서 먼저 아까 만들었던 예시의 문서 4개를 먼저 만들자면 일단 다큐멘터리를 저장할 닥스라는 리스트에 대해서 문서 4개를 만들게요.

문서 0은 먹고 싶은 사과 그리고 문서 간의 구분을 위해서 컨마를 쳐주고요.

두 번째는 먹고 싶은 바나나 길고 노란 바나나 바나나 그리고 저는 과일이 좋아요.

4개를 한번 만들고 출력을 해보겠습니다.

그러면 리스트로 이렇게 4가지 문서가 만들어진 걸 볼 수가 있죠.

그리고 아까 잠깐 언급했던 카운터 벡터라이저에 대해서 먼저 이야기를 드릴게요.

카운터 벡터라이저 같은 경우는 TF-IDF에서 TF까지만의 과정을 거친 벡터라이저라고 보시면 돼요.

그래서 Cyclern에서 FeatureExtraction.

Text라는 클래스를 통해서 호출할 수가 있는데 그럼 Cyclern에 FeatureExtraction.

Text에서 ImportCounterVectorizer를 한 다음에 CounterVectorizer라는 객체를 하나 Vect라는 거에 만들어 두도록 하겠습니다.

그럼 이렇게 어떤 객체가 생성된 걸 볼 수가 있죠.

그리고 이제 저희가 만든 데이터인 독스를 벡터라이저 함수에 적용을 시켜가지고 CounterVectorizer를 이렇게 수행을 시키면 4,9의 크기를 가지는 스팔스 매트릭스가 만들어진 걸 볼 수가 있어요.

근데 지금은 어떤 형태를 가진지 볼 수가 없잖아요.

그래서 얘 같은 경우 JumpToArray라는 명령어로 통해서 위에서 만든 스팔스 매트릭스를 nump 형태로 바꿔주는 명령어거든요.

그래서 JumpToArray를 이렇게 치면 위에서 만들었던 스팔스 매트릭스, 동일하게 스팔스 매트릭스이긴 하지만 Array 형태로 지금 바뀐 거를 볼 수가 있습니다.

근데 지금 문제는 각 인덱스와 컬럼이 무엇을 의미하는지 몰라요.

사실 이 같은 경우 아까 봤던 바나나이긴 할 테지만 얘가 어떤 걸 의미하는지 지금 인덱스에서랑 컬럼에서는 모르니까 그걸 한번 찾아서 데이터 프레임 형태로 바꿔볼게요.

그래서 아까 만들었던 Vect 같은 경우에 Vocabulary라는 이렇게 함수가 저장이 되어 있는데 얘네를 출력해보면 Dictionary 형태로 각각의 단어에 대해서 어떤 인덱스를 가지고 있다는 걸 어떤 컬럼 위치를 가지고 있다는 걸 알 수가 있어요.

과일이 같은 경우는 0번째, 바나나 같은 경우는 4번째, 여기인 걸 정확히 볼 수가 있죠.

그래서 얘를 컬럼명으로 가지도록 하는 데이터 프레임을 만들어주도록 하겠습니다.

근데 참고로 이게 순서가 뒤죽박죽이잖아요.

그래서 Salted라는 함수를 통해서 단어를 정렬을 해볼게요.

그래서 Salted를 치면 과일이 뒤에 Value 값을 기준으로 순서가 정렬이 되는데 보면 과일이 길고 노란 먹고 순서대로 잘 정렬된 걸 볼 수 있죠.

그래서 데이터 프레임은 아까 봤던 카운터 벡터의 Array 형태를 데이터 프레임으로 가지고 컬럼 같은 경우는 벡터라이저의 단어들이 정렬된 걸 컬럼명으로 가지는 카운터 벡터의 데이터 프레임을 만들어주겠다.

그리고 인덱스는 각각 문서 1부터 문서 4까지의 값을 가진다.

라고 하면 여기까지 카운터 벡터라이저에 대한 데이터 프레임 형태를 벡터라이저 형태를 만들어지게 된 겁니다.

그 다음에 Cosine 유사도를 통해서 유사도 계산하는 건 진짜 간단한데 Cycle1의 데이터 분석 관련해서는 패키지들이 정말 잘 되는 것 같아요.

그래서 Cycle1의 매트릭스에서 Pairwise라는 클래스 쪽을 보면 유사도 관련해서 많이 만들어져 있거든요.

거기서 특히 여기에서는 Cosine Similarity를 사용해서 유사도를 계산할 때 데이터 형태 만든 걸 이렇게 간단하게 둘을 넣어서 유사도 계산하게 되면 문서 1과 문서 2가 유사하고 문서 2와 문서 3도 유사하다라는 결과를 얻을 수가 있게 되는 거죠.

그리고 이제 추천 같은 경우는 문서 1과 문서 2가 유사하니까 문서 1을 본 사람들한테는 문서 1을, 문서 2를 본 사람한테는 문서 1과 문서 3을 추천할 수 있다고 결론질 수 있는 거고.

근데 아까 말했듯이 Counter Vectorizer 같은 경우는 단점이 하나 존재한다 했었잖아요.

바로 이제 의미 없는 단어들이 너무 많이 나오니까 걔네를 제거해 줄 필요가 있다는 거고 그거를 제거해 주기 위해서 이제는 이 부분을 아까는 Counter Vectorizer를 호출해가지고 객체로 생성했었는데 이번에는 Counter Vectorizer가 아니라 TF-IDF Vectorizer라는 거를 호출해서 위에 코드를 그대로 동일하게 실행하시면 돼요.

그래서 아까는 여기가 Counter Vectorizer였는데 TF-IDF Vectorizer 통해서 객체 만들고 P통해서 변환시켜준 거 이렇게 호출해 주면 되고요.

그리고 얘를 트랜스폼 시킨 다음에 Array 형태로 변환해 준 값, 그리고 Column도 아까 정렬시켜준 거 그대로 사용하시고 Index 값 보여주면 아까와 같이 각각의 문서에 대해서 TF-IDF를 통해서 Vectorizer된 결과를 얻을 수가 있게 되는 거죠.

그 다음에 똑같이 유사도 계산한 건 동일합니다.

그래서 유사도 계산하게 되면 이런 식으로 결과 얻을 수 있는데 이 결과 값이 지금 의아한 점이 아까 본 이 값하고 조금 다를 거예요.

그리고 여기서는 아마 파라미터까지 조금 더 수정한 게 있어서 결과 값이 다른데 이게 결과마다 조금 다르게 나올 수 있는 이유가 IDF 값을 소프트웨어마다 사용하는 규칙이 조금 달라요.

여기서는 저 같은 경우는 아까 이론 설명할 때 log의 1 더하기 DF의 T분의 N이라고 정리를 했었는데 소프트웨어 같은 경우는 log의 DF분의 N의 플러스 1이 아예 log 밖에 씌워진 형태죠.

그래서 이런 식으로 조금 소프트웨어가 다르기 때문에 이 부분에 대해서는 실제 소프트웨어 코드 어떻게 적용되는지 보시면서 확인하시면 되고 큰 줄기 맥락하에서 TF-IDF는 카운터 벡터라이저의 문제점인 어떤 단어가 특정 문서에서만 나오는 게 아니라 전체 문서에 대해서 많이 뽑히면 그런 걸 잘 제거해주겠다라는 걸 통해서 만든다고 생각하시면 안 됩니다.

그리고 문제점은 아까 봤던 말뭉치가 매우 클 때 메모리상의 문제점이 가지니까 이걸 해결하기 위해서 모두투백이라는 방법론도 있다라는 걸 지금 명심해 두시면 됩니다.

그리고 여기까지 예제 진행하는 데는 다들 문제 없으셨죠?

현재는 편의상으로 명사만, 완전 명사만은 아니죠.

지금 편의상으로 나눴고요.

이거는 아마 벡터라이저 호출되는 게 띄어쓰기 기준으로 진행이 돼요.

그래서 여기서는 먹고 싶은 바나나가 지금 띄어쓰기 형태로 기준이 된 거고요.

실제 글이나 그런 거 전체 텍스트를 다룰 때는 형태소 처리를 해주는 게 훨씬 좋긴 하죠.

여기서 형태소 처리를 하고 자연호처리를 모르시는 분들도 있으니까 설명드리자면 원래 자연호처리 같은 경우 데이터가 되게 불필요한 편들이 많아요.

어떤 거는 특수문자가 의미가 있는 경우도 있긴 하지만 점 이런 것도 사실 좋아요 점 있으면 이렇게 같이 찍히거든요.

그래서 이런 것들부터 잘 처리해주는 것부터 시작해서 숫자 이런 거 불용어라고 보통 표현하는데 그런 거 제거해주고 명사라든지 관사 이렇게 형태 나눠주는 거 형태소 분석, 자연호처리 전 처리부터 이어지는 형태소 분석 단계인데 실제로는 이런 거 전처리 처리를 많이 해주는 게 좋고 저 같은 경우는 그것까지 다루면 너무 양이 방대해지니까 간단하게 표현해주기 위해서 편의상이롭게 진행했습니다.

그리고 여기서 기준은 띄어쓰기 기준인 것만 알아두시면 돼요.

여기까지 지금 실습 진행하는데 문제 있으신 분 있으신가요?

없으시면 다음 예제 한번 같이 진행할게요.

아까 같은 경우 예시가 조금 되게 단순했잖아요.

그래서 이번 예시 같은 경우 실제 위키독스에 있는 예제 참고해서 만든 예시인데 실제 무비 데이터에 메타 정보에 TF-IDF 적용해서 추천시스템 만드는 부분에 대해서 간단하게 소개를 드리고 싶어서 예제를 준비해 왔습니다.

그래서 얘는 IMDb인가?

영화 관련 평점 주는 사이트가 있는데 거기에 있는 무비에 대해서 어떤 영화가 어떤 정보를 가지고 있는지에 대한 메타 데이터고요.

거기에 메타 정보 중에 하나가 오버뷰라고 영화의 각각의 그런 어떤 의미를 가지고 있는지 이 영화가 무슨 영화인지를 간단하게 소개해주는 오버뷰라는 컬럼이 있어가지고 얘를 통해서 한번 TF-IDF를 적용해보고 추천시스템을 만들었을 때 어떤 결과를 가지는지를 한번 소개해드리도록 하겠습니다.

그래서 데이터 컬럼수를 보면 여러가지 있겠지만 장르도 있고 타이틀도 있고 보트 카운트라고 얼마만큼의 사람들이 추천을 했는지 아 추천이래 평점을 남겼는지

그리고 평점의 평균은 얼마나 되는지 그리고 발매일 발매일 같은 경우도 실제 최신 영화인지 최신 영화인지 아닌지 구분해주기 때문에 굉장히 유의미한 피처들인데 이런 거 다 제외하고 한번 여기서 오버뷰라는 항목만 가지고 있을 때 어떤 식으로 추천이 되는지 한번 살펴볼게요.

그래서 일단 결측치가 있는 부분이 있어서 해당 결측치가 있는 부분은 전부 다 제거해줄 거고요.

여기서는 어떻게 결측치를 제거해주냐면 데이터 있는 난 룰이라고 점 난 룰을 하게 되면 얘가 결측치가 없으면 true가 나오고 결측치가 있으면 false로 나오는데 결측치가 없는 true인 부분에 대해서만 데이터를 뽑은 다음에 list의 인덱스를 다시 0부터 데이터 길이까지 조절해주는 명령으로 결측치 있는 항목은 모두 제거하고 진행을 해볼게요.

그리고 집에 있는 컴퓨터에서는 실습 예제 만들 때 다 돌아갔는데 케글 노트북이 램이 16기가 제한이 있어가지고 전체의 영화데이터 사용하면 램이 터지더라고요.

그래가지고 간단하게 2만 개 데이터에 대해서만 사용했고 만일 다른 분들 지금 로컬 환경에서 작업하시는 분들 같은 경우는 이거 전체 데이터 이 부분 코드 그냥 빼고 진행하시면 됩니다.

근데 케글 지금 저 따라오시는 분들은 여기 2만으로 이렇게 변경해주고 실행 진행할게요.

TF-IDF에서 불용어 단어 토큰 제거하는 부분 아까 어떤 분이셨죠?

현웅님이 언급해주신 부분 여기서 간단하게 stopword 해가지고 유의미하지 않은 단어 토큰 제거해주는 거를 vectorize 할 때 stopwords의 English 부분으로 실행해줄 수 있고요.

아까 실행했던 거에서 이제 적용되는 부분만 데이터의 오버뷰를 통해서 적용해볼게요.

그래서 이제 2만 1개에 대한 문서에 대해서 0 포함하니까 2만 1개의 문서에 대해서 단어 토큰이 47,665개 가지는 거를 볼 수가 있죠.

그리고 Cosine Similarity 이렇게 계산하면 2만 1개와 2만 1개의 Matrix에 대해서 여기서는 문서가 아니라 영화관의 유사도 Matrix 계산할 수 있고요.

그래서 Shape 보면 2만 1개의 영화관의 유사도 계산된 거를 볼 수 있습니다.

그리고 이제 얘가 지금 사실 값이 0부터 2만 1이라는 id 값이 아니라 그냥 인덱스 값을 기준으로 지금 정렬이 된 거거든요.

그래서 해당 부분을 조금 수정해줄 필요가 있어요.

무슨 얘기냐면 Cosine Matrix의 인덱스가 지금 0부터 1, 2 이런 식으로 지금 진행이 되는 상황인데 사실 0이라는 인덱스가 0번째 영화를 의미하는 게 아니라 0번째 id의 영화가 아니라 그냥 데이터에 나온 순서대로를 의미하는 거거든요.

데이터에 movie id가 또 따로 있어가지고 그거를 좀 이 id가 따로 있는데 얘랑 지금 맵핑되는 게 아니라 인덱스가 그래서 얘를 좀 맵핑해줄 필요가 있어요.

그래서 그 부분을 지금 딕셔너리를 만들어서 맵핑을 해주는 과정을 거칠게요.

그래서 movie id라는 지금 딕셔너리를 만들고 포문을 통해서 이렇게 Enumerate 함수를 통해서 만들 건데 참고로 이 부분은 그냥 인덱스를 아까 id를 한다 했었는데 그냥 편의상 타이틀로 부분을 만들게요.

이렇게 하게 되면 각각의 타이틀과 그런 인덱스 순서에 따라서 종렬이 되는데 무슨 말이냐면 일단 Enumerate라는 함수가 어떤 기능을 하는지부터 간단하게 이야기하면 그런 타이틀이 Toy Story일 때 0이라는 값이 나오잖아요?

이 0이라는 게 포문을 돌았을 때 몇 바퀴를 의미하는지 값이에요.

그래서 0번째 포문을 의미하니까 이 값이 그냥 인덱스처럼 이렇게 의미하는 건데 그래서 얘를 실제 이렇게 돌리게 되면 0번째부터 샤일대로 이렇게 movie 타이틀이 정확히 순서대로 맵핑이 되는 걸 볼 수 있습니다.

그리고 이 idt movie는 반대로 Toy Story가 0이 이렇게 맵핑이 되도록 그래서 movie.myitems를 치면 딕셔너리에 키와 밸류를 동시에 호출해주는 명령어거든요?

그래서 리스트에 보면 이렇게 키와 밸류를 이렇게 같이 호출해줘요.

그래서 이 i가 의미하는 거는 키 값 0이고 c가 의미하는 거는 밸류 값 Toy Story 다음 포문에서는 1과 주만지 이렇게 나오는 걸 통해서 역 딕셔너리를 만들 수 있습니다.

그래서 Toy Story라는 아이디를 추출했을 때 과연 유사도가 어떻게 나오는지 볼게요.

일단은 저희가 유사도 횡렬 같은 경우 인덱스를 기준으로 종료되었으니까 Toy Story의 인덱스를 한번 추출해보면 Toy Story라는 타이틀을 가진 걸 인덱스로 변환해주는 게 idt movie잖아요?

그래서 얘를 movie.title을 적용해주면 idx가 0이 나오는 걸 볼 수 있습니다.

그래서 이 idx 0번에 대해서 Cosine Matrix에 대해서 0번째를 쳤을 때 유사도가 높은 순서대로 뽑고 싶은데 문제는 지금 정렬이 안 된 상태예요.

얘는 0번째 영화를 의미하고, 첫 번째 영화, 두 번째 영화, 그리고 2만 한 번째 영화를 의미하는데 정렬이 안 됐으니까 각각에 대해서 정렬을 해줄 필요가 있거든요.

그리고 두 번째로 문제점이 얘가 지금 자기 자신에 대한 유사도도 포함되고 있고 어떤 인덱스를 가지는지 저희가 봤을 때는 순서대로 0, 1, 2 이렇게 부여해주면 되는데 그걸 모르니까 인덱스 부여하는 것부터 시작할게요.

심스컬스를 이렇게 Enumerator로 아까처럼 만들면 i가 인덱스 번호가 나오고, i가 포문 돌아가는 순서를 의미하고 c가 유사도 값이니까 얘를 치면 자기 자신, i가 i의 인덱스가 아닌 부분, 자기 자신을 제외하고 인덱스에 대해서 어떤 유사도 값을 가지는지 알 수가 있잖아요?

그 이후에 지금 유사도를 한번 정렬을 해줄 필요가 있는 거죠.

그래서 정렬 같은 경우는 키 값이 아닌 밸류 값으로 기준을 해야 되니까 lambda의 키에 1을 넣어주면 키가 아닌 밸류 값으로 정렬을 할 수가 있고요.

Reverse true는 유사도가 높은 순서대로 정렬을 하라는 의미입니다.

상위 10개에 대해서 인덱스를 추출하게 되면 이런 식으로 순서가 나오고 얘가 지금 어떤 타이틀을 가지는지 저희는 모르잖아요?

그래서 move to id라는 아까 만들었던 딕셔널을 통해서 이 부분에 대해서도 변환을 해주면 Toy Story라는 영화를 넣었을 때 저희가 Toy Story라는 영화를 넣었을 때 오버 빅만을 기준으로 tf.idf 정렬한 결과를 보시면 Toy Story 3과 Toy Story 2라는 영화가 유사한 걸 지금 볼 수가 있습니다.

그래서 간단하게 다시 정리해드리자면 저희가 목적으로 했던 거는 영화관의 유사도를 데이터 오버뷰를 통해서 보고 싶었던 거고 데이터 오버뷰에 대해서 결칙이 있는 걸 간단하게 제거해주고 램 부족 현상으로 인해 특정 문서 2만 1개 정도만 추출해서 사용하는데 멕터라이저를 만들 때 스타버즈, 잉글리시를 통해서 불용어 같은 거 제거 같이 진행해줄 수 있고 이거 같은 경우는 퓌 트랜스포머로 저희가 만든 토큰에 대해서 분석 진행하겠다?

이런 거죠.

그리고 이렇게 만든 tf.matrix를 이제 Cosine Similarity를 계산을 하고 근데 Cosine Similarity를 계산하고 바로 적용하려고 했을 때 문제가 Cosine Similarity 같은 경우 값이 이제 어떤 매트릭스 형태로 이제 인덱스 값을 가지니까 얘를 내가 알고 있는 영화의 타이틀과 맵핑해줄 딕셔너리가 필요해가지고 그 딕셔너리를 이렇게 해서 만들어준 다음에 해당하는 딕셔너리의 유사도 부분만을 이제 추출을 해서 정렬을 해서 높은 순서대로 뽑고 얘를 다시 movie2id라는 딕셔너리를 통해서 인덱스를 뮤비의 타이틀로 변경해주면 각각의 영화 토이스토리 1과 유사한 영화들이 유사도 값과 같이 나오는 것을 볼 수가 있습니다.

tf.idf 단점도 좀 크리티컬해요.

데이터가 지금처럼 좀 많지 않은 경우나 조금 컴퓨팅 자원이 풍부한 상황 같은 데면 tf.idf 적용해가지고 스팟스 매트릭스까지 만든 다음에 유사도 계산하는 게 수월할 텐데 진짜 유튜브, 책 그런 거 되게 데이터 많은 곳도 있잖아요.

사실 그런 곳에서 적용하기는 힘들죠.

왜냐면 데이터도 많고 단어도 많으니까.

그래서 다음에 소개해드릴 게 Word2vec인데 Word2vec의 그런 한계를 좀 극복한 모델이어서 tf.idf가 꽤 원시적인 방법이잖아요.

그래서 좋은 거 많이 사용해야죠.

SUMMARY

인테리어의 인간과 인간의 관계는 추천 시스템의 과거 알고리즘과 기업에서 사용하는 알고리즘을 통해 배울 수 있습니다.

이제는 실제 현업에서 많이 사용하는 컨텐츠 기반과 협업 필터링 기반의 추천 시스템을 살펴보고, 사용자가 이전에 구매한 상품 목록을 살펴보고 이 중에서 사용자가 좋아하는 상품들과 유사한 상품들을 찾아서 추천하는 알고리즘을 살펴보았습니다.

그리고 아이템을 벡터 형태로 표현하고 이 벡터들 간의 유사도를 계산하여 벡터 1을 기준으로 자신과 유사한 벡터를 추출하여 추천을 하는 방법을 공부하였습니다.

유사도 함수는 여러가지가 있으며, 이 중에서 가장 쉬운 것인 유클리디안 유사도는 두 벡터 간의 거리를 계산하면 됩니다.

이것은 분모가 0이 되는 것을 방지하기 위해 작은 값을 더해주고, 두 벡터 간의 거리를 내적하는 방식으로 계산됩니다.

이는 예를 들어 문서 4개가 있고 각각 과일, 길고, 노란, 먹고, 바나나, 사과, 10분, 좋아요라는 단어 토큰을 가진 벡터 4개가 있다면, 두 벡터 간의 거리를 계산하는 방식으로 유사도를 계산할 수 있습니다.

그래서 유사도 값을 계산하기 위해서는 두 문서의 벡터를 비교하여 내적값을 계산하고, 이를 통해 방향을 의미하는 코사인 세타를 계산합니다.

두 문서의 방향이 동일할 때 시뮬러티가 1이고, 방향이 정반대일 때 시뮬러티가 -1이 됩니다.

이를 통해 두 문서의 유사도를 알 수 있습니다.

하지만 이것은 분포나 스케일이 다를 때 문제가 발생할 수 있습니다.

유사도 함수 중 코사인 유사도와 유사도 유사도는 벡터의 크기가 중요하지 않은 경우에 사용하는 매트릭스이다.

예를 들어 문서 내의 단어 빈도수는 길이가 고르지 않더라도 문서 내에 나왔는지 없는지는 비율로 확인할 수 있다.

반면 유쿨리디안 유사도는 벡터의 크기가 중요한 경우에 사용한다.

예를 들어 회색 점이 있을 때 유쿨리디안 유사도와 코사인 유사도를 사용하여 각 벡터와 유사한지 확인할 수 있다.

코사인 유사도는 벡터의 크기가 중요하지 않은 경우에 사용하며, 유쿨리디안 유사도는 벡터의 크기가 중요한 경우에 사용한다.

두 유사도 함수는 각각의 장단점이 있으며, 특정한 문제에 따라 적합한 함수를 선택해야 한다.

유사도 함수 간의 차이점을 잘 이해하고 사용하는 것이 중요합니다.

유클리디안 유사도는 두 벡터 간의 거리를 측정하고, 코사인 유사도는 두 벡터 간의 방향을 측정합니다.

따라서 유클리디안 유사도는 거리가 가장 짧은 벡터를 찾지만, 코사인 유사도는 방향이 가장 유사한 벡터를 찾습니다.

피어슨 유사도는 보통 상관관계를 분석할 때 많이 사용하는 알고리즘으로 두 벡터 간의 값과 평균을 계산합니다.

문서 1과 문서 2의 평균과 분산을 계산하여 유사도를 계산할 수 있습니다.

코사인, 자카드, 유클리디안, 피어슨 등 여러 유사도를 사용할 수 있습니다.

그러면 문서 1과 문서 2는 교집합의 크기가 2가 되고, 집합의 크기가 3+3-2=4가 되므로 4분의 1을 통해 유사도는 0.5가 됩니다.

다이버전스 같은 경우는 분포의 유사도 계산할 때 많이 사용하고, 다이스 유사도 같은 경우도 많이 사용합니다.

소렌센 같은 경우도 현업에서 조금씩 사용하고 있습니다.

또한, 다양한 추천 시스템 모델을 가중치를 두고, 고객 집단마다 다르게 적용할 수도 있습니다.

이러한 다양한 유사도를 종합하여 적용하는 것이 가능합니다.

여기서는 문서들 간의 유사도를 계산하기 위해 다양한 방법론을 사용할 수 있다는 이야기를 하고 있습니다.

이는 문서 1부터 문서 4까지의 유사도를 계산하고 각각의 유사도 매트릭스마다 모델을 만들어서 추천 결과를 결합하거나, 가중치를 줘서 더한 다음에 유사도를 만들어도 된다는 이야기를 하고 있습니다.

그리고 레프레젠트 아이템을 통해 벡터간의 유사도를 계산하고, 아이템을 벡터로 바꾸는 방법 중 가장 기본적인 방법인 TF-IDF를 사용하고 있다는 이야기를 하고 있습니다.

TF-IDF는 단어 빈도(TF)와 영문서 빈도(IDF)를 계산하여 특정 문서의 핵심어 추출, 문서들의 유사도 그리고 검색 결과의 중요도를 정하는데 많이 활용됩니다.

TF는 특정 문서 내에서 특정 단어가 얼마나 자주 등장하는지를 의미하고, IDF는 전체 문서에서 특정 단어가 얼마나 등장하는지를 계산합니다.

따라서 TF, IDF를 곱하여 특정 단어가 특정 문서에서 중요한지 알 수 있습니다.

단어가 문서 내에서 몇 번 등장했는지를 의미하는 거예요.

TF-IDF는 문서 내에서 단어의 빈도수를 기반으로 중요한 단어를 찾아내고, 의미 없는 단어에 대해 페널티를 주는 방법으로, 주어진 문서 4개를 가지고 유사도를 계산하고 추천하는 방법입니다.

TF는 단어가 문서 내에서 몇 번 등장했는지를 의미하고, IDF는 중요하지 않은 단어에 대해 페널티를 주는 것입니다.

TF는 문서 D에서 특정 단어 T가 등장하는 횟수를 의미하며, DF는 특정 단어 T가 얼마만큼 문서에 등장했는지를 의미합니다.

IDF는 이미 정해진 함수를 통해 만들 수 있으며, TF-IDF 매트릭스는 문서 간 벡터 간의 유사도를 계산하여 문서 유사도를 알 수 있게 합니다.

이 과정을 통해 문서 1과 문서 2 간의 유사도는 0.5061로 어느 정도 관련이 있다고 나왔습니다.

TF-IDF는 문서의 중요도를 측정하기 위한 알고리즘으로, 많이 나오는 관사, 조사 등의 단어에 페널티를 주고, 특정 문서에서만 많이 나온 단어를 가중치를 두어 벡터라이저를 하는 것으로 해석이 직관적이고 사용하기 쉬운 것 같다.

또한 유사도 함수를 계산하기 위해 코드가 세~네 줄로 처리되며 단점으로는 메모리 문제가 있다.

Text라는 클래스를 통해서 TF-IDF 벡터라이저를 만들겠습니다.

추천 시스템의 메모리 문제를 해결하기 위해 Word2vec이라는 아이디어가 등장했다.

TF-IDF를 이용해 문서 리스트를 만들고 카운터 벡터라이저로 TF까지의 과정을 거친 벡터라이저를 만들어 메모리 문제를 해결할 수 있다.

ImportCounterVectorizer로 CounterVectorizer 객체를 만들어 Vect에 저장하고, 독스를 벡터라이저 함수에 적용해 4,9 크기의 스팔스 매트릭스를 만들었다.

JumpToArray로 Nump 형태로 바꾸고, Vocabulary 함수로 각 단어의 인덱스와 컬럼을 찾아 데이터 프레임으로 바꾼다.

Salted함수로 단어를 정렬해 카운터 벡터의 데이터 프레임을 만들고, 인덱스는 문서 1부터 문서 4까지의 값을 가진다.

Counter Vectorizer를 통해 데이터 프레임을 만들고, Cosine 유사도를 통해 문서끼리 유사도를 계산할 수 있습니다.

이를 통해 문서 1과 문서 2가 유사하고 문서 2와 문서 3도 유사하다는 결과를 얻을 수 있습니다.

또한 이를 통해 추천 시스템을 만들 수도 있습니다.

하지만 이 방법의 단점은 의미 없는 단어가 많이 나온다는 것입니다.

그래서 Counter Vectorizer 대신 TF-IDF Vectorizer를 사용하고 변환한 Array 값을 사용하여 TF-IDF를 통해 벡터라이저된 결과를 얻을 수 있고, 이를 통해 다시 유사도를 계산할 수 있습니다.

이 문장에서는 TF-IDF를 기반으로 한 단어 카운팅 방법과 이를 해결하기 위한 방법론인 모두투백이 소개되었다.

또한, 띄어쓰기 기준으로 진행되는 벡터라이저 호출과 형태소 처리를 통해 불필요한 편들을 제거하는 것이 필요하다는 것이 밝혀졌다.

이는 특정 단어가 전체 문서에 많이 나오면 그것을 잘 제거하기 위함이다.

이런 전처리 과정부터 띄어쓰기 기준으로 형태소 분석해서 TF-IDF를 적용해서 추천 시스템을 만드는 과정을 간단하게 소개합니다.

영화 메타 데이터에 대한 전처리 과정과 TF-IDF 적용해서 추천 시스템 만드는 과정을 소개하고 있다.

이를 위해 띄어쓰기 기준으로 형태소 분석하고 결측치가 있는 부분은 제거한다.

이를 통해 메타 정보 중 하나인 오버뷰를 가지고 영화의 의미를 간단히 소개해주고 평점, 보트 카운트, 발매일 등의 메타 데이터를 가지고 추천 시스템을 만들었을 때 어떤 결과를 가지는지 소개하고 있다.

여기서는 결측치를 제거하기 위해 데이터 있는 난 룰을 적용하여 true인 부분만 데이터를 뽑고 list 인덱스를 다시 조절하여 결측치 있는 항목을 모두 제거한다.

케글 노트북의 램 제한으로 전체 영화 데이터를 사용하면 램이 터지므로 2만 개 데이터로 진행한다.

TF-IDF에서 불용어 단어를 토큰 제거하는 부분은 stopword로 실행해줄 수 있다.

그리고 2만 1개의 문서에 대해 유의미하지 않은 단어 토큰을 제거하고 Cosine Similarity를 계산하여 2만 1개의 영화관의 유사도 Matrix를 계산할 수 있다.

Cosine Matrix의 인덱스는 0부터 시작해서 데이터에 나온 순서대로 맵핑되는데, 딕셔너리를 통해 movie id와 타이틀을 맵핑하는 Enumerate 함수를 통해 인덱스와 타이틀을 같이 호출하면 이를 통해 역 딕셔너리를 만들 수 있고, 이를 통해 아이디를 추출하여 유사도가 어떻게 나오는지 볼 수 있다.

Toy

Story의 인덱스를 추출해 Cosine Matrix를 이용해 유사도가 높은 순서대로 정렬하려면 0번 인덱스를 기준으로 Enumerator를 사용해 밸류 값으로 정렬하고 Reverse True로 유사도가 높은 순서대로 상위 10개 인덱스를 추출하면 된다.

인덱스는 순서대로 0, 1, 2가 나오고, 인덱스에 대한 유사도 값을 알 수 있으며 타이틀은 모른다.

tf.idf를 통해 영화 간의 유사도를 분석하기 위해 데이터 오버뷰를 제거하고 메모리 부족 문제를 해결하기 위해 불용어를 제거하고 tf.matrix를 만들고 Cosine Similarity를 계산하고 인덱스 값과 영화 타이틀을 맵핑하여 유사도를 계산하는 방법을 소개했다.

그러나 tf.idf는 데이터가 많거나 컴퓨팅 자원이 부족한 경우에는 적합하지 않다.

다음에는 Word2vec이라는 방법을 소개할 것이다.

요즘은 사용하기 쉬운 기술과 소프트웨어가 많이 발전하고 있습니다.

그래서 우리는 좋은 기술과 소프트웨어를 많이 사용해야 합니다.

이러한 기술은 우리의 생활을 편리하게 하고, 우리가 더 나은 결과를 얻을 수 있도록 도와줍니다.

따라서, 우리는 좋은 기술과 소프트웨어를 많이 사용해야 합니다.

우리는 이를 통해 더 나은 생활을 유지하고, 더 나은 결과를 얻을 수 있습니다.

우리는 좋은 기술과 소프트웨어를 사용하여 생활을 편리하고, 더 나은 결과를 얻을 수 있도록 도와줍니다.

그래서 우리는 좋은 기술과 소프트웨어를 많이 사용해야 합니다.

요즘 사용하기 쉬운 기술과 소프트웨어가 발전하고 있어 우리는 좋은 기술과 소프트웨어를 많이 사용해야 합니다.

그러면 생활을 편리하게 하고, 더 나은 결과를 얻을 수 있습니다.

따라서 좋은 기술과 소프트웨어를 많이 사용해야 합니다.