👨🏻‍🏫IT 활동/인공지능교육 - NLP

[NLP] Day 25 - Project 4

728x90
반응형

Projcet 4

스팸 자동 분류

스팸 / 햄 데이터 수집 ( 제목 )

글자가 깨지면

import html

html.parser.unescape(문자열)

In [1]:
from selenium import webdriver
driver = webdriver.Chrome(executable_path='/Users/charming/Python/3. Koipa AI Learning/NLP/chromedriver')
driver.get('https://nid.naver.com/nidlogin.login?mode=form')
In [2]:
driver.get('https://mail.naver.com/?n=1552462013012&v=f#%7B%22fClass%22%3A%22list%22%2C%22oParameter%22%3A%7B%22page%22%3A1%2C%22sortField%22%3A1%2C%22sortType%22%3A0%2C%22folderSN%22%3A%225%22%2C%22type%22%3A%22%22%2C%22isUnread%22%3Afalse%7D%7D')
In [3]:
tagList = list()
for tag in driver.find_elements_by_css_selector('strong.mail_title'):
    tagList.append(tag.text)
In [4]:
tagList
Out[4]:
['[유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.',
 '(제목없음)',
 '(제목없음)',
 '(광고) 로또1등담첨 예상번호 무료로 받아가세요~',
 '(광고) 성공을 위한 1인무점포 창업과 다양한 창업아이템 설명회 안내',
 '(광고) 더 이상 채.무. 로 고통받지 마세요',
 '(광고) 이번 Apple 스페셜 이벤트에서 발표된 놀라운 소식을 살펴보세요.']
In [5]:
import requests
session = requests.Session()
In [6]:
for c in driver.get_cookies():
    print(c['name'], c['value'])
    session.cookies.set(c['name'], c['value'])
    # set으로 다 밀어넣으면됨
NMUSER Y9YmFAEwaqbsFAKrKA2w+Hi9p69CWov9KxUsKxE9FAtqaxvwFAn9KxUmaqgsaqRJaw/wFxRpad/syqvstoRpadUstonstoRzaqROW9e7EoRpadUsawlGW430DVdq74lR74lC+4kZ74FTWLm/axgmar05pzk/7xKRbrkoWrlvMBil74lR74lC+4kZ74FTWLm/axgmam==
NNB FAHDYOHC32TFY
NID_JKL d9FIs84uX9dH5tAsBCfpiFvwv3llgO19O9JDT3oRGyM=
nid_inf 1833080211
NID_SES AAABk5QYDieoCN4mY+gtvakxvAqM38+RmaFjoBUOQY6Ze7K9Wa73RS4RZpe0INCfyC9qBgnOf7EMfs8hjYhHKVTCOTWc2HIRxh0BmWPSSEDy2rJfw2abRTHE7wzLAD3t0txy+wG11St3naVwp1LDa5dsyLJC9u47rqV4UDZM5FGs1aZoqtqewJ8o0tU9oJTnRhKhOJTPwOqKh/43tk6TlBX9qCnTiwTjJwDghzhyqTiLmbMRK0iNqAGm4996yG+g50Jg2OQuzAZRej8qG9MQRD6YsxyvgM+U+1ljXxo8nfrlx+V4VePumqGkqV6KUM3OoDpd26DjvcAofENFNaYDrNc0RQn//ta0kEQpsBsGrF/Fs5+z+Xi65igFRkvnAAT5MhHseYYCo3+KVAqi0gL/zlsauUL4hM4nMKRZR42kX1j0x436hu2RBN7rbiua7H5umgawR0UjRA7mVoCMjI5Gvl4arYxiSlF/hoqXEjy0XAz1Rm1VQaVqssNMtSG81EX5aKV6XhM9bxd3aaEpOqdsdm204S038cnWsOclAohQQXg4eBmA
NID_AUT VkhB6lOEXAIYHCpO7PRLYOePpd+6bpJud0R3/SvplqkUe0OoqTu4WnNwkJ5QcAtn
npic 7j1FQ1c6ilEFX8ILJWYqAn7cB1au6YNwY9H44y9zWbrB7Ry5dID3qE2P5snbHX2ECA==
In [17]:
spamList = list()
for tag in driver.find_elements_by_css_selector('strong.mail_title'):
    spamList.append(tag.text)
    
print(len(spamList))
7
In [18]:
spamList[0]
Out[18]:
'[유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.'
In [21]:
hamList = list()
for tag in driver.find_elements_by_css_selector('strong.mail_title'):
    hamList.append(tag.text)
    if len(hamList) == len(spamList):
        break
    
print(len(hamList))
7
In [22]:
hamList
Out[22]:
['2019 Adobe Design Achievement Awards의 작품 응모가 시작되었습니다!',
 '(광고)[몰테일]4월의 시작~ 몰테일의 이벤트와 함께 Start',
 '(광고) 이차민님, ♥5,000원쿠폰 도착!',
 '이차민님, "회식의 신" 페이지 방문자를 위해 게시물을 작성해보세요.',
 'New! Degrees & MasterTrack Certificates in Data Science, Computer Science, and more',
 '[매일경제] 로이킴, 음란물 유포 혐의 입건…소속사 “모르던 상황”',
 '🎂 오늘은 손석범님과 이시현님의 생일입니다']
In [25]:
hamList
Out[25]:
['2019 Adobe Design Achievement Awards의 작품 응모가 시작되었습니다!',
 '(광고)[몰테일]4월의 시작~ 몰테일의 이벤트와 함께 Start',
 '(광고) 이차민님, ♥5,000원쿠폰 도착!',
 '이차민님, "회식의 신" 페이지 방문자를 위해 게시물을 작성해보세요.',
 'New! Degrees & MasterTrack Certificates in Data Science, Computer Science, and more',
 '[매일경제] 로이킴, 음란물 유포 혐의 입건…소속사 “모르던 상황”',
 '🎂 오늘은 손석범님과 이시현님의 생일입니다']
In [29]:
a = ['spam','spam','spam','spam','spam','spam','spam']
In [31]:
for i, t in enumerate(spamList):
    print(i,t)
0 [유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.
1 (제목없음)
2 (제목없음)
3 (광고) 로또1등담첨 예상번호 무료로 받아가세요~
4 (광고) 성공을 위한 1인무점포 창업과 다양한 창업아이템 설명회 안내
5 (광고) 더 이상 채.무. 로 고통받지 마세요
6 (광고) 이번 Apple 스페셜 이벤트에서 발표된 놀라운 소식을 살펴보세요.
In [32]:
trainingSet = spamList + hamList
In [33]:
trainingSet
Out[33]:
['[유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.',
 '(제목없음)',
 '(제목없음)',
 '(광고) 로또1등담첨 예상번호 무료로 받아가세요~',
 '(광고) 성공을 위한 1인무점포 창업과 다양한 창업아이템 설명회 안내',
 '(광고) 더 이상 채.무. 로 고통받지 마세요',
 '(광고) 이번 Apple 스페셜 이벤트에서 발표된 놀라운 소식을 살펴보세요.',
 '2019 Adobe Design Achievement Awards의 작품 응모가 시작되었습니다!',
 '(광고)[몰테일]4월의 시작~ 몰테일의 이벤트와 함께 Start',
 '(광고) 이차민님, ♥5,000원쿠폰 도착!',
 '이차민님, "회식의 신" 페이지 방문자를 위해 게시물을 작성해보세요.',
 'New! Degrees & MasterTrack Certificates in Data Science, Computer Science, and more',
 '[매일경제] 로이킴, 음란물 유포 혐의 입건…소속사 “모르던 상황”',
 '🎂 오늘은 손석범님과 이시현님의 생일입니다']
In [39]:
trainingSet = list()

for t in spamList:
    trainingSet.append((t,'spam'))

for t in hamList:
    trainingSet.append((t,'ham'))
In [40]:
trainingSet
Out[40]:
[('[유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.', 'spam'),
 ('(제목없음)', 'spam'),
 ('(제목없음)', 'spam'),
 ('(광고) 로또1등담첨 예상번호 무료로 받아가세요~', 'spam'),
 ('(광고) 성공을 위한 1인무점포 창업과 다양한 창업아이템 설명회 안내', 'spam'),
 ('(광고) 더 이상 채.무. 로 고통받지 마세요', 'spam'),
 ('(광고) 이번 Apple 스페셜 이벤트에서 발표된 놀라운 소식을 살펴보세요.', 'spam'),
 ('2019 Adobe Design Achievement Awards의 작품 응모가 시작되었습니다!', 'ham'),
 ('(광고)[몰테일]4월의 시작~ 몰테일의 이벤트와 함께 Start', 'ham'),
 ('(광고) 이차민님, ♥5,000원쿠폰 도착!', 'ham'),
 ('이차민님, "회식의 신" 페이지 방문자를 위해 게시물을 작성해보세요.', 'ham'),
 ('New! Degrees & MasterTrack Certificates in Data Science, Computer Science, and more',
  'ham'),
 ('[매일경제] 로이킴, 음란물 유포 혐의 입건…소속사 “모르던 상황”', 'ham'),
 ('🎂 오늘은 손석범님과 이시현님의 생일입니다', 'ham')]
In [41]:
trainingSetSpam = [k for k in trainingSet if k[1] == 'spam']
trainingSetHam = [k for k in trainingSet if k[1] == 'ham']
In [43]:
trainingSetSpam
Out[43]:
[('[유망창업아이템] 확인해 보시고 많은 도움이 되시길 바랍니다.', 'spam'),
 ('(제목없음)', 'spam'),
 ('(제목없음)', 'spam'),
 ('(광고) 로또1등담첨 예상번호 무료로 받아가세요~', 'spam'),
 ('(광고) 성공을 위한 1인무점포 창업과 다양한 창업아이템 설명회 안내', 'spam'),
 ('(광고) 더 이상 채.무. 로 고통받지 마세요', 'spam'),
 ('(광고) 이번 Apple 스페셜 이벤트에서 발표된 놀라운 소식을 살펴보세요.', 'spam')]
In [44]:
N = len(trainingSet)
In [45]:
priorSpam = len(trainingSetSpam) / N
priorHam = 1 - priorSpam
In [46]:
priorSpam, priorHam, priorHam + priorSpam
Out[46]:
(0.5, 0.5, 1.0)
In [59]:
# 확률 누적
from collections import defaultdict

tokenSpam = defaultdict(int)
tokenHam = defaultdict(int)

for d in trainingSetSpam:
    for t in d[0].split():
        tokenSpam[t] += 1
        
for d in trainingSetHam:
    for t in d[0].split():
        tokenHam[t] += 1
        
vocabulary = set(list(tokenSpam.keys()) + list(tokenHam.keys()))
In [895]:
# tokenSpam
In [896]:
# tokenHam
In [62]:
# 전체의 unique한 단어 set 

len(vocabulary)
Out[62]:
83
In [65]:
# 조건부 확률
sumSpam = sum(tokenSpam.values())
sumHam = sum(tokenHam.values())
In [66]:
sumSpam, sumHam
Out[66]:
(39, 51)

Add - one

In [67]:
from math import log

cpSpam = defaultdict(float)
cpHam = defaultdict(float)

B = len(vocabulary)

for t in vocabulary:
    cpSpam[t] = log((tokenSpam[t]+1) / (sumSpam + B))
    cpHam[t] = log((tokenHam[t]+1) / (sumHam + B))    
    print(t)
    print("Spam, {0} = {1}+1 / {2}+{3}".format(cpSpam[t],tokenSpam[t],sumSpam,B))
    print("Spam, {0} = {1}+1 / {2}+{3}".format(cpHam[t],tokenHam[t],sumHam,B))    
로
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Design
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
고통받지
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
놀라운
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
유포
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
설명회
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
작성해보세요.
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
(광고)[몰테일]4월의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
신"
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
생일입니다
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
예상번호
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
“모르던
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
더
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
채.무.
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
1인무점포
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
입건…소속사
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
바랍니다.
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Degrees
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
창업아이템
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
살펴보세요.
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
이벤트와
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
성공을
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
(제목없음)
Spam, -3.7054087560651467 = 2+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Computer
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
Data
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
시작되었습니다!
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
혐의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
소식을
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
New!
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
이시현님의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
음란물
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
보시고
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Certificates
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
함께
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
이벤트에서
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
게시물을
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
마세요
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
많은
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
more
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
도움이
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
위한
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
2019
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
위해
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
🎂
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
방문자를
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
상황”
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
안내
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Awards의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
MasterTrack
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
발표된
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Achievement
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
(광고)
Spam, -3.1945831322991562 = 4+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
시작~
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
♥5,000원쿠폰
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
and
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
무료로
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
로이킴,
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
페이지
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
응모가
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
Start
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
&
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
[유망창업아이템]
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
in
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
이번
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
이상
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
"회식의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
스페셜
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
작품
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
되시길
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
창업과
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
로또1등담첨
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
몰테일의
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
[매일경제]
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
받아가세요~
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Apple
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
도착!
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
이차민님,
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -3.7992275112828016 = 2+1 / 51+83
오늘은
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
다양한
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
손석범님과
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
확인해
Spam, -4.110873864173311 = 1+1 / 39+83
Spam, -4.897839799950911 = 0+1 / 51+83
Science,
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -3.7992275112828016 = 2+1 / 51+83
Adobe
Spam, -4.804021044733257 = 0+1 / 39+83
Spam, -4.204692619390966 = 1+1 / 51+83
In [112]:
canList = list()
testSet = list()
for tag in driver.find_elements_by_css_selector('strong.mail_title'):
    canList.append(tag.text)

# 하나만 추출 
testSet.append((canList[-2]))

print(type(testSet)),print(testSet)
<class 'list'>
['[매일경제] 발리의 불이 꺼졌다…발리의 별이 켜졌다']
Out[112]:
(None, None)

Add - one 결과

In [116]:
from math import log, exp

for d in testSet:
    scoreSpam = log(priorSpam)
    scoreHam = log(priorHam)
    
    for t in d.split():
        scoreSpam += cpSpam[t]
        scoreHam += cpHam[t]
        
    print(exp(scoreSpam), exp(scoreHam))
    print("확률 차이 : {0}".format(scoreHam-scoreSpam))
    if scoreSpam > scoreHam:
        print("It's Spam")
    else:
        print("It's Ham")
0.006250000000000002 0.014423076923076929
확률 차이 : 0.8362480242006187
It's Ham

Laplace Smoothing

In [114]:
from math import log

cpSpam = defaultdict(float)
cpHam = defaultdict(float)

K = 0.5

for t in vocabulary:
    cpSpam[t] = log((tokenSpam[t]+K) / (sumSpam + 2*K))
    cpHam[t] = log((tokenHam[t]+K) / (sumHam + 2*K))    
    print(t)
    print("Spam, {0} = {1}+1 / {2}+{3}".format(cpSpam[t],tokenSpam[t],sumSpam,B))
    print("Spam, {0} = {1}+1 / {2}+{3}".format(cpHam[t],tokenHam[t],sumHam,B))    
로
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Design
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
고통받지
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
놀라운
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
유포
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
설명회
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
작성해보세요.
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
(광고)[몰테일]4월의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
신"
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
생일입니다
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
예상번호
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
“모르던
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
더
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
채.무.
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
1인무점포
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
입건…소속사
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
바랍니다.
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Degrees
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
창업아이템
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
살펴보세요.
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
이벤트와
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
성공을
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
(제목없음)
Spam, -2.772588722239781 = 2+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Computer
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
Data
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
시작되었습니다!
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
혐의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
소식을
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
New!
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
이시현님의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
음란물
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
보시고
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Certificates
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
함께
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
이벤트에서
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
게시물을
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
마세요
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
많은
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
more
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
도움이
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
위한
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
2019
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
위해
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
🎂
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
방문자를
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
상황”
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
안내
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Awards의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
MasterTrack
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
발표된
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Achievement
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
(광고)
Spam, -2.184802057337662 = 4+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
시작~
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
♥5,000원쿠폰
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
and
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
무료로
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
로이킴,
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
페이지
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
응모가
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
Start
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
&
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
[유망창업아이템]
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
in
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
이번
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
이상
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
"회식의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
스페셜
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
작품
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
되시길
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
창업과
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
로또1등담첨
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
몰테일의
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
[매일경제]
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
받아가세요~
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Apple
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
도착!
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
이차민님,
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.0349529867072724 = 2+1 / 51+83
오늘은
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
다양한
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
손석범님과
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
확인해
Spam, -3.283414346005772 = 1+1 / 39+83
Spam, -4.6443908991413725 = 0+1 / 51+83
Science,
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.0349529867072724 = 2+1 / 51+83
Adobe
Spam, -4.382026634673881 = 0+1 / 39+83
Spam, -3.545778610473263 = 1+1 / 51+83
In [117]:
from math import log, exp

for d in testSet:
    scoreSpam = log(priorSpam)
    scoreHam = log(priorHam)
    
    for t in d.split():
        scoreSpam += cpSpam[t]
        scoreHam += cpHam[t]
        
    print(exp(scoreSpam), exp(scoreHam))
    print("확률 차이 : {0}".format(scoreHam-scoreSpam))    
    if scoreSpam > scoreHam:
        print("It's Spam")
    else:
        print("It's Ham")
0.006250000000000002 0.014423076923076929
확률 차이 : 0.8362480242006187
It's Ham

2. Naive Bayes 문서 분류기

In [763]:
import os

def getFileList(base='./', ext='.txt'):
    fileList = list()
    
    for file in os.listdir(base):
        if file.endswith(ext): # == if file.split('.')[-1] == ext:
            fileList.append('{0}/{1}'.format(base, file))
            
    return fileList
In [764]:
def getContent(file):
    with open(file, encoding='utf-8') as f:
        content = f.read()
    
    return content
In [765]:
cat = getFileList('./News')
catList = list()
for c in cat:
    v = c.split('/')
    v2 = v[2].split('_')
    catList.append(v2[0])
    catList = list(set(catList))
In [766]:
catList
Out[766]:
['정치', '생활문화', '사회', '세계', 'IT과학', '경제']
In [767]:
import os
corpus = list()
for file in os.listdir("./News"):
    for cat in catList:
        if file.startswith(cat):
            with open("./News/" + file, encoding='utf-8') as f:
                corpus.append([f.read(),cat])
In [768]:
trainingSet = corpus
In [769]:
# 카테고리 : 정치
testSet =  [("'긴장 상존' 서부·중부전선 GP까지 개방…'해빙' 흐름 유지노력 일환인듯\
'대북통보 및 동의·유엔사 승인 절차 없이 서둘러 정책 발표' 지적도\
北 '9·19 군사합의' 이행 소극적인 상황서 추진하는 점도 논란 소지 \
둘레길로 개방되는 DMZ(파주=연합뉴스) 임병식 기자 = 정부는 3일 행정안전부, 문화체육관광부, 통일부, 국방부, 환경부 등 5개 부처 합동 브리핑을 열고 비무장지대(DMZ)와 연결된 3개 지역(경기 파주·강원 철원·강원 고성)을 'DMZ 평화둘레길'로 조성한다고 발표했다. 이 가운데 파주는 임진각에서 시작해 도라전망대를 거쳐 9·19 남북군사합의에 따라 철거한 GP 현장까지 방문하는 구간이다. 사진은 3일 도라전망대에서 외국인 관광객들이 기념촬영하는 모습. andphotodo@yna.co.kr\
(서울=연합뉴스) 김호준 기자 = 정부가 3일 발표한 '비무장지대(DMZ) 평화둘레길'은 민간인 관광객이 남북간 군사적 긴장이 상존하는 DMZ에 진입해 시범철수 GP(감시초소) 혹은 비상주 GP를 방문하는 관광코스다.\
관광 프로그램은 군사분계선(MDL) 이남에서만 이뤄지는 것이긴 하다. 그러나 '9·19 군사합의'에 따라 남북이 DMZ 내 GP 11개씩을 시범철수하고도 여전히 북측 150여개, 남측 50여개의 GP에서 중무장한 장병들이 경계를 서고 있어 관광객의 DMZ 진입에 따른 안전 문제가 숙제로 제기되고 있다. \
아울러 관광객들이 전방지역의 민간인통제선을 넘어 DMZ까지 들어섬에 따라 국민의 생명과 안전을 책임져야 할 군의 경계부담이 커질 수 있다는 우려도 나온다. \
정부는 이날 ▲경기도 파주에 있는 임진각에서 출발해 도라전망대를 경유해 시범철수 파주GP까지 방문하는 서부전선 코스 ▲강원도 철원 백마고지 전적비에서 출발해 DMZ 내 화살머리고지까지 방문하는 중부전선 코스 ▲통일전망대에서 출발해 금강산전망대를 견학하고 복귀하는 동부전선 코스 등 'DMZ 평화둘레길'을 단계적으로 민간에 개방한다고 밝혔다. \
서부전선과 중부전선은 DMZ 안으로 진입하는 코스이고, 동부전선은 DMZ 남방한계선(철책) 부근까지만 접근하는 관광코스다.\
정부는 이달 말부터 GOP(일반전초) 철책선 이남의 고성지역(동부전선)을 대상으로 시범운영을 시작하고, 파주(서부전선)와 철원(중부전선) 지역 둘레길도 방문객 접수를 위한 준비가 마무리 되는대로 이어서 개방할 예정이다. \
당초 DMZ 안으로 진입하는 서부전선과 중부전선 코스도 이달부터 개방할 예정이었으나 관광객 안전 문제 등을 보완해 시행키로 했다. 서부전선과 중부전선 둘레길 개방시기는 5~6월로 예상된다. \
국방부는 '군(軍)은 확고한 군사대비 태세를 갖춘 가운데 경계작전에 지장이 없는 범위 내에서 방문객의 견학이 가능토록 조치했다'며 '개방되는 GP는 철거된 GP 또는 비상주 GP로, 현행 작전에 영향을 주지 않는 지역'이라고 설명했다. \
국방부는 또한 '경호지원도 군단 특공연대에서 제공해 현행 작전부대의 부담을 최소화했다'며 '특히, DMZ 내 이동 때는 군 경호 아래 차량으로 단체 이동하는 등 철저한 안전관리 대책을 마련하고 있다'고 강조했다. \
문 대통령, 화살머리 GP 방문(철원=연합뉴스) 배재만 기자 = 문재인 대통령이 28일 강원도 철원 화살머리 GP를 방문, 동행한 장병들을 격려하고 있다. 2018.12.28 scoop@yna.co.kr\
관광객이 3중 철책이 설치된 DMZ 남방한계선을 통과해 GP까지 이동할 때는 차량으로 이동하지만, 철거 GP와 비상주 GP에 도착해서는 차량에서 내려 북측 지역을 조망하게 된다. \
문제는 GP에 도착해 하차했을 때 여전히 운영되는 북측 GP 중화기에 노출된다는 점이다. 관광객이 방문하게 될 파주 철거 GP와 지금도 운영되는 가장 가까운 북측 GP와의 거리는 1.5㎞ 이내로 북측 GP에 배치된 고사총의 사거리 안에 들어온다. \
아울러 DMZ 남북 장병이 지금도 수색·매복 작전을 수행하는 지역이기 때문에 관광객이 DMZ 남측지역을 차량으로 이동하는 중에도 군사적 위협에 노출될 가능성을 완전히 배제할 수 없다. \
게다가 GP 혹은 GOP(일반전초)에서 근무하는 국군 장병들도 관광객의 유출입에 따라 북한군의 동향에 촉각을 곤두세워야 하므로 경계부담이 늘어날 수밖에 없다. 어떤 상황이 벌어질지 장담할 수 없기 때문에 매일 전방의 북한군 동향을 면밀히 살펴야 한다. \
국방부는 이번 DMZ 평화둘레길은 지난해 체결된 9·19 군사합의 이후 남북 간에 쌓아온 신뢰를 전제로 한 사업이라고 설명하나 올해 들어 군사합의는 북한의 소극적인 태도로 원활히 이행되지 않고 있다. \
남북이 군사합의를 통해 4월 1일부터 화살머리고지에서 시작하기로 약속한 DMZ 남북공동유해발굴도 북한이 호응하지 않아 남측 단독으로 해당 지역에서 기초 유해발굴 작업을 진행 중이다. \
DMZ 남북공동유해발굴 북측 무응답 (PG)[정연주 제작] 일러스트\
우리 정부가 DMZ 평화둘레길 사업을 발표하기 전에 북측에 통보해 동의를 얻는 절차가 없었고, 정전협정에 따라 DMZ를 관할하는 유엔군사령부의 승인을 받지 않은 것도 문제로 지적된다. \
국방부 당국자는 '우리 지역에서 안보 견학을 하는 것이기 때문에 북한에 통보할 의무가 있는 사항은 아니다'면서 ''(북측 통보) 필요성도 검토하겠다'고 말했다. \
군 당국은 DMZ로 진입하는 서부전선과 중부전선 코스는 유엔사와 협의를 마치고 민간에 개방할 방침인 것으로 전해졌다. \
이 당국자는 유엔사 승인 문제에 대해서는 '유엔사와 협의를 진행 중'이라며 '유엔사도 안전에 문제가 없다는 것만 확인되면 승인절차에는 문제가 없다는 게 기본 입장'이라고 전했다. \
물론 국방부도 민간인 DMZ 관광의 안전을 100% 장담할 수는 없다는 입장이다. 이 때문에 군 당국은 DMZ 평화둘레길의 코스와 관광 방식을 결정하는 과정에서 안전 우려를 최소화할 것을 정부에 건의한 것으로 알려졌다. \
국방부 관계자는 ''(DMZ 평화둘레길 관광이) 100% 안전하다고 군인 입장에서는 말씀드릴 수는 없지만, GP 후방지역(DMZ 남측지역)이기 때문에 안전이 확보된 지역이라고 생각하면 된다'고 말했다. \
이 관계자는 안전장비와 관련해서는 '민수용 방탄복과 방탄 헬멧을 경호차량에 휴대하고 가게 된다'고 설명했다. \
도라전망대에서 바라본 개성공단(파주=연합뉴스) 임병식 기자 = 3일 경기도 파주시 서부전선 비무장지대(DMZ) 도라전망대에서 바라본 개성공단의 모습. andphotodo@yna.co.kr\
군 당국은 관광객이 GP에 도착해 차량에서 내릴 때는 방탄복과 헬멧을 지급할 방침인 것으로 전해졌다. \
이 프로그램은 단순한 관광 프로젝트를 넘어 2월 북미정상회담 결렬 이후 한반도 정세의 불확실성이 커진 상황에서 한국 주도로 한반도 긴장 완화의 분위기를 이어가는 노력의 일환으로 보이는 측면이 있다. 아울러 향후 북미협상의 방향을 고민하는 북미 양측과 국제사회를 향해 한반도 평화의 흐름에 지속 동참하기를 촉구하는 메시지를 전하는 목적이 내포됐을 수 있다는 평가도 나온다.\
국방부는 '남북 분단의 상징이었던 GOP 이북 DMZ를 일반 국민에게 최초로 개방하는 조치'라며 '한반도 평화정착을 향한 국민적 공감대가 확산하기를 기대한다'고 DMZ 평화둘레길 사업 추진 배경을 설명했다. \
둘레길로 개방되는 비무장지대(파주=연합뉴스) 임병식 기자 = 정부는 3일 행정안전부, 문화체육관광부, 통일부, 국방부, 환경부 등 5개 부처 합동 브리핑을 열고 비무장지대(DMZ)와 연결된 3개 지역(경기 파주·강원 철원·강원 고성)을 'DMZ 평화둘레길'로 조성한다고 발표했다. 이 가운데 파주는 임진각에서 시작해 도라전망대를 거쳐 9·19 남북군사합의에 따라 철거한 GP 현장까지 방문하는 구간이다. 사진은 지난 2월 촬영한 장단면사무소의 모습이며 둘레길을 따라 철거한 GP로 이동하면서 이 건물을 볼 수 있다. 1934년에 지어진 장단면사무소는 일제시대 때 장단 지역의 행정 업무를 맡았으며 현재 한국전쟁 당시 총탄 흔적을 가진 채 DMZ 안에 남아 있다. andphotodo@yna.co.kr\
그럼에도 군 일각에선 DMZ 내 GP가 모두 철거되는 수준으로 9·19 군사합의가 이행되는 단계에서 시작해도 늦지 않을 텐데 정부가 너무 서둘러 DMZ 평화둘레길 관광을 시작하려 한다는 의견도 제기된다. \
지난 2월 말 2차 북미정상회담 결렬 이후 한반도 비핵화와 평화정착을 목표로 한 남북 및 북미 대화도 교착상태인 터에 굳이 DMZ 평화둘레길 관광을 현시점에서 추진할 필요가 있느냐는 지적도 있다.\
익명을 요구한 군의 한 관계자는 '2008년 7월 금강산 관광객 고(故) 박왕자씨가 북한군 초병의 총격으로 사망한 사건을 교훈 삼아 DMZ 평화둘레길 관광을 신중하게 추진할 필요가 있다고 말했다.")]
In [729]:
# 카테고리 : 사회 
testSet = [("인상착의 비슷한 '여장남자' 목격담…경찰 미제팀 ‘전력 수사’\
'포천 여중생 살인사건' 용의자(?)(포천=연합뉴스) 권숙희 기자 = 2004년 발생한 '포천 여중생 살인사건' 관련, 당시 유사한 사건의 피해를 입을 뻔했다고 주장하는 여성의 기억을 토대로 제작된 몽타주. [경기북부지방경찰청 제공]\
(의정부=연합뉴스) 권숙희 기자 = 경기도 포천시에서 90여일간 실종됐다가 싸늘한 주검으로 발견된 여중생 엄모양 살인사건의 실마리가 15년 만에 풀릴까.\
지난달 30일 SBS TV프로그램 '그것이 알고싶다'에서 이 사건을 방영, 미제 살인사건의 용의자일 가능성이 있는 한 남성의 몽타주를 공개하면서 세간의 관심이 쏠리고 있다.\
3일 경기북부지방경찰청 미제사건전담수사팀에 따르면 최근 사흘간 몽타주와 인상착의가 비슷한 사람을 봤다는 112신고 전화 등이 총 10건 접수됐다.\
내용은 주로 '몽타주와 인상착의가 비슷한 여장남자를 목격했다'는 등 서로 비슷했다.\
'포천 여중생 살인사건'은 2004년 2월 8일 경기도 포천시 소흘읍의 한 배수로에서 실종된 지 3개월이 지난 엄모(당시 15세)양이 얼굴에서 가슴까지 훼손돼 형체를 알아보기 어려운 상태로 숨진 채 발견된 사건이다.\
엄양의 손톱과 발톱에 붉은색 매니큐어가 칠해진 것이 특징으로, '포천 매니큐어 살인사건'으로도 불렸다.\
당시 경찰 수사본부는 1년간이나 대대적인 수사를 벌였으나 현장 주변의 폐쇄회로(CC)TV는 물론, 다른 단서나 제보도 없어 결국 미제 사건으로 남게 됐다.\
그러던 중 15년 만에 자신이 유력한 목격자일 수도 있다고 주장하는 시민이 나타났다.\
지난달 7일 새벽, 사건 당시 대학생이던 한 여성이 112에 직접 신고 전화를 했다.\
경찰은 다음날 바로 이 여성과 면담을 진행했으며, 단서 수집에 나섰다. \
이 여성은 경찰에 엄모양이 실종되던 시기 자신도 '흰색 차량'에 의해 납치될 뻔했으며, 그 사건을 겪은 후 얼마 지나지 않아 동네에 엄모양 실종 관련 현수막이 내걸린 것을 봤다고 진술했다.\
이 여성은 당시 차에서 가까스로 탈출해 위기를 모면했으며, 15년이 지나 스마트폰으로 인터넷을 하다가 우연히 '포천 여중생 살인사건' 관련 게시물을 접한 뒤 급하게 제보를 하게 됐다고 덧붙였다.\
몽타주는 이 여성의 기억을 토대로 그려졌다.\
'포천 여중생 살인사건' 현장감식[연합뉴스 자료사진]\
방송 이후 쏟아진 신고 전화 중에 아직 결정적인 제보는 접수되지 않았으며, 전반적인 검토 작업을 하고 있다. \
또 해당 남성이 유력 용의자가 아닐 가능성도 배제할 수 없는 상황에서, 인권 침해의 여지 등을 고려할 때 목격담만으로 전부 용의선상에 올릴 수도 없기 때문이다.\
한편, 이 사건을 포함해 총 13건의 미제사건을 전담하고 있는 경기북부 수사팀의 현재 인원도 4명밖에 없어, 서울(11명), 경기남부(7명), 부산(6명) 등과 비교하면 부족한 편이다. \
2004년 이 사건이 전국적인 관심을 받을 당시 범인 검거에 부담을 느낀 포천경찰서 강력1반장 윤모(47) 경사가 스스로 목숨을 끊는 일도 있었다."

)]
In [664]:
# 카테고리 : 생활문화
testSet = [("일본 도쿄(東京)에는 동물을 보고 만질 수 있는 동물카페가 많다. 우리나라에는 방송에서 연예인들이 동물카페를 방문한 장면들이 나오면서 알려졌다. 일본 관광책자에도 동물카페 소개를 찾아보긴 어렵지 않다. 도쿄 동물카페의 특징은 동물 종류가 각양각색이라는 점이다. 개나 고양이뿐 아니라 부엉이, 고슴도치, 토끼 등으로 특화되어 있다. 도쿄의 번화가 중 하나인 이케부쿠로(池袋)에는 펭귄에게 먹이를 주는 카페가 있을 정도다.\
젊은층과 관광객으로 발 디딜 틈이 없는 하라주쿠(原宿)역 부근, 관광객들에게 인기가 있다는 부엉이 카페를 찾았다. 일본에선 부엉이를 뜻하는 후쿠로(ふくろう) 발음이 복을 뜻하는 후쿠(ふく)와 비슷하고 영화 해리포터에 등장하는 부엉이의 영향으로 부엉이 인기가 많다고 한다. \
온라인에서 예약을 하지 않으면 오래 기다릴 수 있다고 해서 1주일 전 예약을 했다. 평일 오후 2시에 모인 입장객 11명 대부분은 외국인이었다. 1시간 이용하는 데 드는 비용은 1,500엔(약 1만5,000원). 15분은 음료를 마시고, 35분은 부엉이가 있는 데로 들어가 사진을 찍거나 만지고, 이후엔 짐 정리를 하는 식이었다. \
유리문으로 분리된 부엉이 공간은 손님들이 서 있기에 비좁았다. 곧바로 부엉이 11마리에 대한 소개가 시작됐는데 대부분 어디를 만지면 안 된다는 내용이었다. 하지만 너무 빠르게 진행되는 터라 사실 어떤 부엉이가 어떻다는 건지 기억이 나지 않았다.\
일본 도쿄 하라주쿠(原宿)의 한 부엉이 카페에서 손님이 부엉이에게 밥을 주는 체험을 하고 있다. 고은경기자\
일본 도쿄 하라주쿠(原宿)에 있는 부엉이카페에 있는 부엉이. 날아가지 못하도록 발에 줄을 묶어 놓았다. 고은경기자\
다만 부엉이들이 스트레스를 받는 건 그 자리에서도 알 수 있었다. 계속 지지대 위에서 떨어지던 부엉이 한 마리는 결국 커튼 뒤에서 휴식을 취해야 했다. 덩치가 큰 부엉이들이 인기가 많아 아침부터 시달려서인지 주의를 기울여달라고 했다. 그렇다고 만지지 못하게 하거나 사진을 찍지 못하게 할 수는 없었기 때문에 손님들은 큰 부엉이를 손에 앉혔지만 결국 부엉이는 큰 날갯짓을 하며 떨어졌다. 창 밖만 바라보는 부엉이도 있었고 겁에 질려 계속 눈만 껌뻑 거리는 부엉이도 있었다. 날아가지 못하도록 발은 모두 고리에 묶인 채였다. 보통 부엉이 카페를 찾는 사람은 하루에 50~60명. 부엉이들의 ‘고단한’ 하루는 오전 11시부터 오후 8시까지 매 시간 계속됐다. 일본 동물카페 사이트인 애니멀즈닷컴에 따르면 도쿄 근처에 있는 부엉이 카페만 10여곳, 고양이, 토끼, 개 등을 포함하면 50곳이 넘는다.\
일본 내 동물단체와 외신들은 특히 부엉이 카페에 대한 우려를 지속적으로 제기해왔다. 부엉이 카페 운영방식은 야행성 동물인 부엉이의 습성과 정면으로 배치된다. 더욱이 시력과 청력이 좋고 사냥을 하는 본능이 있는데 좁은 공간에 가둔 채 체험에 동원되는 게 심각한 문제라는 것이다. \
기자가 지난 25일 일본 도쿄 하라주쿠(原宿)에 있는 부엉이카페에서 부엉이 한 마리를 손에 올려보고 있다. 고은경 기자\
하지만 부엉이를 비롯해 토끼, 고슴도치 등의 카페는 앞으로도 성행할 것으로 보인다. 일본의 대표적 동물단체인 피스(PEACE)에 따르면 일본 동물애호법에는 동물 카페 개설 조건이 있지만 까다롭지 않아 누구나 마음만 먹으면 열 수 있고, 시설 조건이나 동물 관리방법 등에 대해서도 다루지 않고 있기 때문이다. 또 동물애호법 개정을 앞두고 있지만 일본 환경부는 개와 고양이 이외 다른 동물에 대해서는 기준 마련을 미루고 있다고 했다. \
우리나라도 사정은 다르지 않다. 야생동물을 카페에서 전시하지 못하게 하는 이른바 라쿤카페 금지법이 발의되어 있지만 국회에서 계류 중이다. ‘동물은 괴로운’ 동물카페가 한국에서도 일본에서도 사라지는 날이 오기를 바란다.")]
In [885]:
# 카테고리 : IT과학

testSet = [("간편결제 이용건수·금액도 급증 \
휴대폰 송금[연합뉴스TV 캡처] \
(서울=연합뉴스) 정수연 기자 = 토스, 네이버페이, 카카오페이 등 스마트폰을 통한 간편송금 서비스의 하루평균 이용금액이 1년 만에 3배 가까이로 늘었다.\
한국은행이 3일 발표한 '2018년중 전자지급서비스 이용 현황'을 보면 지난해 간편송금 서비스 이용금액(이하 하루평균)은 1천45억원으로 전년보다 194.1% 증가했다.\
이용 건수는 141만건으로 102.5% 늘었다.\
※ 자료 : 한국은행\
간편송금은 스마트폰에 충전한 선불금을 전화번호나 소셜네트워크서비스(SNS) 등을 활용해 송금하는 서비스를 말한다.\
한은 관계자는 '지난해 토스와 카카오페이가 크게 성장하면서 간편송금 이용금액과 건수가 늘었다'고 설명했다.\
공인인증서나 OTP 없이 비밀번호 등을 이용해 결제하는 간편결제 서비스 규모도 두 배 가까이 성장했다. \
지난해 간편결제 이용금액은 하루평균 1천260억원으로 전년보다 86.2% 늘었다.\
이용 건수도 87.5% 증가한 392만건으로 조사됐다.\
[그래픽] '○○페이'로 송금한 돈 3배로 증가\
간편결제·송금 서비스를 합한 이용금액은 하루평균 2천306억원, 건수는 533만건이다.\
카카오페이, 네이버페이 등 정보·통신(ICT) 분야와 스마일페이, SSG 페이 등 유통·제조 분야 간편결제 서비스도 성장세를 이어갔다.\
온라인쇼핑이 늘어난 영향으로 전자지급결제대행(PG) 서비스 이용금액이 하루평균 4천123억원으로 25.8% 불어났다.\
이용 건수는 29.8% 증가한 826만건으로 집계됐다.\
PG는 전자상거래에서 구매자에게 받은 대금이 판매자에게 지급될 수 있도록 지급결제 정보를 송수신하는 서비스다. 온라인쇼핑이 늘어나면 자연스레 PG 서비스 이용 규모도 확대한다. \
토스 및 선불교통카드 등이 포함된 선불전자지급서비스 규모는 1천428억원, 1천635만건으로 각각 116.4%, 9.1% 늘었다.\
한은 관계자는 '간편송금을 중심으로 증가세가 확대해 전체 선불전자지급서비스 이용 규모가 늘어났다'고 설명했다.\
오픈마켓이 포함된 결제대금 예치 이용금액은 697억원, 건수는 146만건으로 각각 15.1%, 15.3% 증가했다.\
아파트 관리비를 이메일 등 전자 방식으로 발행한 다음 대금을 직접 수수하고 정산을 대행하는 서비스인 전자고지 결제서비스도 늘었다.\
전자고지 결제서비스 이용금액은 29.9% 늘어난 278억원, 건수는 26.6% 증가한 16만건으로 나타났다.\
직불전자지급 서비스 이용금액은 140.2% 증가한 1천564만원으로 나타났다. 이용 건수는 81.5% 늘어난 698건으로 조사됐다.\
직불전자지급 서비스란 스마트폰 인증 절차를 거쳐 편의점 등을 이용할 때 이미 등록된 구매자 계좌에서 판매자 계좌로 자금 이체를 중계하는 서비스를 말한다.")]
In [872]:
# 카테고리 : 경제 
testSet = [("미중 무역분쟁에 세계 경기 둔화 영향\
전문가들 '올해 코스피 이익 정체 또는 감소 전망…하반기 회복 기대'\
작년 상장사 외형 커졌지만 이익은 부진…순이익 112조원 (CG)[연합뉴스TV 제공]\
(서울=연합뉴스) 임미나 기자 = 지난해 코스피와 코스닥 상장사들이 매출은 늘었지만, 이익은 부진했던 것으로 나타났다.\
재작년에 상장사들이 역대 최대 실적을 달성한 데 이어 지난해에도 상승세를 이어갈 것으로 당초 기대됐으나, 반도체 부문 실적이 작년 4분기부터 급감하면서 영업이익은 제자리 수준에 머물렀고 순이익은 소폭 줄었다. \
증시 전문가들은 세계 경기 둔화 흐름 속에 반도체 수출이 올해 상반기까지 부진할 전망이어서 올해 국내 기업의 이익이 작년과 비슷하거나 더 줄어들 것으로 예상했다.\
다만 상반기 기업들의 이익 수준이 바닥을 통과해 하반기에 회복세를 보일 가능성이 있다고 진단했다.\
◇ 경기 둔화·반도체 업황 4분기 추락에 이익 감소\
코스피 상장사는 매출과 영업이익이 작년보다 소폭 늘었지만 순이익은 줄었다.\
3일 한국거래소와 한국상장회사협의회가 12월 결산 코스피 상장사 540개사(금융업 제외)의 연결 실적을 분석한 결과 지난해 매출은 1천894조7천억원으로 전년보다 4.76% 증가했다.\
영업이익도 157조7천억원으로 0.32% 늘었으나, 당기순이익은 108조원으로 6.72% 줄었다.\
코스닥 상장사는 매출만 늘고 영업이익과 순이익은 줄었다.\
거래소와 코스닥협회가 분석한 911개 코스닥 기업의 작년 연결기준 매출은 169조1천억원으로 전년보다 4.69% 늘었다.\
그러나 영업이익과 순이익은 8조4천억원과 4조3천억원으로 각각 11.58%, 8.66% 감소했다.\
코스피와 코스닥 기업을 합친 상장사 순이익은 112조3천억원으로 전년의 120조5천억원보다 6.8% 줄었다.\
조용준 하나금융투자 리서치센터장은 '지난해 세계 경기 성장세가 둔화했고 미국과 중국의 무역분쟁으로 교역량이 급감하면서 국내 수출기업들의 실적이 부진했다'며 '특히 4분기부터 반도체 실적이 크게 하락한 탓이 크다'고 분석했다.\
이창목 NH투자증권 리서치센터장도 '재작년에 코스피 영업이익이 사상 최대를 기록하면서 작년에도 그 이상이 나올 거라고 당초 예상했으나 결과는 좋지 않았다'며 '반도체 부문 이익이 4분기로 갈수록 점점 줄어든 것이 큰 영향을 줬다'고 말했다. \
기업들의 이익지표도 전년보다 나빠졌다.\
코스피 상장사들의 매출액 영업이익률은 8.32%로 전년보다 0.37%포인트, 매출액 순이익률은 5.70%로 0.70%포인트 각각 하락했다.\
코스닥 상장사의 경우에도 영업이익률이 4.98%, 순이익률이 2.55%로 각각 0.92%포인트, 0.38%포인트 낮아졌다.\
정보기술(IT)·반도체 등 일부 업종에 이익 성장세가 쏠리는 현상도 여전했다.\
코스피 상장사 전체 매출 중 12.87%를 차지하는 삼성전자를 제외할 경우 전체 매출액은 1천650조원으로 전년보다 5.22% 증가했으나, 영업이익은 98조8천억원으로 4.57% 줄어 마이너스로 반전했다.\
삼성전자를 제외한 순이익도 63조6천억원으로 13.51% 줄어 삼성전자 포함 시보다 감소율이 약 2배로 심해졌다.\
코스닥 시장에서는 정보기술(IT)업종이 상대적으로 호조를 보였다.\
연결기준으로 IT업종 344개사의 작년 매출액은 4.21% 늘었고 순이익은 18.0% 증가했다.\
반면 나머지 업종 567개사의 매출액은 4.95% 증가했으나, 순이익은 22.52% 감소했다.\
◇ 올해도 코스피·코스닥 이익 정체될 전망\
증시 전문가들은 대체로 올해도 상장사의 실적이 좋지 않을 것으로 봤다. \
미중 무역협상이 당장 타결될 조짐이 보이지 않고 반도체 업황도 상반기까지 침체를 지속해 수출이 회복되기 어렵다는 진단이다.\
오현석 삼성증권 리서치센터장은 '미중 무역분쟁 여파가 상반기까지 반영될 것'이라며 '반도체 이익이 반 토막 이상 급감할 가능성이 커 연간으로 보면 코스피 이익은 작년보다 감소한다고 봐야 할 것'이라고 말했다.\
이창목 센터장도 '올해는 코스피 이익이 작년보다 더 감소할 가능성이 있다'며 '반도체 등 수출량이 감소할 것이 확실해 실적 부진에 영향을 줄 것'이라고 내다봤다.\
고태봉 하이투자증권 리서치센터장은 '올해 코스피 영업이익은 작년보다 15%가량 감소할 것으로 예상한다'며 '세계 경기 하강과 수출주 중심 경기민감주의 부진 등의 영향이 클 것'이라고 분석했다.\
코스피 이익이 하반기부터 회복 추세로 돌아서서 연간 이익은 작년과 비슷한 수준을 보일 것이란 전망도 있다.\
조용준 센터장은 '세계 경기가 연착륙할 가능성이 커지고 각국의 경기부양책도 서서히 효과가 나타나면서 하반기에는 기업들의 실적이 반등할 가능성이 있다'고 전망했다.\
조 센터장은 '반도체 업황도 하반기부터 회복되면서 올해 연간으로 보면 기업 이익이 작년과 비슷하게 유지되거나 소폭 감소할 것으로 보인다'고 덧붙였다.\
코스닥 상장사들도 대기업과 연계된 부품업체들의 이익 감소가 불가피해 실적이 부진할 것으로 관측됐다.\
이창목 센터장은 '코스닥 역시 대기업과 연결된 업체들이 많아서 1∼2분기에 실적이 좋지 않을 것으로 본다'며 '다만 코스닥 주가는 당장의 실적보다 미래에 대한 전망이 크게 영향을 주는 만큼 올해 실적 부진이 증시에 미치는 영향은 제한적일 것'이라고 말했다.")]
In [863]:
# 카테고리 : "세계"

testSet= [("손님을 사정없이 ‘밟아’ 회복불능으로 다치게 한 태국 마사지사가 벌금형을 선고받았다. 2일 말레이시아 매체 월드오브버즈는 지난해 12월 태국 유명 마사지사에게 마사지를 받고 장애를 얻은 프라놈 티엥트롱(46·여성)의 사연을 소개했다. \
태국 동남부 라용에 있는 한 마트에서 식품 판매원으로 일하는 티엥트롱은 몇 달간 계속된 다리와 엉덩이 통증으로 ‘해피 박사’라 불리는 마사지사 키아티삭 차이위몬(21)을 찾았다. 차이위몬은 족도법(발로 밟는 마사지)으로 수천 명을 치료하는 등 인근에서 꽤 알아주는 마사지사였다. \
차이위몬은 티엥트롱을 매트 위에 엎드리게 한 뒤 아픈 다리와 엉덩이를 살폈다. 엉덩이 관절이 탈구된 것이라고 진단한 그는 이내 뼈를 맞추기 위해 티엥트롱의 다리를 밟기 시작했다. \
티엥트롱은 거구의 남성이 밟는 무게를 견디기 힘들었지만, 모든 게 ‘치료 과정’이라고 생각하고 꾹 참았다. \
그러나 문제는 차이위몬이 그의 대퇴부(엉덩관절과 무릎관절을 잇는 넓적다리)를 밟았을 때 발생했다. 참을 수 없는 고통에 비명을 지른 티엥트롱은 '너무 아프다. 그만하라'고 말했다. 그럼에도 차이위몬은 '이쪽이 탈구돼서 그렇다. 뼈를 맞추고 있으니 조금만 참아라'고 다독이며 계속해서 마사지를 이어갔다. \
1시간여의 마사지를 마치고 집으로 돌아온 티엥트롱은 여전히 통증을 호소했다. 점점 나아질 거란 기대로 하루, 이틀 그리고 일주일을 버텼지만 오히려 상태가 더 나빠지고 있었다. 다른 사람의 도움 없이 혼자 걸을 수도 없는 지경이었다.\
이대로는 안 되겠다 싶어 이웃과 함께 병원을 찾은 그는 대퇴부가 골절되고 발목 관절이 탈구됐다는 진단을 받았다. 치료하기 위해서는 거금 13만 바트(약 470만 원)가 필요했다. 완치가 될지 여부는 불투명한 상황이다. 그는 앞으로 휠체어를 타거나 목발을 짚고 다녀야만 할 수도 있다.\
다리가 아파 한 달 가까이 일을 하지 못한 티엥트롱의 수중에는 그런 큰돈이 없었다. 남편과도 이혼해 그를 돌봐줄 사람 또한 없었다.\
티엥트롱은 이 모든 사달을 낸 차이위몬에게 책임을 묻기 위해 연락을 취했으나 묵묵부답이었다. 이후로도 계속 연락이 닿지 않자 결국 그를 경찰에 신고했다. 차이위몬은 자택에서 현장에 출동한 경찰에 의해 체포됐다.\
그는 경찰에 '티엥트롱의 뼈를 맞추기 위해 반복적으로 밟았다'며 '고통스러워했지만 뼈가 부러진 줄은 정말 몰랐다. 너무 세게 밟은 것 같다. 잘못했다'고 선처를 호소했다.\
경찰조사 결과 차이위몬은 마사지자격증이 없는 것으로 드러났다. 불법 시술 행위 및 의료시설 개설 등 혐의로 재판에 넘겨진 그는 벌금형을 선고받았다."

)]
In [834]:
# 정치
trainingSetPol = [d for d in trainingSet if d[1] == "정치"]
# 사회
trainingSetSoc = [d for d in trainingSet if d[1] == "사회"]
# 경제
trainingSetFin = [d for d in trainingSet if d[1] == "경제"]
# 세계
trainingSetWorld = [d for d in trainingSet if d[1] == "세계"]
# 생활문화
trainingSetLife = [d for d in trainingSet if d[1] == "생활문화"]
# IT과학
trainingSetIT = [d for d in trainingSet if d[1] == "IT과학"]
In [835]:
# doc의 전체 갯수 구하기
N = len(trainingSet)
N
Out[835]:
125

전처리

In [836]:
from string import punctuation
In [837]:
range(len(trainingSetPol))
Out[837]:
range(0, 20)
In [838]:
print(punctuation)
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
In [839]:
trainingSetPol[0][0].translate(str.maketrans('', '', punctuation))
Out[839]:
'\n\n\n\n\n  \n\n  김부겸 행정안전부장관이 14일 서울 여의도 국회 행정안전위원회에 출석해 얼굴을 어루만지고 있다 뉴스1           김부겸 행정안전부 장관이 정부의 개각 인사 발표 방식에 대해 “늘 하던 방식이 아닌 출신고별로 발표하는 발상은 누가 했는지 모르지만 상당히 치졸하다고 생각한다”며 비판적 태도를 보였다        김 장관은 14일 국회에서 열린 행정안전위원회 업무보고 오후 질의에서 윤재옥 자유한국당 의원의 질문에 이같이 답했다 이날 질의는 사실상 자신의 마지막 국회 업무보고다      윤 의원은 “장관 일곱 분 개각이 됐는데 TK대구ㆍ경북 출신은 한 명도 없다”며 “정략적으로 고립화한다는 지역 여론이 있다”고 했다 또 “출신 지역을 숨기고 출신고를 발표했는데 그 결과 호남 출신은 한 명도 없는 것으로 나왔으나 실제로는 4명이었다”며 “특정 지역이 소외감을 느끼는 불균형 인사는 빨리 시정돼야 한다 국회로 돌아오면 목소리를 같이 내 달라”고 질의했다      이에 김 장관은 “대한민국에서 인사를 하면 늘 그런 식으로 평가가 엇갈리게 마련이지만 그런 측면이 있더라도 한 국가의 인사에 그런 잣대를 들이대는 것은 지나치다”고 답했다 이에 김 장관은 ‘출신고 기준’ 발표 방식이 치졸하다면서 “앞으로는 제가 국회로 돌아가서 그런 문제에 앞장서겠다”고 말했다      앞서 지난 8일 문재인 대통령은 진영 의원을 새 행안부 장관에 내정했다 당시 청와대는 개각 명단을 발표하면서 이번에 처음으로 출신지를 제외하고 출생연도와 출신 고교ㆍ대학 등 주요 학력과 경력만을 공개했다      문재인 대통령이 지난 8일 7개 부처에 대한 중폭 개각을 단행했다 왼쪽 위부터 시계방향으로 중소벤처기업부장관에 내정된 박영선 더불어민주당 의원 행안부장관에 내정된 진영 더불어민주당 의원 통일부장관에 내정된 김연철 통일연구원장 국토부장관에 내정된 최정호 전 국토부 2차관 과기부장관에 내정된 조동호 카이스트 교수 해수부장관에 내정된 문성혁 세계해사대교수 문체부장관에 내정된 박양우 전 문화관광부 차관 사진 청와대           장관 후보자 중 서울 지역 고등학교 졸업자는 조동호 과학기술정보통신부 장관 후보자서울 배문고 진영 행정안전부 장관 후보자서울 경기고 문성혁 해양수산부 장관 후보자서울 대신고 박영선 중소벤처기업부 장관 후보자서울 수도여고 등 4명이다 김연철 통일부 장관 후보자는 강원 북평고 박양우 문화체육관광부 장관 후보자는 인천 제물포고 최정호 국토교통부 장관 후보자는 경북 금오공고를 나왔다 고등학교 기준으로 하면 서울 4명 인천 1명 경북 1명 강원 1명의 분포다        그러나 종전의 출생지 기준으로 재분류를 하면 전북이 3명진영ㆍ조동호ㆍ최정호이고 광주 1명박양우 부산 1명문성혁 경남 1명박영선 강원 1명김연철의 분포가 된다 청와대 발표에는 안 보이던 호남 출신이 4명이다        당시 청와대는 “지연 중심 문화를 탈피해야 한다는 데 사회의 공감대가 있다”면서 “출신지라는 게 객관적이지도 않아서 그곳에서 태어나 오랫동안 성장한 사람이 있는가 하면 출생만 하고 성장은 다른 곳에서 해온 분들도 있다 불필요한 논란을 끌지 않기 위해 이번에 고등학교 중심으로 발표했다”고 설명했다        한영혜 기자 hanyounghyejoongangcokr  ▶ 중앙일보 홈페이지  페이스북 친구추가▶ 네이버 구독 1위 신문 중앙일보ⓒ중앙일보httpsjoongangcokr 무단 전재 및 재배포 금지\n\t\n'
In [840]:
import re
PolNews = list()
SocNews = list()
FinNews = list()
WorldNews = list()
LifeNews = list()
ITNews = list()

pattern = re.compile(r'[%s]' % re.escape(punctuation))
for i in range(len(trainingSetPol)):
    trainingSetPol[i][0] = trainingSetPol[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetPol[i][0] = trainingSetPol[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    PolNews.append((trainingSetPol[i][0],trainingSetPol[i][1]))
    
for i in range(len(trainingSetSoc)):
    trainingSetSoc[i][0] = trainingSetSoc[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetSoc[i][0] = trainingSetSoc[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    SocNews.append((trainingSetSoc[i][0],trainingSetSoc[i][1]))

for i in range(len(trainingSetFin)):
    trainingSetFin[i][0] = trainingSetFin[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetFin[i][0] = trainingSetFin[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    FinNews.append((trainingSetFin[i][0],trainingSetFin[i][1]))

for i in range(len(trainingSetWorld)):
    trainingSetWorld[i][0] = trainingSetWorld[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetWorld[i][0] = trainingSetWorld[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    WorldNews.append((trainingSetWorld[i][0],trainingSetWorld[i][1]))

for i in range(len(trainingSetLife)):
    trainingSetLife[i][0] = trainingSetLife[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetLife[i][0] = trainingSetLife[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    LifeNews.append((trainingSetLife[i][0],trainingSetLife[i][1]))

for i in range(len(trainingSetIT)):
    trainingSetIT[i][0] = trainingSetIT[i][0].translate(str.maketrans('', '', punctuation))
    trainingSetIT[i][0] = trainingSetIT[i][0].replace('flash 오류를 우회하기 위한 함수 추가\nfunction flashremoveCallback', '')
    ITNews.append((trainingSetIT[i][0],trainingSetIT[i][1]))
In [841]:
# 사전 정보 구하기 prior[c]
# MLE : 주어진 데이터를 이용해 확률값 추정 
priorPol = len(PolNews) / N
priorSoc = len(SocNews) / N
priorFin = len(FinNews) / N
priorWorld = len(WorldNews) / N
priorLife = len(LifeNews) / N
priorIT = len(ITNews) / N
In [842]:
print(priorPol, priorSoc, priorFin, priorWorld, priorLife, priorIT)
print(priorPol+ priorSoc+ priorFin+ priorWorld+ priorLife+ priorIT)
0.16 0.168 0.168 0.168 0.168 0.168
1.0
In [843]:
# 확률 누적시키기 
from collections import defaultdict

tokensPol = defaultdict(int)
tokensSoc = defaultdict(int)
tokensFin = defaultdict(int)
tokensWorld = defaultdict(int)
tokensLife = defaultdict(int)
tokensIT = defaultdict(int)

for d in PolNews:
    for t in d[0].split():
        tokensPol[t] += 1
        
for d in SocNews:
    for t in d[0].split():
        tokensSoc[t] += 1
        
for d in FinNews:
    for t in d[0].split():
        tokensFin[t] += 1
               
for d in WorldNews:
    for t in d[0].split():
        tokensWorld[t] += 1
        
for d in LifeNews:
    for t in d[0].split():
        tokensLife[t] += 1
        
for d in ITNews:
    for t in d[0].split():
        tokensIT[t] += 1
        
vocabulary = set(list(tokensPol.keys()) + list(tokensSoc.keys()) + list(tokensFin.keys()) + list(tokensWorld.keys()) + list(tokensLife.keys()) + list(tokensIT.keys()))
In [844]:
len(vocabulary)
Out[844]:
20180
In [845]:
# 조건부 확률
sumPol = sum(tokensPol.values())
sumSoc = sum(tokensSoc.values())
sumFin = sum(tokensFin.values())
sumWorld = sum(tokensWorld.values())
sumLife = sum(tokensLife.values())
sumIT = sum(tokensIT.values())
In [846]:
sumPol, sumSoc, sumFin, sumWorld, sumLife,sumIT
Out[846]:
(8374, 7226, 7079, 7223, 7550, 7802)

Add - one

In [886]:
from math import log 

cpPol = defaultdict(float)
cpSoc = defaultdict(float)
cpFin = defaultdict(float)
cpWorld = defaultdict(float)
cpLife = defaultdict(float)
cpIT = defaultdict(float)

B = len(vocabulary)

for t in vocabulary:
    cpPol[t] = log((tokensPol[t]+1) / (sumPol + B))  # 1 더해서 smoothing / 분모에 1씩더하는 것은 B를 더하면 됨 
    cpSoc[t] = log((tokensSoc[t]+1) / (sumSoc + B))
    cpFin[t] = log((tokensFin[t]+1) / (sumFin + B))
    cpWorld[t] = log((tokensWorld[t]+1) / (sumWorld + B))
    cpLife[t] = log((tokensLife[t]+1) / (sumLife + B))
    cpIT[t] = log((tokensIT[t]+1) / (sumIT + B))
In [887]:
from math import log, exp

for d in testSet:
    scorePol = log(priorPol)
    scoreSoc = log(priorSoc)
    scoreFin = log(priorFin)
    scoreWorld = log(priorWorld)
    scoreLife = log(priorLife)
    scoreIT = log(priorIT)
    
    for t in d.split():
        # 원래는 곱셈인데 로그 취해서 + 가능 
        scorePol += cpPol[t]   
        scoreSoc += cpSoc[t]
        scoreFin += cpFin[t]
        scoreWorld += cpWorld[t]
        scoreLife += cpLife[t]
        scoreIT += cpIT[t]
    print(scorePol)
    
    AddScoreList = dict({"정치":scorePol,"사회":scoreSoc, "경제": scoreFin, "세계":scoreWorld, "생활문화":scoreLife, "IT과학":scoreIT})    
    print(scorePol, scoreSoc, scoreFin, scoreWorld, scoreLife, scoreIT)  # 로그 상태로 지수 취해서 원래대로 나타냄
    
    
    
# 빈도 수를 따라 training보고 판단했을 것. 
# testSet의 chinese를 하나로 줄이면 No를 반환함 
-844.2176401849878
-844.2176401849878 -816.9799469618122 -812.8597670961316 -835.5306591994145 -846.8130987093292 -794.3306575723009
In [888]:
AddScoreList
Out[888]:
{'정치': -844.2176401849878,
 '사회': -816.9799469618122,
 '경제': -812.8597670961316,
 '세계': -835.5306591994145,
 '생활문화': -846.8130987093292,
 'IT과학': -794.3306575723009}
In [889]:
key_max = max(AddScoreList.keys(), key=(lambda k: AddScoreList[k]))
key_max
Out[889]:
'IT과학'

Laplace Smoothing

In [890]:
from math import log 

cpPol = defaultdict(float)
cpSoc = defaultdict(float)
cpFin = defaultdict(float)
cpWorld = defaultdict(float)
cpLife = defaultdict(float)
cpIT = defaultdict(float)

K = 0.5

for t in vocabulary:
    cpPol[t] = log((tokensPol[t]+K) / (sumPol + K*2))  # 1 더해서 smoothing / 분모에 1씩더하는 것은 B를 더하면 됨 
    cpSoc[t] = log((tokensSoc[t]+K) / (sumSoc + K*2))
    cpFin[t] = log((tokensFin[t]+K) / (sumFin + K*2))
    cpWorld[t] = log((tokensWorld[t]+K) / (sumWorld + K*2))
    cpLife[t] = log((tokensLife[t]+K) / (sumLife + K*2))
    cpIT[t] = log((tokensIT[t]+K) / (sumIT + K*2))
In [891]:
from math import log, exp

for d in testSet:
    scorePol = log(priorPol)
    scoreSoc = log(priorSoc)
    scoreFin = log(priorFin)
    scoreWorld = log(priorWorld)
    scoreLife = log(priorLife)
    scoreIT = log(priorIT)
    
    for t in d.split():
        # 원래는 곱셈인데 로그 취해서 + 가능 
        scorePol += cpPol[t]   
        scoreSoc += cpSoc[t]
        scoreFin += cpFin[t]
        scoreWorld += cpWorld[t]
        scoreLife += cpLife[t]
        scoreIT += cpIT[t]
    
    
    LapScoreList = dict({"정치":scorePol,"사회":scoreSoc, "경제": scoreFin, "세계":scoreWorld, "생활문화":scoreLife, "IT과학":scoreIT})    

    print(exp(scorePol), exp(scoreSoc), exp(scoreFin), exp(scoreWorld), exp(scoreLife), exp(scoreIT))  # 로그 상태로 지수 취해서 원래대로 나타냄

    
    
    
# 빈도 수를 따라 training보고 판단했을 것. 
# testSet의 chinese를 하나로 줄이면 No를 반환함 
0.0 3.50105e-319 4.7653936e-317 0.0 0.0 6.555334197653213e-308
In [892]:
LapScoreList
Out[892]:
{'정치': -777.9569896889809,
 '사회': -733.2715786776461,
 '경제': -728.3580943174702,
 '세계': -757.6771943006822,
 '생활문화': -775.2331678315182,
 'IT과학': -707.3159295426263}
In [893]:
sorted(LapScoreList)
Out[893]:
['IT과학', '경제', '사회', '생활문화', '세계', '정치']
In [894]:
key_max = max(LapScoreList.keys(), key=(lambda k: LapScoreList[k]))
key_max
Out[894]:
'IT과학'


카테고리별로 잘 분류한 모습을 볼 수 있다!


728x90
반응형