GNN과 문자형 변수 처리

강하예진(Erica)·2023년 4월 28일
0

Graph Neural Network

목록 보기
2/10

표제어 추출이 완료된 'Book-Title' column을 벡터로 만드는 두 가지 방법이 있다.

Two Way to Embeddig Test

  1. Label Encoder+Embeddign Layer : 하지만 각 책 제목을 하나의 벡터로 표현하기 때문에, 책 제목 내의 개별 단어들 사이의 관계를 고려하지 못할 수 있다. 그럼에도 불구하고, 간단한 방법으로 적용해 볼 만한 가치는 있다.

  2. word embeddign model : 텍스트 데이터를 토큰화하고, 각 토큰(단어)에 대해 임베딩을 수행한 후, 책 제목에 대한 전체 벡터를 얻기 위해 각 단어 벡터를 평균하거나 합산한다. 이 방식은 책 제목 내의 단어들 사이의 관계를 더 잘 고려할 수 있다.

Token

텍스트 데이터를 토큰화한다는 것은 문자열을 의미 있는 단위(토큰)로 나누는 것이다. 일반적으로 토큰은 단어로 간주되며, 이 경우 단어를 기준으로 문자열을 나눈다.
만약 데이터가 이미 표제어 추출이 완료되어 있는 경우, 간단한 공백 기반 토큰화를 수행할 수 있다. 예를 들어, "macbeth new penguin shakespeare"라는 문자열이 있으면, 토큰화된 결과는 ['macbeth', 'new', 'penguin', 'shakespeare']와 같은 단어 목록이 된다.

Word2Vec / FastText

pre-trained된 Word2Vec이나 FastText모델을 로드하고, 그것으로 각 row를 간단하게 토큰화할 수 있다. 그 다음에는 평균 임베딩을 추출할 수 있다.

예제 코드 - Word2Vec

import gensim.downloader as api

# pre-trained Word2Vec model 로드. 단어 간 유사도를 편리하게 가져와 사용 
word2vec_model = api.load('word2vec-google-news-300')

# 각 'Book-Title'을 토큰화하고 각 토큰에 대한 Word2Vec 임베딩 추출
def get_title_embedding(title, model):
    tokens = title.split()  # 각 책 제목을 공백을 기준으로 토큰화 
    embeddings = []
    
    for token in tokens: 
        if token in model:  # 토큰이 Word2Vec 모델의 어휘에 있는 경우
            embeddings.append(model[token])  # 해당 토큰의 임베딩을 가져와 리스트에 추가 

    # Compute the average of the embeddings
    if len(embeddings) > 0:  # 적어도 하나의 임베딩이 있는 경우
        return np.mean(embeddings, axis=0)  # 임베딩을 평균하여 하나의 벡터로 반환 
    else:
        return None  # 모든 토큰이 모델 어휘에 없는 경우 None을 반환 

# 평균 임베딩 벡터 추출
title_embeddings = []

for title in train_data['Book-Title']:
    embedding = get_title_embedding(title, word2vec_model)
    title_embeddings.append(embedding)

예제 코드 - FastText

일반적으로 더 많은 언어와 신조어를 제공한다. 다국어 데이터셋이거나 Word2Vec으로 했을 때 임베딩 생성이 제대로 안 된다면, FastText 모델을 추천한다.

import fasttext

# 사전 훈련된 FastText 모델 다운로드
!wget https://dl.fbaipublicfiles.com/fasttext/vectors-crawl/cc.en.300.bin.gz
!gunzip cc.en.300.bin.gz

# FastText 모델 로드
fasttext_model = fasttext.load_model("cc.en.300.bin")

def get_title_embedding_fasttext(title):
    words = title.split()
    if len(words) == 0:
        return np.zeros(300)
    embeddings = [fasttext_model.get_word_vector(word) for word in words]
    return np.mean(embeddings, axis=0)
    
title_embeddings = train_data['Book-Title'].apply(get_title_embedding_fasttext).tolist()

Trouble Shooting

Word2Vec 모델에서 임베딩을 추출했는데, 만약 데이터에 신조어나 고유어, 외국어 단어가 섞여 있다면 차원 축소 과정에서 아래와 같은 에러가 발생한다.

ValueError: setting an array element with a sequence.

만약 에러가 발생한다면, 아래와 같은 코드로 Embedding이 제대로 생성되었는지 확인해 보길 바란다.

empty_titles_count = 0
for title in train_data['Book-Title']:
    words = title.split()
    if not words:
        empty_titles_count += 1

print(f"빈 문자열이거나 토큰화된 단어가 없는 책 제목의 개수: {empty_titles_count}")
# 임베딩이 numpy 배열이 아니거나 형태가 (300,)이 아닌 경우 해당 인덱스, 책 제목, 및 임베딩을 출력

for idx, emb in enumerate(title_embeddings):
    if not isinstance(emb, np.ndarray) or emb.shape != (300,):
        print(f"Index: {idx}, Title: {train_data['Book-Title'][idx]}, Embedding: {emb}")

advance

  1. 코드에서 평균 임베딩이 추출되는 원리
    사전 학습된 모델에는 이미 단어들의 임베딩이 저장되어 있다. 따라서, 토큰화된 단어에 맞는 임베딩을 불러오는 것이다. 이후 단어가 1개 이상인 경우, 이 임베딩들을 평균해서 반환한다. 결과적으로 단어의 집합인 문장처럼 만드는 것이다.

  2. PCA 주성분 분석 (Reduce computational cost)
    임베딩 벡터의 차원은 사전 훈련된 모델의 벡터 크기와 같다.
    Google News 데이터셋에 훈련된 Word2Vec 모델의 벡터 크기는 300차원이다. 모델 이름에서도 알 수 있듯, 위 예제 코드의 FastText 모델의 임베딩도 마찬가지로 300차원이다.
    이렇게 큰 차원이 컴퓨팅 리소스 차원에서 부담스럽다면, PCA(주성분 분석)을 통해 임의의 n차원으로 벡터를 축소할 수 있다. 최종적으로는 (num_sample, 30) shape로 차원 축소가 될 것이다.

아래 PCA 주성분 분석으로 임베딩을 차원 축소하는 예제 코드를 남겨둔다.

예제 코드 - PCA

from sklearn.decomposition import PCA

# PCA 객체를 생성
pca = PCA(n_components=30)

# 평균 임베딩 벡터로 구성된 리스트를 NumPy 배열로 변환
title_embeddings_array = np.array(title_embeddings)

# 차원 축소
reduced_title_embeddings = pca.fit_transform(title_embeddings_array)

위 코드를 사용하면, reduced_title_embeddings에는 30차원으로 축소된 책 제목의 평균 임베딩 벡터가 저장된다.

profile
Recommend System & BackEnd Engineering

0개의 댓글