Неделя 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. Следующий шаг - попробовать НЛП для набора данных бразильских фейковых новостей.