Понимание и создание N-грамм для обработки естественного языка (NLP) с библиотекой Python NLTK
При обработке естественного языка (NLP) мы обучаем модели, чтобы компьютеры могли понимать текст и произносимые слова так же, как люди. Человеческий язык полон двусмысленностей, таких как омонимы, омофоны, сарказм, идиомы, метафоры и грамматика, что усложняет обучение моделей, которые точно определяют предполагаемое значение текста.
НЛП включает в себя несколько задач, некоторые из которых могут включать:
- Распознавание речи.
- Тегирование части речи.
- Анализ настроений.
- Генерация естественного языка.
Python предоставляет Natural Language Toolkit (NLTK),который представляет собойколлекцию библиотек с открытым исходным кодом для выполнения задач НЛП.
В этой статье мы обсудим N-граммы, способ помочь машинам понять значение слов и научиться их реализовывать с помощью Python NLTK.
Что такое n-граммы?
Языковые модели часто оценивают распределение вероятностей последовательностей слов. Со случайными длинами последовательностей это огромная задача. Таким образом, предполагается, что вероятность слова зависит только от предшествующих ему N слов. Это называется моделью языка N-грамм.
Таким образом, N-граммы представляют собой тип статистической языковой модели, используемой в обработке естественного языка (NLP) для прогнозирования возможности последовательности слов. N-грамма — это непрерывная серия из n
элементов заданного образца текста, где n
— количество элементов в последовательности.
Классификация n-грамм
У нас есть несколько классификаций n-грамм, в зависимости от числа, которое представляет n
. Наиболее часто используемые n-граммы:
- N-грамм размера 1,
n
= 1, является униграммой. - N-грамм размера 2,
n
= 2, является биграммой. - N-грамм размера 3,
n
= 3, является триграммой.
N-грамма может быть любой длины, n
и разные типы n-грамм подходят для разных приложений.
Мы можем быстро и легко генерировать n-граммы с помощью функции ngrams
, доступной в файле nltk.util module
. Давайте посмотрим, как вышеприведенные n-граммы будут выглядеть, если реализовать их со следующим предложением:
«Обработка естественного языка с помощью N-грамм — это невероятно круто».
from nltk.util import ngrams sentence = "Natural Language Processing using N-grams is incredibly awesome." def generate_n_grams(sentence, n): unigrams = ngrams(sentence.split(), n) return [unigram for unigram in unigrams]
Для Unigrams n
= 1 сохраняет этот текст в токенах из 1 слова:
# n = 1 generate_n_grams(sentence, 1) # Results ('Natural',) ('Language',) ('Processing',) ('using',) ('N-grams',) ('is',) ('incredibly',) ('awesome.',)
Для Bigrams n
= 2 сохраняет этот текст в токенах из 2 слов:
# n = 2 generate_n_grams(sentence, 2) # Results ('Natural', 'Language') ('Language', 'Processing') ('Processing', 'using') ('using', 'N-grams') ('N-grams', 'is') ('is', 'incredibly') ('incredibly', 'awesome.')
Для триграмм n
= 3 сохраняет этот текст в токенах из 3 слов:
# n = 3 generate_n_grams(sentence, 3) # Results ('Natural', 'Language', 'Processing') ('Language', 'Processing', 'using') ('Processing', 'using', 'N-grams') ('using', 'N-grams', 'is') ('N-grams', 'is', 'incredibly') ('is', 'incredibly', 'awesome.')
Когда n > 3
, мы называем их четырьмя граммами или пятью граммами и так далее.
Применение n-грамм в НЛП
- Мы можем использовать их для создания функций из текстового корпуса для алгоритмов машинного обучения, таких как SVM, Naive Bayes и т. д.
- Они помогают развивать такие функции, как:
— Автозамена
— Автодополнение предложений
— Обобщение текста
— Распознавание речи
— Поиск в словаре
— Сжатие текста
— Идентификация языка и т. д.
Давайте теперь возьмем набор данных и используем его для создания n-грамм и продемонстрируем, как мы можем использовать их в НЛП.
Какие советы дают известные компании студентам и стартапам? Мы попросили их! Прочитайте или посмотрите наши отраслевые вопросы и ответы, чтобы получить советы от команд из Стэнфорда, Google и HuggingFace.
Пошаговый подход к созданию n-грамм
В этом разделе мы рассмотрим пошаговую подготовку данных для создания n-грамм.
Набор данных
Во-первых, нам понадобится набор данных. Мы будем использовать данные Financial Sentiment Analysis от Kaggle. Набор данных содержит два поднабора данных (FiQA и Financial PhraseBank), объединенных в один файл CSV. Данные здесь предоставляют финансовые предложения с метками тональности.
Давайте загрузим необходимый импорт:
import pandas as pd import string #library that contains sets of punctuation import nltk from nltk.corpus import stopwords from collections import defaultdict from sklearn.model_selection import train_test_split
Прочитайте данные:
data = pd.read_csv('Financial_Sentiment.csv') print(data.info()) data.head()
Мы видим, что у нас есть два столбца данных и 5842 строки.
Давайте проверим типы настроений и их количество в наборе данных:
data['Sentiment'].unique(), data['Sentiment'].value_counts()
У нас есть три класса чувств:
- нейтральный
- положительный
- отрицательный
Проверьте, содержит ли набор данных нулевые значения:
data.isnull().sum()
Разделение данных на обучающие и тестовые наборы.
Мы разделили данные на 20% тестовый набор и 80% обучающий набор.
train_set, test_set = train_test_split(data, test_size=0.20, random_state=42) train_set.shape, test_set.shape # ((4673, 2), (1169, 2))
Предварительная обработка данных
Прежде чем мы сможем создать n-граммы, нам нужно выполнить определенные операции с данными, которые жизненно важны при выполнении НЛП.
В нашем случае мы проведем следующие операции:
- Токенизация. Здесь мы разбиваем предложения на отдельные слова, также называемые токенами. С помощью этих токенов мы можем создать словарь для представления всех слов в списке.
- Удаление знаков препинания. Нам не нужны знаки препинания в наших токенах.
- Нижний регистр: нам нужно преобразовать все токены в нижний регистр, чтобы избежать избыточности слов, чтобы модель не интерпретировала такие слова, как рынок, рынок и РЫНОК, как разные слова.
- Удаление стоп-слов. Стоп-слова – это слова, которые не добавляют особого значения нашей модели, например "the", "is" и "her". Эти слова действуют как шум, поэтому мы их удалим.
Обратите внимание, что эти операции необязательны для всех задач НЛП. В некоторых задачах, таких как генерация естественного языка, мы можем захотеть сохранить стоп-слова и знаки препинания, но здесь мы сосредоточимся на n-граммах.
Мы можем выполнять другие операции с данными НЛП, такие как стемминг и лемматизация, которые мы здесь не рассматриваем.
В следующем коде мы напишем функцию, которая выполняет вышеуказанные операции над предложениями. Он также будет отвечать за генерацию точных n-грамм.
def generate_ngrams(sentence, ngram=1): # first lets convert the senetence into lower case sentence_lower = sentence.lower() sentence = re.sub(r'[^a-zA-Z0-9\s]', ' ', sentence_lower) # Remove stopwords, and punctuation stop = set(stopwords.words('english') + list(string.punctuation)) # tokenize and display tokenized sentence clean_words = [i for i in word_tokenize(sentence) if i not in stop] print(f"\n===Tokens:=== \n{clean_words}\n") # Generate the n-grams of any size ngrams = zip(*[clean_words[i:] for i in range(ngram)]) return [" ".join(ngram) for ngram in ngrams]
В функцию мы передаем параметры sentence
и ngram
. Мы присваиваем параметру ngram
значение по умолчанию 1, которое вы можете изменить, чтобы сгенерировать n-грамм желаемого размера.
Давайте протестируем функцию:
# Generate n-grams of N=4 from the text text = 'Natural language Processing(NLP) is an awesome task! Learn N-grams today!' generate_ngrams(texts,4)
Это работает отлично. Давайте теперь погрузимся в создание n-грамм!
Теперь, когда наши данные готовы к использованию, давайте приступим к созданию из них фактических n-грамм.
Генерация униграмм
Мы можем создать униграммы из каждого предложения, сгруппированного по каждому из трех классов настроений. Мы будем:
- Проверьте наиболее часто используемые слова.
- Визуализируйте наиболее часто используемые слова для каждой категории.
Получите каждое слово и сгенерируйте униграмму с положительным настроением:
# Initialize a dictionary to store the words together with their counts positiveWords=defaultdict(int) # 1. traverse the dataframe pick sentences with positive sentiment # 1.1. traverse through sentences and pick each word and preprocess # them with the generate_ngrams() functions we created # 1.1.1 store the words in a defaultdict # 2. convert the dictionary into a df for text in train_set[train_set['Sentiment']=='positive']['Sentence']: for word in generate_ngrams(text): positiveWords[word]+=1 df_positive = pd.DataFrame(sorted(positiveWords.items(),key=lambda x:x[1],reverse=True))
Повторите приведенный выше код для каждого слова и сгенерируйте униграмму с «отрицательным» настроением:
negativeWords = defaultdict(int) for text in train_set[train_set['Sentiment']=='negative']['Sentence']: for word in generate_ngrams(text): negativeWords[word]+=1 df_negative = pd.DataFrame(sorted(negativeWords.items(),key=lambda x:x[1],reverse=True))
Получите каждое слово и сгенерируйте униграмму, в которой настроение является «нейтральным»:
for text in train_set[train_set['Sentiment']=='neutral']['Sentence']: for word in generate_ngrams(text): neutralWords[word]+=1 df_neutral = pd.DataFrame(sorted(neutralWords.items(),key=lambda x:x[1],reverse=True))
Давайте визуализируем количество униграмм:
x_positive = df_positive[0][:10] y_positive = df_positive[1][:10] x_negative = df_negative[0][:10] y_negative = df_negative[1][:10] x_neutral = df_neutral[0][:10] y_neutral = df_neutral[1][:10] fig, ax = plt.subplots(3, 1, figsize=(10, 7), layout='tight', dpi=100) ax[0].bar(x_positive, y_positive, color='g') ax[0].set_title('Top 10 words with positive sentiment') ax[0].set_xlabel('Words in the positive df') ax[0].set_ylabel('Count') ax[1].bar(x_negative, y_negative, color='r') ax[1].set_title('Top 10 words with negative sentiment') ax[1].set_xlabel('Words in the negative df') ax[1].set_ylabel('Count') ax[2].bar(x_neutral, y_neutral, color='gray') ax[2].set_title('Top 10 words with neutral sentiment') ax[2].set_xlabel('Words in the neutral df') ax[2].set_ylabel('Count')
Генерация биграмм
Чтобы создать биграммы, мы не забудем вызвать функцию generate_ngrams()
со значением параметра ngram
равным 2.
# Defined new dictionaries positiveWords_bi=defaultdict(int) negativeWords_bi=defaultdict(int) neutralWords_bi=defaultdict(int)
Получите слова и сгенерируйте биграммы, где настроения «положительны»:
# Creating positive bigrams for text in train_set[train_set['Sentiment']=='positive']['Sentence']: for word in generate_ngrams(text, 2): positiveWords_bi[word]+=1 df_positive_bi = pd.DataFrame(sorted(positiveWords_bi.items(),key=lambda x:x[1],reverse=True)) df_positive_bi
Получите слова и сгенерируйте биграммы, где настроение «негативное»:
# Creating negative bigrams for text in train_set[train_set['Sentiment']=='positive']['Sentence']: for word in generate_ngrams(text, 2): negativeWords_bi[word]+=1 df_negative_bi = pd.DataFrame(sorted(negativeWords_bi.items(),key=lambda x:x[1],reverse=True)) df_negative_bi
Получите слова и сгенерируйте биграммы, где настроение является «нейтральным»:
# Creating neutral bigrams for text in train_set[train_set['Sentiment']=='positive']['Sentence']: for word in generate_ngrams(text, 2): neutralWords_bi[word]+=1 df_neutral_bi = pd.DataFrame(sorted(neutralWords_bi.items(),key=lambda x:x[1],reverse=True)) df_neutral_bi
Визуализация:
x_positive_bi = df_positive_bi[0][:10] y_positive_bi = df_positive_bi[1][:10] print(x_positive_bi) x_negative_bi = df_negative_bi[0][:10] y_negative_bi = df_negative_bi[1][:10] x_neutral_bi = df_neutral_bi[0][:10] y_neutral_bi = df_neutral_bi[1][:10] fig, ax = plt.subplots(3, 1, figsize=(10, 7), layout='tight', dpi=100) ax[0].bar(x_positive_bi, y_positive_bi, color='g', width= 0.6) ax[0].set_title('Top 10 words with positive sentiment(Bigrams)') ax[0].set_xlabel('Words in the positive df') ax[0].set_ylabel('Count') ax[1].bar(x_negative_bi, y_negative_bi, color='r', width= 0.6) ax[1].set_title('Top 10 words with negative sentiment(Bigrams)') ax[1].set_xlabel('Words in the negative df') ax[1].set_ylabel('Count') ax[2].bar(x_neutral_bi, y_neutral_bi, color='gray', width= 0.6) ax[2].set_title('Top 10 words with neutral sentiment(Bigrams)') ax[2].set_xlabel('Words in the neutral df') ax[2].set_ylabel('Count')
Генерация триграмм
Чтобы создать триграммы, мы не забудем вызвать функцию generate_ngrams()
со значением параметра ngram
равным 3.
positiveWords_tri = defaultdict(int) negativeWords_tri = defaultdict(int) neutralWords_tri = defaultdict(int)
Получите слова и сгенерируйте триграммы, где настроение «положительно»:
# Creating positive trigrams for text in train_set[train_set['Sentiment']=='positive']['Sentence']: for word in generate_ngrams(text, 3): positiveWords_tri[word] += 1 df_positive_tri = pd.DataFrame(sorted(positiveWords_tri.items(),key=lambda x:x[1],reverse=True)) df_positive_tri
Получите слова и сгенерируйте триграммы, где настроение «негативное»:
for text in train_set[train_set['Sentiment']=='negative']['Sentence']: for word in generate_ngrams(text, 3): negativeWords_tri[word]+=1 df_negative_tri = pd.DataFrame(sorted(negativeWords_tri.items(),key=lambda x:x[1],reverse=True)) df_negative_tri
Получите слова и сгенерируйте триграммы, где настроение является «нейтральным»:
# # Creating neutral trigrams for text in train_set[train_set['Sentiment']=='neutral']['Sentence']: for word in generate_ngrams(text, 3): neutralWords_tri[word]+=1 df_neutral_tri = pd.DataFrame(sorted(neutralWords_tri.items(),key=lambda x:x[1],reverse=True)) df_neutral_tri
Визуализация:
x_positive_tri = df_positive_tri[0][:10] y_positive_tri = df_positive_tri[1][:10] x_negative_tri = df_negative_tri[0][:10] y_negative_tri = df_negative_tri[1][:10] x_neutral_tri = df_neutral_tri[0][:10] y_neutral_tri = df_neutral_tri[1][:10] fig, ax = plt.subplots(3, 1, figsize=(12, 8), layout='tight', dpi=110) ax[0].bar(x_positive_tri, y_positive_tri, color='g', width= 0.6) ax[0].set_title('Top 10 words with positive sentiment(Trigrams)') ax[0].set_xlabel('Words in the positive df') ax[0].set_ylabel('Count') ax[1].bar(x_negative_tri, y_negative_tri, color='r', width= 0.6) ax[1].set_title('Top 10 words with negative sentiment(Trigrams)') ax[1].set_xlabel('Words in the negative df') ax[1].set_ylabel('Count') ax[2].bar(x_neutral_tri, y_neutral_tri, color='gray', width= 0.6) ax[2].set_title('Top 10 words with neutral sentiment(Trigrams)') ax[2].set_xlabel('Words in the neutral df') ax[2].set_ylabel('Count')
Последние мысли
В этой статье мы узнали следующее:
- Что такое n-граммы?
- Классификация и примеры униграмм, биграмм и триграмм.
- Реализация любого размера n-грамм с помощью библиотеки
nltk
Python из набора данных. - Предварительная обработка данных или текста для эффективного создания n-грамм — важный шаг в выполнении задач НЛП с использованием n-грамм.
- Как визуализировать n-граммы и получить их количество на основе настроений.
Как правило, n-граммы, где n > 1
работают лучше всего, поскольку они несут больше информации о контексте в целом.
Примечание редактора. Heartbeat — это интернет-издание и сообщество, созданное участниками и посвященное предоставлению лучших образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.
Независимая от редакции, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и командам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим нашим авторам и не продаем рекламу.
Если вы хотите внести свой вклад, перейдите к нашему призыву к участию. Вы также можете подписаться на получение нашего еженедельного информационного бюллетеня (Еженедельник глубокого обучения), заглянуть в блог Comet, присоединиться к нам в Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов и событий. и многое другое, что поможет вам быстрее создавать более качественные модели машинного обучения.