Текстовая классификация для проекта новостных статей
Вы рады узнать, как очищать и обрабатывать текстовые данные с помощью Python? В этом удобном для начинающих проекте мы рассмотрим этапы очистки новостных данных, чтобы сделать их более удобными для анализа. Не волнуйтесь, если вы новичок в программировании — мы будем делать это шаг за шагом!
Я решил запустить этот код с помощью «Jupyter Lab», вы можете запустить его, перейдя в свою командную программу и перейдя в библиотеку по умолчанию, где на вашем компьютере установлен python. Если python установлен по вашему пути, вам не нужно этого делать и можно просто набрать:
jupyter notebook
Нажмите «Ввод», чтобы запустить блокнот Jupyter в вашем веб-браузере. Вы можете добавить любые соответствующие файлы данных, которые вам нужны, перетащив файлы в каталог из окна поиска или проводника и следуя любым отображаемым на экране подсказкам.
Мы будем использовать эти файлы здесь для этого проекта: https://archive.ics.uci.edu/dataset/359/news+aggregator
Шаг 1. Загрузите набор данных агрегатора новостей.
Скачать набор данных агрегатора новостей
Вам нужно будет извлечь файл и перетащить файлы «newsCorpora» и «2pageSessions» в лабораторию Jupyter, перетащив их на вкладку файлов на веб-странице лаборатории Jupyter, как описано выше.
Детали набора данных:
Набор ссылок (url) на новостные веб-страницы
Набор ссылок на новостные веб-страницы, собранный с онлайн-агрегатора в период с 10 марта по 10 августа 2014 года. Ресурсы сгруппированы в кластеры, представляющие собой страницы, обсуждающие одну и ту же новость. Набор данных также включает ссылки на веб-страницы, которые указывают (имеют ссылку) на одну из страниц новостей в коллекции.
Шаг 2. Запустите новый блокнот Jupyter.
Перейдите в «Файл», затем «Создать» и выберите «Блокнот». Вы увидите пустую полосу, где вы можете начать писать свой код. Выберите ядро Python по умолчанию.
Шаг 3. Загрузите и импортируйте необходимые пакеты
Начните с импорта необходимых пакетов, вы можете скопировать это и вставить в ячейку и запустить, одновременно нажав «shift» и «enter» на клавиатуре или нажав «Выполнить» на верхней панели.
import pandas as pd # Data manipulation import nltk # Natural Language Processing (NLP) from nltk.tokenize import word_tokenize from sklearn.model_selection import train_test_split # For splitting the data from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer # Feature extraction from sklearn.naive_bayes import MultinomialNB # Naive Bayes classifier from sklearn.metrics import classification_report, accuracy_score # Model evaluation
Перейдите в командное окно, чтобы установить эти пакеты, если у вас их нет, используя этот код для каждого отсутствующего пакета:
pip install scikit-learn pip install nltk pip install pandas
Шаг 4. Загрузите набор данных в кадр данных pandas.
Используйте следующий код для чтения первого CSV-файла:
import pandas as pd # Read the CSV file into a DataFrame, skipping lines with parsing errors data = pd.read_csv('[insert full path to your newsCorpora.csv file here]', on_bad_lines='skip') # Now you can work with the 'data' DataFrame
При использовании полного имени пути вы можете использовать двойную обратную косую черту ('\'), чтобы предотвратить ошибки экранирования Unicode в пути к файлу. Это происходит потому, что символ обратной косой черты (‘’) рассматривается как управляющий символ в строках Python.
Если вы заглянули и посмотрели на набор данных, вы также заметите, что таблица структурирована иначе, чем мы привыкли просматривать файлы больших данных, нет нескольких столбцов и только тысячи строк со ссылками. Это может вызвать у нас проблемы с Python при использовании нашего кода как есть. Таким образом, вы можете альтернативно использовать следующий код при импорте/чтении файла csv в python, указав, что заголовков нет.
import pandas as pd # Read the CSV file into a DataFrame, skipping lines with parsing errors data = pd.read_csv('path_to_your_data.csv', on_bad_lines='skip', header=None, usecols=[0]) # Now you can work with the 'data' DataFrame
Кроме того, вы можете определить имена столбцов на основе атрибутов новостных статей, а затем прочитать CSV-файл и указать имена столбцов.
column_names = ['headline', 'attribute1', 'attribute2', ...] # Replace with actual attribute names data = pd.read_csv('path_to_your_data.csv', names=column_names, header=None)
Поскольку у нас есть только один столбец, с которым мы работаем, я решил не использовать заголовки или имена столбцов, остальная часть моего кода отражает это, но вы можете изменить часть данных «[0]» моих кодов, чтобы отразить имена ваших столбцов. или идентификаторы. Например, если ваш столбец был назван «заголовок» в соответствии с этим кодом:
column_names = ['headline', 'attribute1', 'attribute2', ...] # Replace with actual attribute names
Тогда ваш код будет выглядеть следующим образом при удалении дубликатов на шаге 6 и на последующих шагах при перечислении определенного столбца в DataFrame под названием «данные»:
# Removing Duplicates data.drop_duplicates(inplace=True) # Converting to Lowercase data['headline'] = data['headline'].str.lower() # Handling Missing Values data['headline'].fillna("", inplace=True)
Шаг 5: Исходное исследование данных
Чтобы лучше понять набор данных, давайте начнем с некоторого начального исследования. Мы рассмотрим первые несколько строк, проверим пропущенные значения и изучим типы данных.
# Display the first few rows print(data.head()) # Check for missing values print(data.isnull().sum()) # Examine data types print(data.dtypes) 0 0 1\tFed official says weak data caused by weather 1 2\tFed's Charles Plosser sees high bar for cha... 2 3\tUS open: Stocks fall after Fed official hin... 3 4\tFed risks falling 'behind the curve' 4 5\tFed's Plosser: Nasty Weather Has Curbed Job... 0 0 dtype: int64 0 object dtype: object
Шаг 6: Предварительная обработка текстовых данных
Затем я подготовлю и предварительно обработаю этот набор данных, удалив все повторяющиеся строки (это важно при работе с большими наборами данных), а затем преобразую все символы в нижний регистр, чтобы стандартизировать текст и обеспечить, чтобы операции сравнения текста не учитывали регистр. Ценный инструмент при очистке данных.
# Removing Duplicates data.drop_duplicates(inplace=True) # Converting to Lowercase data[0] = data[0].str.lower() # Handling Missing Values data[0].fillna("", inplace=True))
Шаг 7: Маркируйте заголовки новостных статей
Следующий шаг, токенизация заголовков новостей, является важным этапом обработки текстовых данных для анализа. Давайте разберем это в удобной для начинающих форме:
Когда мы говорим о «токенизации», думайте об этом как о разбиении предложения или абзаца на более мелкие части, например, на отдельные слова. Представьте, что у вас есть предложение: «Быстрая коричневая лиса перепрыгивает через ленивую собаку». Токенизация этого предложения означает разбиение его на отдельные слова: [«The», «быстрый», «коричневый», «лиса», «прыгает», «над», «the», «ленивый», «собака»].
Почему мы это делаем?
- Понимание: текст разбивается на слова для лучшего понимания.
- Подготовка данных. Предварительно обрабатывает текст, делая его более чистым и удобным для работы.
- Извлечение признаков: преобразует текст в числовые признаки для анализа.
- Поиск по тексту. Позволяет искать определенные слова или шаблоны.
- НЛП: основа для задач обработки естественного языка.
Вы увидите важность этого в действии, когда мы начнем классифицировать наши данные. Но пока вы можете токенизировать данные, используя следующий код. Не забудьте установить его в свой терминал или командный центр (если он у вас не установлен), используя:
pip install nltk import nltk nltk.download('punkt') # Tokenize the headlines data['tokens'] = data[0].apply(nltk.word_tokenize)
Шаг 8: Удаление «стоп-слов» из наших токенизированных заголовков
Затем мы можем использовать библиотеку NLTK для удаления общих слов, называемых «стоп-словами», из текстовых данных. Такие стоп-слова, как «the» и «and», часто не имеют существенного значения для анализа. Отфильтровав их, мы можем сосредоточиться на более информативных словах, улучшая качество данных для задачи категоризации новостей позже.
from nltk.corpus import stopwords # Download stopwords data (you only need to do this once) import nltk nltk.download('stopwords') # Remove stopwords from each token list stop_words = set(stopwords.words('english')) data['tokens'] = data['tokens'].apply(lambda tokens: [word for word in tokens if word not in stop_words])
Шаг 9: «Вывод» токенизированных данных
На следующем шаге я использую инструмент «PorterStemmer» от NLTK для выполнения поиска по моим токенизированным текстовым данным. Stemming — это метод, который помогает привести слова к их корневой форме, устраняя суффиксы и вариации. Это помогает упорядочить похожие слова и упростить текстовые данные, что делает их более подходящими для задачи категоризации новостей.
from nltk.stem import PorterStemmer # Create a stemmer stemmer = PorterStemmer() # Apply stemming to each token list data['tokens'] = data['tokens'].apply(lambda tokens: [stemmer.stem(word) for word in tokens])
Шаг 10. Удаление специальных символов в токенизированных текстовых данных
В этой части процесса мы подключаем библиотеку «re» для обработки специальных символов в моих токенизированных текстовых данных. Я определяю пользовательскую функцию под названием «remove_special_characters», которая принимает в качестве входных данных список токенов. Эта функция использует регулярные выражения (регулярные выражения) для удаления любых символов, не являющихся буквами или цифрами, эффективно очищая токены. Наконец, я применяю эту функцию к столбцу «токены» моего набора данных, гарантируя, что текстовые данные не содержат нежелательных специальных символов, что делает их более подходящими для анализа.
import re # Define a function to remove special characters from a list of tokens def remove_special_characters(tokens): cleaned_tokens = [re.sub(r'[^a-zA-Z0-9\s]', '', token) for token in tokens] return cleaned_tokens # Apply the function to the 'tokens' column data['tokens'] = data['tokens'].apply(remove_special_characters)
Давайте посмотрим на наш набор данных:
# Display the first few rows print(data.head()) 0 \ 0 1\tfed official says weak data caused by weather 1 2\tfed's charles plosser sees high bar for cha... 2 3\tus open: stocks fall after fed official hin... 3 4\tfed risks falling 'behind the curve' 4 5\tfed's plosser: nasty weather has curbed job... tokens 0 [1, fed, offici, say, weak, data, caus, weather] 1 [2, fed, s, charl, plosser, see, high, bar, ch... 2 [3, us, open, , stock, fall, fed, offici, hint... 3 [4, fed, risk, fall, behind, curv, ] 4 [5, fed, s, plosser, , nasti, weather, curb, j...
Шаг 11: Определите категории
Затем мы можем начать классифицировать наши новостные ссылки/данные, но сначала мы должны определить наши категории, используя общие категории и ключевые слова. Здесь помогут Google и ChatGPT. Вы можете попросить ChatGPT создать список общих категорий новостных статей и связанных с ними ключевых слов или вручную выполнить задачу, используя свои собственные предопределенные категории и ключевые слова из набора данных.
Этот загруженный набор данных поставляется с файлом readme, который предоставляет следующую информацию о наборе данных, чтобы упростить этот процесс, предоставляя структуру данных, категории и многое другое.
Но большинство грязных наборов данных не поставляются с файлами readme. Поэтому я проигнорирую его для своего пошагового руководства по этому проекту, но для справки можно получить доступ к файлу для чтения в папке загрузки набора данных.
Вместо этого я попросил ChatGPT создать общие категории и связанные с ними ключевые слова для новостных статей в США. Если вы не знакомы с ChatGPT, вот несколько ресурсов, которые могут вам помочь:
Освоение ChatGPT: полезные ресурсы для начинающих, чтобы раскрыть всю мощь языковых моделей
Это созданный список:
- Политика
- Виды спорта
- Технологии
- Бизнес
- Здоровье
- Развлечение
Затем я попросил ChatGPT включить связанные ключевые слова с каждой перечисленной категорией. Результат был следующим:
- Политика: политика, правительство, выборы, политика, законодательство, демократия
- Виды спорта: спорт, футбол, баскетбол, бейсбол, футбол, легкая атлетика
- Технологии: технологии, инновации, программное обеспечение, гаджеты, цифровые технологии, искусственный интеллект, кибербезопасность.
- Бизнес: бизнес, экономика, финансы, рынки, акции, предпринимательство, коммерция
- Здоровье: здоровье, хорошее самочувствие, медицина, здравоохранение, фитнес, медицина, питание
- Развлечения: развлечения, фильмы, музыка, знаменитости, телешоу, искусство, культура.
Вы даже можете попросить его отформатировать его в код, используя созданный вами пример, но вернемся к нашим шагам категоризации, используя наш список, мы можем использовать следующий код Python для определения категорий в наших данных, используя ключевые слова, которые мы конкретизировали с помощью нашей токенизации. шаг. Также обратите внимание, что все ключевые слова и категории написаны строчными буквами, чтобы соответствовать нашему набору данных (обратите внимание, что мы преобразовали наш текст в строчные буквы ранее на шаге 5).
# Define the categories and their associated keywords category_keywords = { 'politics': ['politics', 'government', 'election', 'president', 'congress', 'senate'], 'sports': ['sports', 'football', 'basketball', 'baseball', 'soccer', 'athlete'], 'technology': ['technology', 'innovation', 'software', 'AI', 'cybersecurity', 'internet'], 'business': ['business', 'economy', 'finance', 'stocks', 'market', 'entrepreneur'], 'health': ['health', 'medicine', 'wellness', 'pandemic', 'vaccine', 'doctor'], 'entertainment': ['entertainment', 'celebrity', 'movies', 'music', 'Hollywood', 'film'], }
Шаг 12: Категоризация
На этом этапе мы создаем инструмент, который автоматически классифицирует новостные статьи. Мы выбрали конкретные слова, относящиеся к разным темам, таким как «политика», «спорт» и «технологии». Наш инструмент проверяет слова в каждом заголовке новостей и помещает статью в категорию с наиболее подходящими словами. Это облегчает нам понимание того, о чем каждая статья. Это как иметь помощника, который быстро сортирует новостные статьи по корзинам, помеченным основной темой статьи.
# Function for categorization def categorize_tokens(tokens): category_counts = {} for category, keywords in category_keywords.items(): count = sum(1 for token in tokens if token in keywords) category_counts[category] = count return max(category_counts, key=category_counts.get) # Apply categorization function and create a new column data['category'] = data['tokens'].apply(categorize_tokens)
Вы можете просмотреть верхнюю часть недавно измененного набора данных, используя следующий код:
#View the first few rows of the DataFrame print(data.head()) 0 \ 0 1\tfed official says weak data caused by weather 1 2\tfed's charles plosser sees high bar for cha... 2 3\tus open: stocks fall after fed official hin... 3 4\tfed risks falling 'behind the curve' 4 5\tfed's plosser: nasty weather has curbed job... tokens category 0 [1, fed, offici, say, weak, data, caus, weather] politics 1 [2, fed, s, charl, plosser, see, high, bar, ch... politics 2 [3, us, open, , stock, fall, fed, offici, hint... politics 3 [4, fed, risk, fall, behind, curv, ] politics 4 [5, fed, s, plosser, , nasti, weather, curb, j... politics
Давайте сохраним результаты нашего набора данных в виде файла csv.
# Save result as csv data.to_csv('output.csv', index=False)
У нас есть набор данных новостных статей, организованный по категориям. Теперь давайте построим модель.
Шаг 13: Построение модели и оценка
Наконец, на этом последнем шаге мы создаем «машину категоризации новостных статей». Давайте разберем это:
Часть А:
- Преобразование в числовые метки. Прежде чем мы сможем использовать алгоритм «Наивного Байеса», нам нужно преобразовать категориальные категории новостей в числовые метки. Мы используем «LabelEncoder» для достижения этого преобразования.
- Разделение данных. У нас есть несколько новостных статей. Мы разделим их на две группы: одна группа будет обучать нашего «новостного робота», а другая — проверить, хорошо ли он усвоил материал.
from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report import joblib # Extract the category labels train_labels = data['category'] # Initialize the LabelEncoder label_encoder = LabelEncoder() # Convert string labels to numerical labels train_labels_encoded = label_encoder.fit_transform(train_labels) # Split the data train_data, test_data, train_labels_encoded, test_labels = train_test_split( data['tokens'], train_labels_encoded, test_size=0.2, random_state=42 )
Часть Б:
- Использование смарт-инструментов. Мы используем классный инструмент, чтобы улучшить нашу «систему сортировки новостей».
- Подготовка данных. Мы превращаем наши специальные слова в числа, чтобы инструмент мог их понимать. Для этого мы используем специальный способ под названием «TF-IDF».
- Обучение инструмента. У нас есть специальный инструмент обучения под названием «Мультиномиальный наивный байесовский алгоритм». Это обучение на примерах, которые мы ему даем.
- Предсказания. После того, как он узнает, мы позволяем ему угадать, к какой категории относятся новостные статьи.
- Проверка его навыков: мы используем специальный отчет, чтобы увидеть, насколько хорошо он справился, например табель успеваемости для инструмента. Если есть сложная ситуация, когда мы можем разделить на ноль, мы справимся с ней с помощью хитрости (zero_division=1). Это помогает нам беспрепятственно оценить его производительность.
from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import classification_report import joblib # Convert the token lists to strings train_data = train_data.apply(' '.join) test_data = test_data.apply(' '.join) # Convert text data to numerical features (TF-IDF representation) vectorizer = TfidfVectorizer() train_data_tfidf = vectorizer.fit_transform(train_data) test_data_tfidf = vectorizer.transform(test_data) # Create a Naive Bayes classifier clf = MultinomialNB() # Train the model clf.fit(train_data_tfidf, train_labels_encoded) # Save the trained model to a file model_filename = 'news_categorization_model.pkl' joblib.dump(clf, model_filename) # Make predictions predictions_encoded = clf.predict(test_data_tfidf) from sklearn.preprocessing import LabelEncoder # Initialize the LabelEncoder label_encoder = LabelEncoder() # Convert string labels to numerical labels test_labels_encoded = label_encoder.fit_transform(test_labels) # Convert numerical predictions to string labels predictions = label_encoder.inverse_transform(predictions_encoded) # Evaluate the model report = classification_report(test_labels, predictions, zero_division=1) print(report) precision recall f1-score support 0 1.00 0.00 0.00 2534 1 1.00 0.00 0.00 3847 2 1.00 0.00 0.00 2574 3 0.95 1.00 0.98 197671 4 1.00 0.00 0.00 46 5 1.00 0.00 0.00 1131 accuracy 0.95 207803 macro avg 0.99 0.17 0.16 207803 weighted avg 0.95 0.95 0.93 207803
[Необязательно] Шаг 14: Давайте используем нашу новую модель для классификации нашей второй новостной статьи.
Во-первых, давайте предварительно обработаем и извлечем функции из нового набора данных, как мы делали первый ранее. Этот набор данных находится в том же файле набора данных, который мы загрузили на первом этапе. Этот файл называется «2pageSessions.csv».
import pandas as pd # Data manipulation import nltk # Natural Language Processing (NLP) from nltk.tokenize import word_tokenize from sklearn.model_selection import train_test_split # For splitting the data from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer # Feature extraction from sklearn.naive_bayes import MultinomialNB # Naive Bayes classifier from sklearn.metrics import classification_report, accuracy_score # Model evaluation import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.preprocessing import LabelEncoder import joblib # Load the trained model from the saved file model_filename = 'news_categorization_model.pkl' clf = joblib.load(model_filename) # Read the new news articles CSV file data = pd.read_csv('2pageSessions.csv', on_bad_lines='skip', header=None, usecols=[0]) # Removing Duplicates data.drop_duplicates(inplace=True) # Converting to Lowercase data[0] = data[0].str.lower() # Handling Missing Values data[0].fillna("", inplace=True) # Tokenize the headlines data['tokens'] = data[0].apply(nltk.word_tokenize) from nltk.stem import PorterStemmer import nltk from nltk.corpus import stopwords # Remove stopwords from each token list stop_words = set(stopwords.words('english')) data['tokens'] = data['tokens'].apply(lambda tokens: [word for word in tokens if word not in stop_words]) # Create a stemmer stemmer = PorterStemmer() # Apply stemming to each token list data['tokens'] = data['tokens'].apply(lambda tokens: [stemmer.stem(word) for word in tokens]) import re # Define a function to remove special characters from a list of tokens def remove_special_characters(tokens): cleaned_tokens = [re.sub(r'[^a-zA-Z0-9\s]', '', token) for token in tokens] return cleaned_tokens # Apply the function to the 'tokens' column data['tokens'] = data['tokens'].apply(remove_special_characters) # Convert token lists to strings for feature extraction data['processed_text'] = data['tokens'].apply(' '.join) # Convert text data to numerical features (TF-IDF representation) vectorizer = TfidfVectorizer() train_data_tfidf = vectorizer.fit_transform(train_data) test_data_tfidf = vectorizer.transform(test_data) # Make predictions using the loaded model predictions_encoded = clf.predict(test_data_tfidf) # Convert numerical predictions back to original labels predictions = label_encoder.inverse_transform(predictions_encoded) # Print the predictions print(predictions) print("Accuracy:", accuracy_score(predictions_encoded, predictions)) print("Classification Report:\n", classification_report(predictions_encoded, predictions)) [3 3 3 ... 3 3 3] Accuracy: 1.0 Classification Report: precision recall f1-score support 1 1.00 1.00 1.00 5 2 1.00 1.00 1.00 1 3 1.00 1.00 1.00 83116 accuracy 1.00 83122 macro avg 1.00 1.00 1.00 83122 weighted avg 1.00 1.00 1.00 83122
Результаты оценки модели указывают на впечатляющий уровень точности, получив высшую оценку 1,0. Отчет о классификации также подтверждает отличные характеристики модели с точностью, полнотой и оценкой F1 1,00 по всем направлениям. Это означает, что прогнозы модели идеально совпадают с метками истинности для всех трех классов. Примечательно, что класс большинства, помеченный цифрой «3» (политика), включает значительную часть набора данных с поддержкой 83 116 экземпляров. Средневзвешенное значение и среднее макроэкономическое значение, оба равные 1,00, подчеркивают согласованность модели при выполнении точных прогнозов по различным классам. Такие выдающиеся результаты подчеркивают эффективность шагов предварительной обработки и выбранного алгоритма машинного обучения, что делает эту модель отличным кандидатом для реального применения, особенно в задачах категоризации новостей.
Этот код представляет собой подробное пошаговое руководство по проекту классификации текста, включая предварительную обработку, токенизацию, определение категорий, категоризацию и построение/оценку модели.
Полный проект и дополнительные ресурсы можно найти здесь!