ecsimsw

언어 구분 학습 / Scikit-learn 연습 /SVM 본문

언어 구분 학습 / Scikit-learn 연습 /SVM

JinHwan Kim 2020. 1. 24. 03:46

SVM

 

https://ecsimsw.tistory.com/entry/Support-Vector-Machine-Random-Forest

 

Support Vector Machine / Random Forest

from sklearn import svm, metrics clf = svm.SVC() clf.fit(valData,labelData) pre = clf.predict(valTEST) actualScore = metrics.accuracy_score(LabelTEST,pre) from sklearn.ensemble import RandomForestCl..

ecsimsw.tistory.com

 

언어 구분 학습 

 

   - 파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문에 소개된 언어 구분 학습 예제이다. 

 

   - 기본적인 아이디어는 이 세 언어마다 알파벳별 사용 빈도 비율가 달라, 이 빈도 차이를 기준으로 분류 학습을 하면 언어를 구분할 수 있겠다 라는 생각이다. (부호를 포함한 알파벳은 일단 무시하고 학습한다.)

 

왼쪽부터 독일어 / 프랑스어 / 영어

   - 위는 왼쪽부터 독일어 / 프랑스어 / 영어로 쓰여진 "파이썬"에 대한 위키 백과 내용이다. 이런 서로 다른 언어의 기사나 글을 직접 수집하여 사이킷 런으로 머신러닝하여 범주를 나눠주고 새로운 기사를 이 범주에 넣어 언어를 판별해 보았다.

 

   - 언어별 4개씩의 위키백과 자료를 학습 데이터로 하였고, 블로그/기사 등 무작위로 검색한 5개의 자료를 테스트 자료로 하여 학습 결과를 확인하였다.

 

 

Code

 

1. 라이브러리 import, 디렉토리 변수 지정 

import sys
from sklearn import svm, metrics
import urllib
import os.path, glob
import matplotlib.pyplot as plt
import pandas as pd 

path_test ="./test/"
path_data ="./data/"

 

2.  알파벳별 빈도수 비율 반환 함수 정의

# check frequency of using each alphabet 

def checkFreq(fname,path):
    lang = fname.split('-')[0]

    with open(path+fname+'.txt',mode="r", encoding="utf-8") as f:
        text = f.read()
    text.lower()

    cnt = [0 for n in range(0,26)]
    for char in text:
        if ord('a')<= ord(char) <=ord('z') :
            #print(ord(char)-ord('a'))
            cnt[ord(char)-ord('a')] += 1

    freq = list(map(lambda char: char/sum(cnt), cnt))
    return (freq,lang)

   - ord는 char형을 아스키 숫자로 변환한다. 알파벳이 아닌 글자는 무시한다. 

 

3. SVM 학습

# get data files 

data_freq=[]
data_lang=[]

files_data = glob.glob(path_data+'*.txt')
for f in files_data:
    fname= f.split('\\')[1].split('.txt')[0]
    data = checkFreq(fname,path_data)
    data_freq.append(data[0])
    data_lang.append(data[1])
    
clf = svm.SVC()
clf.fit(data_freq,data_lang)

4. test data load, predict

# get test files

test_freq=[]
test_lang=[]

files_test = glob.glob(path_test+'*.txt')
for f in files_test:
    fname= f.split('\\')[1].split('.txt')[0]
    data = checkFreq(fname,path_test)
    test_freq.append(data[0])
    test_lang.append(data[1])

# predict & report

predict = clf.predict(test_freq)
ac_score = metrics.accuracy_score(test_lang,predict)
cl_report = metrics.classification_report(test_lang, predict)

print("score : ",ac_score)
print("report : ")
print(cl_report)

5. 빈도수 그래프로 출력

# print frequency graph

graph_dic={}

for i in range(0,len(data_lang)):
    if not(data_lang[i] in graph_dic):
        graph_dic[data_lang[i]] = data_freq[i]

ascii_list = [chr(n) for n in range(ord('a'),ord('z')+1)]
df=pd.DataFrame(graph_dic,index = ascii_list)

plt.style.use('ggplot')
df.plot(kind='bar', subplots=True, ylim=(0,0.15))
plt.savefig(path_test+"test graph")

 

Result

 

< classification report >

 

   - 정확도 100%로 위키백과와 상관없이, 언어가 3가지 중 하나이고, 길이만 어느정도 긴 기사를 무작위로 저장하여 예측 분류한 5개의 테스트 파일을 모두 옳게 분류하였다. 다만 알파벳 빈도 비율을 기준으로 학습하다 보니, 기사 내용이 매우 짧은 언어는 틀리게 분류한다. 

 

   - 이외에도 예를 들어, 스웨덴 언어의 'å', 'ä' 와 'ö' 또는 한글과 같은 다른 언어와 구별할 수 있는 알파벳이나 글자 문화를 포인트가 되는 글자로 학습에 추가하는 것으로 코드를 작성하면, 더 많은 언어를 보다 정확하게 분류할 수 있을 것 같다.

   

score :  1.0
report :
              precision    recall  f1-score   support

          de       1.00      1.00      1.00         1
          en       1.00      1.00      1.00         3
          fr       1.00      1.00      1.00         1

    accuracy                           1.00         5
   macro avg       1.00      1.00      1.00         5
weighted avg       1.00      1.00      1.00         5

  

< frequency graph >

 

   - 각 언어별 알파벳 사용 비율을 그래프로 그리고 이를 저장하도록 하였다.

dl_language.txt
0.00MB

Comments