Это метод преобразования слов в векторы.

Вложения Word могут быть двух типов:

  1. На основе количества или частоты:
  • ПОКЛОН
  • TF-IDF
  • Одна горячая кодировка
  1. Основанный на глубоком обучении
  • Word2Vec
  • CBOW
  • ПРОПУСТИТЬ ГРАММЫ

Преимущества Word2Vec:

  • Уменьшает разреженность
  • Ограниченное измерение
  • Семантическое значение улавливается

Скажем, есть 6 функций (используя словарь, мы получаем их):

Эти предварительно обученные слова определяются моделью DL, таких слов может быть сотни, тысячи или миллионы. Теперь каждое слово на предварительно обученной стороне сравнивается с признаками (такими как мальчик, девочка, король, королева, яблоко, манго) и присваивается значение, это значение также присваивается моделью DL.

Скажите в приведенном выше примере:

  • Что касается пола — модель присваивает мальчику -1 (с некоторой логикой, которую мы увидим позже), и, поскольку девочка является полной противоположностью мальчика, она получает значение +1. Король получает значение -0,92, а королева противоположного пола, поэтому оно получает значение +0,93 (значение немного отличается, что определяется моделью), Apple получает значение 0, потому что это не имеет ничего общего с полом, и поэтому Манго, поэтому он получает значение 0,1 почти незначительно.
  • Точно так же в отношении королевского — мальчик получает значение 0,01, так как это очень мало связано с принадлежностью к королевской семье, так же как и девочка, поэтому оно получает значение 0,02, но король — это что-то королевское, поэтому он получает значение 0,95, и поэтому ферзь получает значение 0,96. Royal имеет очень мало общего с Apple, поэтому он получает значение -0,02 (отрицательный знак, потому что, возможно, модель считает, что его связь с Royal абсолютно противоположна), тогда как Mango получает 0,01, что также незначительно, но положительно, поскольку мы считаем Манго королем. из всех фруктов может быть именно поэтому он получает положительное значение.
  • По сути, мы в отношении всех слов в предварительно обученной модели сравниваем наши функции и выдаем оценку. Здесь мы использовали только три слова, а вообще их много.

Скажем : из приведенного выше примера мы получаем вектор мальчика как [-1, 0.01, 0.03]

девушка как [1, 0.02, 0.02] король как [-0.92, 0.95, 0.7] королева как [0.93, 0.96, 0.95]

Итак, если мы делаем Король — Мужчина + Девушка, мы получаем Королеву (просто выполните сложение и вычитание векторов, и вы увидите, что результирующий вектор похож или очень близок к вектору королевы)

Примечание. Сходство можно проверить с помощью таких показателей, как косинусное сходство и косинусное расстояние.

Формула: косинус-сходство = 1 — косинус-расстояние

Now the question arises - How are these models getting trained and giving us this score with respect to these pre-trained words.

Непрерывный мешок слов

Пусть рассматриваемое предложение будет:

KRISH CHANNEL СВЯЗАН С НАУКОЙ О ДАННЫХ.

В непрерывном наборе слов у нас есть размер окна. Допустим, окно = 5.

Выберите нечетное окно, чтобы с каждым окном мы получали среднее слово, и это слово было нашим выходом. Например:

Для движущегося размера окна 5 нашим первым окном становится «KRISH CHANNEL IS RELATED TO», поэтому среднее слово «IS» становится нашим O/P, а остальные два слова по обе стороны становятся нашими функции «КРИШ», «КАНАЛ», «СВЯЗАННЫЕ», «КОМУ».

Аналогичным образом мы делаем это и для других, сдвигая окно.

Теперь, основываясь на словарном запасе этого предложения (КРИШ, КАНАЛ, ЕСТЬ, СВЯЗАННЫЙ, ДО, ДАННЫЕ, НАУКА), мы создаем набор слов для каждого слова. Таким образом, количество функций равно 7, а имена строк - это отдельные слова (поскольку все слова здесь уникальны, функции и каждая строка имеют одно и то же имя).

ПОКЛОН:

поэтому вектор KRISH равен [1,0,0,0,0,0,0] и т. д.

Теперь первый документ - ["KRISH", "CHANNEL", "RELATED", "TO"] AND O/P ["IS"] .

Итак, теперь мы пропускаем этот документ через искусственную нейронную сеть с такими функциями, как ["KRISH", "CHANNEL", "RELATED", "TO"] и ["IS"] в качестве меток.

Так, например, каждое слово в функциях представлено 7 значениями в BOW, например KRISH [1,0,0,0,0,0,0]. Таким образом, каждое слово передается как набор из 7 нейронов, и, поскольку на вход поступают 4 слова, входной слой становится нейронами 7x4 . Скрытый слой имеет 5 нейронов, так как размер нашего окна 5, а выходной слой имеет 7 нейронов с активацией softmax, поскольку мы уже говорили, что в этом случае мы представляем каждую букву 7 значениями. чтобы сформировать вектор и, следовательно, у нас есть 7 нейронов на выходе. В этом первом документе «IS» — это наша метка, поэтому для представления «IS» нам нужно 7 значений.

Примечание — каждый нейрон в выходном слое будет выдавать вектор из 5 значений, потому что наше окно равно 5.

СКИПГРАММА

Единственная разница в том, что наш O/P в CBOW становится нашим вводом, а I/P в CBOW становится нашим O/P здесь.

Что касается нейронной сети, просто используйте обратную версию нейронной сети CBOW.

import nltk
import warnings
warnings.filterwarnings('ignore')

import re
from nltk.stem import PorterStemmer, WordNetLemmatizer
from nltk.corpus import stopwords

# Used for creating Bag of Words.
from sklearn.feature_extraction.text import CountVectorizer

# A tokenizing algorithm that tokenizes paragraphs using an unsupervised algorithm.
nltk.download('punkt')

# Stopwords in English
nltk.download('stopwords')
nltk.download('wordnet')
nltk.download('omw-1.4')

from gensim.models import KeyedVectors, Word2Vec
import gensim.downloader as api
import gensim
[nltk_data] Downloading package punkt to
[nltk_data]     /home/cloudcraftz/nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package stopwords to
[nltk_data]     /home/cloudcraftz/nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package wordnet to
[nltk_data]     /home/cloudcraftz/nltk_data...
[nltk_data]   Package wordnet is already up-to-date!
[nltk_data] Downloading package omw-1.4 to
[nltk_data]     /home/cloudcraftz/nltk_data...
[nltk_data]   Package omw-1.4 is already up-to-date!

Загрузка модели word2vec из gensim, которая была обучена на наборе данных Google News с использованием 3 миллионов слов и фраз

w2v = api.load('word2vec-google-news-300')

Используя приведенную выше модель, мы можем делать разные вещи, ниже мы увидим наиболее похожие слова по отношению к данному слову.

# We get the most similar words with their scores arranged in a descending manner .
w2v.most_similar('cricket')
[('cricketing', 0.8372225761413574),
 ('cricketers', 0.8165745735168457),
 ('Test_cricket', 0.8094819188117981),
 ('Twenty##_cricket', 0.8068488240242004),
 ('Twenty##', 0.7624265551567078),
 ('Cricket', 0.75413978099823),
 ('cricketer', 0.7372578382492065),
 ('twenty##', 0.7316356897354126),
 ('T##_cricket', 0.7304614186286926),
 ('West_Indies_cricket', 0.6987985968589783)]

Среднее значение Word2Vec

Мы видели в Word2Vec, что векторное измерение каждого слова равно размеру предварительно обученных слов, которые использует модель. В приведенном выше примере мы видели, что мальчик был представлен как [-1, 0.01, 0.3]. Теперь предположим, что есть предложение Boy is cute, в нем 3 слова, каждое слово описывается вектором размером 300, следовательно, 900 . Этот размер продолжает увеличиваться по мере того, как мы используем более сложную модель и предложения. Чтобы уменьшить это, мы используем среднее значение word2vec , которое просто берет среднее значение каждой строки, то есть, скажем, приведенное выше предложение boy = [-1, -1, 0], is = [1, 1, 1] и cute = [ 0, 1, 0], затем он преобразуется в один вектор как [(-1+1+0)/3, (-1+1+1)/3, (0+1+0)/3] , это наш новый вектор.

Текстовая классификация

Датасет можно скачать с Kaggle — Классификация спама

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = pd.read_csv('spam.csv', encoding="ISO-8859-1").iloc[:, :2]
data.columns = ['Label', 'Message']
data['Label'].value_counts()
ham     4825
spam     747
Name: Label, dtype: int64

Посмотрим, как будут выглядеть сообщения.

data.head()

data['Message'].iloc[2]
"Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's"

Теперь мы перейдем к предварительной обработке набора данных.

lematizer = WordNetLemmatizer()
corpuses = []

for words in data['Message'].values:
    words = re.sub('[^a-zA-Z0-9]', ' ', words)
    words = words.lower()

    sentence = nltk.word_tokenize(words)
    lemma = [lematizer.lemmatize(new) for new in sentence if new not in stopwords.words('english')]

    sentence = ' '.join(lemma)

    if sentence == '':
        sentence = 'stopwords only'

    corpuses.append(sentence)

Ниже мы берем каждый документ за раз и размечаем каждое слово в этом предложении.

word_sent = []

for s in corpuses:
    w = nltk.word_tokenize(s)
    word_sent.append(w)

Теперь наша задача состоит в том, чтобы выбрать размер окна (на данный момент примем его равным 5), существуют различные другие параметры, которые вы можете исследовать. Сейчас мы собираемся не усложнять и использовать только window и min_count, где min_count занимает целое число, означающее, что любое слово с частотой ниже min_count будет игнорироваться.

wtwov = gensim.models.Word2Vec(word_sent, window=5, min_count=1)

Средняя функция Word2Vec

def avgwtovec(docs):
    document = np.mean([wtwov.wv[wo] for wo in docs if wo in wtwov.wv.index_to_key], axis=0)
    return document.tolist()

Ниже мы используем созданную выше функцию average word 2 vec для создания векторного представления предложений.

word2vec = [avgwtovec(sents) for sents in word_sent]
dataset = pd.DataFrame()

for i in range(len(word2vec)):
    dataset = dataset.append(pd.DataFrame(word2vec[i]).T)

Теперь, когда наше функциональное пространство готово, мы готовы построить прогностическую модель. Мы будем использовать XGClassifier для обучения нашей модели.

import xgboost
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score, precision_score, plot_confusion_matrix, classification_report
labels = [1 if l == 'ham' else 0 for l in data['Label'].values]
labels = np.array(labels)
# Train Test Split
X_train, X_test, y_train, y_test = train_test_split(dataset, labels, test_size=0.3, random_state=1)
model_xg = xgboost.XGBClassifier()
model_xg.fit(X_train, y_train)
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,
              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
              early_stopping_rounds=None, enable_categorical=False,
              eval_metric=None, gamma=0, gpu_id=-1, grow_policy='depthwise',
              importance_type=None, interaction_constraints='',
              learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4,
              max_delta_step=0, max_depth=6, max_leaves=0, min_child_weight=1,
              missing=nan, monotone_constraints='()', n_estimators=100,
              n_jobs=0, num_parallel_tree=1, predictor='auto', random_state=0,
              reg_alpha=0, reg_lambda=1, ...)

Давайте посмотрим, как мы справились с нашим тестовым набором.

predicts = model_xg.predict(X_test)
accuracy_score(y_test, predicts)
0.9611244019138756
recall_score(y_test, predicts)
0.9821182943603851
precision_score(y_test, predicts)
0.9734151329243353
plot_confusion_matrix(model_xg, X_test, y_test)
plt.show()

print(classification_report(y_test, predicts))
precision    recall  f1-score   support

           0       0.87      0.82      0.85       218
           1       0.97      0.98      0.98      1454

    accuracy                           0.96      1672
   macro avg       0.92      0.90      0.91      1672
weighted avg       0.96      0.96      0.96      1672

Прогноз кажется вполне приличным, с хорошими accuracy, а также F1-Score. Это был очень простой пример и реализация концепций, которые мы изучали сегодня.

Слой встраивания слов

  1. Возьмите предложения
  2. One Hot Encode их
  3. Заполнение (до или после) это делается потому, что в одном горячем кодировании предложения кодируются на основе слов в предложении, которые могут варьироваться от одного предложения к другому, поэтому, чтобы сделать их все равными, мы добавляем дополнительные 0 впереди или ближе конец .
from tensorflow.keras.preprocessing.text import one_hot
2022-11-02 11:23:20.263421: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-11-02 11:23:20.518424: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2022-11-02 11:23:20.518452: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
2022-11-02 11:23:20.542248: E tensorflow/stream_executor/cuda/cuda_blas.cc:2981] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered
2022-11-02 11:23:21.277570: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory
2022-11-02 11:23:21.277650: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory
2022-11-02 11:23:21.277667: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
# sentences with varying lengths
sent=['the glass of milk',
      'the glass of juice',
      'the cup of tea',
      'I am a good boy',
      'I am a good developer',
      'understand the meaning of words',
      'your videos are good']

Мы должны сами указать размер словаря. Поэтому мы устанавливаем размер вручную, чтобы каждое слово было представлено вектором размера vocab_size.

# Fixed vocab size
vocab_size = 10000

Ниже мы в основном передаем каждое предложение в нашем корпусе через one-hot encoder для создания векторов, здесь one_hot принимает два аргумента. Один из них — это само предложение и vocab_size, то есть длина представляющего вектора.

Он возвращает массив для каждого предложения с набором значений. Каждое значение в массиве представляет собой индекс, в котором оно было «1», потому что при словаре 10000 мы знаем, что в одном горячем кодировании все остальные 9999 позиций будут помечены «0» и будет дана только позиция рассматриваемого слова. «1». Таким образом, он возвращает только эту позицию.

Например, в приведенной ниже кодировке в первом предложении:

  • «стакан молока» задается [6495, 6367, 2709, 7114], где слово «the» равно «1» в индексе 6495, а все остальные 9999 позиций равны «0». Точно так же слово «стекло» равно «1» на позиции 6367, а все остальные 9999 — «0». Таким образом, вместо того, чтобы дать нам полное представление 10000 значений, он дает нам только номер позиции, где он был «1» в этом векторе.
layer = [one_hot(sen, vocab_size) for sen in sent]
layer
[[1020, 7825, 7486, 6986],
 [1020, 7825, 7486, 6611],
 [1020, 8210, 7486, 6831],
 [3055, 9005, 8420, 7388, 1308],
 [3055, 9005, 8420, 7388, 6231],
 [8255, 1020, 8441, 7486, 8499],
 [4567, 3049, 2355, 7388]]

Представление встраивания слов

Обратите внимание, что все предложения имеют разную длину, но модели ML или DL принимают только одинаковое количество функций для каждого документа или каждого наблюдения. Итак, чтобы сделать это, мы будем делать отступы.

from tensorflow.keras.layers import Embedding
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.sequence import pad_sequences

Итак, что мы делаем, так это просто берем длину самого длинного предложения или что-то большее и используем его как maxlen в pad_sequences, что сделает все предложения одинаковой длины, вы можете использовать pre или post по нашему выбору. Если мы используем pre, перед числом else в конце ставится дополнительный «0».

Теперь, поскольку длина нашего самого длинного предложения равна 5, мы взяли значение 8 (которое больше 5) и сделали все массивы одинаковой длины.

sent_length = 8
embedded_docs = pad_sequences(layer, padding='pre', maxlen=sent_length)
print(embedded_docs)
[[   0    0    0    0 1020 7825 7486 6986]
 [   0    0    0    0 1020 7825 7486 6611]
 [   0    0    0    0 1020 8210 7486 6831]
 [   0    0    0 3055 9005 8420 7388 1308]
 [   0    0    0 3055 9005 8420 7388 6231]
 [   0    0    0 8255 1020 8441 7486 8499]
 [   0    0    0    0 4567 3049 2355 7388]]

Теперь у нас есть наш слой встраивания с каждым предложением с одинаковым размером массива, теперь мы конвертируем каждое слово в предложении в word2vec, для этого мы выбираем количество функций для преобразования каждого слова в word2vec (см. объяснение word2vec выше)

# Number of features used for converting each word to word2vec.
dim = 10

Ниже мы создаем нашу собственную модель Word2Vec, используя Embedding Layer. Нам просто нужно передать размер словаря, который мы хотим использовать (здесь 10000), количество функций, которые мы хотим создать word2vec для каждого слова, и максимальную длину, которую мы хотим для представления каждого предложения с дополнением.

model = Sequential()
model.add(Embedding(vocab_size, dim, input_length=sent_length))
model.compile('adam','mse')
2022-11-02 11:23:21.831121: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2022-11-02 11:23:21.831362: W tensorflow/stream_executor/cuda/cuda_driver.cc:263] failed call to cuInit: UNKNOWN ERROR (303)
2022-11-02 11:23:21.831407: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (cloudcraftz-06): /proc/driver/nvidia/version does not exist
2022-11-02 11:23:21.832282: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.

После обучения мы видим в первом предложении, которое мы получили после заполнения, «стакан молока» как [ 0, 0, 0, 0, 6495, 6367, 2709, 7114], и каждое число здесь затем преобразуется в word2vec размера 10, как мы указали dim=10.

Ниже, когда мы предсказываем embedded_docs[0], мы получаем массив размером 8*10, поскольку предложение представлено 8 значениями (с отступами), а каждое значение представлено 10 значениями.

embedded_docs[0]
array([   0,    0,    0,    0, 1020, 7825, 7486, 6986], dtype=int32)
model.predict(embedded_docs[0])
WARNING:tensorflow:Model was constructed with shape (None, 8) for input KerasTensor(type_spec=TensorSpec(shape=(None, 8), dtype=tf.float32, name='embedding_input'), name='embedding_input', description="created by layer 'embedding_input'"), but it was called on an input with incompatible shape (None,).
1/1 [==============================] - 0s 97ms/step





array([[-0.00123087,  0.03647018,  0.03407898,  0.0381111 ,  0.04813857,
         0.00189596,  0.01516304, -0.01877182,  0.01922247, -0.02681679],
       [-0.00123087,  0.03647018,  0.03407898,  0.0381111 ,  0.04813857,
         0.00189596,  0.01516304, -0.01877182,  0.01922247, -0.02681679],
       [-0.00123087,  0.03647018,  0.03407898,  0.0381111 ,  0.04813857,
         0.00189596,  0.01516304, -0.01877182,  0.01922247, -0.02681679],
       [-0.00123087,  0.03647018,  0.03407898,  0.0381111 ,  0.04813857,
         0.00189596,  0.01516304, -0.01877182,  0.01922247, -0.02681679],
       [ 0.02948665,  0.02786222,  0.00702927, -0.03976067,  0.01500887,
        -0.00735202, -0.01333605,  0.00872318, -0.04330127,  0.01748199],
       [-0.04851049, -0.018426  ,  0.01364973, -0.04094089,  0.01301808,
         0.03131111,  0.02555818,  0.01247604,  0.03791109, -0.0394867 ],
       [-0.04684344,  0.00969238, -0.018878  , -0.03609868, -0.03488101,
        -0.00920697,  0.009779  ,  0.00690002, -0.00776314,  0.03579214],
       [-0.04864953, -0.02823101,  0.04531744, -0.04716897,  0.04260788,
         0.03348962, -0.04699815, -0.04278564, -0.01976631, -0.00438765]],
      dtype=float32)

Если вы хотите получить доступ к блокноту, перейдите по ссылке, указанной ниже:
НЛП Часть-2.

На сегодня все, увидимся в следующий раз. Увидимся, выродки!!

Кредиты :

  1. Я хотел бы поблагодарить Криша Наика (основателя iNeuron), я узнал много об этих концепциях из его канала на YouTube.
  2. Мои коллеги из Cloudcraftz Solution Pvt. Ltd., которые помогли мне понять практическое применение концепций, упомянутых выше.