sentences = ['나는 책상 위에 사과를 먹었다.',
'알고 보니 그 사과는 Jason 것이었다.',
'그래서 Jason에게 사과를 했다.']
token2idx = {}
index = 0
for sentence in sentences:
tokens = sentence.split(sentence)
for token in tokens:
if token2idx.get(token) == None:
token2idx[token] = index
index += 1
token2idx
를 Vocabulary라고 한다.def indexed_sentence(sentence):
return [token2idx[token] for token in sentence]
list(map(indexed_sentence, list(map(lambda x: x.split(), sentences))))
문제점
1. 없는 단어가 나오면 어떻게 하지?
2. 조사가 다르다면 다른 단어라고 해야 하나?
3. 동음이의어는 처리가 안되네?
idx2char = {0:'<pad>', 1:'<unk>'}
srt_idx = len(idx2char)
for x in range(32, 127): # 영어 추가
idx2char.update({srt_idx: chr(x)})
srt_idx += 1
for x in range(int('0x3131',16), int('0x3163',16)+1): # 한국어 추가
idx2char.update({srt_idx: chr(x)})
srt_idx += 1
for x in range(int('0xAC00',16), int('0xD7A3',16)+1):
idx2char.update({srt_idx: chr(x)})
srt_idx += 1
char2idx = {v:k for k,v in idx2char.items()}
list(map(lambda x: [char2idx.get(c,0) for c in x], sentences))
문제점
1. 표현법에 대한 학습이 어려움(글자 하나는 의미 보유 x)
문제점
1. 쓸모 없는 조합이 너무 많이 생성됨
2. 사전이 과하게 커진다.
word = 'abbcabcab'
word = word.replace('ab','X')
word = word.replace('cX','Y')
import re, collections
def get_stats(vocab): # 2번 과정 함수
pairs = collections.defaultdict(int) # dictation 생성
for word, freq in vocab.items():
symbols = word.split() # 띄어쓰기 기준으로 나눔
for i in range(len(symbols)-1):
pairs[symbols[i],symbols[i+1]] += freq # 가장 많이 나오는 글자 조합 찾기
return pairs
def merge_vocab(pair, v_in): # 3번 과정 함수
v_out = {}
bigram = re.escape(' '.join(pair)) # 결합
p = re.compile(r'(?<!\\S)' + bigram + r'(?!\\S)')
for word in v_in: # v_in에 있는 쌍 변환
w_out = p.sub(''.join(pair), word)
v_out[w_out] = v_in[word]
return v_out
vocab = {'l o w </w>':4, 'l o w e r </w>':2,
'n e w e s t </w>':6, 'w i d e s t </w>':3}
num_merges = 10
for i in range(num_merges):
pairs = get_stats(vocab)
best = max(pairs, key=pairs.get)
vocab = merge_vocab(best, vocab)
print(f'Step {i+1}')
print(best)
print(vocab)
print('\\n')
!pip install sentencepiece
import sentencepiece as spm
s = spm.SentencePieceProcessor(model_file='spm.model')
for n in range(5):
s.encode('New York', out_type=str, enable_sampling=True, alpha=0.1, nbest=-1)
!pip install transformers
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') # bert-base-uncased 모델에서 사용한 tokenizer 사용
tokenizer.tokenize('My dog is cute. He likes playing')
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-uncased') # bert-base-multilingual-uncased모델에서 사용한 tokenizer(다양한 언어 학습)
tokenizer.tokenize('My dog is cute. He likes playing')
tokenizer.tokenize('나는 책상 위에 사과를 먹었다. 알고 보니 그 사과는 Jason 것이었다. 그래서 Jason에게 사과를 했다.')
V = len(token vocabulary)
라 하고 V 길이의 모두 0값을 가진 0벡터 생성token2idx = {}
index = 0
for sentence in sentences:
tokens = sentence.split(sentence)
for token in tokens:
if token2idx.get(token) == None:
token2idx[token] = index
index += 1
v = len(token2idx)
token2vec = [([0 if i != idx else 1 for i in range(v)], idx, token) for token, idx in token2idx.items()]
import numpy as np
for sentence in sentences:
onehot_s = []
tokens = sentence.split()
for token in tokens:
if token2idx.get(token) != None:
vector = np.zeros((1,v))
vector[:, token2idx[token]] = 1
onehot_s.append(vector)
문제점
1. Sparse하다. (대부분 0이기 때문에 비효율적이다.) - 파이썬의 sparse
라이브러리 활용해 계산, 메모리 효율화 가능
문제점
1. 순서가 무시됨
# 다음 character을 예측하는 모델 구축
# charseq 문제
sample = ' if you want you'
# make dictionary
char_set = list(set(sample))
char_dic = {c:i for i,c in enumerate(char_set)}
# hyperparameters
input_size = len(char_set)
dic_size = len(char_dic)
hidden_size = len(char_dic)
learning_rate = 0.1
# data setting
sample_idx = [char_dic[c] for c in sample] # index 가져옴
x_data = [sample_idx[:-1]] # 마지막 character 제외 후 가져옴
x_one_hot = [np.eye(dic_size)[x] for x in x_data] # np.eye는 Identity matrix임-여기서 원하는 vector 가져옴
y_data = [sample_idx[1:]]
# transform as torch tensor variable
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
# declare RNN
rnn = torch.nn.RNN(input_size, hidden_size, batch_first=True)
# loss&optimizer setting
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), learning_rate)
# start training
for i in range(100):
optimizer.zero_grad()
outputs, _status = rnn(X)
loss = criterion(outputs.view(-1, input_size), Y.view(-1))
loss.backward()
optimizer.step()
result = outputs.data.numpy().argmax(axis=2)
result_str = ''.join([char_set[c] for c in np.squeeze(result)])
print(F'{i}, loss: {loss.item()}, prediction: {result}, true Y: {y_data}, prediction str: {result_str}')
참고
파이썬 딥러닝 파이토치 (이경택, 방성수, 안상준)
모두를 위한 딥러닝 시즌 2 Lab 11-2