인공지능/RNN

자연어 처리 (Gensim)

쿠와와 2020. 11. 24. 16:20
# Day_06_01_gensim.py
import gensim
import nltk
import collections
import pprint


# 건강한 사람과 암에 걸렸을 확률을 계산
# 암에 걸릴 비율 (0.1%), 건강할 확률 (99.9%)

# 암 판정을 받았을 때의 정확도: 95%
# 암이 아니라고 판정했을 때의 오진율 : 2%

# 암 판정
# 실제 암에 걸렸을 확률: (암에 걸릴 확률 * 정확도)(암에 걸리지 않았을 확률 * 오진률)
# 0.001 * 0.95 = 0.00095    -> 0.04538939321548     판정 시 / 전체 확률
# 0.999 * 0.02 = 0.01998    -> 0.954610610678452    아닐 시 / 전체 확률
# --------------------------
# 걸릴 전체 확률 = 0.02093

# 문제
# 암이 아니라는 판정을 팓았을 때, 실제 암에 걸렸을 확률
# 0.999 * 0.98  = 0.97902 암에 걸리지 않았을 판정 -> 걸린 확률 5.106887148007803e-5 거의 확률 없음
# 0.001 * 0.05  = 0.00005 암 판정 받았을 때  ->  아닐 확률 0.99994893
# 0.97907

# rnn
# 소프트 맥스의 연장선
# 다음에 오는 단어를 무엇이 올까요 ?? 굉장히 많은 수 중에서 하나 선택함 -> 자연어에서는 답이 많음
# 자연어는 다음에 오는 단어를 예측하는 것 (classification 한다)


def show_doc2vec():
    # 문제 computer.txt 파일 읽어서 문서별로 단어 토큰을 만드세요
    txt = open('data/computer.txt', 'r', encoding='utf-8')

    text = txt.readlines()

    # print(len(text))
    docs = [d.lower().split() for d in text]
    # print()
    # print(*docs, sep='\n')

    txt.close()

    # 문제 2번
    # docs로 부터 내 불용어 목록을 만들어서 제거하라
    stopwords = ['a', 'the', 'of', 'and', 'in', 'for', 'to']

    tokens = [[t for t in w if t not in stopwords] for w in docs]  # 불용어 제거
    # print(*tokens, sep='\n')

    # 전체 문서에서 토큰이 한 번만 출현한 것 제거

    # 이것도 정답임
    # freq = {}
    # for w in tokens:
    #     for t in w:
    #         freq[t] = freq.get(t, 0) + 1

    freq = collections.Counter([t for token in tokens for t in token])
    tokens = [[t for t in w if freq[t] > 1] for w in tokens]
    print(*tokens, sep='\n')


    # tokens => 어떤 상태인지 알고 있어야함
    dct = gensim.corpora.Dictionary(tokens)     # 12개의 의미있는 단어가 추출 됬음
    # Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)

    print(dct.token2id)     # 문자열을 id로 만듬
    # {'computer': 0, 'human': 1, 'interface': 2, 'response': 3, 'survey': 4,
    # 'system': 5, 'time': 6, 'user': 7, 'eps': 8, 'trees': 9, 'graph': 10, 'minors': 11}

    # print({v: k for k, v in dct.token2id.items()})
    # print(dct.id2token)   # 사용자 정의 느낌 암것도 들어가 있지 않다

    print(dct.doc2bow(['computer', 'trees', 'graph', 'trees']))    # 단어 주머니 도규먼트 전달
    # [(0, 1), (9, 2), (10, 1)] -> 문자열을 숫자로 바꿔줬음    (id, 빈도)
    print()
    # 문제 4
    # docs에 퐇ㅁ된 문서를 bow()로 변환하세요

    print(*[dct.doc2bow(t) for t in tokens], sep='\n')    # 언패킹
    print()
    pprint.pprint([dct.doc2bow(t) for t in tokens])


def show_word2vec_1():
    text = ['나는 너를 사랑해', '나는 너를 미워해']
    token = [s.split() for s in text]
    print(token)

    # embedding = gensim.models.Word2Vec(token, min_count=1, size=5)
    embedding = gensim.models.Word2Vec(token, min_count=1, size=5, sg=True)  # size 굉장히 중요
    #                                 최소 1번 이상 나온 것, 5개의 숫자로 바꿀 것,
    # skip gram -> 더 확률이 높게 나와서 sg만 씀
    print(embedding)

    print(embedding.wv.vectors)     # 행이 4개 -> voca 4개 열은 각 문자를 나타내는 숫자
    print(embedding.wv.vectors.shape)

    print(embedding.wv['나는'])   # 최근 추세


def show_word2vec_2():
    r1 = nltk.corpus.movie_reviews.raw('neg/cv000_29416.txt')       # 전체 문자열
    r2 = nltk.corpus.movie_reviews.words('neg/cv000_29416.txt')     # 1 차원 리스트 -> 단어
    r3 = nltk.corpus.movie_reviews.sents('neg/cv000_29416.txt')     # 2 차원 리스트 -> 한 줄

    print(type(r1), r1[:5])
    print(type(r2), r2[:5])
    print(type(r3), r3[:5])

    sents = nltk.corpus.movie_reviews.sents()
    model = gensim.models.Word2Vec(sents)

    # 코사인 유사도로 유사도를 판별함 -1 ~ 1 사이의 숫자를 가짐 실제로(0~1)   비슷한 단어로 취급이 됨
    # print(model.wv.similarity('villain', 'hero'))
    # print(model.wv.similarity('man', 'woman'))
    # print(model.wv.similarity('chicken', 'hero'))
    # print(model.wv.similarity('test', 'water'))
    #
    # print(model.wv.most_similar('chicken'))     # 유사한 단어를 찾아 줌
    # [('warrior', 0.8634028434753418), ('monkey', 0.8615837097167969),
    # ('supernova', 0.857768714427948), ('velvet', 0.8495028614997864),
    # ('endurance', 0.846551239490509), ('showgirls', 0.8465056419372559),
    # ('13th', 0.8384883403778076), ('psycho', 0.838275134563446),
    # ('snatch', 0.8342502117156982), ('bull', 0.8338596820831299)]
    # print('papa' in model)
    print('papa' in model.wv)
    print(model.wv['apple'])
    print(model.wv['apple'].shape)


# show_doc2vec()
# show_word2vec_1()
show_word2vec_2()