일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Reverse Engineering
- 순차 컨테이너
- 표준 템플릿 라이브러리
- SWiFT
- 2020.06.14
- vector
- 모달인듯 모달 아닌 뷰
- Animation
- 백준 10828
- list
- stl
- Swing
- UIView
- BOJ
- ios
- 컴퓨터구조
- Stack
- 스택
- Reversing
- 백준 1920
- 컴퓨터 구조
- 알고리즘
- 2020.05.17
- class
- NavigationBar
- Constraint
- scroll
- UIPanGestureRecognizer
- 2020.04.19
- struct
- Today
- Total
야금야금
MLP로 텍스트 분류하기 본문
머신러닝 프레임워크는 글을 그대로 입력할 수 없다. 따라서 텍스트 데이터를 숫자로 변환해야 한다. 또한 텍스트 데이터는 이미지 데이터와 다르게 길이가 다르다. 이를 고정된 길이의 벡터로 변환하려면 어떻게 해야 할까?
다중 퍼셉트론(Multi Layer Perceptron, MLP)
: 입력층과 출력층 사이에 각각 전체 결합하는 은닉층을 넣은 뉴럴 네트워크
텍스트 데이터를 고정 길이의 벡터로 변환하는 방법
: 단어 하나하나에 ID를 부여하고 이 ID의 출현 빈도와 정렬 순서를 기반으로 벡터 제작
ex) "몇 번을 쓰러지더라도 몇 번을 무너지더라도 다시 일어나라" 문장 BoW로 나타내기
① 형태소 분석
몇 | 번 | 을 | 쓰러지다 | 몇 | 번 | 을 | 무너지다 | 다시 | 일어나다
② 각 단어에 ID 부여 & 출현 횟수 확인
형태소 | 몇 | 번 | 을 | 쓰러지다 | 무너지다 | 다시 | 일어나다 |
ID | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
출현 횟수 | 2 | 2 | 2 | 1 | 1 | 1 | 1 |
텍스트 분류하기
1] 텍스트에서 불필요한 품사를 제거한다
2] 사전을 기반으로 단어를 숫자로 변환한다
3] 파일 내부의 단어 출현 비율을 계산한다
4] 데이터를 학습시킨다
5] 테스트 데이터를 넣어 성공률을 확인한다
지금까지 텍스트를 분류하는 과정에 대해 알아보았다.
뉴스 기사 형태소 분석 파일을 만드는 실습에 앞서, 한국에서는 어떠한 신문사에서도 말뭉치를 제공하고 있지 않고 무단 전재가 금지돼 있는 관계로 신문 기사를 텍스트 분류의 1번 과정부터 진행하는 것이 아니라 형태소 분석이 되어있는 파일로 실습을 진행하도록 하자
단어를 ID로 변환하고 출현 횟수 구하기
다음은 형태소로 구분한 텍스트를 단어 ID로 변환하고 텍스트 내부에서의 출현 빈도를 구하는 프로그램이다.
import os, glob, json
root_dir = "./newstext"
dic_file= root_dir + "/word-dic.json"
data_file = root_dir + "/data.json"
data_file_min = root_dir + "/data-mini.json"
# 어구를 자르고 ID로 변환하기
word_dic = { "_MAX": 0}
def text_to_ids(text):
text = text.strip()
words = text.split(" ")
result = []
for n in words:
n = m.strip()
if n == "": continue
if not n in word_dic:
wid = word_dic[n] = word_dic["_MAX"]
word_dic["_MAX"] += 1
print(wid, n)
else:
wid = word_dic[n]
result.append(wid)
return result
# 파일을 읽고 고정 길이의 배열 리턴하기
def file_to_ids(fname):
with open(fname, "r") as f:
text = f.read()
return text_to_ids(text)
# 딕셔너리에 단어 모두 등록하기
def register_dic():
files = glob.glob(root_dir+"/*/*.gubun", recursive=True)
for i in files:
file_to_ids(i)
# 파일 내부의 단어 세기
def count_file_freq(fname):
cnt = [0 for n in range(word_dic["_MAX"])]
with open(fname, "r") as f:
text = f.read().strip()
ids = text_to_ids(text)
for wid in ids:
cnt[wid] += 1
return cnt
# 카테고리마다 파일 읽어 들이기
def count_freq(limit = 0):
X = []
Y = []
max_words = word_dic["_MAX"]
cat_names = []
for cat in os.listdir(root_dir):
cat_dir = root_dir + "/" + cat
if not os.path.isdir(cat_dir): continue
cat_idx = len(cat_names)
cat_names.append(cat)
files = glob.glob(cat_dir+"/*.gubun")
i = 0
for path in files:
print(path)
cnt = count_file_freq(path)
X.append(cnt)
Y.append(cat_idx)
if limit > 0:
if i > limit: break
i += 1
return X, Y
# 단어 딕셔너리 만들기
if os.path.exists(dic_file):
word_dic = json.load(open(dic_file))
else:
register_dic()
json.dump(word_dic, open(dic_file, "w"))
# 벡터를 파일로 출력하기
# 테스트 목적의 소규모 데이터 만들기
X, Y = count_freq(20)
json.dump({"X": X, "Y": Y}, open(data_file, "w"))
print("ok")
이 프로그램을 실행하면 6개의 카테고리에서 각각 20개씩만 추출해서 120개의 파일로만 처리한 "data-mini.json"파일과 모든 데이터를 대상으로 처리한 "data.json"파일이 생성된다.
MLP로 텍스트 분류하기
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import np_utils
from sklearn.model_selection import train_test_split
from sklearn import model_selection, metrics
import json
max_words = 56681 # 입력 단어 수: word-dic.json 파일 참고
nb_classes = 6 # 6개의 카테고리
batch_size = 64
nb_epoch = 20
# MLP 모델 생성하기 --- (※1)
def build_model():
model = Sequential()
model.add(Dense(512, input_shape=(max_words,)))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
return model
# 데이터 읽어 들이기--- (※2)
data = json.load(open("./newstext/data-mini.json"))
#data = json.load(open("./newstext/data.json"))
X = data["X"] # 텍스트를 나타내는 데이터
Y = data["Y"] # 카테고리 데이터
# 학습하기 --- (※3)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
Y_train = np_utils.to_categorical(Y_train, nb_classes)
print(len(X_train),len(Y_train))
model = KerasClassifier(
build_fn=build_model,
nb_epoch=nb_epoch,
batch_size=batch_size)
model.fit(X_train, Y_train)
# 예측하기 --- (※4)
y = model.predict(X_test)
ac_score = metrics.accuracy_score(Y_test, y)
cl_report = metrics.classification_report(Y_test, y)
print("정답률 =", ac_score)
print("리포트 =\n", cl_report)
'SWING > 머신러닝' 카테고리의 다른 글
문장의 유사도를 N-gram으로 분석하기 (0) | 2020.08.08 |
---|---|
베이즈 정리로 텍스트 분류하기 (0) | 2020.07.25 |
한국어 분석(형태소 분석) (0) | 2020.07.25 |
머신러닝의 이해와 지도학습을 이용한 분류 (0) | 2020.07.10 |
인공지능 서비스와 기술의 이해 (0) | 2020.07.10 |