Конвейер НЛП
Прежде чем перейти к этапам предварительной обработки текста в обработке естественного языка (NLP), давайте взглянем на стандартный конвейер НЛП, основанный на машинном обучении.
Конвейер НЛП — это набор шагов, которые необходимо выполнить для создания комплексного программного обеспечения НЛП.
Он состоит из следующих шагов:
- Сбор данных
- Подготовка текста
– Очистка текста
– Базовая предварительная обработка
– Расширенная предварительная обработка - Разработка функций
- Моделирование
– Построение модели
– Оценка - Развертывание
– Развертывание
– Мониторинг
– Обновление модели
В этом блоге мы рассмотрим основные этапы предварительной обработки обработки естественного языка на основе машинного обучения.
Если вы хотите получить краткий обзор НЛП, вы можете просмотреть мой предыдущий блог:
Предварительная обработка текста
Для предварительной обработки текста перед разработкой функций и моделированием используются различные методы. Ниже представлены наиболее популярные техники:
Нижний регистр
Данные должны быть записаны строчными буквами, чтобы избежать усложнения модели. Это связано с тем, что Python будет рассматривать Basically
и basically
по-разному. Код для этого может быть:
# suppose we have a dataframe which includes movie reviews along with it's # sentiments # reviews are in review column and sentiments are in sentiment column df['review'] = df['review'].str.lower() # and this simple line of code will transform every review into lowercase # uniformly
Удаление HTML-тегов
Часто данные получаются посредством парсинга веб-страниц или с помощью различных API, и в результате данные содержат HTML-теги, которые используются для семантического значения, важного для браузера, а не для нас. Поэтому нам важно заранее удалить эти HTML-теги. Это делается с помощью регулярных выражений или широко известных как регулярные выражения.
# in our case we scraped data from the IMDB website and thus it does contain # HTML tags # we'll define a simple function that uses regex to remove the HTML tags import re def remove_html_tags(text): ''' takes a string `text` as the input returns a string without HTML tags ''' pattern = re.compile('<.*?>') return pattern.sub(r'', text) df['review'] = df['review'].apply(remove_html_tags)
Удаление URL-адресов
Удаление URL-адресов из наших данных — еще один распространенный шаг предварительной обработки данных при построении модели НЛП. Это связано с тем, что URL-адреса на самом деле не влияют на смысл/настроение текстового сообщения и вместо этого могут запутать нашу модель, поэтому их лучше удалить. Опять же, регулярные выражения используются для удаления URL-адресов из наших данных.
# our movie review data doesn't really have any urls in them (obv) # so I'll use sample data to demonstrate this import re text1 = 'Google search here www.google.com' text2 = 'My Linkedin: https://www.linkedin.com/in/pranshavpatel/' def remove_url(text): ''' takes a string `text` as the input returns a string without any URL ''' pattern = re.compile(r'https?://\S+|www\.\S+') return pattern.sub(r'', text) text_without_url = [] text_without_url.append(remove_url(text1)) text_without_url.append(remove_url(text2)) print(text_without_url) # will print a list containing both the text without any url
Удаление знаков препинания
Пунктуация — это специальные символы, которые помогают в построении предложений на определенном языке. В большинстве случаев рекомендуется удалять знаки препинания из наших данных, поскольку это может привести к дополнительной сложности и даже запутать модель. Например, при токенизации данных (о токенизации речь пойдет позже) Hello
и Hello!
будут считаться разными. Библиотека строк Python предоставляет знаки пунктуации, присутствующие в английском языке.
import string print(string.punctuation) # prints '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' def remove_punc(text): ''' takes a string `text` as the input returns a string without any punctuation ''' for char in string.punctuation: text = text.replace(char, '') return text
Этот код будет работать отлично, но поскольку мы разработали эту функцию, используя нашу собственную логику, она довольно медленная, а на больших наборах данных (что-то вроде обзоров фильмов IMDB) это займет значительное количество времени, поэтому мы будем использовать следующий код, который делает то же самое. вещь, но это намного быстрее.
import string def remove_punc_fast(text): ''' takes a string `text` as the input returns a string without any punctuation ''' return text.translate(str.maketrans('', '', string.punctuation)) df['review'] = df['review'].apply(remove_punc_fast)
Обработка слов/сленгов в чате
В современном быстро меняющемся мире люди обычно используют аббревиатуры и короткие формы вместо того, чтобы вводить слова целиком. Например, LMAO, ROFL, LOL, GN, ASAP, FYI
и т. д., и нам важно преобразовать их в длинные формы, чтобы достичь их семантического значения и не запутать нашу модель. Это можно сделать, используя простой словарь с ключом в качестве краткой формы и значением в качестве полной формы, а затем написав функцию, которая проверяет каждое слово предложения, заменяя его длинной формой, если оно присутствует в словаре.
Ссылка на репозиторий Github, содержащий сленги и их длинные формы:
chat_words = {} # the dictionary containing the slang words and full forms def chat_conversion(text): ''' takes a string `text` as the input returns a string with the slangs replaced by their full forms ''' new_text = [] for w in text.split(): if w.upper() in chat_words: new_text.append(chat_words[w.upper()]) else: new_text.append(w) return ' '.join(new_text) print(chat_conversion('IMO he is the best')) # Output: In My Opinion he is the best
Исправление орфографии
Думаю, не нужно объяснять, почему это важно. Орфографическая ошибка может полностью изменить семантическое значение предложения или запутать модель, снизив ее точность, поэтому важно исправить написание наших текстовых данных без обучения модели. Для этого можно использовать различные библиотеки. В этом блоге я буду использовать textblob
.
from textblob import TextBlob incorrect_text = 'i doont knoww howw to typpe.' textBlb = TextBlob(incorrect_text) print(textBlb.correct().string) #output: 'i dont know how to type.'
Удаление стоп-слов
Стоп-слова — это слова, которые помогают в формировании предложения, но на самом деле не влияют на его смысл и поэтому обычно удаляются из набора данных. В английском языке есть несколько распространенных стоп-слов: a, the of, are, my
и т. д. Эти слова бесполезны для таких задач, как анализ настроений или классификация документов. Стоп-слова можно легко удалить с помощью библиотеки NLTK.
Примечание. В некоторых задачах НЛП, таких как маркировка частей речи, стоп-слова не удаляются.
from nltk.corpus import stopwords print(stopwords.words('english')) # prints the stopwords present in english # the method followed is very similar to that followed in chat word treatment def remove_stopwords(text): ''' takes a string `text` as the input returns a string with stop words removed ''' new_text = [] for w in text.split(): if w in stopwords.words('english'): new_text.append('') else: new_text.append(w) return ' '.join(x) print(remove_stopwords('NLP is very interesting')) # output: 'NLP interesting' df['review'] = df['review'].apply(remove_stopwords)
Обработка смайлов
В наши дни смайлы очень распространены, и мы используем их в наших ежедневных разговорах, но машинам может быть довольно сложно расшифровать их значение. Есть два способа обработки смайлов:
- Удалите их: просто используйте регулярные выражения, чтобы удалить их из данных (да, шаблоны могут быть довольно сложными из-за кодировки «utf-8» :/)
- Замените их текстовым значением. Библиотека смайлов в Python предоставляет нам функцию «демоджиза», которая заменяет смайлик его текстовым описанием.
# Remove emojis import re def remove_emoji(text): emoji_pattern = re.compile("[" u"\U0001F600-\U0001F64F" # emoticons u"\U0001F300-\U0001F5FF" # symbols & pictographs u"\U0001F680-\U0001F6FF" # transport & map symbols u"\U0001F1E0-\U0001F1FF" # flags (iOS) u"\U00002702-\U000027B0" u"\U000024C2-\U0001F251" "]+", flags=re.UNICODE) return emoji_pattern.sub(r'', text) print(remove_emoji('Loved the movie. It was 😘')) # output: 'Loved the movie. It was ' # Replace emojis with text import emoji print(emoji.demojize('Loved the movie. It was 😘')) #output: 'Loved the movie. It was :face_blowing_a_kiss:'
Токенизация
Вероятно, это самый важный шаг в предварительной обработке текстовых данных. Это включает в себя токенизацию текстовых данных в предложения, фразы или слова. Например, 'NLP is very interesting'
можно преобразовать в слово ['NLP', 'is', 'very', 'interesting']
.
Токенизация очень важна, поскольку это базовый этап разработки функций, который определяет, как наша модель будет интерпретировать данные. Таким образом, для инженера НЛП очень важно правильно маркировать данные, чтобы избежать путаницы. Вот несколько примеров, отражающих проблемы, с которыми сталкиваются во время токенизации: $20
: Здесь важно токенизировать $ отдельно и 20 отдельно. 10km
: Здесь важно токенизировать 10 отдельно и км отдельно. U.S.
: Здесь важно токенизировать США как один токен вместо токенизации U отдельно и S отдельно.
Таким образом, для правильной токенизации наших данных необходимо сделать множество исключений.
Я рассмотрю код нескольких методов, которые можно применить для токенизации наших данных.
# 1. Using the split function # The most naive approach, and obviously it won't cover any corner cases sent = 'NLP is very interesting' print(sent.split()) # output: ['NLP', 'is', 'very', 'interesting'] # 2. Using regular expressions # This might work but one has to make many complex patterns to fit corner cases # can be tedious at times but better than the split function import re sent = 'NLP is very interesting' tokens = re.findall("[\w']+", sent) print(tokens) # output: ['NLP', 'is', 'very', 'interesting'] # 3. Using python libraries # The most optimal solution, handles the complexes cases on its own # 3.1 NLTK from nltk.tokenize import word_tokenize sent = 'NLP is very interesting!' print(word_tokenize(sent)) # output: ['NLP', 'is', 'very', 'interesting', '!'] # Note: In the first two cases the exclamation mark wouldn't have been # considered as a separate token # Still NLTK doesn't provide the best solution and misses a few exceptions # 3.2 Spacy import spacy nlp = spacy.load('en_core_web_sm') doc = nlp(sent) for token in doc: print(token) #output: # NLP # is # very # interesting # ! # Spacy is the preferred choice because it handles corner cases more # effectively than NLTK.
Стемминг/лемматизация
Переходим к последнему, но не менее важному методу предварительной обработки текста.
Сначала давайте разберемся, что такое флексия? В грамматике флексия — это модификация слова для выражения различных грамматических категорий, таких как время, падеж , голос, аспект, лицо, число, пол и настроение. Например, прогулка может быть выражена как ходьба, шел, прогулка и т. д. И как вы правильно догадались, перегиб является проблемой для нашей модели, поскольку он приводит к дополнительной сложности и может запутать нашу модель.
Так как же это связано со Стеммингом? Стемминг – это процесс приведения слов к их корневым формам, например сопоставление группы слов с одной и той же основой даже если сама основа не является допустимым словом в языке.
Стемминг в основном используется в системах информационного поиска. Например, когда вы ищете рыбу в Google, вы также получаете результаты рыбалки. Это из-за Стемминга.
Алгоритмы, используемые для стемминга, называются стеммерами, и в этом блоге мы обсудим конкретный стеммер под названием Porter Stemmer, который используется специально для английского языка.
Реализовать стемминг мы будем через библиотеку NLTK.
from nltk.stem.porter import PorterStemmer ps = PorterStemmer def stem_words(text): ''' takes a string `text` as the input returns a string with every word transformed into its stem word ''' return ' '.join([ps.stem(word) for word in text.split()]) # list comprehensions are so concise, that's the reason I love them! sample = 'walk walks walking walked' stem_words(sample) # output: 'walk walk walk walk' # now let's try this with another sentence text = 'probably my all time favorite horror movie is the conjuring' stem_words(text) # output: 'probabl my all time favorit horror movi is the conjur'
Обратите внимание, что во втором предложении основы даже не являются настоящими словами. Это может быть проблемой, если по какой-то причине вы хотите показать этот вывод своему пользователю/клиенту.
Таким образом, чтобы решить эту проблему, используется Лемматизация, которая по сути делает то же самое, но вместо этого ищет настоящие английские слова (или язык, над которым вы работаете) в качестве основных слов для каждого слова.
По этой причине лемматизация выполняется медленнее, чем стемминг, и если вам не нужно показывать этот вывод пользователю, обычно используется стемминг, поскольку он быстрее.
Лемматизация, в отличие от стемминга, правильно уменьшает количество измененных слов, гарантируя, что корень слова принадлежит языку. В лемматизации корневое слово называется леммой.
В отличие от стемминга, который использует алгоритм, в лемматизации словарь используется для преобразования слов в лемму (мы будем использовать WordNet Lemmatizer, который представляет собой лексический словарь, в котором хранятся связи между английскими словами). Теперь, поскольку мы ищем в словаре замену слов, а не просто используем определенный алгоритм, лемматизация работает медленнее, чем стемминг.
Примечание. При лемматизации вам также необходимо указать части речи, в которых вы хотите, чтобы ваша лемма (глагол, существительное, прилагательное и т. д.)
Мы можем реализовать лемматизацию, используя библиотеку NLTK:
import nltk from nltk.stem import WordNetLemmatizer wordnet_lemmatizer = WordNetLemmatizer() sentence = "I love coding whilst listening to music." punctuations="?:!.,;" sentence_words = nltk.word_tokenize(sentence) for word in sentence_words: if word in punctuations: sentence_words.remove(word) sentence_words print("{0:20}{1:20}".format("Word","Lemma")) for word in sentence_words: print ("{0:20}{1:20}".format(word,wordnet_lemmatizer.lemmatize(word,pos='v'))) #output: # Word Lemma # I I # love love # coding code # whilst whilst # listening listen # to to # music music
Заключение
В этом блоге мы углубились в важнейший мир этапов предварительной обработки текста НЛП. Целью НЛП является понимание человеческого языка, и эти этапы предварительной обработки являются основой, на которой мы строим значимые идеи. От преобразования текста в нижний регистр до обработки сложных элементов, таких как смайлы, мы изучили все важные аспекты подготовки текстовых данных для задач НЛП. Эти шаги не только повышают точность наших моделей, но и открывают путь к более четкому общению между людьми и машинами. Поскольку мы продолжаем продвигаться в области обработки естественного языка, овладение этими методами предварительной обработки становится все более важным. Итак, продолжайте экспериментировать, продолжайте учиться и продолжайте расширять границы возможного в НЛП!
и это конец!
Свяжитесь со мной:
Идентификатор электронной почты:[email protected]
Linkedin:https://www.linkedin.com/in/pranshavpatel/
Github:https://www.github.com/pranshavpatel
Стеккадемический
Спасибо, что дочитали до конца. Прежде чем уйти:
- Пожалуйста, рассмотрите возможность аплодировать и следовать автору! 👏
- Следуйте за нами в Twitter(X), LinkedIn и YouTube.
- Посетите Stackademic.com, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.