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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | # 파일 읽어오기 - byte 단위로 읽어오기 위해 'rb' 사용 file = open('/content/drive/My Drive/train_char.txt','rb') # 데이터 전처리해서 새로 저장하기 lines = [] for s in file: # 소문자로 변형 s = s.lower() # \n, \r 제거 s = s.strip() # 바이트 열 제거 s = s.decode('ascii', 'ignore') # 전처리한 문장들을 lines 에 저장 if len(s) > 0: lines.append(s) # 각각의 문장들을 ' ' 로 구분하지 않고, 하나의 원문으로 뭉치기 text = ' '.join(lines) # 알파벳 단위로 정렬된 집합 만들기 # set 연산 - 중복되지 않도록 알파벳을 하나의 집합으로 변환 # list 연산 - sorted 연산을 위해서 list 로 변형시키기 위함 char_set = sorted(list(set(text))) char_size = len(char_set) # 딕셔너리 만들기 (1) - char_to_idx tmp_dict = [] for idx, c in enumerate(char_set): tmp_dict.append([c, idx]) char_to_idx = dict(tmp_dict) # 딕셔너리 만들기 (2) - idx_to_char idx_to_char = {} idx = 0 for c in char_to_idx: idx_to_char[idx] = c idx += 1 # 훈련 데이터 만들기 - 특정 길이만큼 분할한 뒤, 정수 인코딩을 모두 시켜준다 import numpy as np len_line = 60 num_sentence = int(len(text)/len_line) train_X = [] train_Y = [] tmp_line = [] for i in range(num_sentence): tmp_line = text[ i * len_line : (i+1) * len_line] train_X.append([char_to_idx[c] for c in tmp_line]) tmp_line=[] tmp_line = text[ i * len_line + 1: (i+1) * len_line + 1] train_Y.append([char_to_idx[c] for c in tmp_line]) tmp_line=[] # padding 과정 수행하기 from tensorflow.keras.preprocessing.sequence import pad_sequences max_len = 60 train_X = pad_sequences(train_X, maxlen = max_len) trian_Y = pad_sequences(train_Y, maxlen = max_len) # 원핫벡터로 만들기 - X 값도 원핫벡터로 만들기 때문에, 따로 임베딩 과정이 필요없어진다 from tensorflow.keras.utils import to_categorical onehot_X = to_categorical(train_X) onehot_Y = to_categorical(train_Y) # 모델 설계 from tensorflow.keras.layers import Dense, LSTM from tensorflow.keras.models import Sequential model = Sequential() model.add(LSTM(256, input_shape=(None, char_size), return_sequences=True)) model.add(LSTM(256, return_sequences=True)) model.add(Dense(units=char_size, activation='softmax')) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc']) model.fit(x=onehot_X, y=onehot_Y, batch_size=100, epochs=10, verbose=2) | cs |
1. 임베딩 층이 따로 없다는게 독특하다.
임베딩 층이 없기 때문에, X 값을 원핫벡터로 변환시켜주는 과정이 필요하다
2. LSTM 에서 받아야 하는 argument 값은 오직, "하나의 셀에 있는 은닉 벡터의 차원 수" 다.
따로 input_shape = () 를 통해서 전달받아야 한다면,
(배치 size, 임베딩 층의 벡터 dimension) 을 전달받는다
3. 그렇다면 LSTM 의 time series 갯수는 어떻게 알 수 있을까?
-> 추측으론, 인풋 값의 shape 를 이용해서 구하는 걸로 보인다.
ex) 저기선, onehot_X 의 shape = (2464, 60, 56) 이었기 때문에,
총 60번의 time series 를 지난다
(2464 는 데이터의 갯수, 56은 임베딩 층의 벡터 dimension 이다)
4. 저번과 마찬가지로, N:N 모델이기 때문에 return_sequences=True 처리를 해줘야 한다
-> 근데, LSTM 이 두 개가 있는 경우엔 어떻게 되는거지?
둘 다 return_sequences=True 를 해버리면, 출력값의 길이가 이상해지는데...
'기계학습 > 자연어 처리 머신러닝' 카테고리의 다른 글
유동 인구 예측 - 실전 프로젝트 (0) | 2020.02.20 |
---|---|
글자 단위 RNN - N:1 모델 LSTM (0) | 2020.02.18 |
품사 태깅 - N:N 양방향 LSTM 모델 (0) | 2020.02.18 |
개체명 인식기 - N:N 양방향 LSTM 모델 (0) | 2020.02.17 |
신문 제목 분류 실습 - 나이브 베이즈 분류기 (0) | 2020.02.14 |