ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TensorFlow 기초 38 - 문자열(corpus - 자연어 데이터 집합) 토큰화 + LSTM으로 감성 분류
    TensorFlow 2022. 12. 13. 17:30

     

    padding : 서로 다른 길이의 데이터를 가장 긴 데이터의 길이와 같게 만듦

    Embedding에 입력될 단어의 수를 지정하는데 가능한 토큰 갯수는 단어 인덱스 최대값 + 1을 부여한다.

    # 문자열(corpus - 자연어 데이터 집합) 토큰화 + LSTM으로 감성 분류
    # 토큰(Token): text를 단어, 문장, 형태소 별로 나눌 수 있는데 이렇게 나뉜 조각들을 token이라고 한다.
    import numpy as np
    from keras.preprocessing.text import Tokenizer 
    from keras.utils import pad_sequences
    
    docs = ['너무 재밌네요', '최고에요', '참 잘 만든 작품입니다', '추천하고 싶어요', '한 번 더 보고 싶군요', '글쎄요', '별로네요', '생각보다 너무 지루해요', '연기가 어색하더군요', '재미없어요']
    labels = np.array([1,1,1,1,1,0,0,0,0,0])
    
    token = Tokenizer()
    token.fit_on_texts(docs) # 정수 인코딩
    print(token.word_index) # 각 단어에 대한 인덱싱 확인
    
    x = token.texts_to_sequences(docs) # 텍스트를 정수 인덱싱하여 list로 반환
    print(x)
    
    # padding : 서로 다른 길이의 데이터를 가장 긴 데이터의 길이와 같게 만듦
    padded_x = pad_sequences(x, 5)
    print('padded_x :\n', padded_x)
    
    # model
    from keras.models import Sequential
    from keras.layers import Dense, Flatten, Embedding, LSTM
    
    word_size = len(token.word_index) + 1 # Embedding에 입력될 단어의 수를 지정. 가능한 토큰 갯수는 단어 인덱스 최대값 + 1
    model = Sequential()
    
    model.add(Embedding(word_size, 8, input_length=5)) # (가능 토큰 수, 임베딩 차원, 입력 수)
    model.add(LSTM(32, activation='tanh')) # 자연어 처리
    
    model.add(Flatten())
    
    model.add(Dense(units=32, activation='relu'))
    model.add(Dense(units=1, activation='sigmoid'))
    print(model.summary())
    
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    model.fit(padded_x, labels, epochs=20, verbose=2)
    print('evaluate :', model.evaluate(padded_x, labels))
    
    print('predict :', np.where(model.predict(padded_x) > 0.5, 1, 0).ravel())
    print('labels :', labels)
    
    
    <console>
    {'너무': 1, '재밌네요': 2, '최고에요': 3, '참': 4, '잘': 5, '만든': 6, '작품입니다': 7, '추천하고': 8, '싶어요': 9, '한': 10, '번': 11, '더': 12, '보고': 13, '싶군요': 14, '글쎄요': 15, '별로네요': 16, '생각보다': 17, '지루해요': 18, '연기가': 19, '어색하더군요': 20, '재미없어요': 21}
    [[1, 2], [3], [4, 5, 6, 7], [8, 9], [10, 11, 12, 13, 14], [15], [16], [17, 1, 18], [19, 20], [21]]
    padded_x :
     [[ 0  0  0  1  2]
     [ 0  0  0  0  3]
     [ 0  4  5  6  7]
     [ 0  0  0  8  9]
     [10 11 12 13 14]
     [ 0  0  0  0 15]
     [ 0  0  0  0 16]
     [ 0  0 17  1 18]
     [ 0  0  0 19 20]
     [ 0  0  0  0 21]]
    
    Model: "sequential"
    _________________________________________________________________
     Layer (type)                Output Shape              Param #   
    =================================================================
     embedding (Embedding)       (None, 5, 8)              176       
                                                                     
     lstm (LSTM)                 (None, 32)                5248      
                                                                     
     flatten (Flatten)           (None, 32)                0         
                                                                     
     dense (Dense)               (None, 32)                1056      
                                                                     
     dense_1 (Dense)             (None, 1)                 33        
                                                                     
    =================================================================
    Total params: 6,513
    Trainable params: 6,513
    Non-trainable params: 0
    _________________________________________________________________
    None
    Epoch 1/20
    1/1 - 1s - loss: 0.6936 - accuracy: 0.3000 - 1s/epoch - 1s/step
    Epoch 2/20
    1/1 - 0s - loss: 0.6929 - accuracy: 0.6000 - 2ms/epoch - 2ms/step
    Epoch 3/20
    1/1 - 0s - loss: 0.6924 - accuracy: 0.8000 - 2ms/epoch - 2ms/step
    Epoch 4/20
    1/1 - 0s - loss: 0.6919 - accuracy: 0.8000 - 2ms/epoch - 2ms/step
    Epoch 5/20
    1/1 - 0s - loss: 0.6915 - accuracy: 0.8000 - 1ms/epoch - 1ms/step
    Epoch 6/20
    1/1 - 0s - loss: 0.6911 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 7/20
    1/1 - 0s - loss: 0.6906 - accuracy: 0.9000 - 3ms/epoch - 3ms/step
    Epoch 8/20
    1/1 - 0s - loss: 0.6902 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 9/20
    1/1 - 0s - loss: 0.6897 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 10/20
    1/1 - 0s - loss: 0.6891 - accuracy: 0.9000 - 997us/epoch - 997us/step
    Epoch 11/20
    1/1 - 0s - loss: 0.6886 - accuracy: 0.9000 - 996us/epoch - 996us/step
    Epoch 12/20
    1/1 - 0s - loss: 0.6879 - accuracy: 0.9000 - 997us/epoch - 997us/step
    Epoch 13/20
    1/1 - 0s - loss: 0.6873 - accuracy: 0.9000 - 997us/epoch - 997us/step
    Epoch 14/20
    1/1 - 0s - loss: 0.6865 - accuracy: 0.9000 - 3ms/epoch - 3ms/step
    Epoch 15/20
    1/1 - 0s - loss: 0.6856 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 16/20
    1/1 - 0s - loss: 0.6847 - accuracy: 0.9000 - 996us/epoch - 996us/step
    Epoch 17/20
    1/1 - 0s - loss: 0.6837 - accuracy: 0.9000 - 996us/epoch - 996us/step
    Epoch 18/20
    1/1 - 0s - loss: 0.6826 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 19/20
    1/1 - 0s - loss: 0.6814 - accuracy: 0.9000 - 2ms/epoch - 2ms/step
    Epoch 20/20
    1/1 - 0s - loss: 0.6802 - accuracy: 0.9000 - 996us/epoch - 996us/step
    
    1/1 [==============================] - ETA: 0s - loss: 0.6788 - accuracy: 0.9000
    1/1 [==============================] - 0s 271ms/step - loss: 0.6788 - accuracy: 0.9000
    evaluate : [0.6788328289985657, 0.8999999761581421]
    
    1/1 [==============================] - ETA: 0s
    1/1 [==============================] - 0s 301ms/step
    predict : [1 0 1 1 1 0 0 0 0 0]
    labels : [1 1 1 1 1 0 0 0 0 0]

    텍스트를 정수 인덱싱하여 list로 반환하여 출력하였다.

     

     

     

    Embedding 클래스 : 문장 토큰화와 단어 토큰화를 위한 개념 이해용 소스

    참고 : 케라스의 Embedding 레이어는 처음에 무작위로 초기화된 상태에서 정수로 오는 word를 정해진 크기의 벡터로 바꿔서 다음 레이어로 넘기고, 학습단계에서는 역전파되는 기울기를 바탕으로 해당 word의 임베딩 값을 조정한다. 즉 주변 문맥을 반영하지 않는다. 그럼 Dense레이어랑  같은거 아닌가 싶지만  차이점은 원핫벡터로 값을 안넣어줘도 되서 덕분에 메모리 절약할 수 있고, 케라스에서 지원하는 masking 기능을 사용할 수 있고, 꼭 문장뿐만아니라 추천 시스템 등에서 User 등을 벡터로 나타낼 때도 사용할 수 있다. 하지만 웬만하면 weights 지정 기능을 이용해서 pre-trained 된 word2vec 등을 지정해야 할 것이다.

     

    출처 : https://cafe.daum.net/flowlife/S2Ul/19

    댓글

Designed by Tistory.