[카테고리:] tensorflow

tensorflow 테스트

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

    대박이다!! 1,000회를 돌렸는데 0.87 정확도를 보였는데, verb까지 검사하니 0.93에서 시작한다!! kkma가 동사로 끝나는 명사형 단어를 동사로 인식한다!!

    사용자 입력을 받아들여 단어를 분석하는 부분을 아래와 같이 했다.

    from konlpy.tag import Okt
    okt=Okt()
    from gensim.models import Word2Vec
    from keras.layers import Dense, Flatten, SimpleRNN, Dropout
    from keras.models import Sequential
    from keras.preprocessing.sequence import pad_sequences
    from keras.layers.embeddings import Embedding
    from keras.utils import to_categorical
    import numpy as np
    from sklearn.cluster import KMeans
    
    def main():
        model=Word2Vec.load('./TagWord2VecModel')
        print(model)
        MAX_VOCAB=len(model.wv.vocab)
        WV_SIZE=model.wv.vectors.shape[1]
        WORD_MAX=6
        CATEGORIY_SIZE=7
        print("로드한 모델 vocab 최대값은", MAX_VOCAB)
        print("로드한 모델 vectror 크기는", WV_SIZE)
        #단어 표시
        showWord2VecClusters(Model=model)
    
        #keras 모델 설정.
        model2= Sequential()
        model2.add(Embedding(input_dim=MAX_VOCAB, output_dim=WV_SIZE, input_length=WORD_MAX, weights=[model.wv.vectors], trainable=False))
        #model2.add(Flatten())
        model2.add(SimpleRNN(256, input_shape=(4,4)))
        model2.add(Dropout(0.2))
        model2.add(Dense(128))
        model2.add(Dropout(0.2))
        model2.add(Dense(64, activation='relu'))
        model2.add(Dropout(0.2))
        model2.add(Dense(CATEGORIY_SIZE, activation='softmax'))
    
        #load model 경로.
        weight_path = "./saved_network_weight.h5"
        model2.load_weights(weight_path)
        print("저장된 weights를 불름")
        model2.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
        model2.summary()
        checkSentenceWord(Model=model)
        userInput(Word2Vec=model, Networks=model2, Maxword=WORD_MAX)
    
    
    def showWord2VecClusters(Model):
        #현재 입력된 단어 표시
        #클러스터링 사용.
        word_vectors = Model.wv.syn0 # 어휘의 feature vector
        num_clusters = int(word_vectors.shape[0]/50) # 어휘 크기의 1/5나 평균 5단어
        print(num_clusters)
        num_clusters = int(num_clusters)
    
        kmeans_clustering = KMeans(n_clusters=num_clusters)
        idx = kmeans_clustering.fit_predict(word_vectors)
    
        idx = list(idx)
        names = Model.wv.index2word
        word_centroid_map = {names[i]: idx[i] for i in range(len(names))}
    
    
        for c in range(num_clusters):
            # 클러스터 번호를 출력
            print("\ncluster {}".format(c))
    
            words = []
            cluster_values = list(word_centroid_map.values())
            for i in range(len(cluster_values)):
                if (cluster_values[i] == c):
                    words.append(list(word_centroid_map.keys())[i])
            print(words)
    
    
    
    def userInput(Word2Vec, Networks, Maxword):
        EndFlag=False
        while True:
            #사용자 입력 확인
            ErrorFlag=False
            ZeroFlag=False
            wordToPredictSentence = []
            wordToPredictSentenceStr = []
            index = 0
            #총 MAX개수만큼 입력을 받아들이고, 
            #단어를 판단
            # 인덱스를 증가하지 말지 판단하기 위해 while루프 사용
            #print("WORD_MAX는",Maxword)
            while (index < Maxword):
            #for index in range(Maxword):
                print("%d/6 단어 입력"%(index+1))
                print("끝내려면 END!!를 입력")
                print("마지막까지 0을 채우려면 ZERO!!를 입력")
                if(not ZeroFlag):
                    userInput=input()
                #input_predict =model.wv.vocab.get(word[0]).index
                #print(repr(userInput))
    
                if(userInput == "END!!"):
                    EndFlag=True
                    break
                if(userInput == "ZERO!!"):
                    ZeroFlag=True
    
                try:
                    #Try에서 에러플래그를 다시 초기화
                    ErrorFlag=False
                    num = Word2Vec.wv.vocab.get(userInput).index
                    print(num)
                except AttributeError:
                    if(not ZeroFlag):
                        print("리스트에 없는 단어 입력함. 다시 입력하세요")
                        ErrorFlag=True
    
                #전에 정확하게 입력했는지 확인
                if(ErrorFlag == True):
                    continue
                else:
                    index=index+1
                    if(not ZeroFlag):
                        wordToPredictSentence.append(num)
                        wordToPredictSentenceStr.append(userInput)
                        print(wordToPredictSentence)
                    else:
                        wordToPredictSentence.append(0)
                        wordToPredictSentenceStr.append(userInput)
                        print(wordToPredictSentence)
    
                #input_predict = np.asarray([[num0, num1, num2, 0, 0, 0]])
                input_predict = np.asarray([wordToPredictSentence])
                #print("input_predict 는",input_predict.shape)
            if(EndFlag == False):
                print("입력한 단어는",wordToPredictSentenceStr)
                myPrediction = Networks.predict_classes(input_predict, batch_size=100, verbose=0)
                myPredictionAcc = Networks.predict(input_predict, batch_size=100, verbose=0)
                print("내 예상", myPrediction, "확률", myPredictionAcc)
            else:
                #while 루프 탈출.
                break
    
    
    def checkSentenceWord(Model):
        print(Model)
        sample_sentence="B220ST YD5 CLAMP 잠김"
        tokenlist = okt.pos(sample_sentence, stem=True, norm=True)
        for word in tokenlist:
            print(word)
    
    
    if __name__=="__main__":
        main()
    

    네트웍은 LSTM을 복잡한 형식으로 썼다. 네트웍 구조가 json으로, 웨이트가 h5로 저장된다. 나중에 네트웍 구조를 json으로 저장하고, json으로 부르는 부분으로 수정해야 겠다.

    위에 “B220ST YD5 CLAMP 잠김”을 분석하면 아래로 분석한다.

    ('B', 'Alpha')
    ('220', 'Number')
    ('ST', 'Alpha')
    ('YD', 'Alpha')
    ('5', 'Number')
    ('CLAMP', 'Alpha')
    ('잠기다', 'Verb')
    from konlpy.tag import Okt
    okt=Okt()
    from gensim.models import Word2Vec
    from keras.layers import Dense, Flatten, SimpleRNN, Dropout, LSTM
    from keras.models import Sequential
    from keras.preprocessing.sequence import pad_sequences
    from keras.layers.embeddings import Embedding
    from keras.utils import to_categorical
    from keras.optimizers import Adam
    import numpy as np
    #label encoder로 text를 int로 변경.
    from sklearn.preprocessing import LabelEncoder
    #model save
    from keras.callbacks import ModelCheckpoint
    
    
    targetFile = open("./tag정리.txt", "r", encoding='UTF-8')
    #lines=targetFile.readline()
    #model=Word2Vec.load('./myModelV1')
    model=Word2Vec.load('./TagWord2VecModel')
    
    MAX_VOCAB=len(model.wv.vocab)
    WV_SIZE=model.wv.vectors.shape[1]
    print("로드한 모델 vocab 최대값은", MAX_VOCAB)
    print("로드한 모델 vectror 크기는", WV_SIZE)
    
    i=0
    sentence_by_index=[]
    training_result=[]
    result=[]
    WORD_MAX=16
    
    
    while True:
    
        lines = targetFile.readline()
        firstColumn = lines.split(',')
        #print(lines)
        
        if not lines:break
        #if i == 1000: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","Verb"]:
                #temp.append(model.wv[word[0]])
                #word[0]를 index로 변경.
                #단어장에 없는 단어를 예외처리
                #입력과 출력을 같이 맞추기 위해, 입출력 동시에 append
                try:
                    #print("---------")
                    #print(i)
                    #print(word[0])
                    temp.append(model.wv.vocab.get(word[0]).index)
                    #print(model.wv.vocab.get(word[0]).index)
    
                except AttributeError:
                    #값을 못찾으면 0값 입력
                    temp.append(0)
                    #print(temp)
        #print("index is ", i)
        #print("temp is", temp)
    
        #가져단 쓴 코드는 temp에 값이 있을 경우에만 append.
        #출력과 맞추기 위해, list가 비어있어도 append로 변경.
        #if temp:
        #    sentence_by_index.append(temp)
        sentence_by_index.append(temp)
    
        #결과를 배열로 입력
        tempResult=firstColumn[2].strip('\n')
        training_result.append(tempResult)
    
    
    targetFile.close()
    #print(tokenlist)
    
    #출력을 categorical로 변경.
    
    label_encoder = LabelEncoder()
    training_result_asarray = np.asarray(training_result)
    integer_encoded = label_encoder.fit_transform(training_result_asarray)
    categorical_training_result = to_categorical(integer_encoded, dtype='int')
    
    #입력, 출력 확인
    fixed_sentence_by_index = pad_sequences(sentence_by_index, maxlen=WORD_MAX, padding='post', dtype='int')
    #print("입력은",fixed_sentence_by_index)
    #print("출력은",integer_encoded)
    #print("출력은",categorical_training_result)
    size_categorical_training_result = categorical_training_result.shape[1]
    print("출력 크기는",size_categorical_training_result)
    
    #keras 모델 설정.
    model2= Sequential()
    model2.add(Embedding(input_dim=MAX_VOCAB, output_dim=WV_SIZE, input_length=WORD_MAX, weights=[model.wv.vectors], trainable=False))
    #model2.add(Flatten())
    model2.add(LSTM(1024, input_shape=(4,4)))
    model2.add(Dropout(0.2))
    model2.add(Dense(512))
    model2.add(Dropout(0.2))
    model2.add(Dense(256, activation='relu'))
    model2.add(Dropout(0.2))
    model2.add(Dense(size_categorical_training_result, activation='softmax'))
    model2.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001, epsilon=1e-08, decay=0.0), metrics=['accuracy'])
    
    #save model 경로.
    weight_path = "./saved_network_weight.h5"
    checkpoint = ModelCheckpoint(weight_path, monitor='acc', verbose=2, save_best_only=True, mode='auto') 
    callbacks_list = [checkpoint]
    
    model2.fit(x=fixed_sentence_by_index, y=categorical_training_result, epochs=1000, verbose=2, validation_split=0.2, callbacks=callbacks_list, batch_size=200)
    model2.summary()

    로 분석하면, 대충 아래와 같다.

    로드한 모델 vocab 최대값은 694
    로드한 모델 vectror 크기는 10
    출력 크기는 7
    Train on 7602 samples, validate on 1901 samples
    Epoch 1/1000
     - 7s - loss: 1.0435 - acc: 0.5389 - val_loss: 1.7584 - val_acc: 0.7564
    
    Epoch 00001: acc improved from -inf to 0.53894, saving model to ./saved_network_weight.h5
    Epoch 2/1000
     - 3s - loss: 0.4565 - acc: 0.8172 - val_loss: 2.1145 - val_acc: 0.7480
    
    Epoch 00002: acc improved from 0.53894 to 0.81715, saving model to ./saved_network_weight.h5
    Epoch 3/1000
     - 3s - loss: 0.4405 - acc: 0.8508 - val_loss: 2.5999 - val_acc: 0.7575
    
    Epoch 00003: acc improved from 0.81715 to 0.85083, saving model to ./saved_network_weight.h5
    Epoch 4/1000
     - 3s - loss: 0.2354 - acc: 0.9100 - val_loss: 2.1261 - val_acc: 0.7475
    
    Epoch 00004: acc improved from 0.85083 to 0.91002, saving model to ./saved_network_weight.h5
    Epoch 5/1000
     - 3s - loss: 0.1733 - acc: 0.9323 - val_loss: 2.2204 - val_acc: 0.7522
    
    Epoch 00005: acc improved from 0.91002 to 0.93225, saving model to ./saved_network_weight.h5
    Epoch 6/1000
     - 3s - loss: 0.2758 - acc: 0.9025 - val_loss: 3.7245 - val_acc: 0.7543
  • keras로 키워드 분석(3/5)

    과거 acc를 못 올리는 이유를 알아보았다. 둘 중 하나를 선택하는 문제는 activation softmax대신 sigmoid를 사용해야 한다. 아래로 고치고 1,000번 학습시켰다. 최고값을 찾은 weight를 파일로 저장했다. 147번 학습해보니 0.99?? 정확도를 보이나, vlaidation 체크용은 0.87대 정확도를 보인다.

    from konlpy.tag import Okt
    okt=Okt()
    from gensim.models import Word2Vec
    from keras.layers import Dense, Flatten, SimpleRNN
    from keras.models import Sequential
    from keras.preprocessing.sequence import pad_sequences
    from keras.layers.embeddings import Embedding
    import numpy as np
    
    #model save
    from keras.callbacks import ModelCheckpoint
    
    model=Word2Vec.load('./myModel')
    MAX_VOCAB=len(model.wv.vocab)
    WV_SIZE=model.wv.vectors.shape[1]
    print("로드한 모델 vocab 최대값은", MAX_VOCAB)
    print("로드한 모델 vectror 크기는", WV_SIZE)
    
    #b=model.wv.most_similar(positive=["클램프", "잠김"])
    print(model)
    
    #print(model.wv["후드힌지시프트"])
    
    #tokenizer 설정.
    #Okt()사용.
    
    targetFile = open("./tagv4태그붙인파일.csv", "r", encoding='UTF-8')
    
    i=0
    sentence_by_index=[]
    traing_result=[]
    WORD_MAX=6
    #WV_SIZE=10
    #model을 load후 최대값 확인
    #MAX_VOCAB=3532
    
    #못찾은 단어를 입력하기 위한 부분.
    #삭제.
    #VACANT_ARRAY = np.zeros((4,1))
    
    
    while True:
    
        lines = targetFile.readline()
        firstColumn = lines.split(',')
        #print(lines)
    
        if not lines:break
        #if i == 1000: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]])
                #word[0]를 index로 변경.
                #단어장에 없는 단어를 예외처리
                #입력과 출력을 같이 맞추기 위해, 입출력 동시에 append
                try:
                    #print("---------")
                    #print(i)
                    #print(word[0])
                    temp.append(model.wv.vocab.get(word[0]).index)
                    #print(model.wv.vocab.get(word[0]).index)
    
                except AttributeError:
                    #값을 못찾으면 0값 입력
                    temp.append(0)
                    #print(temp)
        #print("index is ", i)
        #print("temp is", temp)
    
        #가져단 쓴 코드는 temp에 값이 있을 경우에만 append.
        #출력과 맞추기 위해, list가 비어있어도 append로 변경.
        #if temp:
        #    sentence_by_index.append(temp)
        sentence_by_index.append(temp)
    
        #결과를 배열로 입력
        tempResult=firstColumn[4].strip('\n')
        traing_result.append(tempResult)
    
    targetFile.close()
    training_result_asarray = np.asarray(traing_result)
    
    #최대 단어를 6으로 설정.
    #행 수보다 6까지 뒤쪽으로 0을 채움.
    #word2Vec가 실수이므로 float32로 설정
    #result가 embedding_matrix
    fixed_sentence_by_index = pad_sequences(sentence_by_index, maxlen=WORD_MAX, padding='post', dtype='int')
    print("입력 시퀀스는", fixed_sentence_by_index.shape)
    print("출력 시퀀스는", training_result_asarray.shape)
    #print("index로 변경한 값은",fixed_sentence_by_index)
    #print("embedding vector는", model.wv.vectors)
    
    #keras 모델 설정.
    model2= Sequential()
    model2.add(Embedding(input_dim=MAX_VOCAB, output_dim=WV_SIZE, input_length=WORD_MAX, weights=[model.wv.vectors], trainable=False))
    #model2.add(Flatten())
    model2.add(SimpleRNN(128, input_shape=(4,4)))
    model2.add(Dense(1, activation='sigmoid'))
    model2.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    #save model 경로.
    weight_path = "./saved_network_weight.h5"
    checkpoint = ModelCheckpoint(weight_path, monitor='acc', verbose=2, save_best_only=True, mode='auto')
    callbacks_list = [checkpoint]
    
    model2.fit(x=fixed_sentence_by_index, y=training_result_asarray, epochs=10, verbose=1, validation_split=0.2, callbacks=callbacks_list)
    model2.summary()
    
    
    #input_predict =model.wv.vocab.get(word[0]).index
    num0 = model.wv.vocab.get("B").index
    num1 = model.wv.vocab.get("180").index
    num2 = model.wv.vocab.get("셔틀").index
    num3 = model.wv.vocab.get("불간섭").index
    
    input_predict = np.asarray([[num0, num1, num2, num3, 0, 0]])
    #print("input_predict 는",input_predict.shape)
    myPrediction = model2.predict_classes(input_predict, batch_size=10, verbose=1)
    myPredictionAcc = model2.predict(input_predict, batch_size=10, verbose=1)
    print("내 예상", myPrediction,  "with ", myPredictionAcc)
    

    1,000회 하는데 4~5시간정도 걸린 듯 하다. 그러나 불행하게도 weight는 초기에 한번 업데이트하고 말아버렸다. 그래도 이렇게 간단한 구조인데도 87%를 유지하니 좀 파보면 나아질 듯 하다.

    이제 입력을 받아들여 이를 판정하는 부분을 만들어 보자.

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

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

    keras가 지원하는 embedding을 어떻게 사용하는지 몰랐다. keras가 제공하는 문서가 embedding 기능을 정확히 설명한다.

    https://keras.io/layers/embeddings/#embedding

    weight로 embedding_matrix를 입력하고, input으로 index를 입력하면 index를 vector로 변경한다. 따라서 아래와 같은 순서로 작업해야 한다.

    1. 미리 만든 word2vec 파일을 불러온다.
    2. 전체 vocab 총 양을 embedding_matrix로 설정한다.
    3. konlpy로 각 태그를 분리한다.
    4. 불러온 word2vec 파일에서 해당하는 단어 index를 구하고, 이를 문장으로 만든다.
    5. 적절한 길이로 padding한다.
    6. 이를 입력으로 먹인다.

    대충 어떻게 할 지 감 잡았으니, 이제 다시 삽질을 시작하자.

    다시 아래와 같이 작성했다. 일단 네트웍을 fit으로 훈련시킬 수 있는지 없는지 확인했다. 일단 된다. 모든 입력과 출력을 정확하게 읽었고, 2진 분류기로 만들었다. embedding도 제대로 되는 듯 하다.

    from konlpy.tag import Okt
    okt=Okt()
    from gensim.models import Word2Vec
    from keras.layers import Dense, Flatten
    from keras.models import Sequential
    from keras.preprocessing.sequence import pad_sequences
    from keras.layers.embeddings import Embedding
    import numpy as np
    
    model=Word2Vec.load('./myModel')
    #b=model.wv.most_similar(positive=["클램프", "잠김"])
    print(model)
    
    #print(model.wv["후드힌지시프트"])
    
    #tokenizer 설정.
    #Okt()사용.
    
    targetFile = open("./tagv4태그붙인파일.csv", "r", encoding='UTF-8')
    
    i=0
    sentence_by_index=[]
    traing_result=[]
    WORD_MAX=6
    WV_SIZE=4
    MAX_VOCAB=3532
    
    #못찾은 단어를 입력하기 위한 부분.
    VACANT_ARRAY = np.zeros((4,1))
    
    
    while True:
    
        lines = targetFile.readline()
        firstColumn = lines.split(',')
        #print(lines)
        
        if not lines:break
        #if i == 1000: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]])
                #word[0]를 index로 변경.
                #단어장에 없는 단어를 예외처리
                #입력과 출력을 같이 맞추기 위해, 입출력 동시에 append
                try:
                    #print("---------")
                    #print(i)
                    #print(word[0])
                    temp.append(model.wv.vocab.get(word[0]).index)
                    #print(model.wv.vocab.get(word[0]).index)
    
                except AttributeError:
                    #값을 못찾으면 0값 입력
                    temp.append(0)
                    #print(temp)
        #print("index is ", i)
        #print("temp is", temp)
    
        #가져단 쓴 코드는 temp에 값이 있을 경우에만 append.
        #출력과 맞추기 위해, list가 비어있어도 append로 변경.
        #if temp:
        #    sentence_by_index.append(temp)
        sentence_by_index.append(temp)
    
        #결과를 배열로 입력
        tempResult=firstColumn[4].strip('\n')
        traing_result.append(tempResult)
    
    targetFile.close()
    training_result_asarray = np.asarray(traing_result)
    
    #최대 단어를 6으로 설정.
    #행 수보다 6까지 뒤쪽으로 0을 채움.
    #word2Vec가 실수이므로 float32로 설정
    #result가 embedding_matrix
    fixed_sentence_by_index = pad_sequences(sentence_by_index, maxlen=WORD_MAX, padding='post', dtype='int')
    print("입력 시퀀스는", fixed_sentence_by_index.shape)
    print("출력 시퀀스는", training_result_asarray.shape)
    #print("index로 변경한 값은",fixed_sentence_by_index)
    #print("embedding vector는", model.wv.vectors)
    
    #keras 모델 설정.
    model2= Sequential()
    model2.add(Embedding(input_dim=MAX_VOCAB, output_dim=4, input_length=WORD_MAX, weights=[model.wv.vectors], trainable=False))
    model2.add(Flatten())
    model2.add(Dense(1, activation='softmax'))
    model2.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    model2.fit(x=fixed_sentence_by_index, y=training_result_asarray, epochs=1000, verbose=1, validation_split=0.2)
    
    model2.summary()

    네트웍을 조금 복잡하게 하고, gtx1060 gpu로 1000번 훈련 시켰다.

    root@AMD-1804:/home/mnt/konlpy_190910_moved# python tagCheckerv3.py 
    /usr/local/lib/python3.5/dist-packages/jpype/_core.py:210: UserWarning: 
    -------------------------------------------------------------------------------
    Deprecated: convertStrings was not specified when starting the JVM. The default
    behavior in JPype will be False starting in JPype 0.8. The recommended setting
    for new code is convertStrings=False.  The legacy value of True was assumed for
    this session. If you are a user of an application that reported this warning,
    please file a ticket with the developer.
    -------------------------------------------------------------------------------
    
      """)
    Using TensorFlow backend.
    Word2Vec(vocab=3532, size=4, alpha=0.025)
    2019-09-11 11:02:33.941682: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties: 
    name: GeForce GTX 1060 6GB major: 6 minor: 1 memoryClockRate(GHz): 1.7085
    pciBusID: 0000:01:00.0
    totalMemory: 5.93GiB freeMemory: 5.38GiB
    2019-09-11 11:02:33.941740: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0
    2019-09-11 11:02:34.356140: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
    2019-09-11 11:02:34.356206: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988]      0 
    2019-09-11 11:02:34.356217: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0:   N 
    2019-09-11 11:02:34.356473: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5138 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060 6GB, pci bus id: 0000:01:00.0, compute capability: 6.1)
    Train on 77696 samples, validate on 19424 samples
    Epoch 1/1000
    77696/77696 [==============================] - 19s 248us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 2/1000
    77696/77696 [==============================] - 18s 238us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 3/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 4/1000
    77696/77696 [==============================] - 19s 239us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 5/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 6/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 7/1000
    77696/77696 [==============================] - 18s 238us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 8/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 9/1000
    77696/77696 [==============================] - 19s 243us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 10/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 11/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 12/1000
    77696/77696 [==============================] - 18s 238us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 13/1000
    77696/77696 [==============================] - 18s 238us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 14/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 15/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 16/1000
    77696/77696 [==============================] - 19s 242us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 17/1000
    77696/77696 [==============================] - 19s 242us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 18/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 19/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 20/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 21/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 22/1000
    77696/77696 [==============================] - 19s 242us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 23/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 24/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 25/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 26/1000
    77696/77696 [==============================] - 19s 239us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 27/1000
    77696/77696 [==============================] - 19s 242us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 28/1000
    77696/77696 [==============================] - 19s 243us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 29/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 30/1000
    77696/77696 [==============================] - 19s 240us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 31/1000
    77696/77696 [==============================] - 18s 237us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325
    Epoch 32/1000
    77696/77696 [==============================] - 19s 241us/step - loss: 11.2624 - acc: 0.2936 - val_loss: 12.2350 - val_acc: 0.2325

    acc와 loss가 변할 조짐이 없다. 다음에는 네트웍을 조금 복잡하게 해보고 다시 훈련시켜야겠다.

  • 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'])
    

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

  • docker+tensorflow

    나는 구형 x1055 cpu를 사용하고 있다. 10년 넘어가고 있다. 다행히 6코어라 병렬처리 지원 프로그램은 빠르다. 요즘들어 병렬처리지원 프로그램을 많이 만드는 듯 하다. 아쉽게도 avx 등 명령세트를 지원하지 않는다. 구글이 컴파일한 whl버전을 설치하면 core dumped로 죽는다. 이를 해결하려면 내가 source build를 해야한다. source build하려면 우분투 16.04에 cuda, cudnn, bazel을 설치해야 한다. 얼마? 전 나온 ubuntu 18.04를 쓰고 싶은데, 컴파일할 수 없어 설치하기 꺼려진다. 게다가 conda, 가상화 등이 작업환경을 망치는 기분이다.

    이 중 docker를 알았다. host에 영향주지 않고, 안전하게 tensorflow를 쓸 수 있다. 시험으로 tensorflow 1.10 이미지에 내가 컴파일한 whl을 설치했다. 잘 된다. 이번에 밀어 버렸다.

    여기에 보면 아주 쉽게 build할 수 있다. 그러나 처음 시도한 이미지로 nvidia driver를 올릴 수 없었다. 다음으로 ubuntu 16.04에서 bazel, cuda, cudnn을 차근차근 설치했다. 이 이미지가 build를 못한다. Workspace 에러가 나를 막았다.

    이번에는 bazel 설치 이미지로 찾아 bazel test 했다. tensorflow cpu 컴파일도 Workspace 에러없었다. 컴파일 되는 이미지 dockerfile을 봤다. jdk8 버전에서 bazel을 설치했다.

    FROM openjdk:8
    # Bazel uses jdk8. Importing jdk8 image in advance, docker runs faster.
    # but there are some problem between openjdk8 and Bazel 0.5.3.
    
    MAINTAINER Tadashi KOJIMA <nsplat@gmail.com>
    
    # To install Bazel, see https://docs.bazel.build/versions/master/install-ubuntu.html#install-with-installer-ubuntu
    RUN apt-get update \
    	&& apt-get install -y pkg-config zip g++ zlib1g-dev unzip \
    	&& wget https://github.com/bazelbuild/bazel/releases/download/0.16.1/bazel-0.16.1-installer-linux-x86_64.sh \
    	&& chmod +x ./bazel-0.16.1-installer-linux-x86_64.sh \
    	&& ./bazel-0.16.1-installer-linux-x86_64.sh \
    
    # run bazel test
    	&& ls -l bin/ \
    	&& export PATH="$PATH:/root/bin" \
    	&& echo $PATH \
    	&& which bazel \
    	&& bazel \
    	&& echo "export PATH=\$PATH:/root/bin" >> /root/.bash_profile \
    	&& echo "exec /bin/bash" >> /root/.bash_profile \
    	&& . /root/.bash_profile
    
    # Set up workspace
    WORKDIR /home

    몇 줄 진행(한시간정도?)하다 컴파일 에러났다. 이번에는ubuntu 16.04에서 시작했다. cuda, cudnn, git 필요 모듈을 설치했다. 일단 컴파일은 에러없이 성공했다. 그러나 이 빌드 gpu 버전은 gpu를 동작시키지 않는다. 나중에 중요한 사실을 알았다. 구글이 source build 문서 아래에 검증된 tensorflow, bazel, cuda 버전을 기록했다. 내가 설치한 bazel 버전이 너무 높았다. 진작 알았으면 하루 벌었는데.

    https://www.tensorflow.org/install/source

    마지막으로 1.10-rc2-dev-gpu-py3 docker 이미지를 받아 해봤다. 너무나 쉽게 성공했다. docker 이미지가 한글을 지원하지 않아, 환경변수를 설정했다.

    python에서 한글 터미널 에러

    https://www.44bits.io/ko/post/setup_linux_locale_on_ubuntu_and_debian_container

    이거 한다고 주말을 다 날렸다. 컴파일하는데 약 3시간 걸렸다. 테스트 시간이 많아 확인하기 어려웠다.