Методы предварительной обработки текста для глубокого обучения
Изучите различные точки зрения на этапы предварительной обработки нейронных сетей глубокого обучения, имеющие отношение к любой проблеме обработки естественного языка (NLP).
Глубокое обучение, особенно обработка естественного языка (NLP), в наши дни вызвало огромный интерес. Некоторое время назад на Kaggle проходило соревнование по НЛП под названием Quora Question Infincerity Challenge. Конкурс — это задача классификации текстов, которая стала легче для понимания после прохождения конкурса, и благодаря работе ценных ядер, предложенных экспертами Kaggle.
Во-первых, давайте объясним проблему классификации текста в конкурсе.
Категоризация текста— распространенная задача обработки естественного языка, которая преобразует текстовую последовательность неопределенной длины в текстовую категорию. Как вы можете это использовать?
- Чтобы найти настроение комментариев
- Найдите токсичные комментарии на таких платформах, как Facebook.
- Найдите неискренние вопросы на Quora — конкурсе, который в настоящее время проходит на Kaggle.
- Найдите поддельные отзывы на сайтах
- Проблема определения того, будет ли нажато текстовое объявление
Теперь у каждого из этих вопросов есть что-то общее. С точки зрения машинного обучения эти проблемы по сути одинаковы, только изменилась метка цели и больше ничего. Тем не менее, добавление бизнес-знаний может помочь этим моделям стать более надежными, что мы и хотим включить при предварительной обработке данных для классификации тестов.
Хотя конвейеры предварительной обработки, на которых мы сосредоточимся в этом посте, в основном ориентированы на глубокое обучение, большинство из них также применимы к традиционным моделям машинного обучения.
Во-первых, прежде чем пройти все шаги, давайте взглянем на поток конвейера глубокого обучения для текстовых данных, чтобы получить общее представление обо всем процессе.
Обычно мы начинаем с очистки текстовых данных и выполнения базовой EDA. Здесь мы пытаемся улучшить качество наших данных, очищая их. Мы также пытаемся улучшить качество наших вложений Word2Vec, удаляя слова OOV (вне словарного запаса). Между этими первыми двумя шагами обычно нет никакого порядка, и мы обычно ходим туда и обратно между этими двумя шагами.
Затем мы создаем представление текста, которое можно передать в модель глубокого обучения. Затем мы начинаем создавать наши модели и обучать их. Наконец, мы оцениваем модель с помощью соответствующих показателей и получаем одобрение от соответствующих акционеров на развертывание нашей модели. Не волнуйтесь, если эти термины не имеют смысла прямо сейчас. Мы постараемся объяснить их в процессе этой статьи.
На этом перекрестке давайте сделаем небольшой крюк и поговорим о встраивании слов. Нам придется учитывать их при предварительной обработке данных для нашей модели глубокого обучения.
Учебник по встраиванию слов
Нам нужен способ представления слов в словаре. Один из способов — использовать однократное кодирование векторов слов, но это не лучший выбор. Одна из основных причин заключается в том, что векторы однократных слов не могут точно выразить сходство между разными словами, например косинусное сходство.
Учитывая структуру векторов с горячим кодированием, сходство между разными словами всегда выражается в виде 0. Другая причина заключается в том, что эти горячие кодированные векторы становятся очень большими по мере увеличения размера словаря.
Word2VecВышеуказанные трудности преодолеваются путем предоставления нам векторного представления слов фиксированной длины и выявления сходств и аналогий между разными словами.
Векторы слов Word2vec изучаются таким образом, что это позволяет нам изучать различные аналогии. Это позволяет нам выполнять алгебраические операции над словами, которые раньше были невозможны. Например. Что такое король - мужчина + женщина? В результате получается королева.
Векторы Word2Vec также могут помочь нам найти сходство между словами. Если мы попытаемся найти слова, похожие на «хорошо», мы найдем «отлично», «отлично» и т. д. Именно эта особенность word2vec делает его незаменимым при классификации текстов. Наша сеть глубокого обучения теперь понимает, что «хорошо» и «отлично» — это, по сути, слова со схожими значениями.
** Итак, говоря очень простым языком, word2vec создает векторы для слов. Итак, у нас есть d-мерный вектор для каждого слова в словаре (а также для общих больших слов). **Обычно мы используем предварительно обученные векторы слов, которые нам предоставляют другие после обучения на больших текстах, таких как Википедия, Твиттер и т. д. Наиболее часто используемые предварительно обученные векторы слов — это 300-мерные векторы слов Glove и Fasttext. В этой статье мы будем использовать Glove.
Основные методы предварительной обработки текстовых данных
В большинстве случаев мы наблюдаем, что текстовые данные не совсем чистые. Данные из разных источников имеют разные характеристики, что делает предварительную обработку текста одним из самых важных этапов конвейера классификации.
Например, текстовые данные из Twitter полностью отличаются от текстовых данных из Quora или некоторых новостных/блоговых платформ, поэтому с ними нужно обращаться иначе. К счастью, методы, которые мы обсудим в этом посте, являются общими для любого типа данных, с которыми вы можете столкнуться в джунглях НЛП.
Очистите специальные символы и удалите знаки препинания
Наш конвейер предварительной обработки сильно зависит от вложений word2vec, которые мы будем использовать для задачи классификации.В принципе, наша предварительная обработка должна соответствовать предварительной обработке перед обучением встраиванию слов.. Поскольку большинство вложений не предоставляют векторных значений для знаков препинания и других специальных символов, первое, что вам нужно сделать, — это удалить специальные символы из текстовых данных. Это некоторые специальные символы, присутствующие в данных вопроса Quora, мы используем функцию замены, чтобы удалить эти специальные символы.
# Некоторая предварительная обработка, которая будет общей для всех методов классификации текста, которые вы увидите.
Python
puncts = [',', '.', '"', ':', ')', '(', '-', '!', '?', '|', ';', "'", '$', '&', '/', '[', ']', '>', '%', '=', '#', '*', '+', '\\', '•', '~', '@', '£', '·', '_', '{', '}', '©', '^', '®', '`', '<', '→', '°', '€', '™', '›', '♥', '←', '×', '§', '″', '′', ' ', '█', '½', 'à', '…', '“', '★', '”', '–', '●', 'â', '►', '−', '¢', '²', '¬', '░', '¶', '↑', '±', '¿', '▾', '═', '¦', '║', '―', '¥', '▓', '—', '‹', '─', '▒', ':', '¼', '⊕', '▼', '▪', '†', '■', '’', '▀', '¨', '▄', '♫', '☆', 'é', '¯', '♦', '¤', '▲', 'è', '¸', '¾', 'Ã', '⋅', '‘', '∞', '∙', ')', '↓', '、', '│', '(', '»', ',', '♪', '╩', '╚', '³', '・', '╦', '╣', '╔', '╗', '▬', '❤', 'ï', 'Ø', '¹', '≤', '‡', '√', ]
Python
def clean_text(x): x = str(x) for punct in puncts: if punct in x: x = x.replace(punct, '') return x
Это также можно сделать с помощью простого регулярного выражения. Но в целом нам нравится описанный выше метод, потому что он помогает понять, какие символы мы хотим удалить из данных.
питон
def clean_text(x): pattern = r'[^a-zA-z0-9\s]' text = re.sub(pattern, '', x) return x
очистить числа
Почему мы заменяем числа знаками #? Потому что большая часть встроенного текста предварительно обрабатывается таким образом.
**Советы по Python. ** Мы используем оператор if в приведенном ниже коде, чтобы заранее проверить, существует ли число в тексте. Это потому, что если всегда лучше, чемre.sub
Команды выполняются быстро, и большая часть нашего текста не содержит цифр.
питон
def clean_numbers(x): if bool(re.search(r'\d', x)): x = re.sub('[0-9]{5,}', '#####', x) x = re.sub('[0-9]{4}', '####', x) x = re.sub('[0-9]{3}', '###', x) x = re.sub('[0-9]{2}', '##', x) return x
удалить опечатки
Всегда полезно обнаружить опечатки в данных. Поскольку вложения для этих слов не существуют в word2vec, мы должны заменить слова их правильным написанием для лучшего охвата встраивания.
Приведенный ниже артефакт кода является адаптацией программы проверки орфографии Питера Норвига. оно используетword2vec
порядок слов для аппроксимации вероятностей слов, потому что Googleword2vec
Очевидно, отсортировано по убыванию частоты в обучающем корпусе. Вы можете использовать его, чтобы найти некоторые слова с ошибками в имеющихся у вас данных.
Это из сценария CPMP в конкурсе Quora Question Similarity Challenge.
Python
import re from collections import Counter import gensim import heapq from operator import itemgetter from multiprocessing import Pool
model = gensim.models.KeyedVectors.load_word2vec_format('../input/embeddings/GoogleNews-vectors-negative300/GoogleNews-vectors-negative300.bin', binary=True) words = model.index2word
w_rank = {} for i,word in enumerate(words): w_rank[word] = i
WORDS = w_rank
def words(text): return re.findall(r'\w+', text.lower())
def P(word): "Probability of `word`." # use inverse of rank as proxy # returns 0 if the word isn't in the dictionary return - WORDS.get(word, 0)
def correction(word): "Most probable spelling correction for word." return max(candidates(word), key=P)
def candidates(word): "Generate possible spelling corrections for word." return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
def known(words): "The subset of `words` that appear in the dictionary of WORDS." return set(w for w in words if w in WORDS)
def edits1(word): "All edits that are one edit away from `word`." letters = 'abcdefghijklmnopqrstuvwxyz' splits = [(word[:i], word[i:]) for i in range(len(word) + 1)] deletes = [L + R[1:] for L, R in splits if R] transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1] replaces = [L + c + R[1:] for L, R in splits if R for c in letters] inserts = [L + c + R for L, R in splits for c in letters] return set(deletes + transposes + replaces + inserts)
def edits2(word): "All edits that are two edits away from `word`." return (e2 for e1 in edits1(word) for e2 in edits1(e1))
def build_vocab(texts): sentences = texts.apply(lambda x: x.split()).values vocab = {} for sentence in sentences: for word in sentence: try: vocab[word] += 1 except KeyError: vocab[word] = 1 return vocab
vocab = build_vocab(train.question_text)
top_90k_words = dict(heapq.nlargest(90000, vocab.items(), key=itemgetter(1)))
pool = Pool(4) corrected_words = pool.map(correction,list(top_90k_words.keys()))
for word,corrected_word in zip(top_90k_words,corrected_words): if word!=corrected_word: print(word,":",corrected_word)
После того, как мы нашли данные с ошибками, следующим шагом будет использование карты с ошибками и функции регулярного выражения для их замены.
Python
mispell_dict = {'colour': 'color', 'centre': 'center', 'favourite': 'favorite', 'travelling': 'traveling', 'counselling': 'counseling', 'theatre': 'theater', 'cancelled': 'canceled', 'labour': 'labor', 'organisation': 'organization', 'wwii': 'world war 2', 'citicise': 'criticize', 'youtu ': 'youtube ', 'Qoura': 'Quora', 'sallary': 'salary', 'Whta': 'What', 'narcisist': 'narcissist', 'howdo': 'how do', 'whatare': 'what are', 'howcan': 'how can', 'howmuch': 'how much', 'howmany': 'how many', 'whydo': 'why do', 'doI': 'do I', 'theBest': 'the best', 'howdoes': 'how does', 'mastrubation': 'masturbation', 'mastrubate': 'masturbate', "mastrubating": 'masturbating', 'pennis': 'penis', 'Etherium': 'Ethereum', 'narcissit': 'narcissist', 'bigdata': 'big data', '2k17': '2017', '2k18': '2018', 'qouta': 'quota', 'exboyfriend': 'ex boyfriend', 'airhostess': 'air hostess', "whst": 'what', 'watsapp': 'whatsapp', 'demonitisation': 'demonetization', 'demonitization': 'demonetization', 'demonetisation': 'demonetization'}
грамматика
def _get_mispell(mispell_dict): mispell_re = re.compile('(%s)' % '|'.join(mispell_dict.keys())) return mispell_dict, mispell_re
mispellings, mispellings_re = _get_mispell(mispell_dict) def replace_typical_misspell(text): def replace(match): return mispellings[match.group(0)] return mispellings_re.sub(replace, text)
# Usage replace_typical_misspell("Whta is demonitisation")
удалить сокращения
Аббревиатуры — это слова, которые мы пишем штрихом и штрихом. Примерами аббревиатур являются такие слова, как «не» или «не». Поскольку мы хотим стандартизировать наш текст, имеет смысл расширить эти сокращения. Ниже мы используем для этого карты сокращений и функции регулярных выражений.
Python
contraction_dict = {"ain't": "is not", "aren't": "are not","can't": "cannot", "'cause": "because", "could've": "could have", "couldn't": "could not", "didn't": "did not", "doesn't": "does not", "don't": "do not", "hadn't": "had not", "hasn't": "has not", "haven't": "have not", "he'd": "he would","he'll": "he will", "he's": "he is", "how'd": "how did", "how'd'y": "how do you", "how'll": "how will", "how's": "how is", "I'd": "I would", "I'd've": "I would have", "I'll": "I will", "I'll've": "I will have","I'm": "I am", "I've": "I have", "i'd": "i would", "i'd've": "i would have", "i'll": "i will", "i'll've": "i will have","i'm": "i am", "i've": "i have", "isn't": "is not", "it'd": "it would", "it'd've": "it would have", "it'll": "it will", "it'll've": "it will have","it's": "it is", "let's": "let us", "ma'am": "madam", "mayn't": "may not", "might've": "might have","mightn't": "might not","mightn't've": "might not have", "must've": "must have", "mustn't": "must not", "mustn't've": "must not have", "needn't": "need not", "needn't've": "need not have","o'clock": "of the clock", "oughtn't": "ought not", "oughtn't've": "ought not have", "shan't": "shall not", "sha'n't": "shall not", "shan't've": "shall not have", "she'd": "she would", "she'd've": "she would have", "she'll": "she will", "she'll've": "she will have", "she's": "she is", "should've": "should have", "shouldn't": "should not", "shouldn't've": "should not have", "so've": "so have","so's": "so as", "this's": "this is","that'd": "that would", "that'd've": "that would have", "that's": "that is", "there'd": "there would", "there'd've": "there would have", "there's": "there is", "here's": "here is","they'd": "they would", "they'd've": "they would have", "they'll": "they will", "they'll've": "they will have", "they're": "they are", "they've": "they have", "to've": "to have", "wasn't": "was not", "we'd": "we would", "we'd've": "we would have", "we'll": "we will", "we'll've": "we will have", "we're": "we are", "we've": "we have", "weren't": "were not", "what'll": "what will", "what'll've": "what will have", "what're": "what are", "what's": "what is", "what've": "what have", "when's": "when is", "when've": "when have", "where'd": "where did", "where's": "where is", "where've": "where have", "who'll": "who will", "who'll've": "who will have", "who's": "who is", "who've": "who have", "why's": "why is", "why've": "why have", "will've": "will have", "won't": "will not", "won't've": "will not have", "would've": "would have", "wouldn't": "would not", "wouldn't've": "would not have", "y'all": "you all", "y'all'd": "you all would","y'all'd've": "you all would have","y'all're": "you all are","y'all've": "you all have","you'd": "you would", "you'd've": "you would have", "you'll": "you will", "you'll've": "you will have", "you're": "you are", "you've": "you have"}
Python
def _get_contractions(contraction_dict): contraction_re = re.compile('(%s)' % '|'.join(contraction_dict.keys())) return contraction_dict, contraction_re
contractions, contractions_re = _get_contractions(contraction_dict)
def replace_contractions(text): def replace(match): return contractions[match.group(0)] return contractions_re.sub(replace, text)
# Usage replace_contractions("this's a text with contraction")
В дополнение к вышеупомянутым методам существуют другие методы предварительной обработки текста, такие как выделение корней, фразирование и удаление стоп-слов. Поскольку эти методы не используются с моделями глубокого обучения НЛП, мы не будем их здесь обсуждать.
Создание последовательности характеристик
Одна из вещей, которая делает глубокое обучение «первым выбором» для НЛП, заключается в том, что нам на самом деле не нужно вручную создавать функции из текстовых данных. Алгоритмы глубокого обучения принимают на вход последовательность текста и изучают структуру текста, как человек. Поскольку машины не понимают слов, они хотят представлять свои данные в числовой форме. Поэтому мы хотим представить текстовые данные в виде ряда чисел.
Чтобы понять, как это сделать, нам нужно взглянуть на функции токенизатора Keras. Можно использовать любой другой токенизатор, но токенизатор Keras является популярным выбором.
маркер
Проще говоря, токенизатор — это служебная функция, которая разбивает предложения на слова.keras.preprocessing.text.Tokenizer
, который токенизирует (разбивает) текст на токены (слова), сохраняя при этом только те слова, которые чаще всего встречаются в текстовом корпусе.
Python
#Signature: Tokenizer(num_words=None, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, split=' ', char_level=False, oov_token=None, document_count=0, **kwargs)
num_words
Параметр содержит только заранее заданное количество слов в тексте. Это полезно, потому что мы не хотим, чтобы наша модель получала много шума, рассматривая слова, которые появляются очень редко. В реальных данных большинство слов, которые мы оставляем с параметром num_words, обычно написаны с ошибками. Токенизатор также по умолчанию фильтрует некоторые нежелательные токены и преобразует текст в нижний регистр.
После подгонки к данным токенизатор также сохраняет индекс слова (словарь слов, который мы можем использовать для присвоения слову уникального номера), доступ к которому можно получить через .
tokenizer.word_index
Слова в проиндексированном словаре упорядочены по частоте.
Итак, весь код с использованием токенизатора приведен ниже.
Python
from keras.preprocessing.text import Tokenizer ## Tokenize the sentences tokenizer = Tokenizer(num_words=max_features) tokenizer.fit_on_texts(list(train_X)+list(test_X)) train_X = tokenizer.texts_to_sequences(train_X) test_X = tokenizer.texts_to_sequences(test_X)
вtrain_X
иtest_X
список документов в корпусе.
последовательность заполнения
Как правило, наша модель предполагает, что каждая последовательность (каждый обучающий пример) будет иметь одинаковую длину (одинаковое количество слов/символов). мы можем использоватьmaxlen
параметры для управления этим.
Например.
Python
train_X = pad_sequences(train_X, maxlen=maxlen) test_X = pad_sequences(test_X, maxlen=maxlen)
Теперь наши обучающие данные содержат список чисел. Каждый список имеет одинаковую длину. У нас все еще естьword_index
, который представляет собой словарь наиболее часто встречающихся слов в текстовом корпусе.
Встроенное обогащение
Как упоминалось выше, мы будем использовать GLoVE.Word2Vec
Встраивание для учета богатства.Предварительно обученные векторы для GLoVEпрошел обучение на корпусе Википедии.
Это означает, что некоторые слова, которые могут появиться в ваших данных, могут не отображаться во внедрении. Как мы можем справиться с этой проблемой? Давайте сначала загрузим Glove Embeddings.
Python
def load_glove_index(): EMBEDDING_FILE = '../input/embeddings/glove.840B.300d/glove.840B.300d.txt' def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')[:300] embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE)) return embeddings_index
glove_embedding_index = load_glove_index()
Обязательно укажите путь к папке, в которую вы скачали эти векторы GLoVE.
этоglove_embedding_index
Что включено? Это просто словарь, где ключами являются слова, а значениями являются векторы слов, длиной 300np.array
. Длина этого словаря составляет около 1 миллиарда. Поскольку мы хотим только нашегоword_index
Вложения слов в , создадим матрицу, содержащую только нужные вложения.
Индекс tokenizer.word для предварительной обработки текста
Python
def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0.005838499,0.48782197 all_embs = np.stack(embeddings_index.values()) embed_size = all_embs.shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size)) count_found = nb_words for word, i in tqdm(word_index.items()): if i >= max_features: continue embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: count_found-=1 print("Got embedding for ",count_found," words.") return embedding_matrix
Приведенный выше код прекрасно работает, но есть ли способ использовать предварительную обработку в GLoVE в наших интересах?
да. Создатели не переводили слова в нижний регистр при предварительной обработке перчатки. Это означает, что он содержит несколько вариантов слова, например «США», «США» и «США». Это также означает, что в некоторых случаях, хотя слово, подобное «Word», появляется, его аналог в нижнем регистре, «слово», не появляется.
Мы можем решить эту ситуацию, используя приведенный ниже код.
питон
def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0.005838499,0.48782197 all_embs = np.stack(embeddings_index.values()) embed_size = all_embs.shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size)) count_found = nb_words for word, i in tqdm(word_index.items()): if i >= max_features: continue embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: if word.islower(): # try to get the embedding of word in titlecase if lowercase is not present embedding_vector = embeddings_index.get(word.capitalize()) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: count_found-=1 else: count_found-=1 print("Got embedding for ",count_found," words.") return embedding_matrix
Вышеприведенное — всего лишь пример того, как мы можем использовать знания о встраиваниях для лучшего охвата. Иногда, в зависимости от проблемы, мы также можем извлечь пользу, добавив дополнительную информацию к встраиванию, используя некоторые знания предметной области и навыки НЛП.
Например, мы можем добавить внешние знания к самому встраиванию, добавив полярность и субъективность слова из пакета TextBlob в Python.
Python
from textblob import TextBlob word_sent = TextBlob("good").sentiment print(word_sent.polarity,word_sent.subjectivity) # 0.7 0.6
Мы можем получить полярность и субъективность любого слова, используя TextBlob. Очень хорошо! Давайте попробуем добавить эту дополнительную информацию в наше встраивание.
Python
def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0.005838499,0.48782197 all_embs = np.stack(embeddings_index.values()) embed_size = all_embs.shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size+4)) count_found = nb_words for word, i in tqdm(word_index.items()): if i >= max_features: continue embedding_vector = embeddings_index.get(word) word_sent = TextBlob(word).sentiment # Extra information we are passing to our embeddings extra_embed = [word_sent.polarity,word_sent.subjectivity] if embedding_vector is not None: embedding_matrix[i] = np.append(embedding_vector,extra_embed) else: if word.islower(): embedding_vector = embeddings_index.get(word.capitalize()) if embedding_vector is not None: embedding_matrix[i] = np.append(embedding_vector,extra_embed) else: embedding_matrix[i,300:] = extra_embed count_found-=1 else: embedding_matrix[i,300:] = extra_embed count_found-=1 print("Got embedding for ",count_found," words.") return embedding_matrix
Инженерные встраивания — важная часть повышения производительности моделей глубокого обучения на более позднем этапе. Как правило, на этапе проекта мы несколько раз пересматриваем эту часть кода, пытаясь улучшить нашу модель. Вы можете проявить много творчества здесь, чтобы улучшить свойword_index
, и включите дополнительные функции в свою вставку.
Дополнительные инженерные функции
Метод предварительной обработки текста Embedding_matrix
Всегда можно добавить определенные функции предложения, такие как длина предложения, количество уникальных слов и т. д., в качестве еще одного входного слоя, чтобы предоставить дополнительную информацию глубокой нейронной сети.
Например, мы создали эти дополнительные функции как часть конвейера разработки функций для Quora Unrealistic Classification Challenge.
питон
def add_features(df): df['question_text'] = df['question_text'].progress_apply(lambda x:str(x)) df["lower_question_text"] = df["question_text"].apply(lambda x: x.lower()) df['total_length'] = df['question_text'].progress_apply(len) df['capitals'] = df['question_text'].progress_apply(lambda comment: sum(1 for c in comment if c.isupper())) df['caps_vs_length'] = df.progress_apply(lambda row: float(row['capitals'])/float(row['total_length']), axis=1) df['num_words'] = df.question_text.str.count('\S+') df['num_unique_words'] = df['question_text'].progress_apply(lambda comment: len(set(w for w in comment.split()))) df['words_vs_unique'] = df['num_unique_words'] / df['num_words'] return df
Суммировать
НЛП по-прежнему остается очень интересной проблемой в области глубокого обучения, поэтому мы призываем вас провести много экспериментов и посмотреть, что работает, а что нет. Мы пытаемся дать здравый взгляд на этапы предварительной обработки нейронных сетей глубокого обучения для любой проблемы НЛП, но это не означает, что она детерминирована.
тема.
глубокое обучение, НЛП, машинное обучение, ИИ, искусственный интеллект, python, нейронные сети