자연어처리(텍스트 이진 분류)
텍스트 이진 분류
- acllmdb_v1_small 폴더의 훈련 데이터는 긍부정 각 30개씩, 테스트 데이터는 긍부정 각 10개씩만 가지고 있다.
- 자료가 너무 적어 정상적인 정확도는 나오지 않고 연습용으로만 사용
Train Data Loading
imdb_dir = '/content/gdrive/My Drive/pytest/aclImdb_v1_small/aclImdb/'
import os
train_dir = os.path.join(imdb_dir, 'train') # aclimdb 폴더의 훈련 데이터 내용을 가져온다
labels = [] ; texts = [] # labels와 texts 라는 두 개의 빈 리스트를 만든다
for label_type in ['neg', 'pos']: # train 폴더에 있는 pos 12,500 + neg 12,500 개의 데이터를 읽는다
dir_name = os.path.join(train_dir, label_type) # neg와 pos 폴더 각각에 접근한다
for fname in os.listdir(dir_name):
if fname[-4:] == '.txt': # 마지막 4 글자가 .txt 로 끝나는지를 확인한다
f = open(os.path.join(dir_name, fname), encoding='utf8')
texts.append(f.read()) # 텍스트를 읽어서 texts 리스트에 연결한다
f.close()
if label_type == 'neg': # 만약 현재 폴더가 neg 폴더라면
labels.append(0) # texts와 같은 순서의 labels 리스트에 0을 저장한다
else:
labels.append(1) # pos 폴더라면 같은 순서의 labels 리스트에 1을 저장
Data Tokenizing
텍스트에 사용된 단어의 종류를 빈도 순으로 정렬하는 작업이다.
%tensorflow_version 2.x
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
import numpy as np
import math
validation_ratio = math.floor(len(texts) * 0.3) # 최적 모델 판정을 위한 검증 샘플은 전체의 30%로 한다
max_words = 10000 # 데이터셋에서 가장 빈도 높은 9,999 개의 단어만 사용한다
maxlen = 200 # 항상 각 문장의 길이가 200 단어가 되도록 고정한다
tokenizer = Tokenizer(num_words=max_words) # 상위빈도 max_words 개의 단어를 추려내는 Tokenizer 객체 생성
tokenizer.fit_on_texts(texts) # texts 내용에 대한 단어 인덱스를 구축한다. 사용할 단어가 결정된다
word_index = tokenizer.word_index # 단어와 인덱스의 쌍을 가져온다
#print(word_index) : {'the' : 1,'and' : 2 ,'a' :3 ...}
Tokenizer 예시
Tokenizing을 할 때는 그 대상들이 별개의 원소로 있어야 한다.
- 자료가 중첩 리스트로 있을 때의 경우이다. 중첩 리스트일때 원소가 분리가 안되있을 때 별개의 원소로 분리 해주어야 한다.
sample1=[['사과 감자 옥수수'],['딸기 감자 옥수수'],['양파 부추 옥수수']] # 출력 : ['사과 감자 옥수수':1,'딸기 감자 옥수수':2,'양파 부추 옥수수' :3] sample2 = [['사과', '감자', '옥수수'], ['너희', '감자', '옥수수'], ['그들', '감자', '옥수수'], ['양파', '부추', '옥수수']] # 출력 : ['옥수수':1,'감자':2,'사과':3,'그들':5,'양파':6,'부추':7]
-
단일리스트일 경우 별개의 원소로 분리되지 않아도 가능하다
sample3 = ['사과 감자 옥수수 너희 그들 양파 부추'] # 출력 : ['사과':1,'감자':2,'옥수수':3,'너희':4,'그들':5,'양파':6,'부추':7] sample4 = ['사과', '감자', '옥수수', '너희', '그들', '양파', '부추’] # 출력 : ['사과':1,'감자':2,'옥수수':3,'너희':4,'그들':5,'양파':6,'부추':7]
Data Sequencing
문자를 숫자로 변환하는 작업을 수행한다.
data = tokenizer.texts_to_sequences(texts) # 위에서 설정한 빈도 10,000의 결과가 여기서 반영된다.
Data Padding
- Padding은 데이터의 길이를 고정시켜준다. -> 행렬 연산을 쉽게하기 위함
- 지정된 길이에서 모자라는 것은 0으로 채우고, 넘치는 것은 잘라낸다.
- 길이를 고정해야 텐서의 크기가 맞춰진다,
- 기본값으로 단어의 선택은 뒤에서부터 한다.
- nested list를 2D 텐서(2차원 넘파이 배열)로 만든다.
from keras.preprocessing.sequence import pad_sequences
sequences=[[1,2,3,4,5],[1,2,3,4],[1]] # nested list
padded = pad_sequences(sequences,maxlen=3)
print(padded)
# 출력 : [[3 4 5]
# [2 3 4]
# [0 0 1]]
One-Hot Encoding
one-hot encoding은 모든 숫자를 0과 1로만 만든다.
def to_one_hot(sequences,dimension):
#zeros는 전달받은 x,y값으로 x*y행렬을 만들어 모두 0으로 채워준다.
results = np.zeros((len(sequences),dimension)
for i,sequence in enumerate(sequences):
results[i,sequence]=1
return results
)
data = to_one_hot(data,dimension=max_words)
#다중분류에서는 labels도 원-핫 인코딩을 한다
labels = np.asarray(labels).astype('float32')
Leave a comment