인공지능으로 자연어 분석을 많이한다. 나도 남 따라 해보기로 했다. 조금씩 배워하므로 코드는 별거 없지만 많은 시간을 쓰고있다. 생각은 이렇다.
- 나는 설비 태그를 가지고 있다. 사람마다 태그 작성을 다르게 한다. 이렇게 되면 일관성없어 분석하기 어렵다. 이를 표준화? – 적어도 형식에 벗어난 태그를 찾기위해 – 하는 무엇인가 있으면 좋겠다.
- 태그를 준비한다. 한글+영어로 구성된다.
- 간단한 분류기를 구성한다. 처음과 끝 단어를 기준으로 OK, NG를 임의로 넣는다.
- 한글을 사용하여 형태소를 기준으로 자른다. konlpy로 태그를 자른다.
- 핫한 word2vec를 활용한다.
- 내 맘대로 네트웍을 구성하여 학습하고 결과를 본다.
일단 word2vec를 만들었다. 인터넷에 이 유명한 word2vec 대한 설명을 쉽게 찾는다. 이론은 그렇다치고, 응용을 어떻게할지 확인했다. https://wikidocs.net/book/2155 를 그대로 참조했다.
태그를 word2vec에서 사용한 vector로 나타내야 한다. 인터넷에 위키피디아 등 방대한 문서로 학습한 word2vec를 구할 수 있고, 쉽게 적용할 수 있다. 그러나 내가 가진 태그는 이쪽 업계 자의적, 단축 단어로 이뤄졌다. 예를 들어 차종, 절환 등 일본어 비슷한 단어를 주로 사용한다. 이 단어는 표준어도 아니고, 심지어 위키피디아에서 사용하지 않는다. 이를 구분하려면 사용자 정의 사전에 입력해야 한다. 인터넷 능력자의 도움으로 명사로 추가했다. 위 링크 핵심은 1. 사용할 형태소 분석기 압축을 푼다. 2. 사전 파일에 단어를 추가한다. 3. 다시 jar로 압축한다. 이다.
다시 konlpy로 단어, 숫자,영어로 분리한다. 아래 코드의 word[0]은 단어이고, word[1]은 품사 정도 된다.
이제 분리한 단어를 word2vec 함수로 vector를 만들어 파일로 저장한다. 아래 코드는 인터넷에서 구했고 나는 정말 조금만 수정했다.
from konlpy.tag import Okt okt=Okt() from gensim.models import Word2Vec targetFile = open("./tagv4태그붙인파일.csv", "r", encoding='UTF-8') #lines=targetFile.readline() i=0 result=[] while True: lines = targetFile.readline() firstColumn = lines.split(',') #print(lines) #print(lines[0]) #print(firstColumn[1]) #print(firstColumn[4]) #firstColumn[4]가 마지막 OK, NG 플래그 #if not lines:break #1000라인에서 쉽게 끊기 위해 넣어줌. if i == 1000: break #print(lines) i=i+1 if i%1000 == 0: print("%d번째 while문"%i) tokenlist = okt.pos(firstColumn[1], stem=True, norm=True) temp=[] for word in tokenlist: if word[1] in ["Noun","Alpha","Number"]: temp.append((word[0])) if temp: result.append(temp) # print(result) targetFile.close() #print(result[100:]) print(result) #print(tokenlist) model=Word2Vec(sentences=result, size=200, window=4, min_count=2, workers=6, sg=0, iter=100) model.save('myModel') a=model.wv.most_similar("센서") print(a) """ sent_text = sent_tokenize(lines) normalized_text = [] for string in sent_text: tokens = re.sub(r"[^a-z0-9]+", " ", string.lower()) normalized_text.append(tokens) result=[] result=[word_tokenize(sentence) for sentence in normalized_text] #print(result) #print(lines) model=Word2Vec(sentences=result, size=100, window=5, min_count=3, workers=6, sg=0, iter=10000) print(model) a=model.wv.most_similar("you") #print(model['man']) print(a) #print(normalized_text) #print(result[:10]) """
이제 vector를 불러와 keras로 학습을 시켜야 한다. rnn이나 lstm 이런 모듈을 사용할 예정이다. 학습할 입력을 vector 형식으로 네트웍에 집어 넣어야하는데, embedding으로 쉽게 사용할 수 있는 듯 하다. 입력으로 넣기 위해 크기를 일정하게 맞춰야한다. pad_sequences로 쉽게 가능하다. 다만 dtype=’float32’로 소수점 버림을 막아준다.
pad_sequences를 적용하기 전에는 스트링으로 인식하는데, 이 후에 바로 vector로 바꿔준다. 어디까지 해줄 지 모르겠으나, 이 부분을 직접 입력으로 넣어도 될 듯 하다. vector 크기를 100으로 했는데 너무 크게 잡은 듯 하다. 나중에 줄여야겠다.
중간에 실재 6개(내가 정한 최대값)로 일치되는지와 각 단어를 vector로 print로 뽑았다. 역시 word2vec를 만든 형태소 분석기를 그대로 사용했다.
from konlpy.tag import Okt okt=Okt() from gensim.models import Word2Vec from keras.layers import Dense, LSTM, Dropout from keras.models import Sequential from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences import numpy as np model=Word2Vec.load('./myModel') #b=model.wv.most_similar(positive=["클램프", "잠김"]) print(model) #tokenizer 설정. #Okt()사용. targetFile = open("./tagv4태그붙인파일.csv", "r", encoding='UTF-8') i=0 result=[] WORD_MAX=10 WV_SIZE=200 blankArray = np.zeros(WV_SIZE) while True: lines = targetFile.readline() firstColumn = lines.split(',') if i == 100: break i=i+1 #word2vec를 만든 형태소 분석기를 사용.. tokenlist = okt.pos(firstColumn[1], stem=True, norm=True) temp=[] for word in tokenlist: #word[0]은 단어. #word[1]은 품사. #print("word[0]은",word[0]) #print("word[1]은",word[1]) if word[1] in ["Noun","Alpha","Number"]: temp.append(model.wv[word[0]]) if temp: result.append(temp) targetFile.close() #최대 단어를 6으로 설정. #행 수보다 6까지 뒤쪽으로 0을 채움. #word2Vec가 실수이므로 float32로 설정 fixed_result = pad_sequences(result, maxlen=6, padding='post', dtype='float32') #정확하게 입력되어 있는지 테스트하는 부분. print(len(fixed_result)) j=0 while True: print("여기가 시작") print(len(fixed_result[j])) #print(fixed_result[j][0].shape) print(result[j]) #print(fixed_result[j]) print(fixed_result[j][0]) print(fixed_result[j][1]) print(fixed_result[j][2]) print(fixed_result[j][3]) print(fixed_result[j][4]) print(fixed_result[j][5]) j=j+1 if j == 100: break; #print(result[0][0]) #print(result[0][1]) #b1=model.wv[result[0][0]] #b2=model.wv[result[0][1]] #print(b1) #print(b2) #keras 모델 설정. model = Sequential() Dense(100, input_dim=200, kernel_initializer='uniform', activation='relu') Dense(2, input_dim=100, activation='softmax') model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
이 후는 나중에 계속 해야된다.