ML 커뮤니티 데이는 11월 9일입니다! TensorFlow, JAX에서 업데이트를 우리와 함께, 더 자세히 알아보기

Word2Vec

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 소스 보기 노트북 다운로드

Word2Vec은 단일 알고리즘이 아니라 대규모 데이터 세트에서 단어 임베딩을 학습하는 데 사용할 수 있는 모델 아키텍처 및 최적화 제품군입니다. Word2Vec을 통해 학습된 임베딩은 다양한 다운스트림 자연어 처리 작업에서 성공적인 것으로 입증되었습니다.

이 논문은 단어 표현을 학습하는 두 가지 방법을 제안했습니다.

  • 상황에 맞는 단어를 주변에 따라 중간 단어를 예측 연속 가방 - 중 - 단어 모델. 컨텍스트는 현재(중간) 단어 앞뒤에 몇 개의 단어로 구성됩니다. 이 아키텍처는 컨텍스트에서 단어의 순서가 중요하지 않기 때문에 bag-of-words 모델이라고 합니다.
  • 연속 건너 뛰기 그램 모델은 이전과 같은 문장에서 현재 단어 후 일정 범위 내에서 단어를 예측하고있다. 이에 대한 작업 예가 아래에 나와 있습니다.

이 자습서에서는 skip-gram 접근 방식을 사용합니다. 먼저, 설명을 위해 단일 문장을 사용하여 건너뛰기 그램 및 기타 개념을 탐색합니다. 다음으로 작은 데이터 세트에서 자체 Word2Vec 모델을 훈련합니다. 이 튜토리얼은 또한 그들을 훈련 묻어을 수출하고 시각화하는 코드를 포함 TensorFlow 임베딩 프로젝터 .

스킵 그램 및 네거티브 샘플링

bag-of-words 모델은 인접 컨텍스트가 주어지면 단어를 예측하는 반면 skip-gram 모델은 단어 자체가 주어지면 단어의 컨텍스트(또는 이웃)를 예측합니다. 이 모델은 토큰을 건너뛸 수 있도록 하는 n-그램인 건너뛰기 그램에 대해 학습됩니다(예를 보려면 아래 다이어그램 참조). 단어의 컨텍스트 스킵 그램 쌍의 집합으로 표현 될 수있다 (target_word, context_word) 여기서 context_word 의 주변 상황에 나타나는 target_word .

다음의 8단어 문장을 고려하십시오.

넓은 길은 뜨거운 태양에 반짝거렸다.

이 문장의 8개 단어 각각에 대한 컨텍스트 단어는 창 크기로 정의됩니다. 창 크기가 양쪽 단어의 폭을 결정 target_word 간주 될 수 context word . 다양한 창 크기를 기반으로 하는 대상 단어에 대한 이 건너뛰기 그램 표를 살펴보십시오.

word2vec_skipgrams

skip-gram 모델의 학습 목표는 대상 단어가 주어진 컨텍스트 단어를 예측할 확률을 최대화하는 것입니다. 2w 1w 단어의 순서에 대해서는, ... T 대물는 평균 로그 확률로 기록 될 수있다

word2vec_skipgram_objective

여기서 c 훈련 컨텍스트의 크기입니다. 기본 skip-gram 공식은 softmax 함수를 사용하여 이 확률을 정의합니다.

word2vec_full_softmax

VV '은 단어의 대상 및 상황 벡터 표현이며, W는 단어의 크기이다.

이 제제의 분모를 계산 종종 큰 전체 어휘 (105 -10 (7))에 걸쳐 측면 전체를 softmax를 수행하는 것을 포함한다.

소음 대조적 추정 손실 함수는 전체 softmax를위한 효율적인 근사하다. 대신 워드 분포 모델링 워드 묻어 배울 목적으로 NCE 손실 될 수 간략화 제외 샘플링을 사용한다.

목표 단어 대물 샘플링 단순화 네가티브 워드 잡음 분포 P N (w)로부터 인출 num_ns 마이너스 샘플로부터 컨텍스트 단어를 구별하는 것이다. 보다 정확하게는, 어휘 풀 softmax를 효율적 근사치 컨텍스트 단어 num_ns 네가티브 샘플 사이의 분류 문제로 대상 단어에 대한 손실을 야기하는 스킵 그램 쌍이다.

네가티브 샘플은 context_word가 나타나지 않는되도록 (target_word, context_word) 쌍으로 정의 window_size target_word의 근방. 예제 문장, 이러한 몇 부정적 샘플 (이다 window_size 있다 2).

(hot, shimmered)
(wide, hot)
(wide, sun)

다음 섹션에서는 단일 문장에 대해 건너뛰기 그램과 부정 샘플을 생성합니다. 또한 서브샘플링 기술에 대해 배우고 자습서 뒷부분에서 양성 및 음성 훈련 예제에 대한 분류 모델을 훈련합니다.

설정

import io
import re
import string
import tqdm

import numpy as np

import tensorflow as tf
from tensorflow.keras import layers
# Load the TensorBoard notebook extension
%load_ext tensorboard
SEED = 42
AUTOTUNE = tf.data.AUTOTUNE

예제 문장을 벡터화

다음 문장을 고려하십시오.
The wide road shimmered in the hot sun.

문장을 토큰화:

sentence = "The wide road shimmered in the hot sun"
tokens = list(sentence.lower().split())
print(len(tokens))
8

토큰에서 정수 인덱스로의 매핑을 저장하는 어휘를 만듭니다.

vocab, index = {}, 1  # start indexing from 1
vocab['<pad>'] = 0  # add a padding token
for token in tokens:
  if token not in vocab:
    vocab[token] = index
    index += 1
vocab_size = len(vocab)
print(vocab)
{'<pad>': 0, 'the': 1, 'wide': 2, 'road': 3, 'shimmered': 4, 'in': 5, 'hot': 6, 'sun': 7}

정수 인덱스에서 토큰으로 매핑을 저장하는 역어휘를 만듭니다.

inverse_vocab = {index: token for token, index in vocab.items()}
print(inverse_vocab)
{0: '<pad>', 1: 'the', 2: 'wide', 3: 'road', 4: 'shimmered', 5: 'in', 6: 'hot', 7: 'sun'}

문장을 벡터화하십시오.

example_sequence = [vocab[word] for word in tokens]
print(example_sequence)
[1, 2, 3, 4, 5, 1, 6, 7]

한 문장에서 건너뛰기 그램 생성

tf.keras.preprocessing.sequence 모듈은 유용한 기능 Word2Vec 위해 이러한 단순화 데이터 준비를 제공한다. 당신은 사용할 수 있습니다 tf.keras.preprocessing.sequence.skipgrams 으로부터 스킵 그램 쌍을 생성하는 example_sequence 주어진와 window_size 범위의 토큰에서 [0, vocab_size) .

window_size = 2
positive_skip_grams, _ = tf.keras.preprocessing.sequence.skipgrams(
      example_sequence,
      vocabulary_size=vocab_size,
      window_size=window_size,
      negative_samples=0)
print(len(positive_skip_grams))
26

몇 가지 긍정적인 스킵 그램을 살펴보십시오.

for target, context in positive_skip_grams[:5]:
  print(f"({target}, {context}): ({inverse_vocab[target]}, {inverse_vocab[context]})")
(3, 1): (road, the)
(6, 1): (hot, the)
(2, 1): (wide, the)
(6, 7): (hot, sun)
(6, 5): (hot, in)

하나의 skip-gram에 대한 네거티브 샘플링

skipgrams 소정 윈도우 기간 동안 밀어서 리턴 모든 긍정적 스킵 g 쌍 기능. 훈련을 위한 음성 샘플 역할을 하는 추가 스킵 그램 쌍을 생성하려면 어휘에서 임의의 단어를 샘플링해야 합니다. 사용 tf.random.log_uniform_candidate_sampler 샘플 기능 num_ns 창에서 주어진 목표 단어에 대해 부정적인 샘플의 수입니다. 하나의 skip-gram의 대상 단어에 대해 함수를 호출하고 컨텍스트 단어를 실제 클래스로 전달하여 샘플링에서 제외할 수 있습니다.

# Get target and context words for one positive skip-gram.
target_word, context_word = positive_skip_grams[0]

# Set the number of negative samples per positive context.
num_ns = 4

context_class = tf.reshape(tf.constant(context_word, dtype="int64"), (1, 1))
negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
    true_classes=context_class,  # class that should be sampled as 'positive'
    num_true=1,  # each positive skip-gram has 1 positive context class
    num_sampled=num_ns,  # number of negative context words to sample
    unique=True,  # all the negative samples should be unique
    range_max=vocab_size,  # pick index of the samples from [0, vocab_size]
    seed=SEED,  # seed for reproducibility
    name="negative_sampling"  # name of this operation
)
print(negative_sampling_candidates)
print([inverse_vocab[index.numpy()] for index in negative_sampling_candidates])
tf.Tensor([2 1 4 3], shape=(4,), dtype=int64)
['wide', 'the', 'shimmered', 'road']

하나의 교육 예제 구성

주어진 양의 경우 (target_word, context_word) 건너 그램, 당신은 이제이 num_ns 의 창 크기 인근에 표시되지 않습니다 부정적인 샘플링 상황에 맞는 단어 target_word . 일괄 처리하세요 1 긍정적 인 context_wordnum_ns 한 텐서에 부정적인 상황에 맞는 단어. 이것은 (긍정적으로 표시 스킵 그램 세트 생성 1 (로 표시) 및 음성 시료 0 각각의 타겟 워드를위한).

# Add a dimension so you can use concatenation (on the next step).
negative_sampling_candidates = tf.expand_dims(negative_sampling_candidates, 1)

# Concat positive context word with negative sampled words.
context = tf.concat([context_class, negative_sampling_candidates], 0)

# Label first context word as 1 (positive) followed by num_ns 0s (negative).
label = tf.constant([1] + [0]*num_ns, dtype="int64")

# Reshape target to shape (1,) and context and label to (num_ns+1,).
target = tf.squeeze(target_word)
context = tf.squeeze(context)
label = tf.squeeze(label)

위의 skip-gram 예제에서 대상 단어에 대한 컨텍스트와 해당 레이블을 살펴보십시오.

print(f"target_index    : {target}")
print(f"target_word     : {inverse_vocab[target_word]}")
print(f"context_indices : {context}")
print(f"context_words   : {[inverse_vocab[c.numpy()] for c in context]}")
print(f"label           : {label}")
target_index    : 3
target_word     : road
context_indices : [1 2 1 4 3]
context_words   : ['the', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

의 튜플 (target, context, label) 텐서는 Word2Vec 모델을 샘플링하여 스킵 그램 음성 훈련에 대해 하나 개의 훈련 예를 구성한다. 통지 대상이 형상 있음 (1,) 컨텍스트 및 라벨 형상 동안 (1+num_ns,)

print("target  :", target)
print("context :", context)
print("label   :", label)
target  : tf.Tensor(3, shape=(), dtype=int32)
context : tf.Tensor([1 2 1 4 3], shape=(5,), dtype=int64)
label   : tf.Tensor([1 0 0 0 0], shape=(5,), dtype=int64)

요약

이 그림은 문장에서 훈련 예제를 생성하는 절차를 요약한 것입니다.

word2vec_negative_sampling

모든 단계를 하나의 함수로 컴파일

스킵그램 샘플링 테이블

큰 데이터 세트는 불용어와 같이 더 자주 사용되는 단어의 수가 많은 더 많은 어휘를 의미합니다. 일반적으로 발생하는 단어 샘플링에서 얻은 교육 사례 (예 : the , is , on 에서 배울 수있는 모델에 대한 많은 유용한 정보를 추가하지 마십시오). Mikolov et al. 임베딩 품질을 향상시키는 데 도움이 되는 방법으로 자주 사용하는 단어의 서브샘플링을 제안합니다.

tf.keras.preprocessing.sequence.skipgrams 함수는 토큰 채취 인코딩 확률에 나타난 샘플링 인자를 받아 들인다. 당신은 사용할 수 있습니다 tf.keras.preprocessing.sequence.make_sampling_table 워드 주파수 순위 기반의 확률 적 샘플링 테이블을 생성하고 그것을 전달하는 skipgrams 기능. A에 대한 샘플링 확률을 살펴보세요 vocab_size (10)를.

sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(size=10)
print(sampling_table)
[0.00315225 0.00315225 0.00547597 0.00741556 0.00912817 0.01068435
 0.01212381 0.01347162 0.01474487 0.0159558 ]

sampling_table[i] 데이터 세트에서의 i 번째 가장 일반적인 단어의 의미를 샘플링 확률. 이 함수는 가정 이는 Zipf의 유통 샘플링 단어 주파수를.

훈련 데이터 생성

위에서 설명한 모든 단계를 모든 텍스트 데이터 세트에서 얻은 벡터화된 문장 목록에서 호출할 수 있는 함수로 컴파일합니다. 샘플링 테이블은 skip-gram 단어 쌍을 샘플링하기 전에 작성됩니다. 이 기능은 이후 섹션에서 사용합니다.

# Generates skip-gram pairs with negative sampling for a list of sequences
# (int-encoded sentences) based on window size, number of negative samples
# and vocabulary size.
def generate_training_data(sequences, window_size, num_ns, vocab_size, seed):
  # Elements of each training example are appended to these lists.
  targets, contexts, labels = [], [], []

  # Build the sampling table for vocab_size tokens.
  sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(vocab_size)

  # Iterate over all sequences (sentences) in dataset.
  for sequence in tqdm.tqdm(sequences):

    # Generate positive skip-gram pairs for a sequence (sentence).
    positive_skip_grams, _ = tf.keras.preprocessing.sequence.skipgrams(
          sequence,
          vocabulary_size=vocab_size,
          sampling_table=sampling_table,
          window_size=window_size,
          negative_samples=0)

    # Iterate over each positive skip-gram pair to produce training examples
    # with positive context word and negative samples.
    for target_word, context_word in positive_skip_grams:
      context_class = tf.expand_dims(
          tf.constant([context_word], dtype="int64"), 1)
      negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
          true_classes=context_class,
          num_true=1,
          num_sampled=num_ns,
          unique=True,
          range_max=vocab_size,
          seed=SEED,
          name="negative_sampling")

      # Build context and label vectors (for one target word)
      negative_sampling_candidates = tf.expand_dims(
          negative_sampling_candidates, 1)

      context = tf.concat([context_class, negative_sampling_candidates], 0)
      label = tf.constant([1] + [0]*num_ns, dtype="int64")

      # Append each element from the training example to global lists.
      targets.append(target_word)
      contexts.append(context)
      labels.append(label)

  return targets, contexts, labels

Word2Vec용 훈련 데이터 준비

스킵 그램 네거티브 샘플링 기반 Word2Vec 모델에 대해 한 문장으로 작업하는 방법을 이해하면 더 많은 문장 목록에서 훈련 예제를 생성할 수 있습니다!

텍스트 코퍼스 다운로드

이 튜토리얼에서는 셰익스피어가 쓴 텍스트 파일을 사용합니다. 자신의 데이터에 대해 이 코드를 실행하려면 다음 줄을 변경하십시오.

path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt
1122304/1115394 [==============================] - 0s 0us/step
1130496/1115394 [==============================] - 0s 0us/step

파일에서 텍스트를 읽고 처음 몇 줄을 살펴보십시오.

with open(path_to_file) as f: 
  lines = f.read().splitlines()
for line in lines[:20]:
  print(line)
First Citizen:
Before we proceed any further, hear me speak.

All:
Speak, speak.

First Citizen:
You are all resolved rather to die than to famish?

All:
Resolved. resolved.

First Citizen:
First, you know Caius Marcius is chief enemy to the people.

All:
We know't, we know't.

First Citizen:
Let us kill him, and we'll have corn at our own price.

구성하는 비 빈 줄을 사용 tf.data.TextLineDataset 다음 단계에 대한 개체를.

text_ds = tf.data.TextLineDataset(path_to_file).filter(lambda x: tf.cast(tf.strings.length(x), bool))

말뭉치에서 문장을 벡터화

당신은 사용할 수 있습니다 TextVectorization 코퍼스에서 문장을 벡터화 층. 이이 레이어를 사용하는 방법에 대해 자세히 알아보기 텍스트 분류 자습서. 위의 처음 몇 문장에서 텍스트는 한 경우에 사용해야 하고 구두점은 제거해야 함을 알 수 있습니다. 이렇게하려면 정의 custom_standardization function TextVectorization 층에 사용될 수있다.

# Now, create a custom standardization function to lowercase the text and
# remove punctuation.
def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  return tf.strings.regex_replace(lowercase,
                                  '[%s]' % re.escape(string.punctuation), '')


# Define the vocabulary size and number of words in a sequence.
vocab_size = 4096
sequence_length = 10

# Use the TextVectorization layer to normalize, split, and map strings to
# integers. Set output_sequence_length length to pad all samples to same length.
vectorize_layer = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

전화 adapt 어휘를 만들 텍스트 데이터 세트에.

vectorize_layer.adapt(text_ds.batch(1024))

층의 상태 텍스트 언어 자료를 표현하도록 구성되면, 어휘에 액세스 할 수 get_vocabulary() . 이 함수는 빈도에 따라 정렬(내림차순)된 모든 어휘 토큰 목록을 반환합니다.

# Save the created vocabulary for reference.
inverse_vocab = vectorize_layer.get_vocabulary()
print(inverse_vocab[:20])
['', '[UNK]', 'the', 'and', 'to', 'i', 'of', 'you', 'my', 'a', 'that', 'in', 'is', 'not', 'for', 'with', 'me', 'it', 'be', 'your']

vectorize_layer 이제 각 요소의 벡터를 생성하기 위해 사용될 수있다 text_ds .

# Vectorize the data in text_ds.
text_vector_ds = text_ds.batch(1024).prefetch(AUTOTUNE).map(vectorize_layer).unbatch()

데이터세트에서 시퀀스 가져오기

이제이 tf.data.Dataset 정수 인코딩 된 문장을. Word2Vec 모델 훈련을 위한 데이터세트를 준비하려면 데이터세트를 문장 벡터 시퀀스 목록으로 병합합니다. 이 단계는 데이터 세트의 각 문장을 반복하여 긍정적이고 부정적인 예를 생성하기 때문에 필요합니다.

sequences = list(text_vector_ds.as_numpy_iterator())
print(len(sequences))
32777

에서 몇 가지 예를 살펴보세요 sequences .

for seq in sequences[:5]:
  print(f"{seq} => {[inverse_vocab[i] for i in seq]}")
[ 89 270   0   0   0   0   0   0   0   0] => ['first', 'citizen', '', '', '', '', '', '', '', '']
[138  36 982 144 673 125  16 106   0   0] => ['before', 'we', 'proceed', 'any', 'further', 'hear', 'me', 'speak', '', '']
[34  0  0  0  0  0  0  0  0  0] => ['all', '', '', '', '', '', '', '', '', '']
[106 106   0   0   0   0   0   0   0   0] => ['speak', 'speak', '', '', '', '', '', '', '', '']
[ 89 270   0   0   0   0   0   0   0   0] => ['first', 'citizen', '', '', '', '', '', '', '', '']

시퀀스에서 훈련 예제 생성

sequences 지금 INT 인코딩 된 문장의 목록입니다. 그냥 전화 generate_training_data() Word2Vec 모델에 대한 교육 예제를 생성하기 위해 이전 정의 함수를. 요약하자면, 이 함수는 각 시퀀스의 각 단어를 반복하여 긍정적이고 부정적인 컨텍스트 단어를 수집합니다. 대상의 길이, 컨텍스트 및 레이블은 동일해야 하며 총 교육 예제 수를 나타냅니다.

targets, contexts, labels = generate_training_data(
    sequences=sequences,
    window_size=2,
    num_ns=4,
    vocab_size=vocab_size,
    seed=SEED)

targets = np.array(targets)
contexts = np.array(contexts)[:,:,0]
labels = np.array(labels)

print('\n')
print(f"targets.shape: {targets.shape}")
print(f"contexts.shape: {contexts.shape}")
print(f"labels.shape: {labels.shape}")
100%|██████████| 32777/32777 [00:33<00:00, 976.91it/s]
targets.shape: (64889,)
contexts.shape: (64889, 5)
labels.shape: (64889, 5)

성능을 위한 데이터세트 구성

훈련 예제의 잠재적으로 많은 수의 효율적인 배치를 수행하려면 사용 tf.data.Dataset API를. 이 단계 후에는 것이다 tf.data.Dataset 의 객체 (target_word, context_word), (label) 당신의 Word2Vec 모델을 훈련하는 요소!

BATCH_SIZE = 1024
BUFFER_SIZE = 10000
dataset = tf.data.Dataset.from_tensor_slices(((targets, contexts), labels))
dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)
print(dataset)
<BatchDataset shapes: (((1024,), (1024, 5)), (1024, 5)), types: ((tf.int64, tf.int64), tf.int64)>

추가 cache()prefetch() 성능을 개선 할 수 있습니다.

dataset = dataset.cache().prefetch(buffer_size=AUTOTUNE)
print(dataset)
<PrefetchDataset shapes: (((1024,), (1024, 5)), (1024, 5)), types: ((tf.int64, tf.int64), tf.int64)>

모델 및 교육

Word2Vec 모델은 스킵 그램의 실제 컨텍스트 단어와 네거티브 샘플링을 통해 얻은 잘못된 컨텍스트 단어를 구별하는 분류기로 구현될 수 있습니다. 대상 단어와 컨텍스트 단어의 임베딩 사이에 내적을 수행하여 레이블에 대한 예측을 얻고 데이터 세트의 실제 레이블에 대한 손실을 계산할 수 있습니다.

서브클래싱된 Word2Vec 모델

사용 Keras 하위 클래스의 API를 다음 층으로 Word2Vec 모델을 정의합니다 :

  • target_embedding 하십시오 tf.keras.layers.Embedding 이 타겟 워드로 표시 될 때 단어의 매립을 보이는 층. 이 층에서의 파라미터의 수이다 (vocab_size * embedding_dim) .
  • context_embedding : 다른 tf.keras.layers.Embedding 그것은 상황에 맞는 단어로 표시 될 때 단어의 삽입을 보이는 계층. 이 층에서의 파라미터의 개수는 동일하다 target_embedding(vocab_size * embedding_dim) .
  • dots 하십시오 tf.keras.layers.Dot 트레이닝 쌍의 타겟과 문맥 묻어의 내적을 계산하는 층.
  • flatten 하십시오 tf.keras.layers.Flatten 계층의 결과 평탄화 dots logits으로 층.

서브 클래 싱 모델에는 정의 할 수있다 call() 허용 함수 (target, context) 그들의 대응 매립 층으로 전달 될 수있는 쌍. 모양 변경 context_embedding 가진 내적을 수행 할 target_embedding 및 평탄화 된 결과를 반환합니다.

class Word2Vec(tf.keras.Model):
  def __init__(self, vocab_size, embedding_dim):
    super(Word2Vec, self).__init__()
    self.target_embedding = layers.Embedding(vocab_size,
                                      embedding_dim,
                                      input_length=1,
                                      name="w2v_embedding")
    self.context_embedding = layers.Embedding(vocab_size,
                                       embedding_dim,
                                       input_length=num_ns+1)

  def call(self, pair):
    target, context = pair
    # target: (batch, dummy?)  # The dummy axis doesn't exist in TF2.7+
    # context: (batch, context)
    if len(target.shape) == 2:
      target = tf.squeeze(target, axis=1)
    # target: (batch,)
    word_emb = self.target_embedding(target)
    # word_emb: (batch, embed)
    context_emb = self.context_embedding(context)
    # context_emb: (batch, context, embed)
    dots = tf.einsum('be,bce->bc', word_emb, context_emb)
    # dots: (batch, context)
    return dots

손실 함수 정의 및 모델 컴파일

단순화하기 위해, 당신은 사용할 수 있습니다 tf.keras.losses.CategoricalCrossEntropy 부정적인 샘플링 손실에 대한 대안으로. 사용자 정의 손실 함수를 작성하려면 다음과 같이 할 수도 있습니다.

def custom_loss(x_logit, y_true):
      return tf.nn.sigmoid_cross_entropy_with_logits(logits=x_logit, labels=y_true)

모델을 만들 시간입니다! 포함 차원이 128인 Word2Vec 클래스를 인스턴스화합니다(다른 값으로 실험할 수 있음). 와 모델 컴파일 tf.keras.optimizers.Adam 최적화.

embedding_dim = 128
word2vec = Word2Vec(vocab_size, embedding_dim)
word2vec.compile(optimizer='adam',
                 loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                 metrics=['accuracy'])

또한 텐서보드에 대한 훈련 통계를 기록하는 콜백을 정의합니다.

tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="logs")

와 모델 기차 dataset 신 (新) 시대의 어떤 수에 상기에서 제조합니다.

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
63/63 [==============================] - 1s 9ms/step - loss: 1.6083 - accuracy: 0.2309
Epoch 2/20
63/63 [==============================] - 0s 2ms/step - loss: 1.5890 - accuracy: 0.5520
Epoch 3/20
63/63 [==============================] - 0s 3ms/step - loss: 1.5413 - accuracy: 0.6021
Epoch 4/20
63/63 [==============================] - 0s 2ms/step - loss: 1.4584 - accuracy: 0.5789
Epoch 5/20
63/63 [==============================] - 0s 2ms/step - loss: 1.3598 - accuracy: 0.5857
Epoch 6/20
63/63 [==============================] - 0s 2ms/step - loss: 1.2622 - accuracy: 0.6127
Epoch 7/20
63/63 [==============================] - 0s 2ms/step - loss: 1.1710 - accuracy: 0.6456
Epoch 8/20
63/63 [==============================] - 0s 2ms/step - loss: 1.0867 - accuracy: 0.6804
Epoch 9/20
63/63 [==============================] - 0s 3ms/step - loss: 1.0085 - accuracy: 0.7123
Epoch 10/20
63/63 [==============================] - 0s 2ms/step - loss: 0.9361 - accuracy: 0.7418
Epoch 11/20
63/63 [==============================] - 0s 2ms/step - loss: 0.8690 - accuracy: 0.7669
Epoch 12/20
63/63 [==============================] - 0s 2ms/step - loss: 0.8070 - accuracy: 0.7891
Epoch 13/20
63/63 [==============================] - 0s 2ms/step - loss: 0.7500 - accuracy: 0.8082
Epoch 14/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6977 - accuracy: 0.8249
Epoch 15/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6498 - accuracy: 0.8393
Epoch 16/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6061 - accuracy: 0.8528
Epoch 17/20
63/63 [==============================] - 0s 3ms/step - loss: 0.5663 - accuracy: 0.8651
Epoch 18/20
63/63 [==============================] - 0s 3ms/step - loss: 0.5300 - accuracy: 0.8762
Epoch 19/20
63/63 [==============================] - 0s 2ms/step - loss: 0.4970 - accuracy: 0.8858
Epoch 20/20
63/63 [==============================] - 0s 2ms/step - loss: 0.4670 - accuracy: 0.8947
<keras.callbacks.History at 0x7fbea4362490>

Tensorboard는 이제 Word2Vec 모델의 정확도와 손실을 보여줍니다.

%tensorboard --logdir logs

조회 및 분석 포함

사용하여 모델에서 가중치를 확보 get_layer()get_weights() . get_vocabulary() 함수는 라인 당 하나의 토큰으로 메타 데이터 파일을 구축 할 수있는 어휘를 제공한다.

weights = word2vec.get_layer('w2v_embedding').get_weights()[0]
vocab = vectorize_layer.get_vocabulary()

벡터 및 메타데이터 파일을 만들고 저장합니다.

out_v = io.open('vectors.tsv', 'w', encoding='utf-8')
out_m = io.open('metadata.tsv', 'w', encoding='utf-8')

for index, word in enumerate(vocab):
  if index == 0:
    continue  # skip 0, it's padding.
  vec = weights[index]
  out_v.write('\t'.join([str(x) for x in vec]) + "\n")
  out_m.write(word + "\n")
out_v.close()
out_m.close()

다운로드 vectors.tsv 하고 metadata.tsv 에서 얻어진 묻어 분석 임베딩 프로젝터 .

try:
  from google.colab import files
  files.download('vectors.tsv')
  files.download('metadata.tsv')
except Exception:
  pass

다음 단계

이 튜토리얼에서는 처음부터 네거티브 샘플링을 사용하여 스킵 그램 Word2Vec 모델을 구현하고 얻은 단어 임베딩을 시각화하는 방법을 보여주었습니다.