Неделя 5: НЛП для обнаружения фейковых новостей
Пошаговое руководство по обработке естественного языка.
Пятая неделя Pyrentena и я наконец погрузились в обработку естественного языка! На самом деле, это шестая неделя Пирентены…. Проект 5 был основан на наборе данных COVID-19: прогнозирование положительного результата тестирования на болезнь года. Отличный проект, чтобы узнать о методах классификации и энтропии гиперпараметров! Я решил не писать об этом и статьи - модель предсказания была предназначена только для исследовательских целей, а не для какого-то огромного откровения, поэтому я подумал, что лучше не говорить об этом. Вы можете проверить полный код на моем Github и проверить свои навыки по методам классификации.
Вдохновленный мыслью о том, что «это может быть немного искажено», я решил, что мой первый проект НЛП будет касаться темы, очень чувствительной для меня как журналиста: фальшивых новостей. Помимо жутких текстов в WhatsApp, фальшивые новости представляют опасность для нашего общества, и я очень верю, нашей демократии в целом. Добро пожаловать на пятую (6?) Неделю Пирентены: мы создаем детектор фейковых новостей!
Исследование данных
Набор данных доступен на Kaggle и был разделен на два CSV: фальшивые и правдивые новости. Давайте взглянем:
Фальшивые новости csv выглядели точно так же, но только с фейковыми новостями в качестве данных. Я начал с создания нашей целевой переменной True / Fake и объединения двух CSV в один:
# adding feature that will be target variable True/Fake fake_news['True/Fake'] = 'True' true_news['True/Fake'] = 'Fake' # combining the dataframes into a single one using concat method total_news = pd.concat([true_news, fake_news]) total_news['Article'] = total_news['title'] + total_news['text']
Базовая очистка данных
Многие онлайн-данные представлены в виде текста (электронные письма, статьи, документы и т. Д.), И одно из самых захватывающих приложений ML - учиться на этих текстах! Для анализа этих данных мы используем так называемый «мешок слов»: вы подсчитываете частоту, с которой это слово появляется в вашем наборе данных. Это позволяет нам получить из каждого заголовка или текста количество слов в тексте. Обратной стороной является то, что порядок, в котором расположены эти слова, не имеет значения, что является большим противоречием, когда вы думаете о том, что на самом деле включает чтение настоящего текста.
Некоторые слова - это то, что мы называем «малоинформативными словами», например, «the», «and», «you». Почти каждый английский текст в мире содержит это слово, поэтому оно не имеет особого значения для нашей модели машинного обучения. К этому типу слов относятся стоп-слова, которые имеют высокую частоту, но низкую ценность - они просто создают шум в наборе данных. Мы получаем функцию, обрабатывающую эти «пробные слова» из библиотеки NLTK (National Language Toolkit).
Одна уловка заключается в том, что NLTK нельзя вызвать на ноутбуке после его установки, вам нужно настроить загрузку внутри самого ноутбука, как я сделал ниже:
# downloading stopword from nltk lib import nltk nltk.download('stopwords') # output [nltk_data] Downloading package stopwords to /root/nltk_data... [nltk_data] Unzipping corpora/stopwords.zip. True
После загрузки мы можем импортировать эти библиотеки в обычном режиме и начать их использовать! Я построил функцию для обработки наших данных: избавиться от знаков препинания и применить технику игнорируемых слов.
# build function to process text def process_text(s): # Check each string for punctuation no_punc = [char for char in s if char not in string.punctuation] # Join the characters again no_punc = ''.join(no_punc) # Convert string to lowercase and remove stopwords clean_string = [word for word in no_punc.split() if word.lower() not in stopwords.words('english')] return clean_string
Функция готова к работе! Я создал новую функцию в наборе данных: total_news [«Чистый текст»] и применил наш process_text к функции «Статья». Здесь вам нужно немного терпения ... Наш объединенный набор данных содержит более 40 тысяч строк! Я настоятельно рекомендую вам построить эту модель в облачном сервисе, таком как Google Colab, вместо Jupyter Notebook. Я сделал это на обоих, в среднем 30 минут на запуск на GColab и 3 часа на Jupyter.
# processing the text wo we can have a Clean Text feature # this process might take a while: avg 30 mim total_news['Clean Text'] = total_news['Article'].apply(process_text)
Можете ли вы поверить, что выполнение этой единственной строчки кода заняло все это время ?! Что ж, с НЛП легко перейти от данных к каким-то большим данным, так что нам лучше к этому привыкнуть! Как только это было сделано, наша функция «Чистый текст» была готова к работе:
Векторизация
Пора посчитать частоту каждого слова, используя технику набора слов:
# importing libs from sklearn.feature_extraction.text import CountVectorizer # Bag-of-Words (bow) accountf for the frequency of the text data bow_transformer = CountVectorizer(analyzer=process_text).fit(total_news['Clean Text'])
Общий словарный запас: 39099. Давайте проверим форму наших матричных данных и перейдем к Tfidf tehcnic!
# printing out the shape of our Matrix print(f'Shape of Sparse Matrix: {news_bow.shape}') print(f'Amount of Non-Zero occurences: {news_bow.nnz}') # output Shape of Sparse Matrix: (44898, 39099) Amount of Non-Zero occurences: 44898
Tfidf: обратная частота документов
Представление Tfidf - это еще одна обработка текста, которую мы можем применить к нашим текстовым данным. «Tf» обозначает частоту термина, а «Idf» обозначает «обратную частоту документа». Tf работает так же, как мешок слов: анализирует частоту этого. Часть idf объясняет идею о том, что слово также имеет "вес", исходя из того, насколько часто оно встречается во всем наборе данных вместе, высоко оценивая реже. Чем это отличается от мешка слов? Что ж, Tfidf в целом оценивает слова от редких к обычным, оценивая редкие слова выше. Этот метод позволяет нам обнаруживать интересные случаи в кучу перекрывающихся текстов на одну и ту же тему! Получая доступ к «редким» словам через Tfidf, мы можем узнать самую важную информацию о том, что происходит в наборе данных.
# applying Tfidf to check for rare words from sklearn.feature_extraction.text import TfidfTransformer # checking news_bow shape tfidf_transformer = TfidfTransformer().fit(news_bow) news_tfidf = tfidf_transformer.transform(news_bow) print(news_tfidf.shape) # output (44898, 39099)
Построить и обучить модель
Я остановил обработку текста здесь, но есть несколько других приемов, которые вы можете применить к своим текстовым данным. Предлагаю изучить их все, ведь каждый набор данных имеет свои особенности! Чтобы обучить нашу модель, я решил использовать полиномиальный наивный байесовский алгоритм. Наивный Байес получил такое название, потому что на самом деле он не заботится о порядке, а о частотах - поэтому он «наивный». Этот алгоритм достаточно хорошо работал во многих реальных ситуациях, таких как классическая классификация документов и фильтрация спама. Казалось, хороший выбор.
# importing algorithm to build the model from sklearn.naive_bayes import MultinomialNB fakenews_detect_model = MultinomialNB().fit(news_tfidf, total_news['True/Fake'])
После разделения моих данных с помощью train_test_split я решил построить конвейер, чтобы вся эта обработка текста происходила организованным образом: наши данные поезда будут проходить векторизацию с набором слов, за которым следует метод Tdif , а для них - алгоритм классификатора Наивный Байес.
# building pipeline from sklearn.pipeline import Pipeline pipeline = Pipeline ([('bow', CountVectorizer(analyzer=process_text)), ('tfidf', TfidfTransformer()) ('classifier', MultinomialNB()), ]) pipeline.fit(news_train,text_train)
Выход нашего трубопровода:
Красивый! Это был мой первый раз, когда я строил трубопровод, и я очень этим горжусь. Пора сделать некоторые прогнозы на наших тестовых данных и оценить модель.
Оценка модели
Чтобы оценить нашу модель, я решил воспользоваться классификационным отчетом от Sickit Learn. Это отличный отчет, который дает не только точность, которая, на мой взгляд, является слабой оценочной метрикой, но также точность, отзывчивость и показатель f1!
from sklearn.metrics import classification_report # predicting news on test dataset prediction = pipeline.predict(news_test) # printing out classification report print(classification_report(prediction,text_test))
Выход:
Полиномиальный наивный байесовский алгоритм хорошо работал с нашими обработанными текстовыми данными, успешно предсказывая как ложные, так и истинные новости! Мы получили высокие баллы как по точности, отзывчивости, так и по шкале f1. Я подробнее расскажу об этих оценочных показателях в другой статье и дам более подробную информацию о том, когда использовать каждый из них, но знайте: это довольно хороший результат! (если мы не переобучаемся, да поможет нам Бог).
Вы можете проверить полный код на моем Github. Следующий шаг - попробовать НЛП для набора данных бразильских фейковых новостей.