[태그:] 자연어처리

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

    정말 간단한 LSTM으로 정확도 80%대까지 올렸다. 23,000개 데이터를 7,000번 학습시겼다. 정확하게 하려면 모든 카테고리 데이터를 동일하게 맞추고, 내부 태그를 정확하게 정리해야 하는데 시간없어 하지 못했다.

    [21:33:28]>cat process | head -100
    로드한 모델 vocab 최대값은 2611
    로드한 모델 vectror 크기는 5
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    Model: "sequential_1"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    embedding_1 (Embedding)      (None, 10, 5)             13055     
    _________________________________________________________________
    lstm_1 (LSTM)                (None, 32)                4864      
    _________________________________________________________________
    dropout_1 (Dropout)          (None, 32)                0         
    _________________________________________________________________
    dense_1 (Dense)              (None, 16)                528       
    _________________________________________________________________
    dropout_2 (Dropout)          (None, 16)                0         
    _________________________________________________________________
    dense_2 (Dense)              (None, 9)                 153       
    =================================================================
    Total params: 18,600
    Trainable params: 5,545
    Non-trainable params: 13,055
    _________________________________________________________________
    Train on 18757 samples, validate on 4690 samples
    Epoch 1/1000
     - 5s - loss: 2.1842 - acc: 0.0887 - val_loss: 2.1683 - val_acc: 0.0908
    Epoch 00001: acc improved from -inf to 0.08866, saving model to ./saved_network_weightv2.h5
    Epoch 2/1000
     - 4s - loss: 2.1073 - acc: 0.1674 - val_loss: 2.1181 - val_acc: 0.2066
    Epoch 00002: acc improved from 0.08866 to 0.16735, saving model to ./saved_network_weightv2.h5
    Epoch 3/1000
     - 4s - loss: 2.0133 - acc: 0.2660 - val_loss: 2.0448 - val_acc: 0.2652
    Epoch 02019: acc improved from 0.88084 to 0.88122, saving model to ./saved_network_weightv2.h5
    Epoch 02129: acc improved from 0.88122 to 0.88218, saving model to ./saved_network_weightv2.h5
    Epoch 02190: acc improved from 0.88218 to 0.88292, saving model to ./saved_network_weightv2.h5
    Epoch 02542: acc improved from 0.88292 to 0.88394, saving model to ./saved_network_weightv2.h5
    Epoch 02805: acc improved from 0.88394 to 0.88426, saving model to ./saved_network_weightv2.h5
    Epoch 02928: acc improved from 0.88426 to 0.88474, saving model to ./saved_network_weightv2.h5
    Epoch 03050: acc improved from 0.88474 to 0.88607, saving model to ./saved_network_weightv2.h5
    Epoch 03836: acc improved from 0.88607 to 0.88650, saving model to ./saved_network_weightv2.h5
    Epoch 03940: acc improved from 0.88650 to 0.88762, saving model to ./saved_network_weightv2.h5
    Epoch 04337: acc improved from 0.88762 to 0.88810, saving model to ./saved_network_weightv2.h5
    

    전에 텍스트 0이 인덱스 번호 47번인가 그랬다. 아무래도 이상하여 확이해보니 zero padding에는 0으로 넣었다. 0을 숫자로 처리할지, zero padding 값으로 처리할 지 결정해야 한다. 일단 검증할 경우에는 0을 강제로 입력했다.

    입력한 단어는 ['M', 'YD', '4', 'PIN', 'SHIFT', '1', '전진', '단', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 0.87확율로 [4]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    YD
    1
    [69, 1]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    4
    11
    [69, 1, 11]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    10
    21
    [69, 1, 11, 21]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ST
    0
    [69, 1, 11, 21, 0]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    PIN
    154
    [69, 1, 11, 21, 0, 154]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    후진
    42
    [69, 1, 11, 21, 0, 154, 42]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    단
    13
    [69, 1, 11, 21, 0, 154, 42, 13]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 1, 11, 21, 0, 154, 42, 13, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 1, 11, 21, 0, 154, 42, 13, 0, 0]
    입력한 단어는 ['M', 'YD', '4', '10', 'ST', 'PIN', '후진', '단', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 0.84확율로 [4]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    OTR
    91
    [69, 91]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    랙
    28
    [69, 91, 28]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    10
    21
    [69, 91, 28, 21]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    번방
    121
    [69, 91, 28, 21, 121]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    차종
    6
    [69, 91, 28, 21, 121, 6]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    20
    51
    [69, 91, 28, 21, 121, 6, 51]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    이상
    8
    [69, 91, 28, 21, 121, 6, 51, 8]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 91, 28, 21, 121, 6, 51, 8, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 91, 28, 21, 121, 6, 51, 8, 0, 0]
    입력한 단어는 ['M', 'OTR', '랙', '10', '번방', '차종', '20', '이상', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [5]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    70
    36
    [69, 36]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ST
    0
    [69, 36, 0]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    주변
    292
    [69, 36, 0, 292]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    설비
    322
    [69, 36, 0, 292, 322]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    비상
    63
    [69, 36, 0, 292, 322, 63]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    정지
    73
    [69, 36, 0, 292, 322, 63, 73]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 36, 0, 292, 322, 63, 73, 0]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 36, 0, 292, 322, 63, 73, 0, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 36, 0, 292, 322, 63, 73, 0, 0, 0]
    입력한 단어는 ['M', '70', 'ST', '주변', '설비', '비상', '정지', 'ZERO!!', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [2]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    보조제어
    리스트에 없는 단어 입력함. 다시 입력하세요
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    보조
    26
    [69, 26]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    제어
    38
    [69, 26, 38]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    GP
    228
    [69, 26, 38, 228]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    동작
    29
    [69, 26, 38, 228, 29]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    선택
    14
    [69, 26, 38, 228, 29, 14]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    16
    448
    [69, 26, 38, 228, 29, 14, 448]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 26, 38, 228, 29, 14, 448, 0]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 26, 38, 228, 29, 14, 448, 0, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 26, 38, 228, 29, 14, 448, 0, 0, 0]
    입력한 단어는 ['M', '보조', '제어', 'GP', '동작', '선택', '16', 'ZERO!!', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [0]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    70
    36
    [69, 36]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    RH
    9
    [69, 36, 9]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    피더
    457
    [69, 36, 9, 457]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    전후진
    리스트에 없는 단어 입력함. 다시 입력하세요
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    LS
    75
    [69, 36, 9, 457, 75]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    이상
    8
    [69, 36, 9, 457, 75, 8]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 36, 9, 457, 75, 8, 0]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 36, 9, 457, 75, 8, 0, 0]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 36, 9, 457, 75, 8, 0, 0, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 36, 9, 457, 75, 8, 0, 0, 0, 0]
    입력한 단어는 ['M', '70', 'RH', '피더', 'LS', '이상', 'ZERO!!', 'ZERO!!', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [5]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    80
    209
    [69, 209]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    LH
    5
    [69, 209, 5]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    카울
    리스트에 없는 단어 입력함. 다시 입력하세요
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    PIN
    154
    [69, 209, 5, 154]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    LS
    75
    [69, 209, 5, 154, 75]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    이상
    8
    [69, 209, 5, 154, 75, 8]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 209, 5, 154, 75, 8, 0]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 209, 5, 154, 75, 8, 0, 0]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 209, 5, 154, 75, 8, 0, 0, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 209, 5, 154, 75, 8, 0, 0, 0, 0]
    입력한 단어는 ['M', '80', 'LH', 'PIN', 'LS', '이상', 'ZERO!!', 'ZERO!!', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [5]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
    1/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    M
    69
    [69]
    2/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    60
    134
    [69, 134]
    3/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    RH
    9
    [69, 134, 9]
    4/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    CAM
    179
    [69, 134, 9, 179]
    5/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    YD
    1
    [69, 134, 9, 179, 1]
    6/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    제품
    50
    [69, 134, 9, 179, 1, 50]
    7/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    감지
    53
    [69, 134, 9, 179, 1, 50, 53]
    8/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    1
    7
    [69, 134, 9, 179, 1, 50, 53, 7]
    9/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    ZERO!!
    zero index는 0
    [69, 134, 9, 179, 1, 50, 53, 7, 0]
    10/10 단어 입력
    끝내려면 END!!를 입력
    마지막까지 0을 채우려면 ZERO!!를 입력
    zero index는 0
    [69, 134, 9, 179, 1, 50, 53, 7, 0, 0]
    입력한 단어는 ['M', '60', 'RH', 'CAM', 'YD', '제품', '감지', '1', 'ZERO!!', 'ZERO!!']
    내 예상은 이번 텍스트가 1.00확율로 [6]임.
    인티저 값은 ['AUX' 'DATA' 'EMER' 'END_A' 'END_B' 'ERROR' 'PROX_INTLK' 'SOL_A' 'SOL_B']
    출력 크기는 9
  • keras로 키워드 분석(5/5)

    간단한 데이터(1,200개)로 태그 분류기를 만들었다. validation을 0.2로 설정하면 val_acc가 0.3에서 움직이지 않는다. 그러나 0.1로 바꾸면 0.99까지 올라가는 마법을 볼수있다. 데이터가 적어 많이 입력하면 어떨지 잘 모르겠다. 똥을 먹으면 똥을 싼다. 똥을 음식으로 바꾸려면 물, 비료도 주고 햇빛도 잘 쬐여야한다. 농사나 손가락 노가다나 별 차이없어 보인다.

    모델을 저장해서, 다시 불러오는 방식으로 바꾸었다. 하도 많이 수정하다 보니 이 방식이 유리하다. 덕분에 디멘전 틀림을 찾았다. 16개 vector를 입력하는 구조에 6개만 입력해도 불만없이 잘? 예측했다. 저장한 모델을 불러오면 여기에서 체크를 한다.

  • 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가 변할 조짐이 없다. 다음에는 네트웍을 조금 복잡하게 해보고 다시 훈련시켜야겠다.