일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 백준 1920
- 순차 컨테이너
- 컴퓨터구조
- Reverse Engineering
- UIPanGestureRecognizer
- 모달인듯 모달 아닌 뷰
- vector
- NavigationBar
- list
- stl
- Constraint
- 스택
- BOJ
- 2020.06.14
- 알고리즘
- 2020.04.19
- scroll
- 컴퓨터 구조
- 2020.05.17
- Reversing
- Swing
- class
- 표준 템플릿 라이브러리
- Stack
- SWiFT
- UIView
- 백준 10828
- ios
- struct
- Animation
- Today
- Total
야금야금
베이즈 정리로 텍스트 분류하기 본문
베이지안 필터
: 베이즈 정리를 이용한 텍스트 분류 방법으로 학습을 많이 시키면 시킬수록 필터의 분류 능력이 오른다는 특징이 있다.
머신러닝의 종류 중 교사학습에 해당한다.
베이즈 정리
: 조건부 확률과 관련된 이론으로 토머스 베이즈에 의해 정립된 이론이다.
P(B|A) = P(A|B)P(B)/P(A)
P(A) : A가 일어날 확률
P(B) : B가 일어날 확률
P(A|B) : B가 일어난 후에 A가 일어날 확률(조건부 확률, 사후 확률)
P(B|A) : A가 일어난 후에 B가 일어날 확률(조건부 확률, 사전 확률)
조건부 확률
: 어떤 A라는 사건이 일어났다는 조건에서 다른 사건 B가 일어날 확률
P(B|A) = P(B∩A)/P(A)
결합 확률과 곱셈 법칙
동시에 또는 연속적으로 2가지 사건이 발생할 때는 두 사건의 확률을 곱한다.
나이브 베이즈 분류
: 베이지안 필터는 나이브 베이즈 분류라는 알고리즘을 사용하며 나이브 베이즈 분류는 베이즈 정리를 사용한 분류 방법이다.
나이브 베이즈 분류는 텍스트 내부에서의 단어 출현 비율을 조사한다. 그리고 이를 기반으로 해당 텍스트를 어떤 카테고리로 분류하는 것이 적합한지 알아본다
실제로 판정을 할 때 P(A|B)는 1개의 확률이 아니라 여러 개의 카테고리 중에 어떤 카테고리에 속할 확률이 가장 큰지를 나타내는 정보이다. 따라서 베이즈 정리 분모에 있는 P(A)는 입력 텍스트가 주어질 확률이다.
다만 어떤 카테고리를 판정하든 같은 입력 텍스트가 주어지는 것이므로 같은 값으로 생각하면 되어 따로 고려하지 않아도 된다. 이때 공식은 다음과 같다.
P(B|A) = P(B) x P(A|B)
이때 P(B)는 각 카테고리로 분류될 확률을 나타낸다. 전체 문서에서 해당 카테고리의 문서가 나올 확률이라고 생각하자
이어서 P(A|B)를 생각해보자.
입력 텍스트 A는 단어들의 집합이라고 할 수 있다. 그래서 텍스트들을 단어들로 분리한다. 집합이므로 순서에는 큰 의미가 없으며 단어가 문서의 어떤 위치에 있다는 정보 등은 고려하지 않아도 된다. 가방 안에 단어들을 그냥 넣어서 사용하는 것과 같다고 해서 이러한 텍스트 표현(순서를 고려하지 않고 단어로만 표현하는 것)을 "BoW = bag - of - word" (단어가 담긴 가방)이라고 부른다.
입력 텍스트 A를 각 단어(aN)의 집합이라고 할 때, P(A|B)는 다음과 같은 식으로 나타낼 수 있다.
P(aN | B)의 확률은 단어가 카테고리에 속할 확률이다. 어떤 카테고리에 해당 단어가 출현할 확률을 구하면 되는데, 이는 다음과 같이 구할 수 있다.
<단순한 출현율> = <단어의 출현 횟수> / <카테고리 전체 단어 수>
베이지안 필터 사용해보기
다음은 베이지안 필터를 구현한 BayesianFilter 클래스이다.
파일명 : bayes.py
import math, sys
from konlpy.tag import Oktclass BayesianFilter:
def __init__(self):
self.words = set() #출현한 단어 기록
self.word_dict = {} #카테고리마다의 출현 횟수 기록
self.category_dict = {} #카테고리 출현 횟수 기록
# 형태소 분석하기(※1)
def split(self, text):
results = []
okt = Okt()
# 단어의 기본형 사용
malist = okt.pos(text, norm=True, stem=True)
for word in malist:
# 어미/조사/구두점 등은 대상에서 제외
if not word[1] in ["Josa", "Eomi", "Punctuaion"]:
results.append(word[0])
return results
# 단어와 카테고리의 출현 횟수 세기(※2)
def inc_word(self, word, category):
# 단어를 카테고리에 추가하기
if not category in self.word_dict:
self.word_dict[category] = {}
if not word in self.word_dict[category]:
self.word_dict[category][word] = 0
self.word_dict[category][word] += 1
self.words.add(word)
def inc_category(self, category):
# 카테고리 계산하기
if not category in self.category_dict:
self.category_dict[category] = 0
self.category_dict[category] += 1
# 텍스트 학습하기(※3)
def fit(self, text, category):
""" 텍스트 학습 """
word_list = self.split(text)
for word in word_list:
self.inc_word(word, category)
self.inc_category(category)
# 단어 리스트에 점수 매기기(※4)
def score(self, words, category):
score = math.log(self.category_prob(category))
for word in words:
score += math.log(self.word_prob(word, category))
return score
# 예측하기(※5)
def predict(self, text):
best_category = None
max_score = -sys.maxsize
words = self.split(text)
score_list = []
for category in self.category_dict.keys():
score = self.score(words, category)
score_list.append((category, score))
if score > max_score:
max_score = score
best_category = category
return best_category, score_list
# 카테고리 내부의 단어 출현 횟수 구하기
def get_word_count(self, word, category):
if word in self.word_dict[category]:
return self.word_dict[category][word]
else:
return 0
# 카테고리 계산
def category_prob(self, category):
sum_categories = sum(self.category_dict.values())
category_v = self.category_dict[category]
return category_v / sum_categories
# 카테소리 내부의 단어 출현 비율 계산(※6)
def word_prob(self, word, category):
n = self.get_word_count(word, category) + 1 #(※6a)
d = sum(self.word_dict[category].values()) + len(self.words)
return n / d
위의 클래스를 사용하여 스팸 메일과 중요 메일을 분류할 수 있게 하는 간단한 프로그램을 진행해 보았다.
몇 가지 메일을 학습시킨 이후에 새로운 메일이 왔을때 제대로 분류할 수 있는지 테스트해 보았다.
파일명 : bayes_test.py
from bayes import BayesianFilter
bf = BayesianFilter()
#텍스트 학습
bf.fit("파격 세일 - 오늘까지만 30% 할인", "광고")
bf.fit("쿠폰 선물 & 무료 배송", "광고")
bf.fit("현데계 백화점 세일", "광고")
bf.fit("봄과 함께 찾아온 따뜻한 신제품 소식", "광고")
bf.fit("인기 제품 기간 한정 세일", "광고")
bf.fit("오늘 일정 확인", "중요")
bf.fit("프로젝트 진행 상황 보고", "중요")
bf.fit("계약 잘 부탁드립니다", "중요")
bf.fit("회의 일정이 등록되었습니다.", "중요")
bf.fit("오늘 일정이 없습니다.", "중요")
# 예측
pre, scorelist = bf.predict("재고 정리 할인, 무료 배송")
print("결과 =", pre)
print(scorelist)
실행 결과 제대로 광고라고 판정하였다.
'SWING > 머신러닝' 카테고리의 다른 글
문장의 유사도를 N-gram으로 분석하기 (0) | 2020.08.08 |
---|---|
MLP로 텍스트 분류하기 (0) | 2020.08.02 |
한국어 분석(형태소 분석) (0) | 2020.07.25 |
머신러닝의 이해와 지도학습을 이용한 분류 (0) | 2020.07.10 |
인공지능 서비스와 기술의 이해 (0) | 2020.07.10 |