[태그:] 형태소분석

  • keras로 키워드 분석(1/5)

    keras로 키워드 분석(1/5)

    인공지능으로 자연어 분석을 많이한다. 나도 남 따라 해보기로 했다. 조금씩 배워하므로 코드는 별거 없지만 많은 시간을 쓰고있다. 생각은 이렇다.

    1. 나는 설비 태그를 가지고 있다. 사람마다 태그 작성을 다르게 한다. 이렇게 되면 일관성없어 분석하기 어렵다. 이를 표준화? – 적어도 형식에 벗어난 태그를 찾기위해 – 하는 무엇인가 있으면 좋겠다.
    2. 태그를 준비한다. 한글+영어로 구성된다.
    3. 간단한 분류기를 구성한다. 처음과 끝 단어를 기준으로 OK, NG를 임의로 넣는다.
    4. 한글을 사용하여 형태소를 기준으로 자른다. konlpy로 태그를 자른다.
    5. 핫한 word2vec를 활용한다.
    6. 내 맘대로 네트웍을 구성하여 학습하고 결과를 본다.

    일단 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'])
    

    이 후는 나중에 계속 해야된다.