반응형

임베딩에 관련된 설명 및 예제 참고 ↓

[AI] Word2Vec, GloVe, FastText, ELMo 기본 설명 및 실습

 

Embedding + LSTM 분류 실습

  • 초반에 LSTM 분류를 원핫인코딩으로 했던걸, 글로브 벡터 입력으로 받도록 해서 수정
from collections import Counter
import urllib.request # spam 메일 데이터 받아오려고 씀
import pandas as pd
import numpy as np
import tensorflow as tf

import nltk
from nltk.tokenize import sent_tokenize
from nltk import WordPunctTokenizer

nltk.download('punkt')
from google.colab import drive
drive.mount('/content/drive')
# spam classification data loading : 스팸 분류 데이터 로딩
urllib.request.urlretrieve("https://raw.githubusercontent.com/mohitgupta-omg/Kaggle-SMS-Spam-Collection-Dataset-/master/spam.csv", filename="spam.csv")
data = pd.read_csv('spam.csv', encoding='latin-1')
data[:5]

 

texts = list(data['v2'])
labels = list(data['v1'])

print(texts[:5])
print(labels[:5])

print(Counter(labels)) # ham 갯수, spam 갯수 출력

 

  • glove 벡터 불러오기 → 구글 드라이브에 올려서 가져오기
# glove vector model initialize : 글로브 벡터 모델 초기화
glove = {}
with open('/content/drive/My Drive/Colab Notebooks/data/news_sample/glove.6B.50d.txt', 'r', encoding='utf-8') as fr:
    for line in fr.readlines():
        temp = line.strip().split()
        word = temp[0]
        vector = temp[1:]

        glove[word] = list(map(float, vector))

 

  • get_vector 함수
    • 문장을 받아서 tokenize를 해주고 token마다 돌면서 이 토큰이 glove 벡터 모델에 있으면 glove에서 벡터 모델을 가지고 오고, 없으면 0 *50 개를 넣는다.
def tokenize(document):
  words = []
	# sentence tokenizing : 구문을 문장 단위로 분리
  sentences = sent_tokenize(document) 

  for sentence in sentences:
    words.extend(WordPunctTokenizer().tokenize(sentence)) # word tokenizing

  return [word.lower() for word in words] # case normalization : 표준화

def get_vector(sentence):
  tokens = tokenize(sentence)
  vector = [glove[token] if token in glove.keys() else [0]*50 for token in tokens]

  while len(vector) < 256:
    vector.append([0] * 50)
  
  return vector[:256]

 

  • texts들을 벡터로 다 가지고 오게 함!
    • 5000개 기준으로 나눠서 numpy로 감싸줌
  • y는 labels가 spam이랑 ham이 있기때문에 spam일 때는 0, 아닐때는 1
    • y도 마찬가지로 5000개를 기준으로 나눠줌
x = [get_vector(text) for text in texts]
x_train, x_test = np.array(x[:5000]), np.array(x[5000:])
y = [0 if label == 'spam' else 1 for label in labels]
y_train, y_test = np.array(y[:5000]), np.array(y[5000:])

 

  • 분류를 2가지로 분류하기 때문에 softmax를 2로 줌
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Input(shape=(x_train.shape[1], x_train.shape[2])))
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(128)))
model.add(tf.keras.layers.Dense(64, activation = 'relu'))
model.add(tf.keras.layers.Dense(2, activation = 'softmax'))

model.summary()

 

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

model.fit(x_train, y_train, epochs=2)

 

model.evaluate(x_test, y_test, verbose=2)

glove가 word2vec 중에서 제일 학습이 잘되있고 성능이 잘나오다보니 glove랑 lstm을 가지고 문장을 분류하는 것을 굉장히 많이 활용이 된다.
→ 지금은 BERT를 많이 이용한다.
반응형
반응형

단어표현방법(word representation) 및 Word2Vec에 대한 설명 포스팅 참고 ↓

[AI] 단어표현방법 (Bag of Words, Word2Vec, One-hot Vector 등) 설명 및 실습

 

 

word2vec 실습

다운로드

https://dumps.wikimedia.org/kowiki/latest/

kowiki-latest-pages-articles.xml.bz2 다운로드 받고 Zip 파일 압축 풀지 않고 바로 붙여 넣기

wikimedia 데이터를 받은 후 바로 사용이 불가능하다. → 데이터 전처리를 위해 아래의 github 주소의 코드를 다운로드 (wikimedia 데이터를 전처리, 추출하기 위한 소스코드)

https://github.com/MouhamadAboShokor/wikiextractor

다운로드 ZIP → 압축 풀고 폴더 복붙

 

파이참에서 터미널 열기

  • day3 폴더로 이동 → cd C:\Python\nlp2\day3
  • python -m wikiextractor.WikiExtractor kowiki-latest-pages-articles.xml.bzs 입력
    → parsing 파싱 시작! (시간이 꽤 걸림)
  • wikiextractor 라이브러리를 Install 한다.

 

cmd창

  • day3의 text 폴더로 이동 → cd C:\Python\nlp2\day3\text
  • txt 파일 복사 → copy AA\wiki* wikiAA.txt
  • wikiextractor-master 폴더 안에 생성된 wikiAA.txt 파일을 day3 폴더로 이동시킨다.

 

data_preprocessing.py

  • 필요 없는 라인 <doc 으로 시작하거나 </doc>으로 시작하거나 빈문장은 넘어감
with open('wiki_preprocessed.txt','w',encoding='utf-8') as fw:
    with open('wikiAA.txt','r',encoding='utf-8') as fr:
        for line in fr.readlines():
            if line.startswith('<doc') or line.startswith('</doc>') or len(line.strip())==0:
                continue
            fw.write(line)
print('done')

→ 깨끗하게 preprocessing 된 wiki_preprocessed.txt 파일이 생성됨

 

word2vec.py

from gensim.models import Word2Vec

data = []

with open('wiki_preprocessed.txt', 'r', encoding='utf-8') as fr:
    for line in fr.readlines():
        words = line.strip().split()
        data.append(words)

#print(data)

print('Word2Vex training start')
# data : should 2D list.(list of sentences) size : vector size, min-count : 5번이상나온것만 데이터를 만듬 , workers : 변결처리, sg가 1일때 skip-gram 0이면 CBOW
model = Word2Vec(data, size=100, window=5, min_count=5, workers=4, sg=1)

model.save('word2vec.model')

 

word2vec_test.py

from gensim.models import Word2Vec

model = Word2Vec.load('word2vec.model')

print(model.wv.vocab.keys())

 

문장 단위로 말고 형태소 분석으로 한번 다시 해보자 ↓

 

word2vec.py

from konlpy.tag import Okt

from gensim.models import Word2Vec

okt = Okt()

data = []

with open('wiki_preprocessed.txt', 'r', encoding='utf-8') as fr:
    for line in fr.readlines():
        morphs = okt.pos(line.strip())
        data.append([morph[0] for morph in morphs])

print('Word2vec training start')
model = Word2Vec(data, size=100, window=5, min_count=5, workers=4, sg=1) #size: vector size, data: should 2D list.(list of sentences)

model.save('word2vec_morph.model')

print('done')

 

word2vec_test.py

import numpy as np
from gensim.models import Word2Vec

model = Word2Vec.load('word2vec.model')

# print(model.wv.vocab.keys())

def is_oov(token):
    if token not in model.wv.vocab.keys(): # 단어가 있는가? 있으면 False 없으면 True
        return True
    else:
        return False

# # OOV 테스트
print(is_oov('대한민국')) 
print(is_oov('서울'))
print(is_oov('일본'))
print(is_oov('도쿄'))

# # 유사도 테스트
print(model.similarity("대한민국", "일본"))
print(model.similarity("서울", "도쿄"))
print(model.similarity("강아지", "고양이"))
print(model.similarity("강아지", "서울"))

# most similar
print(model.most_similar("강아지"))

# analogy test
# 대한민국 + 일본 - 서울
print(model.most_similar(positive=["대한민국", "일본"], negative=["서울"]))

wikidata 같은 경우 많이 활용됨

 

반응형

GloVe (Global Vectors for Word Represintation)

  • 카운트 기반과 예측 기반을 모두 사용하는 방법 → Word2Vec은 예측만 사용
  • 임베딩 된 중심 단어와 주변 단어 벡터의 내적이 전체 코퍼스에서의 동시 등장 확률이 되도록 만드는 것

https://nlp.stanford.edu/projects/glove/

→ Glove에 대한 자세한 정보, pre-trained 된 모델들도 다운로드할 수 있음

  • 영어권에서는 제일 많이 활용되는 Word2Vec 모델 중 하나
  • OOV에 문제가 있음
학습을 할 때 동시 등장 행렬을 따로 계산을 해준다
동시 등장 행렬 : 특정 단어가 동시 등장 횟수를 카운트를 하고 특정 단어가 등장했을 때 다른 단어가 등장할 조건부 확률

 

glove 실습

https://github.com/stanfordnlp/GloVe

glove.6B.zip 파일 다운로드하고 압축을 풀면 txt 파일이 4개가 생성이 되는데 이걸 파이참 glove 폴더 안에 복사 붙여 넣기

파이참에서 glove_python 라이브러리 Install 하기!!

 

nlp2 > day3 > glove 폴더 > glove_loading.py

  • vector = temp[1:]에 50차원의 실수가 들어있는데 str로 읽혔기 때문에 float로 바꿔야 함 → glove[word] = list(map(float, vector))
import numpy as np

def cosine_similarity(A, B):
    return np.dot(A, B) / (np.linalg.norm(A) * np.linalg.norm(B))

glove = {}

with open('glove.6B.50d.txt', 'r', encoding='utf-8') as fr:
    for line in fr.readlines():
        temp = line.strip().split()
        word = temp[0]
        vector = temp[1:]

        glove[word] = list(map(float, vector))

print('glove vector loaded')

# vector = glove['dog']
# print(cosine_similarity(vector, vector))
print(cosine_similarity(glove['dog'], glove['cat']))

glove 벡터를 사용할 때 코사인 유사도를 직접 만들어서 사용하면 됨
Glove는 학습이 되게 잘 돼있어서 성능이 잘 나옴

 

FastText

  • 위에서 Glove모델에서 OOV의 문제를 해결하기 위해 만들 Word 임베딩 모델
  • 단어를 n-gram으로 나눠서 학습
    • n-gram은 글자 개수로 나눠서 토큰을 만든다.
    • n-gram의 범위가 2-5로 설정한 경우 : assumption = {as, ss, su, …, ass, ssu, sum, …, mptio, ption, assumption}
    • 학습할 때 없던 단어가 들어왔을 때도 n-gram에 대한 단어는 웬만하면 있어서 커버 칠 수 있음
  • 실제 사용 시에는, 입력 단어가 사전에 있을 경우 해당 단어의 벡터를 곧바로 리턴하고 사전에 없는 경우 (OOV, Out-of-Vocabulary) 입력 단어의 n-gram vector를 합산하여 반환

https://research.fb.com/fasttext/ → github 주소도 있음

사람들이 오타를 냈을 때도 각 n-gram의 벡터의 합을 반환하기 때문에 비슷한 단어가 나올 수 있음

 

fasttext 실습

nlp2 > day3 > fasttext

  • gensim에서는 word2vec 로딩을 위한 함수를 제공함
    → 이미 tokenize가 되어 있어야 함
import gensim
from gensim.models.fasttext import FastText

path = '../word2vec/wiki_preprocessed.txt'

# gensim에서는 word2vec 로딩을 위한 함수를 제공함
sentences = gensim.models.word2vec.Text8Corpus(path)

model = FastText(sentences, min_count=5, size=100, window=5)

model.save('fasttext_model')

saved_model = FastText.load('fasttext_model')

word_vector = saved_model['이순신']
print(word_vector)

print(saved_model.similarity('이순신', '이명박'))
print(saved_model.similarity('이순신', '원균'))

print(saved_model.similar_by_word('이순신'))
print(saved_model.similar_by_word('조선'))

saved_model.most_similar(positive=['대한민국', '도쿄'], negative=['서울'])

 

import gensim
from gensim.models.fasttext import FastText

path = '../word2vec/wiki_preprocessed.txt'

# gensim에서는 word2vec 로딩을 위한 함수를 제공함
sentences = gensim.models.word2vec.Text8Corpus(path)

model = FastText(sentences, min_count=5, size=100, window=5)

model.save('fasttext_model')

saved_model = FastText.load('fasttext_model')

word_vector = saved_model['이순신']
print(word_vector)

print(saved_model.similarity('이순신', '이명박'))
print(saved_model.similarity('이순신', '원균'))

print(saved_model.similar_by_word('이순신'))
print(saved_model.similar_by_word('조선'))

saved_model.most_similar(positive=['대한민국', '도쿄'], negative=['서울'])

 

 

ELMo (Embeddings from Language Model)

  • 위의 word2vec 모델들 같은 경우에는 윈도우 사이즈가 있다보니까 window 내에 있는 단어들에 대해서만 학습을 하는데 밖에 있어도 문맥을 반영을 하고 싶고, 글자가 같은 단어도 다른 뜻을 가지는 경우가 있는데 그런 문제를 해결하기 위해 고안한 모델
  • Pre-trained 모델의 시작

→ 위의 그림처럼 단어의 뜻이 다른데도 벡터가 하나밖에 없으면 문제이기 때문에 해결하고, 문장의 전체 문맥까지 고려할 수 있는 임베딩 기법

 

  • Elmo는 언어모델인데, lstm을 가지고 순방향 하나 역방향 하나 만들어서 합친것
  • 입력이 문장으로 들어가고, 나올때도 문장 기준으로 벡터가 나옴
    • 한칸의 한칸의 벡터들이 워드에 대한 벡터이기는 하지만 문맥을 고려해서 벡터를 입력을 받기 때문에 문장을 입력했을 때 성능이 훨씬 잘나옴

 

 

 

 

반응형
반응형

단어표현방법(word representation)

  • DTM: Document-Term Matrix (문서 단어 행렬)
  • LSA: Latent Semantic Analysis (잠재 의미 분석)

  • N-gram : N(숫자)가 2라면 2글자씩 토큰으로 만든다.
  • Glove : Count랑 Word2Vec이랑 합친것
  • LSA : 문서 전체에서 count하는 방법

 

Bag of Words (BoW)

  • 단어들의 순서는 전혀 고려하지 않고, 단어들의 출현 빈도를 활용하는 단어 표현 방법
  • 단어들의 가방이라는 뜻으로 모든 단어를 가방에 넣어서 표현한다는 의미
  • BoW를 만드는 과정
    1. 각 단어에 고유한 정수 인덱스를 부여
      → one hot vector에서 처음에 vocab을 생성했던 부분과 동일
    2. 각 인덱스의 위치에 단어 토큰의 등장 횟수를 기록한 벡터를 생성

예시

 

Bag of Words 실습

  • 형태소 분석기 활용
!pip install konlpy

from konlpy.tag import Kkma

import nltk
from nltk.tokenize import sent_tokenize

nltk.download('punkt')

class Tokenizer:
  def __init__(self):
    self.kkma = Kkma()

  def make_vocab(self, documents):
    word2index = {'<unk>':0}
    for document in documents:
      tokens = self.tokenize(document)
      for voca in tokens:
        if voca not in word2index.keys(): # voca가 key 리스트에 없으면 리스트에 추가
          word2index[voca] = len(word2index)
    self.vocab = word2index

	# 형태소 분석
  def tokenize(self, document):
    morphs = []
    sentences = sent_tokenize(document)

    for sentence in sentences:
      sentence_morphs = self.kkma.pos(sentence)
      morphs.extend([morph[0] + '/' + morph[1] for morph in sentence_morphs])

    print(morphs)
    return morphs
  
	# BOW
  def bag_of_words(self, sentence):
    morphs = self.tokenize(sentence)
    vector = [0] * len(self.vocab)
    for morph in morphs:
      if morph not in self.vocab.keys():
        morph = '<unk>'
      vector[self.vocab[morph]] += 1
    
    return vector

→ 형태소 분석까지 다 한 다음

 

tokenizer = Tokenizer()
texts = ['안녕하세요', '안녕하십니까', '오늘은 날씨가 좋네요', '기분이 좋아요']
tokenizer.make_vocab(texts) # texts 리스트로 vocab을 만듬

print(tokenizer.vocab) # vocab 출력

tokenizer.bag_of_words('오늘은 날씨가 어떨 것 같으세요') # 문장의 벡터가 됨

→ 0 인덱스의 unk : 5개 , 6 인덱스의 '오늘' : 1개 , 7 인덱스의 '은' : 5개 , 8 인덱스의 '날씨' : 1개 , 9 인덱스의 '가' : 1개

 

 


DTM (Document Term Matrix)

  • 다수의 문서에서 등장하는 각 단어들의 빈도를 행렬로 표현한 것
  • 각 문서에 대한 BoW를 하나의 행렬로 만든 것과 동일

 

TF-IDF (Term Frequency-Inverse Document Frequency)

  • 단어의 빈도와 역 문서 빈도를 사용하여 각 단어들마다 중요한 정도를 가중치로 주는 방법
  • tf(d, t) : 특정 문서 d에서의 특정 단어 t의 등장 횟수
  • df(t) : 특정 단어 t가 등장한 문서의 수
  • idf(d, t) : df(t) 에 반비례하는 수

n : 총 문서 수

 

  1. DTM을 생성
  2. TF 는 각 문서에서 특정 단어 등장 횟수
    tf(문서1, 사과) → 1
    df(사과) → 1
    idf(d, 사과) → log(4/2) → log2
  3. tf(문서1, 사과) → 1
    tf(문서3, 바나나) → 2
    df(사과) → 1
    df(바나나) → 2
  4. '과일이' idf = log(4/1+1)
    '바나나' idf = log(4/1+2)
  5. TF-IDF = 각 문서에서 특정 단어 등장 횟수 (tf 값) 에 idf 값을 곱한 값

 

Tf-idf 실습

from sklearn.feature_extraction.text import TfidfVectorizer

documents = {
    'you knew I want your love',
    'I like you',
    'what should I do',
}

vectorizer = TfidfVectorizer().fit(documents)

print(vectorizer.transform(documents).toarray())

 

  • 검색할때 TF IDF 스코어를 활용을 하기 때문에 TF IDF 같이 나옴
DTM에서 TF-IDF의 차이는? 
DTM : Bag of Words 를 행렬로 나타낸 것
→ 모든 문서에서 등장한 단어는 특징이 없다고 의미될 수 있음
→ idf 값을 곱해줌으로써 자주 나오는 단어는 점수를 낮추고, 드물게 나오는 단어는 점수를 높이는 효과

DTM : 순수 단어 카운팅 TF-IDF : 모든 문서에서 등장하는 단어는 가중치를 낮추고, 드물게 나오는 단어는 가중치를 높이는 알고리즘

 

반응형

임베딩

희소표현 (Sparse Representation)

  • 원핫인코딩(one-hot encoding 방식) , tf-idf
  • 엄청 큰 메트릭스지만 특정부분에 하나씩만 사용
    → 숫자가 나오는것 자체가 희소하기 때문에 희소표현이라고 부름

밀집표현 (Dense Representation)

  • word2vec
  • 차원을 줄일때 사용자 설정값으로 줄이고, 벡터가 조밀해졌다고 해서 밀집벡터이라고 부름
  • 0보다는 거의 모든 케이스에 값이 다 들어있다

워드 임베딩

  • 밀집표현으로 벡터를 표현하는 방법
  • 임베딩 벡터 - 워드 임베딩 과정을 통해 나온 벡터
  • Word2Vec , Glove , FastText

 

Word2Vec

  • 비슷한 위치에서 등장하는 단어들은 비슷한 의미를 가진다라는 가정
    • ‘강아지’와 ‘고양이’는 주변에 서로 비슷한 단어가 나올 것
    • ‘강아지’와 ‘자연어’는 주변에 전혀 다른 단어가 나올 것
  • 중심 단어와 주변 단어로 학습하므로 라벨링이 필요 없음
    • 문장이 들어왔을때 tokenizer 한 다음에 해당 token들을 가지고 '강아지'라는 단어가 있을때 앞이나 뒤에 있는 단어들을 보고 학습
    • → 비지도학습(unsupervised learning)
  • CBOW(Continuous Bag of Words), Skip-gram 방식

 

CBOW (Continuous Bag of Words)

  • 주변에 있는 단어로부터 중심 단어를 예측하는 방법
  • 중심 단어를 예측하기 위해서 앞, 뒤로 몇 개의 단어를 볼지에 대한 범위를 윈도우(window)라고 함

→ Projection layer 모델은 복잡할 수 있음

→ set 이라는 단어를 예측하기 위해서는 fat , cat , on , the 라는 단어들을 가지고 예측을 한다.

→ 윈도우가 3개면 앞에 3단어 , 뒤에 3단어로 학습

 

Skip-gram

  • CBOW와 반대되는 개념 - 입력과 아웃풋이 반대
  • 중심단어에서 주변단어를 예측하는 방식

 

네거티브 샘플링 (Negative Sampling)

  • one-hot encoding으로 모든 단어에 대해서 cross entropy를 계산하고 weight를 조정하려면 단어 개수에 따라서 무거운 작업이 될 수 있음

→ 만약 단어가 10만개가 있다면 10만에 대한 cross entropy를 계산을 해야하는데 너무 오래 걸릴 수가 있다. 단어 갯수가 많아질수록 무거워진다.

→ 그래서 sampling 샘플링을 해준다.

  • 주변 단어-중심 단어 관계를 가지고 지정한 윈도우 사이즈 내에 존재하면 1, 그렇지 않으면 0으로 이진분류 문제로 변경하여 학습하면 더 빠르게 학습할 수 있음
    → cross entropy는 binary에 대해서만 계산하면 되고 , weight도 두개만 업데이트하면 됨
  • 전체 단어가 아니라, 일부에 대해서만 학습하도록 샘플링
Word2Vec 같은 경우 비지도 학습이다 보니 방대한 양의 데이터 학습 가능
→ 데이터가 너무 많기 때문에 네거티브 샘플링처럼 샘플링을 해서 연관이 있는지 학습

 

코사인 유사도 (Cosine Similarity)

  • 두 특성 벡터간의 유사정도를 코사인 값으로 표현한 것
  • 코사인 유사도는 -1에서 1까지의 값을 가지며, -1은 서로 완전히 반대, 0은 서로 독립, 1은 서로 같은 경우를 의미

그 외의 유사도 평가 방법 유클리드 거리(Euclidean Distance) , 자카드 유사도(Jaccard Similarity)

 

Word Analogy

  • 유추를 통한 평가로 유추에 대한 데이터가 존재해야 테스트를 할 수 있음
  • 명사뿐만이 아니라 형용사, 동명사에서도 똑같이 비슷하게 나오기도 함

→ man - woman + king = queen

→ 한국 - 서울 = 일본 - 도쿄

반응형
반응형

벡터화

  • 자연어가 기계가 이해할 수 있도록 숫자로 변환해주는 과정

 

원-핫 인코딩(One-Hot Encoding)

  • 단어 집합의 크기를 벡터의 차원으로 하고, 표현하고 싶은 단어의 인덱스에 1의 값을 부여하고, 다른 인덱스에는 0을 부여하는 벡터 표현 방식
  • 원-핫 인코딩 과정
    1. 각 단어에 고유한 인덱스 부여
    2. 표현하고 싶은 단어의 인덱스에 1, 아닌 단어에는 0 부여

 

원-핫 인코딩 실습1

from my_tokenizer import tokenize

# 사전 생성
def make_vocab(tokens):
    word2index = {}
    for voca in tokens:
        if voca not in word2index.keys():
            word2index[voca] = len(word2index)
    return word2index

# 원핫인코딩
def one_hot_encoding(word, word2index):
    one_hot_vector = [0] * (len(word2index))
    index = word2index[word]
    one_hot_vector[index] = 1
    return one_hot_vector


if __name__ == '__main__':
    document = '안녕하세요. 이번에 같이 교육받게 된 김지선이라고 합니다.'
    tokens = tokenize(document, 'lemma')
    word2index = make_vocab(tokens)
    # print(word2index)
    print('dictionary:', word2index) 
    print(one_hot_encoding('같이', word2index))

 

 

원-핫 인코딩 실습2

import nltk
from nltk.tokenize import sent_tokenize
from nltk import WordPunctTokenizer
from nltk.stem import LancasterStemmer
from nltk.stem import WordNetLemmatizer


class Tokenizer:
    def __init__(self, tokenize_type): # 클래스로 만들어서 self 가 자동으로 붙음
        self.type = tokenize_type

    def make_vocab(self, document):
        tokens = self.tokenize(document)
        word2index = {'<unk>': 0}
        for voca in tokens:
            if voca not in word2index.keys():
                word2index[voca] = len(word2index)
        self.vocab = word2index
        print('dictionary:', self.vocab)

    # types = ['stem', 'lemma', 'pos']
    def tokenize(self, document):
        words = []
        sentences = sent_tokenize(document)  # sentence tokenizing
        for sentence in sentences:
            words.extend(WordPunctTokenizer().tokenize(sentence))  # word tokenizing
        if self.type == 'stem':
            lancaster_stemmer = LancasterStemmer()
            tokenized = [lancaster_stemmer.stem(w) for w in words]  # stemming
        elif self.type == 'lemma':
            lemmatizer = WordNetLemmatizer()
            tokenized = [lemmatizer.lemmatize(w).lower() for w in words]  # lemmatizing
        elif self.type == 'pos':
            # tokenized = nltk.pos_tag(words) # pos tagging
            tokenized = [token[0] + '/' + token[1] for token in nltk.pos_tag(words)]
        else:
            raise TypeError
        return tokenized

    def one_hot_encoding(self, word):
        one_hot_vector = [0] * (len(self.vocab))
        if word not in self.vocab:
            word = "<unk>"
        index = self.vocab[word]
        one_hot_vector[index] = 1
        return one_hot_vector

    def get_vector(self, sentence):
        # return 2차원 배열
        tokens = self.tokenize(sentence)
        print('Tokenized:', tokens)
        return [self.one_hot_encoding(token) for token in tokens]


if __name__ == '__main__':
    document = 'Hi! 안녕하세요.\n 이번에 같이 교육받게 된 김지선\n이라고 합니다.'
    tokenizer = Tokenizer('lemma')
    tokenizer.make_vocab(document)
    print(tokenizer.get_vector('hi, 같이 김지선'))

 

 

반응형
반응형

전처리 이해

  • 토큰화
    • 주어진 데이터를 토큰(Token)이라 불리는 단위로 나누는 작업
    • 토큰이 되는 기준은 다를 수 있음(어절, 단어, 형태소, 음절, 자소 등)
  • 정제
    • 불필요한 데이터(Noise data)를 제거하는 작업
  • 정규화
    • 표현 방법이 다른 단어들을 통합시켜서 같은 단어로 만들어주는 작업
  • 문장 토큰화
  • 문장분리
  • 단어 토큰화“Hello, World!” -> “Hello”, “,”, “World”, “!”
  • 구두점 분리, 단어 분리

 

토큰화 실습

# 문장 분리 
from nltk.tokenize import sent_tokenize 
text = "Hello, world. These are NLP tutorials." 
print(sent_tokenize(text))

 

 

import nltk from nltk import WordPunctTokenizer 
nltk.download('punkt') 
text = "Hello, world. These are NLP tutorials." 
print(WordPunctTokenizer().tokenize(text))

 

 


정제&정규화

  • 불필요한 데이터를 제거하는 작업
  • 표기가 다른 단어들의 통합 예시) US, USA -> USA, 어간 추출(stemming), 표제어 추출(lemmatization)
  • 대소문자 통합: 문장 첫 글자 문제
  • 불필요한 단어 제거 예시) 불용어(stopwords), 영어가 아닌 외국어
  • 정규표현식

어간추출&표제어 추출

  • 어간추출(stemming)
    • 축약형으로 변환
  • 표제어추출(lemmatization)
    • 품사 정보가 보존된 형태의 기본형으로 변환

 

어간추출&표제어추출 실습

### 어간 추출 ###

from nltk import WordPunctTokenizer
from nltk.stem import PorterStemmer
from nltk.stem import LancasterStemmer

text = "Hello, world. These are NLP tutorials."
words = WordPunctTokenizer().tokenize(text)
print(words)
porter_stemmer = PorterStemmer()
print([porter_stemmer.stem(w) for w in words])
lancaster_stemmer = LancasterStemmer()
print([lancaster_stemmer.stem(w) for w in words])

 

#### 표제어 추출 ####

import nltk
from nltk import WordPunctTokenizer
from nltk.stem import WordNetLemmatizer
nltk.download('wordnet')
text = "Hello, world. These are NLP tutorials."
words = WordPunctTokenizer().tokenize(text)
lemmatizer = WordNetLemmatizer()
print(words)
print([lemmatizer.lemmatize(w) for w in words])

 

반응형

 

불용어 실습

## 불용어 확인 ##

import nltk
from nltk.corpus import stopwords

nltk.download('stopwords')
english_stopwords = stopwords.words('english')
print(len(english_stopwords))
print(english_stopwords[:10])

 

## 불용어 제거 ##
from nltk.corpus import stopwords
from nltk import WordPunctTokenizer

text = "Hello, world. These are NLP tutorials."
stop_words = stopwords.words('english')
stop_words.append('hello')

words = WordPunctTokenizer().tokenize(text)
words = [word.lower() for word in words]


result = []
for word in words:
    if word not in stop_words:
        result.append(word)
print(words)
print(result)

 

POS Tagging, Named Entity Recognition 실습

# POS tagging (part of speeck tagging)
# Named Entity Recognition

import nltk
from nltk import WordPunctTokenizer

nltk.download('averaged_perceptron_tagger')
nltk.download('words')
nltk.download('maxent_ne_chunker')

text = "Hello, world. These are NLP tutorials."

word = WordPunctTokenizer().tokenize(text)
tagged = nltk.pos_tag(word)
entities = nltk.chunk.ne_chunk(tagged)

print(word)
print(tagged)
print(entities)

 

토크나이저 실습

import nltk
from nltk.tokenize import sent_tokenize
from nltk import WordPunctTokenizer
from nltk.stem import LancasterStemmer
from nltk.stem import WordNetLemmatizer

types = ['stem', 'lemma', 'pos']

def tokenize(document, type):
    words = []

    sentences = sent_tokenize(document) # sentence tokenizing
    for sentence in sentences:
        words.extend(WordPunctTokenizer().tokenize(sentence)) # word tokenizeing

    # sentence tokenizing
    # word tokenizing
    # 타입에 따라서 토큰으로 분리
    if type == 'stem':
        lancaster_stemmer = LancasterStemmer()
        tokenized = ([lancaster_stemmer.stem(w) for w in words]) # stemming
    elif type == 'lemma':
        lemmatizer = WordNetLemmatizer()
        tokenized = ([lemmatizer.lemmatize(w) for w in words]) # lemmatizing
    elif type == 'pos':
        # tokenized = nltk.pos_tag(words) # pos tagging
        tokenized = [token[0]+'/'+token[1] for token in nltk.pos_tag(words)]
    else:
        raise TypeError
    return tokenized

if __name__ == '__main__':
    document = '안녕하세요. 이번에 같이 교육받게 된 김지선이라고 합니다.'
    print(tokenize(document, 'pos'))

 

반응형

+ Recent posts