상대적 출현 비율을 통한 키워드 추출
이 내용은 김현중 박사님께 받은 2020 패스트캠퍼스 수업을 기반으로 작성했음을 알려드립니다.
키워드를 추출하는 방식에는 다양한 방식이 있습니다. 저는 그 중에서 간단한 방식이면서 직관적인 방식인 상대적 출현 비율을 통한 키워드 추출을 해보겠습니다.
상대적 출현 비율이란 말 그대로 특정 단어가 특정 군집에서 얼마나 사용되었는가에 대한 비율을 말합니다. 예를 들어 애완동물 커뮤니티와 직업 커뮤니티의 글을 분석할 때 강아지라는 단어는 직업 커뮤니티보다 애완동물 커뮤니티에서 등장 할 확률이 높을 것 입니다.
상대적 출현 비율을 구하는 방법을 말하자면 특정 군집에서 원하는 단어의 수를 계산 한 뒤 비교하고자 하는 군집의 단어 수와 합한 후 나누어 주면 됩니다. 식으로 표현하면 다음과 같습니다.
\[score = \frac {P('강아지'|D_{pet})} {P('강아지'|D_{pet}) + P('강아지'|D_{work})}\]실제로 어떤 결과가 나오는지 직접 코드를 작성해보도록 하겠습니다.
1. 데이터 수집
https://github.com/lovit/petitions_dataset
저는 lovit님의 github 소스를 통해 국민청원 데이터를 수집하였습니다. 소스의 사용방법에 대해서는 위의 사이트로 접속하여 쉽게 사용할 수 있으니 설명하지 않겠습니다.
2. 데이터 전처리
이번 예제에서는 분류 및 임베딩 방식이 따로 들어가지 않고 그저 Frequency만을 이용하는 방식이므로 불필요한 텍스트를 삭제하는 정규표현식을 사용하여 데이터를 제거하였습니다.
mean_ful_reg = re.compile('[^가-힣a-zA-Z\s]+')
double_space_reg = re.compile('[\s]+')
3. Counter 작성
def LionCounter(*args):
all_Count_Vector = defaultdict(int)
word_set = sorted(' '.join(list(reduce(lambda x, y: x + y, args))).split(' '))
dict_template = defaultdict(int, {key: 0 for key in word_set})
args_dicts = [copy(dict_template) for idx in range(len(args))]
all_Count_Vector = Counter(word_set)
for idx in range(len(args)):
args_dicts[idx].update(Counter(' '.join(args[idx]).split(' ')))
return {'부분': args_dicts, '전체': all_Count_Vector}
LionCounter는 이러한 데이터 별 Count를 계산하는 알고리즘이 자주 등장할 것 같아서 전체 데이터에 대한 등장 빈도와 데이터 별 등장 빈도를 따로 계산해주는 방식으로 만들어 보았습니다.
사실 sklearn의 CounterVectorize를 사용하는 방식과 비슷하지만 직접 만들어보고 싶은 마음이 있어서 만들어보았습니다. 또한 이 방식에서는 여러 리스트를 넣으면 각각의 등장빈도를 따로따로 구해줌으로써 소스를 좀 짧게 해보자라는 생각으로 만들어보았습니다.
이후에 상대적 출현 비율을 계산할 때 이 Counter를 사용합니다.
결과는 다음과 같습니다.
tmp = LionCounter(dataset['일자리'],dataset['반려동물'])
tmp
4. 상대적 출현 비율 함수 작성
def LionRelativeAppearanceRatio(*args):
Counters_ = LionCounter(*args)
words = list(Counters_['전체'].keys())
max_count = np.array(list(Counters_['전체'].values()))
appearance_ratio = []
for idx in range(len(args)):
appearance_ratio.append(np.array(list(Counters_['부분'][idx].values())) / max_count)
result = defaultdict(list)
for idx,ratio in enumerate(get_elements_in_2D_list(appearance_ratio)):
result[words[idx]] = ratio
return result
LionRelativeAppearanceRatio 함수는 LionCounter를 사용하여 모든 리스트에서 해당 단어의 등장 빈도를 구해주는 함수입니다.
이 함수를 이용하여 강아지라는 단어의 점수를 각각 살펴보겠습니다
tmp = LionRelativeAppearanceRatio(dataset['일자리'],dataset['반려동물'])
print(tmp['강아지'])
'[0.0044004400440044, 0.9955995599559956]'
LionRelativeAppearanceRatio를 사용하면 2개 이상의 리스트에서도 점수를 추출할 수 있습니다. 3개의 데이터에서 강아지 단어의 점수를 살펴보겠습니다.
tmp = LionRelativeAppearanceRatio(dataset['일자리'],dataset['반려동물'],dataset['미래'])
print(tmp['강아지'])
'[0.0043859649122807015, 0.9923245614035088, 0.003289473684210526]'
역시나 예상했던대로 반려동물에 대한 토픽에서 강아지라는 단어가 가장 많이 쓰였다는 것을 알 수 있습니다. 동시에 반려동물에 대한 토픽에서 “강아지”는 높은 대표성을 가지고 있다. = 키워드일 가능성이 높다. 와 같은 추측을 할 수 있습니다.
참조
https://lovit.github.io/nlp/2018/04/12/proportion_keywords/