다중 퍼셉트론을 이용해서 텍스트 분류하기

2018. 5. 20. 13:34Python-이론/python-인공지능

다중 퍼셉트론을 이용해서 텍스트 분류하기




필요한 데이터들 

신문기사자료1.zip

신문기사자료2.zip

신문기사자료3.zip


저번 글에서는 베이즈의 정리를 사용해서 텍스트를 구분시켜 보았는데 이번에는 딥러닝을 사용해서 구분시켜보겠습니다.

다중 퍼셉트론이란 

입력 층과 출력 층사이에 이 두개를 연결하는 은닉층을 넣는 뉴럴 네트워크입니다. 

데이터를 어떤형태로 만들 것인가??

1. 하나의 뉴스기사를 단어들을 모두 구분 시켜놓는다. 
2. 각 단어마다 ID값을 지정해줍니다.
3. {X:[ [기사 1의 단어 베열] , [기사 2의 단어배열], [기사 3의 단어 배열] .....},Y:[기사1의 카테고리 , 기사2의 카테고리 .......] 이런식으로 표현 시켜준다. 

json파일을 만드는 코드 
 



import os, sys, glob
import json
root = "./newsData/"
wordsData = "./words.json"
mainData = "./data.json"
miniData = "./miniData.json"
word_dic = {"MAX":0}

def makingXY(limit=0):
    fileList = os.listdir(root)
    Y =[]
    X = []
    i = 0
    for fileName in fileList:
        if os.path.isdir(root+fileName):
            Xdata = globFile(root+fileName,X,Y,i,limit)
            i+=1
    return X,Y

def globFile(fileName,X,Y,categoryNum,limit):
    fileList = glob.glob(fileName+"/*.txt.wakati")
    r = []
    result = []
    j = 0
#입력 데이터 만들기 
    for fileName in fileList:
        Y.append(categoryNum)
        Xdata = fileRead(fileName)
        Xdata = incWordDic(Xdata)
        cnt = setCnt(Xdata)
        if limit > 0:
            if limit == j:break
            j+=1
        X.append(cnt)


def fileRead(fileName):
    fp = open(fileName,'r',encoding ='utf-8')
    fp = fp.read().strip()
    return fp.split(" ")
#각 단어의 id만들기
def incWordDic(Xdata):
    result = []
    for data in Xdata:
        if data not in word_dic:
            wid = word_dic[data] = word_dic["MAX"]
            word_dic["MAX"] += 1
        else:
            wid = word_dic[data]
        result.append(wid)
    return result
#각기사에 대한 단어 출현 정보 만들기
def setCnt(wordNum):
    cnt = [ 0 for i in range(word_dic["MAX"])]
    for num in wordNum:
        cnt[num] += 1
    return cnt

if os.path.exists(wordsData):
    word_dic = json.load(open(wordsData,'r'))
else:
    fileList = glob.glob(root+"*/*.*.wakati")
    for fileName in fileList:
        Xdata = fileRead(fileName)
        incWordDic(Xdata)
    json.dump(word_dic ,open(wordsData,'w'))

X,Y = makingXY()
#딥러닝에 사용할 입력데이터 만들기 
json.dump({"X":X,"Y":Y},open(mainData,'w'))

딥러닝 코드




from sklearn.model_selection import train_test_split
from sklearn import model_selection, metrics

from keras.models import Sequential
from keras.layers import Activation, Dropout,Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import np_utils

import json
import numpy as np
jsonFile = json.load(open('data.json'))
wordsFile = json.load(open('words.json'))
max_words = wordsFile["MAX"]

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(6))
    model.add(Activation('softmax'))
    model.compile(loss='categorical_crossentropy',
            optimizer='adam',
            metrics=['accuracy'])
    return model

X = jsonFile["X"]
Y = jsonFile["Y"]

trainData, testData, trainLabel, testLabel = train_test_split(X,Y)
Y_train = np_utils.to_categorical(trainLabel,6)
model = KerasClassifier(
        build_fn = build_model,
        nb_epoch = 30,
        batch_size =64
        )
model.fit(np.array(trainData),np.array(trainLabel))
y = model.predict(np.array(testData))
ac_score = metrics.classification_report(np.array(y),np.array(testLabel))
report = metrics.accuracy_score(np.array(y),np.array(testLabel))

print(ac_score)
print(report)




원래 원본데이터는 각 칵테고리당 3000개 정도의 기사가 있었는데 필자의 경우에는 데이터가 너무 커서 컴퓨터가 돌리지 못했다 그래서 각 칵테고리당 20개의 기사를 사용했다. 그래서 정확률이 높게 않나온 것을 알 수 있다.