Skip to content

Commit 272d269

Browse files
authored
Update preprocess.py
1 parent 939a295 commit 272d269

File tree

1 file changed

+57
-79
lines changed

1 file changed

+57
-79
lines changed

6.CHATBOT/preprocess.py

Lines changed: 57 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import os
2-
import re
1+
# 1. preprocess.py :데이터불러오고가공
2+
# 2. Preprocess.ipynb :사전구성과 학습에사용될데이터로 구성
3+
# 3. seq2seq.ipynb :모델구성과 학습,평가,실행 할수있는파일
4+
5+
6+
import os # 운영체제기능사용
7+
import re # 정규표현식사용
38
import json
49

510
import numpy as np
611
import pandas as pd
712
from tqdm import tqdm
813

9-
from konlpy.tag import Okt
14+
from konlpy.tag import Okt # 한글형태소활용
1015

1116

1217
FILTERS = "([~.,!?\"':;)(])"
13-
PAD = "<PAD>"
14-
STD = "<SOS>"
15-
END = "<END>"
16-
UNK = "<UNK>"
18+
PAD = "<PAD>" # 아무의미없는 패딩토큰
19+
STD = "<SOS>" # 시작토큰의미
20+
END = "<END>" # 종료토큰의미
21+
UNK = "<UNK>" # 사전에없는단어를의미
1722

1823
PAD_INDEX = 0
1924
STD_INDEX = 1
@@ -25,112 +30,88 @@
2530

2631
MAX_SEQUENCE = 25
2732

28-
29-
def load_data(path):
30-
# 판다스를 통해서 데이터를 불러온다.
31-
data_df = pd.read_csv(path, header=0)
32-
# 질문과 답변 열을 가져와 question과 answer에 넣는다.
33-
question, answer = list(data_df['Q']), list(data_df['A'])
34-
33+
# 1데이터를 판다스를통해 불러와서 데이터프레임형태로만듬 /question,answer반환
34+
def load_data(path):
35+
data_df = pd.read_csv(path, header=0)
36+
question, answer = list(data_df['Q']), list(data_df['A'])
3537
return question, answer
3638

37-
39+
# 2데이터를 단어리스트로만듬
3840
def data_tokenizer(data):
3941
# 토크나이징 해서 담을 배열 생성
4042
words = []
4143
for sentence in data:
4244
# FILTERS = "([~.,!?\"':;)(])"
43-
# 위 필터와 같은 값들을 정규화 표현식을
44-
# 통해서 모두 "" 으로 변환 해주는 부분이다.
45-
sentence = re.sub(CHANGE_FILTER, "", sentence)
45+
# 위 필터와 같은 값들을 정규화 표현식을 통해서 모두 "" 으로 변환 해주는 부분이다.
46+
sentence = re.sub(CHANGE_FILTER, "", sentence) # 정규표현식을사용해 특수기호제거, 공백문자기준으로 단어를나눠 전체데이터의 모든단어를 포함하는 단어리스트로 만듬
4647
for word in sentence.split():
4748
words.append(word)
48-
# 토그나이징과 정규표현식을 통해 만들어진
49-
# 값들을 넘겨 준다.
49+
# 토그나이징과 정규표현식을 통해 만들어진값들을 넘겨 준다.
5050
return [word for word in words if word]
5151

52-
52+
# 3텍스트를 형태소로 분리
5353
def prepro_like_morphlized(data):
5454
morph_analyzer = Okt()
5555
result_data = list()
5656
for seq in tqdm(data):
5757
morphlized_seq = " ".join(morph_analyzer.morphs(seq.replace(' ', '')))
5858
result_data.append(morphlized_seq)
59-
6059
return result_data
6160

62-
63-
def load_vocabulary(path, vocab_path, tokenize_as_morph=False):
64-
# 사전을 담을 배열 준비한다.
65-
vocabulary_list = []
66-
# 사전을 구성한 후 파일로 저장 진행한다.
67-
# 그 파일의 존재 유무를 확인한다.
68-
if not os.path.exists(vocab_path):
69-
# 이미 생성된 사전 파일이 존재하지 않으므로
70-
# 데이터를 가지고 만들어야 한다.
71-
# 그래서 데이터가 존재 하면 사전을 만들기 위해서
72-
# 데이터 파일의 존재 유무를 확인한다.
73-
if (os.path.exists(path)):
74-
# 데이터가 존재하니 판단스를 통해서
75-
# 데이터를 불러오자
61+
# 4단어사전을 만드는함수
62+
def load_vocabulary(path, vocab_path, tokenize_as_morph=False):
63+
vocabulary_list = [] # 사전을담을배열
64+
65+
# 사전을 구성한 후 파일로 저장 진행한다.
66+
if not os.path.exists(vocab_path): # 이미생성된 사전파일이 존재하지않음. 데이터를가지고 만든다. 데이터존재시 사전만듬
67+
if (os.path.exists(path)): # 데이터존재함. 판다스로 데이터불러옴
7668
data_df = pd.read_csv(path, encoding='utf-8')
77-
# 판다스의 데이터 프레임을 통해서
78-
# 질문과 답에 대한 열을 가져 온다.
69+
70+
# 판다스의 데이터 프레임을통해서 질문과 답에 대한 열을 가져 온다.
7971
question, answer = list(data_df['Q']), list(data_df['A'])
80-
if tokenize_as_morph: # 형태소에 따른 토크나이져 처리
81-
question = prepro_like_morphlized(question)
82-
answer = prepro_like_morphlized(answer)
72+
if tokenize_as_morph: # 형태소에따른 토크나이져 처리
73+
question = prepro_like_morphlized(question) # 텍스트를형태소로분리(앞의함수)
74+
answer = prepro_like_morphlized(answer) # 텍스트를형태소로분리(앞의함수)
75+
8376
data = []
84-
# 질문과 답변을 extend을
85-
# 통해서 구조가 없는 배열로 만든다.
86-
data.extend(question)
87-
data.extend(answer)
88-
# 토큰나이져 처리 하는 부분이다.
89-
words = data_tokenizer(data)
90-
# 공통적인 단어에 대해서는 모두
91-
# 필요 없으므로 한개로 만들어 주기 위해서
92-
# set해주고 이것들을 리스트로 만들어 준다.
93-
words = list(set(words))
94-
# 데이터 없는 내용중에 MARKER를 사전에
95-
# 추가 하기 위해서 아래와 같이 처리 한다.
96-
# 아래는 MARKER 값이며 리스트의 첫번째 부터
97-
# 순서대로 넣기 위해서 인덱스 0에 추가한다.
98-
# PAD = "<PADDING>"
77+
# 질문과 답변을 extend을 통해서 구조가 없는 배열로 만든다.
78+
data.extend(question)
79+
data.extend(answer)
80+
words = data_tokenizer(data) # 데이터를단어리스트로만듬(앞의함수)
81+
words = list(set(words)) # 공통적인 단어에 대해서 한개로 만들어 주기 위해서 set해주고 이것들을 리스트로 만들어 준다.
82+
# PAD = "<PADDING>" # 데이터 없는 내용중에 MARKER를 사전에 추가 하기 위해서 아래와 같이 처리 한다.
9983
# STD = "<START>"
10084
# END = "<END>"
10185
# UNK = "<UNKNWON>"
102-
words[:0] = MARKER
103-
# 사전을 리스트로 만들었으니 이 내용을
104-
# 사전 파일을 만들어 넣는다.
86+
words[:0] = MARKER # 아래는 MARKER 값이며 리스트의 첫번째부터 순서대로 넣기 위해서 인덱스 0에 추가한다.
87+
88+
# 사전을 리스트로 만들었으니 이 내용을 사전 파일을 만들어 넣는다.
10589
with open(vocab_path, 'w', encoding='utf-8') as vocabulary_file:
10690
for word in words:
10791
vocabulary_file.write(word + '\n')
10892

109-
# 사전 파일이 존재하면 여기에서
110-
# 그 파일을 불러서 배열에 넣어 준다.
93+
# 사전 파일이 존재하면 여기에서 그 파일을 불러서 배열에 넣어 준다.
11194
with open(vocab_path, 'r', encoding='utf-8') as vocabulary_file:
11295
for line in vocabulary_file:
11396
vocabulary_list.append(line.strip())
11497

115-
# 배열에 내용을 키와 값이 있는
116-
# 딕셔너리 구조로 만든다.
98+
# 배열에 내용을 키와 값이 있는 딕셔너리 구조로 만든다.
11799
char2idx, idx2char = make_vocabulary(vocabulary_list)
118-
# 두가지 형태의 키와 값이 있는 형태를 리턴한다.
119-
# (예) 단어: 인덱스 , 인덱스: 단어)
100+
# 두가지 형태의 키와 값이 있는 형태를 리턴한다. (예) 단어: 인덱스 , 인덱스: 단어)
120101
return char2idx, idx2char, len(char2idx)
121102

122103

123-
def make_vocabulary(vocabulary_list):
124-
# 리스트를 키가 단어이고 값이 인덱스인
125-
# 딕셔너리를 만든다.
104+
# 5단어리스트를 인자로 두개의 딕셔너리를만듬
105+
def make_vocabulary(vocabulary_list):
106+
# vocabulary_list에 [안녕,너는,누구야] 들어있다면 word2idx에는 key가 안녕,너는,누구야/value는 0,1,2 이고, idx2word는 key,value가반대이다.
107+
# 리스트를 키가 단어이고 값이 인덱스인 딕셔너리를 만든다.
126108
char2idx = {char: idx for idx, char in enumerate(vocabulary_list)}
127-
# 리스트를 키가 인덱스이고 값이 단어인
128-
# 딕셔너리를 만든다.
109+
# 리스트를 키가 인덱스이고 값이 단어인 딕셔너리를 만든다.
129110
idx2char = {idx: char for idx, char in enumerate(vocabulary_list)}
130111
# 두개의 딕셔너리를 넘겨 준다.
131112
return char2idx, idx2char
132113

133-
114+
# 6인코더적용 입력값 만듬
134115
def enc_processing(value, dictionary, tokenize_as_morph=False):
135116
# 인덱스 값들을 가지고 있는
136117
# 배열이다.(누적된다.)
@@ -180,7 +161,7 @@ def enc_processing(value, dictionary, tokenize_as_morph=False):
180161
# 그 길이를 넘겨준다.
181162
return np.asarray(sequences_input_index), sequences_length
182163

183-
164+
# 7디코더의 입력값을 만드는함수
184165
def dec_output_processing(value, dictionary, tokenize_as_morph=False):
185166
# 인덱스 값들을 가지고 있는
186167
# 배열이다.(누적된다)
@@ -222,22 +203,19 @@ def dec_output_processing(value, dictionary, tokenize_as_morph=False):
222203
# 넘파이 배열에 인덱스화된 배열과 그 길이를 넘겨준다.
223204
return np.asarray(sequences_output_index), sequences_length
224205

225-
206+
# 8디코더의 타깃값을 만드는 전처리함수
226207
def dec_target_processing(value, dictionary, tokenize_as_morph=False):
227-
# 인덱스 값들을 가지고 있는
228-
# 배열이다.(누적된다)
208+
# 인덱스 값들을 가지고 있는 배열이다.(누적된다)
229209
sequences_target_index = []
230210
# 형태소 토크나이징 사용 유무
231211
if tokenize_as_morph:
232212
value = prepro_like_morphlized(value)
233213
# 한줄씩 불어온다.
234214
for sequence in value:
235215
# FILTERS = "([~.,!?\"':;)(])"
236-
# 정규화를 사용하여 필터에 들어 있는
237-
# 값들을 "" 으로 치환 한다.
216+
# 정규화를 사용하여 필터에 들어 있는값들을 "" 으로 치환 한다.
238217
sequence = re.sub(CHANGE_FILTER, "", sequence)
239-
# 문장에서 스페이스 단위별로 단어를 가져와서
240-
# 딕셔너리의 값인 인덱스를 넣어 준다.
218+
# 문장에서 스페이스 단위별로 단어를 가져와서 딕셔너리의 값인 인덱스를 넣어 준다.
241219
# 디코딩 출력의 마지막에 END를 넣어 준다.
242220
sequence_index = [dictionary[word] if word in dictionary else dictionary[UNK] for word in sequence.split()]
243221
# 문장 제한 길이보다 길어질 경우 뒤에 토큰을 자르고 있다.

0 commit comments

Comments
 (0)