일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 머신러닝
- leetcode 49
- 데이터레이크와 데이터웨어하우스
- Hadoop
- docker로 airflow 설치하기
- leetcode 238
- leetcode 234
- leetcode 5
- ctf-d
- airflow docker
- webcrawler
- leetcode 819
- 스파크 완벽 가이드
- Python
- wargame.kr
- MapReduce 실습
- 빅데이터를 지탱하는 기술
- 컴퓨터구조
- leetcode125
- leetcode 344
- 블로그 이전했어요
- 올바른 변수명 짓기
- leetcode 937
- leetcode 561
- leetcode 15
- leetcode 121
- leetcode
- Hortonworks Sandbox
- 배열
- 문자열 조작
- Today
- Total
HyeM
6부_3장 베이스정리로 텍스트 분류하기 본문
01. 텍스트 분류
텍스트 분류에는 여러 가지 방법이 있는데, 자주 사용되는 방법인 “베이지안 필터” 를 이용해 실습해본다.
베이지안 필터
- 스팸 메일이나 글을 구분할때 많이 사용됨.
- 교사학습/ 비교사학습/ 강화학습의 3가지 머신러닝 종류중 교사학습에 해당한다.
- 사용자가 따로 키워드를 지정하지 않아도 스팸 메일을 구분할 수 있음
02. 베이즈 정리
베이즈 정리는 '조건부 확률'과 관련된 이론으로, 토머스 베이즈에 의해 정립된 이론이다.
P(A|B) = P(A|B)P(B)/P(A)
조건부 확률
<어떤 A라는 사건이 일어났다는 조건>에서 <다른 사건 B가 일어날 확률>을 나타냄. = P(B|A)
결합확률과 곱셈 법칙
예를 들어 정육면체 주사위를 두 번 던져서 "첫번째가 3", "두 번째가 짝수" 될 확률은
1/6 X 1/2 = 1/12 이다.
=> 동시에( 연속적으로) 2가지 사건이 발생할 때는 두 사건의 확률을 곱하면 된다.
베이즈 정리
"B와 A의 결합 확률"은 "A와 B의 결합 확률" 과 같다는 점을 변형하면 베이즈 정리가 나오게 된다.
B와 A의 결합 확률 = P(A|B) X P(B)
A와 B의 결합 확률 = P(A|B) X P(A)
P(A|B) X P(B) = P(A|B) X P(A)
03. 나이브 베이즈 분류
베이지안 필터는 나이브 베이즈 분류 알고리즘을 사용하는데, 나이브 베이즈 분류는 베이즈 정리를사용한 분류 방법이다.
베이즈 정리는 A라는 사건이 B에 속하는지 판단할 때 사용함.
Ex. 텍스트 분류 : A_텍스트 , B_카테고리 판정 결과
이메일 스팸 필터 : A_받은 메일, B_ 스팸 메일 판정 결과
나이브 베이즈 분류는 어떤 문장을 카테고리 분류할 때, 텍스트 내부에서의 단어 출현 비율을 조사한다.
그리고 이를 기반으로 해당 테스트를 어떤 카테고리로 분류하는 것이 적합한지 알아본다.
P(B|A) = P(B) x P(A|B)
(나이브 베이즈 분류 공식 )
P(A)는 입력텍스트A가 주어질 확률 ; A는 단어들의 집합=> (단어가 문서의 어떤 위치에 있는지는 고려하지 않음)
P(B)는 각 카테고리로 분류될 확률 (전체 문서에서 해당 카테고리의 문서가 나올 확률)
P(A|B) = P(a_a1 | B) P(_a2|B) P(_a3|B) ... P(a_xN |B))
입력텍스트 A를 각 단어(aN)의 집합
P(aN |B)는 단어가 카테고리에 속할 확률
<단순한 출현율>=<단어의 출현 횟수>/<카테고리 전체 단어 수>
04. 베이지안 필터 사용해보기
간단한 베이지안 필터를 파이썬 프로그램으로 구현해본다.
다음 코드에서 베이지안 필터를 구현한 클래스는 BayesianFilter이다.
import math, sys
from konlpy.tag import Okt
class BayesianFilter:
"""베이지안 필터"""
def __init__(self): #생성자
self.words = set() #출현한 단어 기록
self.word_dict ={} #카테고리마다의 단어 출현 횟수 기록; [카테고리][단어]=출현횟수
self.category_dict ={} #카테고리 출현 횟수 기록
#형태소 분석하기 ---(#1)
def split(self, text):
results =[]
okt=Okt() #Okt 형태소 분석기를 이용함.
#단어의 기본형 사용
malist =okt.pos(text, norm=True, stem=True)
for word in malist:
#어미/조사/구두점 등은 대상에서 제외
if not word[1] in ["Josa", "Eomi", "Punctuation"]:
results.append(word[0]) #형태소를 results 배열에 저장하여,
return results #return 한다.
#단어와 카테고리의 출현 횟수 세기 --(#2)
#단어를 카테고리에 추가하기
def inc_word(self, word, category):
if not category in self.word_dict: #카테고리마다의 단어 출현 횟수 기록하는 (word_dict)에 카테고리가 없다면,
self.word_dict[category]={} #공간 만들어줌.
if not word in self.word_dict[category]: #카테고리 목록의 해당 카테고리에 word가 없다면,
self.word_dict[category][word] =0
self.word_dict[category][word] +=1 #그리고, 해당 단어를 해당 카테고리에 추가+1 해준다.
self.words.add(word)
#카테고리 계산하기
def inc_category(self, category):
if not category in self.category_dict: #카테고리 목록(category_dict)에 카테고리가 없다면,
self.category_dict[category]=0 #공간 만들어줌.
self.category_dict[category]+=1 #그리고, 해당 카테고리에 추가+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
d= sum(self.word_dict[category].values()) + len(self.words)
return n/d
#1. 형태소 분석 _ koNLPy의 Okt 형태소 분석 사용
#2. 단어를 카테고리에 추가하고, 카테고리 내부의 단어 출현 빈도를 구할 수 있게 출현 횟수를 셈
inc_word() 메서드에서는 word_dict를 사용해 단어 출현 횟수를 세고, inc_category() 메서드에서는 category_dict를 사용해 카테고리의 출현 횟수를 센다.
#3. 텍스트를 학습하는 fit()메서드를 정의함 _ fit메서드에서는 텍스트를 형태소로 분할하고, 카테고리와 단어를 연결함.
#4. 단어 리스트를 주면 점수를 계산해주는 메서드
#5. 텍스트의 카테고리를 구분하는 메서드_ 텍스트가 주어졌을 때 카테고리 점수를 계산, 가장 점수가 높은 카테고리를 결과로 return
#6. 단어 출현률을 계산할 때 학습사전(word_dict)에 없는 단어가 나오면 카테고리의 확률이 0이 됨
*__init__ : 자바에서의 생성자를 파이썬에서는 __init__으로 표기한다.
이제 베이지안 필터를 구현한 이 클래스를 가지고,
메일의 제목으로 스팸을 구분하는 상황을 가정해서, 메일의 제목을 기반으로 "광고", "중요"메일을 구분하는 예제이다.
from bayes import BayesianFilter #위에서 만든 BayesianFilter클래스를 import 해준다.
bf=BayesianFilter() # 생성자를 호출하여, 객체 생성.
#텍스트 학습 _ fit 함수를 이용
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)
적당한 텍스트를 학습시키고,제대로 판정하는지 확인함.
[실행결과]
위 글은 [(파이썬을 이용한)머신러닝, 딥러닝 실전 개발 입문] 을 읽고 정리한 글입니다.
'Study > AI&DeepLearning' 카테고리의 다른 글
6부_5장 N-gram으로 문장유사도 분석하기 (0) | 2020.08.04 |
---|---|
6부_4장 MLP 텍스트 분류하기 (2) | 2020.08.01 |
6부_2장 Word2Vec로 문장을 백터로 변환하기 (0) | 2020.07.17 |
6부_1장 한국어 분석(형태소 분석) (1) | 2020.07.17 |
2부_3장 머신러닝의 이해와 지도학습을 이용한 분류(2) (0) | 2020.07.10 |