자연어로 된 내용인 뉴스, 블로그 게시글, 댓글 등의 데이터를 카테고리별로 분류해주는 머신러닝을 구현해 보겠습니다.
( 참고로 머신러닝을 개발하기 위해 필요한 모델은 오픈 소스를 이용할 예정입니다 )
데이터 수집
기계를 학습시키기 위해선 Train Data 즉 라벨링이 된 데이터를 필요로 합니다.
Train Data를 보여드리자면 아래와 같은 형식입니다.
필자의 경우 Train Data를 뉴스 기사, 본문, 언론사, 카테고리로 만들었습니다. ( 확장자는 csv 이며 DB를 이용할 수 있으신 분이면 DB를 이용하셔도 됩니다. )
정부에서 운영하고 있는 공공데이터포털은 존재하지만 국내에는 Kaggle과 같은 빅데이터를 공유하는 활성화가 잘 된 포럼이 없습니다. 그래서 저는 기사를 크롤링해서 뉴스 데이터를 수집했습니다. 크롤링한 사이트는 네이버 뉴스 카테고리입니다. 제가 크롤링한 데이터를 배포하고 싶지만 저작권 문제가 있어 배포할 수 없습니다. 하지만 저와 같은 데이터를 가지고 싶으시다면 제 github에 올라와 있는 크롤러를 이용하시면 됩니다. 뉴스 크롤러: https://github.com/lumyjuwon/newscrawler
데이터 셔플
크롤링을 통해 많은 데이터를 수집하셨다면 그 다음 필요한 것은 데이터 셔플입니다. 이 프로젝트를 진행할 때 데이터 셔플을 진행하지 않고 10만 개 사회 데이터 -> 10만 개 정치 데이터-> 10만 개 스포츠 데이터 순서로 된 30만 개의 데이터를 학습시켰던 적이 있습니다. 이렇게 학습시킬 경우 사회 데이터를 Optimizing 한 다음 정치 카테고리를 사회 카테고리로 인식해버립니다.
즉 10만 개 사회 데이터만 연속으로 학습을 시키다 보니깐 최적의 W를 사회 카테고리에서만 발견하게 되고 다음 카테고리 데이터에서는 별 효율이 없는 학습을 진행하게 된다는 것입니다.
데이터 셔플이 안 된 데이터를 가지고 학습 시킨 머신러닝에게 정치 데이터를 입력시켜도 사회라고 출력하며 스포츠를 입력해도 사회를 출력합니다.
이러한 결과를 만들어 내지 않기 위해서 csv를 합친 후에 셔플하는 방법에 대해서 말씀드리겠습니다.
제가 올려둔 크롤러를 통해 모은 데이터를 하나의 데이터로 합칩니다.
데이터를 하나의 csv로 합치기 어려우신 분은 아래 코드를 참고하시면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import csv import os os.chdir("C:\\Users\\Juwon\\PycharmProjects\\tensorflows\\parser\\Csv") // Csv가 있는 파일 위치 수정 category = ['IT과학', '경제', '정치', 'e스포츠', '골프', '농구', '배구', '야구', '일반 스포츠', '축구', '사회', '생활문화'] file_unity = open('Article_unity.csv', 'w', encoding='euc-kr') wcsv = csv.writer(file_unity) count = 0 for category_element in category: file = open('Article_'+category_element+'.csv', 'r', encoding='euc-kr', newline="") line = csv.reader(file) try: for line_text in line: wcsv.writerow([line_text[0], line_text[1], line_text[2], line_text[3]]) except: pass |
위 코드를 이용해 모든 데이터를 하나의 csv로 통합시킵니다.
통합시킨 csv를 가지고 이제 shuffle을 할 차례입니다.
참고로 여기서 shuffle이라는 것은 순서대로 되어 있는 데이터를 섞는다는 뜻입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import csv import random import os os.chdir("C:\\Users\\Juwon\\PycharmProjects\\tensorflows\\parser\\Csv") // Csv가 있는 경로 설정 file = open('Article_unity.csv', 'r', encoding='euc-kr') line = file.readlines() random.shuffle(line) rcsv = csv.reader(line) file_write = open('Article_shuffled.csv', 'w', encoding='euc-kr', newline="") wcsv = csv.writer(file_write) for i in rcsv: try: wcsv.writerow([i[0].strip(), i[1], i[2], i[3]]) except: pass |
위 코드를 이용해 데이터 셔플을 해주시면 됩니다.
* Csv 용량이 커서 마이크로소프트 엑셀로 못 여는 경우가 생깁니다. 이런 경우 파이썬에서 Csv를 열어 한 줄 한 줄 씩 출력하시는 수밖에 없습니다. Csv 열어 확인하는 방법은 아래 코드를 참고하시기 바랍니다.
1 2 3 4 5 6 7 8 9 10 11 12 |
import csv import os os.chdir("C:\\Users\\Juwon\\PycharmProjects\\tensorflows\\parser\\Csv") // 파일 경로 변경 file = open('Article_shuffled.csv', 'r', encoding='euc-kr') line = csv.reader(file) for i in line: print(i[0], i[1], i[2], i[3]) |
형태소 분석 및 Word2Vec
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 32 33 34 35 36 37 38 |
from konlpy.tag import Twitter from gensim.models import Word2Vec import csv twitter = Twitter() file = open("Article_shuffled.csv", 'r', encoding='euc-kr') line = csv.reader(file) token = [] embeddingmodel = [] for i in line: sentence = twitter.pos(i[0], norm=True, stem=True) temp = [] temp_embedding = [] all_temp = [] for k in range(len(sentence)): temp_embedding.append(sentence[k][0]) temp.append(sentence[k][0] + '/' + sentence[k][1]) all_temp.append(temp) embeddingmodel.append(temp_embedding) category_number_dic = {'IT과학': 0, '경제': 1, '정치': 2, 'e스포츠': 3, '골프': 4, '농구': 5, '배구': 6, '야구': 7, '일반 스포츠': 8, '축구': 9, '사회': 10, '생활문화': 11} all_temp.append(category_number_dic.get(category)) token.append(all_temp) print("토큰 처리 완료") embeddingmodel = [] for i in range(len(token)): temp_embeddingmodel = [] for k in range(len(token[i][0])): temp_embeddingmodel.append(token[i][0][k]) embeddingmodel.append(temp_embeddingmodel) // max_vocab size 10000000 개당 1 GB 메모리 차지 embedding = Word2Vec(embeddingmodel, size=300, window=5, min_count=10, iter=5, sg=1, max_vocab_size = 360000000) embedding.save('post.embedding') |
위 코드를 이용해 shuffle 된 통합 데이터를 형태소 분석 한 다음 분석 된 데이터를 가지고 Word2Vec을 진행합니다.
참고로 Word2Vec을 진행하는데 시간이 오래 걸리니 참고하시기 바랍니다.
* 본문에서는 뉴스 기사의 제목을 가지고 Word2Vec을 진행하게 됩니다. 그래픽카드 TensorFlow 버전 및 메모리가 충분하신 분들은 뉴스 기사 본문을 가지고 Word2Vec 하셔도 됩니다 *
머신러닝 학습 Bi_LSTM 모델
Bi_LSTM 모델을 이용하여 머신을 학습시킵니다.
형태소 분석 및 Word2Vec ~ BI_LSTM 학습까지에 관한 소스를 아래 Github에 올려두었습니다.
+ 기사 제목이 Word2Vec (embedding) 된 파일을 github에 같이 넣어 뒀으므로 Classifier.py를 실행하셔서 테스트 해보시기 바랍니다.
게시글 및 댓글 카테고리 분석기: https://github.com/lumyjuwon/CategoryClassifier
결과
AI 서비스 ‘목소리’는 누굴까
IT과학 73.96 %
경제 18.72 %
정치 0.11 %
e스포츠 1.91 %
골프 0.0 %
농구 0.0 %
배구 0.0 %
야구 0.0 %
일반 스포츠 0.02 %
축구 0.0 %
사회 3.24 %
생활문화 2.03 %
티몬, 독립운동가 후손 주거 개선에 2500만원 기부
IT과학 4.53 %
경제 85.36 %
정치 0.83 %
e스포츠 0.0 %
골프 0.0 %
농구 0.0 %
배구 0.0 %
야구 0.0 %
일반 스포츠 0.11 %
축구 0.0 %
사회 3.31 %
생활문화 5.86 %
한국기자협회 창립 54주년 기념식…”언론자유 위한 노력 박차”
IT과학 0.47 %
경제 3.59 %
정치 4.22 %
e스포츠 0.04 %
골프 0.08 %
농구 0.0 %
배구 0.18 %
야구 0.04 %
일반 스포츠 5.86 %
축구 0.21 %
사회 6.45 %
생활문화 78.87 %
[떠나요 강심장] 일제강점기·해방공간 아픔 밴 여수여행
IT과학 0.04 %
경제 3.25 %
정치 0.47 %
e스포츠 0.0 %
골프 0.01 %
농구 0.0 %
배구 0.0 %
야구 0.01 %
일반 스포츠 0.41 %
축구 0.0 %
사회 3.77 %
생활문화 92.03 %
‘강승호-최항 활약’ SK 내야, 긴장-경쟁의 기운 감돈다
IT과학 0.0 %
경제 0.0 %
정치 0.0 %
e스포츠 0.0 %
골프 0.0 %
농구 0.0 %
배구 0.0 %
야구 100.0 %
일반 스포츠 0.0 %
축구 0.0 %
사회 0.0 %
생활문화 0.0 %
타격이야 거의 입증될듯 싶고 둘다 수비만 더 잘해주면 매우 든든하겠는데..
IT과학 0.0 %
경제 0.0 %
정치 0.0 %
e스포츠 0.0 %
골프 0.01 %
농구 0.0 %
배구 0.0 %
야구 99.85 %
일반 스포츠 0.09 %
축구 0.03 %
사회 0.0 %
생활문화 0.01 %
[스포티비뉴스=홍지수 기자] 당연한 것도 없고 정해진 것도 없다. SK 와이번스 내야수들은 좀더 긴장할 필요가 생겼다.
최항의 성장, 그리고 이적생 강승호의 활약이 SK 내야진에 긴장된 분위기를 만들고 있다. 감독이나 코치진이 바라볼 때는 좋은 방향으로 가고 있는 것이다. 선수들도 더 긴장하고 노력하게 되면서 한층 더 실력을 키우는 계기가 될 것이다. 지난달 31일, 트레이드로 LG 트윈스를 떠나 SK 유니폼을 입은 강승호는 최근 맹타를 휘두르고 있다. SK 이적 후 16일까지 타율 0.400(25타수 10안타) 1홈런 9타점 활약을 펼치고 있다. 트레이드 때 병역 의무를 마친 내야수 자원 보강을 고민하던 SK였다. 강승호를 영입한 이유는 내야 멀티 포지션 수비를 소화할 수 있다는 장점을 봤기 때문이다. 물론 타격 능력도 준수하다고 평가했다. 정경배 코치는 “SK로 오기 전 LG 코치님들이 승호를 많이 가르쳐주신 듯 하다. 가능성이 보이니까 더 가르치려고 하게 되는거다”고 설명하기도 했다. 최근 기대 이상으로 해주고 있다. 더구나 최정의 공백도 잘 메웠다. 왼쪽 허벅지 근육 손상으로 전력에서 이탈했던 최정. 재활에 전념한 뒤 돌아왔지만 아직 정상 컨디션이 아닌 상황에서 강승호의 존재가 든든할 수밖에 없다.
IT과학 0.0 %
경제 0.0 %
정치 0.01 %
e스포츠 0.05 %
골프 0.0 %
농구 0.0 %
배구 0.0 %
야구 99.25 %
일반 스포츠 0.65 %
축구 0.0 %
사회 0.0 %
생활문화 0.04 %
후기
거의 한 달의 기간 동안 데이터 수집부터 시작해서 머신러닝에 관한 전반적인 내용을 이해하느라 꽤 고생했던거 같습니다.
하지만 새로운 분야에 접할 수 있어서 머신러닝의 어려운 점과 같은 광범위한 내용들을 학습할 수 있었던거 같습니다.
무엇보다 인공지능 분야는 수학 전공자에게 유리하다는 것을 알게 됐습니다. 저는 단지 딥러닝 모델을 가져와 Input, Output 부분만 수정 및 추가하여 썼기 때문에 머신러닝 전체를 만들지는 못한다는 것입니다. 인공 신경망 등을 만들기 위해선 매우 많은 전공 수학들이 필요하고 거기서 더 깊숙하게 들어가기엔 아직 한참 멀었기 때문이죠.
원래는 댓글의 카테고리를 분류하기 위해 개발했지만 방대한 데이터와 Bi_LSTM 모델을 이용함으로서 모든 자연어 내용에 대한 카테고리를 분류해줄 수 있게 됐습니다. 글의 제목, 본문, 댓글 등의 내용이 있는 모든 것들을 말이죠
단점이라고 하면 카테고리가 크게 세분화 되지 않아서 정해진 카테고리 외의 내용에 대해서는 모호한 결과를 내놓을 수 있다는 것입니다.뿐만 아니라 가끔은 데이터 학습 과정에서 특정 데이터가 부족한 부분들이 있는 경우도 있어 의도치 않은 결과를 내놓기도 합니다.이런 문제들은 튜닝을 통해 고쳐가야 하지만 Learning_rate 라던지 epoch, batch_size 등의 매우 많은 요인들이 있어 시간적인 어려움이 있었습니다.
머신러닝을 하면서 느꼈던 것은 이 분야가 정말 매우 많은 곳에 사용될 수 있다는 것입니다. 요즘 게임 분야에서도 인공지능을 도입하여 게임 데이터를 분석하거나 더 좋은 게임 AI를 개발하고 있습니다. 또한 클린한 게임 환경을 만들기 위해 머신러닝을 사용하고 있습니다.블리자드 같은 경우 머신러닝을 도입하여 오버워치와 같은 게임에서 채팅으로 욕설을 하는 유저를 판단하여 제재하는 등의 기술을 선보이고 있습니다. 앞으로 개발자에게는 프로그램 개발 능력만 중요시하게 되는 것이 아니라 프로그램 개발 후의 수집되는 데이터를 어떻게 처리해 자신이 맡고 있는 프로그램을 어떤 방식으로 개선해 나갈지 중요한 요인이 될 것 같습니다.
정리
- 머신러닝을 어떤 용도로 쓸 것인지에 대해 결정
- 결정한 용도에 맞는 인공신경망 모델 탐색
- 학습을 시킬 수 있을 정도의 데이터 수집
2019년 6월 6일 이후 .. 추가 내용을 남깁니다.
꽤 많은 분들이 제 글을 보시고 머신러닝, 자연어 처리 등의 새로운 분야로 뛰어드시고 계셔서 기쁘다는 말씀을 드립니다.
Classifier 진행을 하시기 전에 참고하셔야 하는 부분을 말씀드립니다.
본 게시글은 작년에 작성된 게시글이라 현재 Tensorflow 버전 및 gensim에 맞지 않는 코드들이 있을 수 있습니다. 또한 이 Classifier 코드와는 다르게 KoreaNewsCrawler는 지속적으로 업데이트가 되고 있어 Classifier 코드에서 CSV의 column 번호가 KoreaNewsCrawler에서 수집한 데이터 CSV column번호와 달라 오류가 발생할 수 있으니 이 부분은 따로 코드를 수정해주셔야 합니다.
나중에 시간이 된다면 Classifier를 수정해서 글을 재작성 하도록 하겠습니다. 감사합니다.
(+ Classifier에 하드 코딩 된 부분이 꽤 많습니다… )
이 머신에 추가된 다른 내용을 또 교육을 시키고 싶을 때 플로우를 알려주실 수 있나요 ?!
답장이 늦어 죄송합니다. 추가된 다른 내용이라는게 정확하게 어떤 의미인지 알려주실 수 있으신가요 ?
답장 감사합니다 !
그 먼저 사전에 뉴스데이터로 교육을 시키고나서 내용을 기존에서 더 추가하고 싶을때 (기존 데이터)
Bi_LSTM_csv_train.py 이 파일을 가지고 하는 것 같던데,, 잘 안되서 혹시 어떻게 하면 되나요..?!
예로 들어 뉴스 데이터를 100개 만큼 학습을 시켜둔 모델에 뉴스 데이터 100개를 더 학습시켜 총 200개를 학습시킨 모델을 만들고 싶으시다는 말씀이신가요 ?
네네 ㅠㅠ 그 만약에 어떤 문장을 기입했을 때 원하는 카테고리가 안나왔을 경우
머신에 Train 시켜서 그 문장은 이 카테고리라고 교육하는거에요 ㅠㅠ !
Classifier.py에 가보시면 Convert2Vec 함수가 있는데 if (word in model.wv.vocab): sub.append(model.wv[word]) else: #수동 학습 sub.append(np.random.uniform(-0.25, 0.25, 300)) ## used for OOV words 단어가 이미 학습시킨 trained model의 wv.vocab에 존재하는 경우 trained model에서 가져와 return을 합니다. 하지만 그렇지 않은 경우 임시로 -0.25~0.25의 값들로 300차원 백터를 return 합니다. 김학생님이 말씀해주셨던 수동 학습은 #수동 학습이라 주석처리 돼 있는 else 문 안에서 처리해주셔야 할 것 같습니다. else문 안에서 처리하는 방법은 입력한 문장 전체를 Word2Vec해서 다시 Train 하는 방법 밖에 없습니다. 아마도 김학생님이 원하시는 내용은 동적 학습인거 같은데 저도 동적 학습을 한 적은 없어서 구체적으로 설명을 드릴 순 없을 것 같습니다. 제가 추천드리고 싶은 것은 정적… Read more »
자세한 설명 정말 감사드립니다 !!
C2Word2Vec.py 를 해서 post.embedding이 만들어지던데 이것이 trained model 인가요??
저는 이렇게 교육을 시키고 추가적으로 csv를 만들어서 Bi_LSTM_csv_train.py 로 돌려봤는데
Bidirectional_LSTM에 로그들이 들어가는 것 같고 Bi_LSTM.data-0000-of-00001 과 index, meta 등 여러 파일이 생성 되던데 이렇게 수동으로 교육을 해서 다시 Classifie.py 를 켜서 같은 문장을 입력해도 이전의 결과값과 동일해서 혹시 추가 교육하는 부분은 구현 안되어있는 것인가요 ..??
귀중한 시간 내주셔서 정말 감사드립니다..ㅠㅠ
네 post.embedding이 trained model입니다. 먼저 추가 교육하는 부분은 구현이 돼 있지 않습니다. 김학생님이 추가적으로 csv를 만들어서 Bi_LSTM_csv_train.py를 돌려보셨다고 해주셨는데 Bi_LSTM_csv_train.py에는 이미 생성된 trained model에서 학습 상황을 불러오는 기능은 추가 돼지 않았습니다. 그래서 추가적으로 csv를 만들어서 train을 하셔도 추가적으로 만든 csv가 train 되는 것이지 기존 + 추가 데이터가 train되는 것은 아닙니다. 그리고 classifier.py켜서 문장을 입력해도 기존과 똑같다 하셨는데 그건 Classifier.py 안에 embedding = Convert2Vec(‘Data\\post.embedding’, tokens) embedding이 post.embedding을 불러오기 때문입니다. 이 부분을 수정하시면 달라질 것입니다. 원하시는 내용을 제가 해본다 치면, 기존 학습 된 모델의 가중치를 불러와서 추가적인 학습을 할 것 같습니다. Tensorflow에서는 이미 학습 된 모델에 추가적인 학습을 하는 걸 checkpointing라 부릅니다.… Read more »
자세한 설명 정말 감사합니다 ㅎㅎ
좋은 글 좋은 설명 잘 보고 갑니다 ㅎㅎ
넵 감사합니다 ㅎㅎ
.
저기 ,, 이거 보고 공부하고 있는 학생입니다.
train 이 파이썬 파일에 i[1]로 되어있는데 csv에는 4번째에 카테고리가 있어서 i[3] 아닌가요 ?
헷갈려서 질문드립니다.
넵 맞습니다. 지속적으로 KoreanNewsCrawler는 업데이트 되면서 column이 좀 바껴가지고 .. 머신러닝 파트는 신경쓰질 못했네요 .. 다른 column들도 바꿔주셔야 할겁니다 ㅠㅠ 업데이트를 해야 했는데 혼란을 드려 죄송합니다.
아 방금 다시 확인해 봤는데 csv에 5번째가 카테고리로 돼 있더군요, i[4]로 해주셔야 할 것 같습니다.
하늘이님이 보셨던 i[3]는 아마도 sport_article 였던 것 같습니다. 현재 sport_article crawler는 오류가 있어서 article_crawler 기준의 column을 이용해 주세요 ~
github 커밋 해뒀으니 최신걸로 해보세요
아 정말 감사합니다 ㅎㅎ !!
해당 예제 실행해 보려고 하니 Use standard file APIs to check for files with this prefix. 요렇게 나오고 종료 처리 되네요 ㅠㅠ 혹시 버전이 안맞아서 생기는 문제일까요? 그렇다면 버전좀 알려주시면 감사하겠습니다.
Use standard file APIs to check for files with this prefix. 마지막에 이런 문구가 나오고 프로그램이 종료처리 되는데 혹시 이유를 알 수 있을까요?
아마 버전 문제인 것 같습니다. 버전은 tensorflow 1.1~ 버전이었던 것 같습니다.
pip install KoreaNewsCrawler 를 명령어로 쳤더니 만족하는 버전을 찾을 수 없다고 뜨는데 어찌 입력해야하나요?
파이썬 버전이 3.6 이상 맞으신가요 ?
헉! 댓글보고 버전 찾아봤더니 3.5.2였네요! 업데이트 하니 해결되었습니다 감사합니다!!!!
올려주신 내용 아주 잘 이용하고 있습니다. 궁금한 게 하나 생겼는데 크롤링을 하는데는 총 얼마의 기간이 소모되셨나요? 크롤링 기간을 한 2~3년으로 좀 길게 잡고 싶은데 하나의 컴퓨터에서 이정도 기간을 돌리려면 예정 완료 시간이 어느정도 될지 모르겠습니다.
대상 카테고리에 따라 달라질 것으로 예상됩니다. 아마 300만 데이터 수집하는데 거의 5일 넘게 걸렸던 것으로 기억납니다.
메일로 드리긴 했는데
가 학습을 시키려고 하는데 파일을 구동중에
ValueError: Cannot feed value of shape (32, 4) for Tensor ‘Y:0’, which has shape ‘(?, 12)’
sess.run(optimizer, feed_dict={X: train_batch_X, Y: train_batch_Y, seq_len: batch_seq_length})
이런 에러가 나오고 있습니다. ㅠㅠ
아마 이 부분에서 선언했던 shape가 틀려서 그런거 같은데
혹시 왜 그런지 알 수 있을까요
네 shape가 틀려서 그런건데 .. 데이터 변환할 때 어떤 shape를 가지는지 Tracking 해보시면 될 것 같습니다.
워드에 이모티콘 있으신분들 ms949입니다 인코딩 ms949로 해주세요
안녕하세요! 혹시 Bi_LSTM.data-0000-of-00001 과 index, meta 이 파일들은 어느 과정에서 생기는 파일인지 알 수 있을까요?
질문이 있습니다! 뉴스 카테고라이징을 하고 있는데 임베딩한 파일을 어디에 넣어야 하나요? data폴더 안에 이미 post.embedding이 존재하던데 그건 예제 파일인가요? 제가 만든 post.embedding 파일을 오버라이드하면 될까요?
그리고 classifier로 결과값을 낼때 정치/경제/사회/세계만 분류해서 내고 싶은데 스포츠 카테코리를 막 지우면 안되는 거 같더라고요 ㅠㅠ 어떤 부분을 수정해야 하는지 알려주시면 감사하겠습니다 ㅠㅠ