সাহায্য Kaggle উপর TensorFlow সঙ্গে গ্রেট বেরিয়ার রিফ রক্ষা চ্যালেঞ্জ যোগদান

word2vec

TensorFlow.org এ দেখুন Google Colab-এ চালান GitHub-এ উৎস দেখুন নোটবুক ডাউনলোড করুন

word2vec একটি একক অ্যালগরিদম নয়, বরং এটি মডেল আর্কিটেকচার এবং অপ্টিমাইজেশনের একটি পরিবার যা বড় ডেটাসেট থেকে শব্দ এমবেডিং শিখতে ব্যবহার করা যেতে পারে। Word2vec-এর মাধ্যমে শেখা এমবেডিংগুলি ডাউনস্ট্রিম প্রাকৃতিক ভাষা প্রক্রিয়াকরণের বিভিন্ন কাজে সফল বলে প্রমাণিত হয়েছে।

এই কাগজগুলি শব্দের উপস্থাপনা শেখার জন্য দুটি পদ্ধতির প্রস্তাব করেছে:

  • কন্টিনিউয়াস ব্যাগ-অফ-শব্দ মডেল : পার্শ্ববর্তী প্রসঙ্গ শব্দের উপর ভিত্তি করে মধ্যবর্তী শব্দের পূর্বাভাস দেয়। প্রসঙ্গটি বর্তমান (মধ্য) শব্দের আগে এবং পরে কয়েকটি শব্দ নিয়ে গঠিত। এই স্থাপত্যটিকে একটি ব্যাগ-অফ-শব্দ মডেল বলা হয় কারণ প্রসঙ্গে শব্দের ক্রম গুরুত্বপূর্ণ নয়।
  • ক্রমাগত স্কিপ-গ্রাম মডেল : একই বাক্যে বর্তমান শব্দের আগে এবং পরে একটি নির্দিষ্ট পরিসরের মধ্যে শব্দগুলির পূর্বাভাস দেয়। এটির একটি কার্যকর উদাহরণ নীচে দেওয়া হল।

আপনি এই টিউটোরিয়ালে স্কিপ-গ্রাম পদ্ধতি ব্যবহার করবেন। প্রথমত, আপনি উদাহরণের জন্য একটি বাক্য ব্যবহার করে স্কিপ-গ্রাম এবং অন্যান্য ধারণাগুলি অন্বেষণ করবেন। এরপর, আপনি একটি ছোট ডেটাসেটে আপনার নিজের word2vec মডেলকে প্রশিক্ষণ দেবেন। এই টিউটোরিয়ালটিতে প্রশিক্ষিত এম্বেডিংগুলিকে রপ্তানি করার এবং টেনসরফ্লো এম্বেডিং প্রজেক্টরে তাদের কল্পনা করার জন্য কোড রয়েছে৷

স্কিপ-গ্রাম এবং নেগেটিভ স্যাম্পলিং

যখন একটি ব্যাগ-অফ-শব্দ মডেল প্রতিবেশী প্রসঙ্গ দেওয়া একটি শব্দের ভবিষ্যদ্বাণী করে, একটি স্কিপ-গ্রাম মডেল একটি শব্দের প্রসঙ্গ (বা প্রতিবেশীদের) ভবিষ্যদ্বাণী করে, শব্দটি নিজেই। মডেলটিকে স্কিপ-গ্রামের উপর প্রশিক্ষিত করা হয়, যা এন-গ্রাম যা টোকেনগুলিকে এড়িয়ে যাওয়ার অনুমতি দেয় (উদাহরণের জন্য নীচের চিত্রটি দেখুন)। একটি শব্দের প্রসঙ্গটি স্কিপ-গ্রাম জোড়ার একটি সেটের মাধ্যমে উপস্থাপন করা যেতে পারে (target_word, context_word) যেখানে context_word target_word প্রসঙ্গে উপস্থিত হয়।

আটটি শব্দের নিম্নলিখিত বাক্যটি বিবেচনা করুন:

প্রশস্ত রাস্তা প্রখর রোদে ঝলমল করছে।

এই বাক্যটির 8টি শব্দের প্রতিটির জন্য প্রসঙ্গ শব্দগুলি একটি উইন্ডো আকার দ্বারা সংজ্ঞায়িত করা হয়েছে। উইন্ডোর আকার একটি target_word উভয় পাশে শব্দের স্প্যান নির্ধারণ করে যেটিকে একটি context word হিসেবে বিবেচনা করা যেতে পারে। নীচে বিভিন্ন উইন্ডো আকারের উপর ভিত্তি করে লক্ষ্য শব্দের জন্য স্কিপ-গ্রামের একটি সারণী রয়েছে।

word2vec_skipgrams

স্কিপ-গ্রাম মডেলের প্রশিক্ষণের উদ্দেশ্য হল লক্ষ্য শব্দের প্রেক্ষিতে প্রসঙ্গ শব্দের পূর্বাভাস দেওয়ার সম্ভাবনাকে সর্বাধিক করা। শব্দের একটি ক্রম w 1 , w 2 , ... w T , উদ্দেশ্যটিকে গড় লগ সম্ভাব্যতা হিসাবে লেখা যেতে পারে

word2vec_skipgram_objective

যেখানে c হল প্রশিক্ষণের প্রেক্ষাপটের আকার। মৌলিক স্কিপ-গ্রাম ফর্মুলেশন softmax ফাংশন ব্যবহার করে এই সম্ভাব্যতা সংজ্ঞায়িত করে।

word2vec_full_softmax

যেখানে v এবং v ' শব্দের লক্ষ্য এবং প্রসঙ্গ ভেক্টর উপস্থাপনা এবং W হল শব্দভান্ডার আকার।

এই ফর্মুলেশনের হর গণনা করার জন্য পুরো শব্দভান্ডারের শব্দগুলির উপর একটি সম্পূর্ণ সফটম্যাক্স সম্পাদন করা জড়িত, যেগুলি প্রায়শই বড় (10 5 -10 7 ) পদ।

নয়েজ কন্ট্রাস্টিভ এস্টিমেশন (NCE) লস ফাংশন হল একটি পূর্ণ সফটম্যাক্সের জন্য একটি দক্ষ অনুমান। ওয়ার্ড ডিস্ট্রিবিউশন মডেল করার পরিবর্তে শব্দ এমবেডিং শেখার উদ্দেশ্য নিয়ে, নেতিবাচক নমুনা ব্যবহার করার জন্য NCE ক্ষতি সরলীকৃত করা যেতে পারে।

একটি লক্ষ্য শব্দের জন্য সরলীকৃত নেতিবাচক নমুনা উদ্দেশ্য হল শব্দের শব্দের বন্টন P n (w) থেকে অঙ্কিত num_ns নেতিবাচক নমুনা থেকে প্রসঙ্গ শব্দটিকে আলাদা করা। আরও স্পষ্টভাবে, শব্দভান্ডারের উপর সম্পূর্ণ সফ্টম্যাক্সের একটি দক্ষ অনুমান হল, একটি স্কিপ-গ্রাম জোড়ার জন্য, প্রসঙ্গ শব্দ এবং num_ns নেতিবাচক নমুনার মধ্যে শ্রেণীবিভাগের সমস্যা হিসাবে একটি লক্ষ্য শব্দের ক্ষতিকে জাহির করা।

একটি নেতিবাচক নমুনাকে একটি (target_word, context_word) জোড়া হিসাবে সংজ্ঞায়িত করা হয় যাতে context_word target_word window_size পাড়ায় উপস্থিত হয় না। উদাহরণ বাক্যের জন্য, এগুলি কয়েকটি সম্ভাব্য নেতিবাচক নমুনা (যখন 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

একটি উদাহরণ বাক্য ভেক্টরাইজ করুন

নিম্নলিখিত বাক্যটি বিবেচনা করুন:

প্রশস্ত রাস্তা প্রখর রোদে ঝলমল করছে।

বাক্যটিকে টোকেনাইজ করুন:

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 ব্যবহার করতে পারেন পরিসরে [0, vocab_size) টোকেন থেকে প্রদত্ত window_size সহ example_sequence থেকে skip-gram জোড়া তৈরি করতে।

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]})")
(2, 3): (wide, road)
(5, 3): (in, road)
(4, 2): (shimmered, wide)
(1, 7): (the, sun)
(4, 1): (shimmered, the)

একটি স্কিপ-গ্রামের জন্য নেতিবাচক নমুনা

skipgrams ফাংশন একটি প্রদত্ত উইন্ডো স্প্যানের উপর স্লাইড করে সমস্ত ইতিবাচক স্কিপ-গ্রাম জোড়া প্রদান করে। অতিরিক্ত স্কিপ-গ্রাম জোড়া তৈরি করতে যা প্রশিক্ষণের জন্য নেতিবাচক নমুনা হিসাবে কাজ করবে, আপনাকে শব্দভান্ডার থেকে এলোমেলো শব্দের নমুনা দিতে হবে। একটি উইন্ডোতে প্রদত্ত টার্গেট শব্দের জন্য নেতিবাচক নমুনার num_ns সংখ্যার নমুনা করতে tf.random.log_uniform_candidate_sampler ফাংশনটি ব্যবহার করুন। আপনি একটি স্কিপ-গ্রামের টার্গেট শব্দে ফাংশনটিকে কল করতে পারেন এবং নমুনা করা থেকে বাদ দিতে প্রসঙ্গ শব্দটিকে সত্য শ্রেণী হিসাবে পাস করতে পারেন।

# 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_word এবং num_ns নেতিবাচক প্রসঙ্গ শব্দগুলিকে ব্যাচ করুন। এটি প্রতিটি টার্গেট শব্দের জন্য ইতিবাচক স্কিপ-গ্রাম ( 1 হিসাবে লেবেলযুক্ত) এবং নেতিবাচক নমুনা ( 0 হিসাবে লেবেলযুক্ত) তৈরি করে।

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

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

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

# Reshape the 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)

উপরের স্কিপ-গ্রাম উদাহরণ থেকে লক্ষ্য শব্দের জন্য প্রসঙ্গ এবং সংশ্লিষ্ট লেবেলগুলি দেখুন:

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    : 2
target_word     : wide
context_indices : [3 2 1 4 3]
context_words   : ['road', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

আপনার স্কিপ-গ্রাম নেগেটিভ স্যাম্পলিং word2vec মডেলের প্রশিক্ষণের জন্য একটি টিপল (target, context, label) টেনসর একটি প্রশিক্ষণ উদাহরণ গঠন করে। লক্ষ্য করুন যে লক্ষ্যটি আকৃতির (1,) যখন প্রসঙ্গ এবং লেবেলটি আকারের (1+num_ns,)

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

সারসংক্ষেপ

এই চিত্রটি একটি বাক্য থেকে একটি প্রশিক্ষণের উদাহরণ তৈরি করার পদ্ধতির সংক্ষিপ্ত বিবরণ দেয়:

word2vec_negative_sampling

লক্ষ্য করুন temperature এবং code শব্দগুলি ইনপুট বাক্যের অংশ নয়। উপরের চিত্রে ব্যবহৃত কিছু অন্যান্য সূচকের মতো এগুলি শব্দভান্ডারের অন্তর্গত।

একটি ফাংশনে সমস্ত পদক্ষেপ কম্পাইল করুন

স্কিপ-গ্রাম স্যাম্পলিং টেবিল

একটি বৃহৎ ডেটাসেটের অর্থ হল বৃহত্তর শব্দভাণ্ডার যেখানে স্টপওয়ার্ডের মতো ঘন ঘন শব্দের সংখ্যা বেশি। সাধারণত ব্যবহৃত শব্দের নমুনা থেকে প্রাপ্ত প্রশিক্ষণ উদাহরণগুলি (যেমন the is , on ) মডেলটির শেখার জন্য খুব বেশি দরকারী তথ্য যোগ করে না। মিকোলভ এট আল। এমবেডিং গুণমান উন্নত করার জন্য একটি সহায়ক অনুশীলন হিসাবে ঘন ঘন শব্দের সাবস্যাম্পলিং পরামর্শ দিন।

tf.keras.preprocessing.sequence.skipgrams ফাংশন কোনো টোকেন নমুনা করার সম্ভাবনা এনকোড করার জন্য একটি নমুনা টেবিল আর্গুমেন্ট গ্রহণ করে। আপনি tf.keras.preprocessing.sequence.make_sampling_table ব্যবহার করতে পারেন একটি শব্দ-ফ্রিকোয়েন্সি র্যাঙ্ক ভিত্তিক সম্ভাব্য নমুনা টেবিল তৈরি করতে এবং এটিকে skipgrams ফাংশনে পাস করতে পারেন। 10 এর একটি vocab_size এর জন্য নমুনা সম্ভাব্যতা পরিদর্শন করুন।

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 এর বিতরণ অনুমান.

প্রশিক্ষণ ডেটা তৈরি করুন

উপরে বর্ণিত সমস্ত ধাপগুলিকে একটি ফাংশনে কম্পাইল করুন যা যেকোনো পাঠ্য ডেটাসেট থেকে প্রাপ্ত ভেক্টরাইজড বাক্যের তালিকায় কল করা যেতে পারে। লক্ষ্য করুন যে স্যাম্পলিং টেবিলটি স্কিপ-গ্রাম শব্দ জোড়ার নমুনা দেওয়ার আগে তৈরি করা হয়েছে। আপনি পরবর্তী বিভাগে এই ফাংশন ব্যবহার করবেন.

# 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 the 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 a 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 the 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 the `output_sequence_length` length to pad all samples to the
# same length.
vectorize_layer = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

শব্দভান্ডার তৈরি করতে টেক্সট ডেটাসেটে TextVectorization.adapt কল করুন।

vectorize_layer.adapt(text_ds.batch(1024))

লেয়ারের অবস্থা টেক্সট কর্পাস প্রতিনিধিত্ব করার জন্য অভিযোজিত হয়ে গেলে, TextVectorization.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']

text_ds vectorize_layer a tf.data.Dataset ) এর প্রতিটি উপাদানের জন্য ভেক্টর তৈরি করতে ব্যবহার করা যেতে পারে। Dataset.batch , Dataset.prefetch , Dataset.map এবং Dataset.unbatch প্রয়োগ করুন।

# 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 এনকোড করা বাক্যগুলির একটি তালিকা। word2vec মডেলের জন্য প্রশিক্ষণের উদাহরণ তৈরি করতে আগে সংজ্ঞায়িত generate_training_data ফাংশনটিকে কল করুন। রিক্যাপ করার জন্য, ফাংশনটি ইতিবাচক এবং নেতিবাচক প্রসঙ্গ শব্দ সংগ্রহ করতে প্রতিটি ক্রম থেকে প্রতিটি শব্দের উপর পুনরাবৃত্তি করে। টার্গেটের দৈর্ঘ্য, প্রসঙ্গ এবং লেবেল একই হওয়া উচিত, প্রশিক্ষণের মোট উদাহরণের সংখ্যা উপস্থাপন করে।

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:40<00:00, 811.35it/s]
targets.shape: (66005,)
contexts.shape: (66005, 5)
labels.shape: (66005, 5)

কর্মক্ষমতা জন্য ডেটাসেট কনফিগার করুন

সম্ভাব্য বড় সংখ্যক প্রশিক্ষণ উদাহরণের জন্য দক্ষ ব্যাচিং করতে, tf.data.Dataset API ব্যবহার করুন। এই ধাপের পরে, আপনার word2vec মডেলকে প্রশিক্ষণ দেওয়ার জন্য আপনার কাছে (target_word, context_word), (label) উপাদানগুলির একটি tf.data.Dataset অবজেক্ট থাকবে!

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 element_spec=((TensorSpec(shape=(1024,), dtype=tf.int64, name=None), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None)), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None))>

কর্মক্ষমতা উন্নত করতে Dataset.cache এবং Dataset.prefetch প্রয়োগ করুন:

dataset = dataset.cache().prefetch(buffer_size=AUTOTUNE)
print(dataset)
<PrefetchDataset element_spec=((TensorSpec(shape=(1024,), dtype=tf.int64, name=None), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None)), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None))>

মডেল এবং প্রশিক্ষণ

word2vec মডেলটিকে স্কিপ-গ্রাম থেকে সত্য প্রসঙ্গ শব্দ এবং নেতিবাচক নমুনার মাধ্যমে প্রাপ্ত মিথ্যা প্রসঙ্গ শব্দগুলির মধ্যে পার্থক্য করার জন্য একটি শ্রেণিবদ্ধকারী হিসাবে প্রয়োগ করা যেতে পারে। আপনি লেবেলের জন্য ভবিষ্যদ্বাণী পেতে এবং ডেটাসেটে সত্যিকারের লেবেলের বিপরীতে ক্ষতির ফাংশন গণনা করতে লক্ষ্য এবং প্রসঙ্গ শব্দের এম্বেডিংয়ের মধ্যে একটি ডট পণ্য গুণন করতে পারেন।

উপশ্রেণীর word2vec মডেল

নিম্নলিখিত স্তরগুলির সাথে আপনার word2vec মডেলকে সংজ্ঞায়িত করতে Keras সাবক্লাসিং API ব্যবহার করুন:

  • 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 স্তরের ফলাফলগুলিকে লজিটে সমতল করতে।

সাবক্লাসড মডেলের সাথে, আপনি 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
64/64 [==============================] - 1s 4ms/step - loss: 1.6081 - accuracy: 0.2343
Epoch 2/20
64/64 [==============================] - 0s 3ms/step - loss: 1.5878 - accuracy: 0.5475
Epoch 3/20
64/64 [==============================] - 0s 3ms/step - loss: 1.5381 - accuracy: 0.5813
Epoch 4/20
64/64 [==============================] - 0s 3ms/step - loss: 1.4545 - accuracy: 0.5620
Epoch 5/20
64/64 [==============================] - 0s 3ms/step - loss: 1.3567 - accuracy: 0.5764
Epoch 6/20
64/64 [==============================] - 0s 3ms/step - loss: 1.2603 - accuracy: 0.6070
Epoch 7/20
64/64 [==============================] - 0s 3ms/step - loss: 1.1703 - accuracy: 0.6403
Epoch 8/20
64/64 [==============================] - 0s 3ms/step - loss: 1.0866 - accuracy: 0.6756
Epoch 9/20
64/64 [==============================] - 0s 3ms/step - loss: 1.0090 - accuracy: 0.7087
Epoch 10/20
64/64 [==============================] - 0s 3ms/step - loss: 0.9368 - accuracy: 0.7371
Epoch 11/20
64/64 [==============================] - 0s 3ms/step - loss: 0.8699 - accuracy: 0.7631
Epoch 12/20
64/64 [==============================] - 0s 3ms/step - loss: 0.8081 - accuracy: 0.7849
Epoch 13/20
64/64 [==============================] - 0s 3ms/step - loss: 0.7512 - accuracy: 0.8052
Epoch 14/20
64/64 [==============================] - 0s 3ms/step - loss: 0.6991 - accuracy: 0.8230
Epoch 15/20
64/64 [==============================] - 0s 3ms/step - loss: 0.6514 - accuracy: 0.8378
Epoch 16/20
64/64 [==============================] - 0s 3ms/step - loss: 0.6079 - accuracy: 0.8517
Epoch 17/20
64/64 [==============================] - 0s 3ms/step - loss: 0.5683 - accuracy: 0.8641
Epoch 18/20
64/64 [==============================] - 0s 3ms/step - loss: 0.5322 - accuracy: 0.8747
Epoch 19/20
64/64 [==============================] - 0s 3ms/step - loss: 0.4994 - accuracy: 0.8844
Epoch 20/20
64/64 [==============================] - 0s 3ms/step - loss: 0.4695 - accuracy: 0.8935
<keras.callbacks.History at 0x7fc21c237050>

টেনসরবোর্ড এখন word2vec মডেলের নির্ভুলতা এবং ক্ষতি দেখায়:

#docs_infra: no_execute
%tensorboard --logdir logs

এম্বেডিং লুকআপ এবং বিশ্লেষণ

Model.get_layer এবং Layer.get_weights ব্যবহার করে মডেল থেকে ওজন প্রাপ্ত করুন। TextVectorization.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

পরবর্তী পদক্ষেপ

এই টিউটোরিয়ালটি আপনাকে দেখিয়েছে কিভাবে স্ক্র্যাচ থেকে নেতিবাচক নমুনা সহ একটি skip-gram word2vec মডেল বাস্তবায়ন করা যায় এবং প্রাপ্ত শব্দ এমবেডিংগুলিকে কল্পনা করা যায়।