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 | # 파일 가져오기 f = open('/content/drive/My Drive/train_char.txt', 'rb') # 불필요한 내용들 제거 lines = [] for s in f: # \n, \r 제거 s = s.strip() # 길이=0 인 문장 제거 if len(s)==0: continue # 소문자 변환 s = s.lower() # 아스키코드 제거 s = s.decode('ascii', 'ignore') lines.append(s) f.close() # 하나의 text 로 연결지어주기 text = " ".join(lines) # 특정 길이만큼씩 text 를 분할해서 저장하기 len_text = len(text) train_X = [] train_Y = [] len_line = 10 for i in range(len_line, len_text-len_line): tmp = text[ i : i + len_line] train_X.append(tmp) train_Y.append(text[i+len_line]) # char_to_idx, idx_to_char 만들기 char_list = sorted(list(set(text))) char_size = len(char_list) char_to_idx = {} idx_to_char = {} for idx, char in enumerate(char_list): char_to_idx[char]=idx idx_to_char[idx]=char # train_X, train_Y 를 정수로 인코딩 하기 seq_X = [] seq_Y = [] tmp = [] for line in train_X: tmp = [char_to_idx[c] for c in line] seq_X.append(tmp) tmp = [] for c in train_Y: seq_Y.append(char_to_idx[c]) # 패딩 연산 수행하기 from tensorflow.keras.preprocessing.sequence import pad_sequences pad_X = pad_sequences(seq_X, maxlen=len_line) # X 데이터를 원핫벡터로 변환하기 from tensorflow.keras.utils import to_categorical onehot_X = to_categorical(pad_X) onehot_Y = to_categorical(seq_Y) # 모델 설계하기 from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, LSTM, TimeDistributed model = Sequential() model.add(LSTM(256, input_shape=(None, char_size))) model.add(Dense(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=5) | cs |
N:N 방식과 다를 게 없는 모델이었다.
전처리 하는 방식이 조금 색다르긴 하다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import numpy as np # 임의의 문장을 출력하는 함수 생성 - 모델, 입력 문장, 희망 문장 길이를 받는다 def sentence_generate(model, seed_sentence, len_make_sentence): # seed_sentence : 계속 원문을 유지한 채로, 새로운 char 를 맨 뒤에 덧붙인다. str 자료형. seed_sentence = seed_sentence.lower() for i in range(len_make_sentence): # seq_X_encoded : seed_sentence 를 매 반복문마다 정수 인코딩해준 리스트 seq_X_encoded = [char_to_idx[c] for c in seed_sentence] seq_X_encoded = pad_sequences([seq_X_encoded], maxlen=len_make_sentence, padding='pre') onehot_X_encoded = to_categorical(seq_X_encoded, num_classes=char_size) predict_idx = np.argmax(model.predict(x=onehot_X_encoded)) tmp_char = idx_to_char[predict_idx] seed_sentence = tmp_char return seed_sentence | cs wlr |
>> sentence_generate(model, 'I GET on W', len_line)
이런 식으로, 임의의 str 을 전달한 뒤, 최대 문장 길이인 len_line 을 전달하면
전달받은 seed_sentence 를 기점으로 새로운 문장을 생성해낸다
**
다른 것보다, 차원수를 맞추기 위해 전처리 하는 과정이 꽤 걸렸다.
pad_sequence 를 하기 위해선 최소 2차원 텐서이여야 하며,
to_categorical 에서 num_classes 를 설정해주면, 원핫벡터의 차원 수를 내가 원하는 만큼 설정할 수 있으므로 차원수를 맞출때 용이하다
argmax 의 경우, 최대 value 값을 가진 key 값인 인덱스 값을 출력한다는 점도 기억하자
'기계학습 > 자연어 처리 머신러닝' 카테고리의 다른 글
활성화 함수 & 출력층 함수 개념정리 (0) | 2020.02.21 |
---|---|
유동 인구 예측 - 실전 프로젝트 (0) | 2020.02.20 |
글자단위 예측 모델 - N:N 모델 LSTM (0) | 2020.02.18 |
품사 태깅 - N:N 양방향 LSTM 모델 (0) | 2020.02.18 |
개체명 인식기 - N:N 양방향 LSTM 모델 (0) | 2020.02.17 |