Текстовая классификация для проекта новостных статей

Вы рады узнать, как очищать и обрабатывать текстовые данные с помощью 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», «ленивый», «собака»].

Почему мы это делаем?

  1. Понимание: текст разбивается на слова для лучшего понимания.
  2. Подготовка данных. Предварительно обрабатывает текст, делая его более чистым и удобным для работы.
  3. Извлечение признаков: преобразует текст в числовые признаки для анализа.
  4. Поиск по тексту. Позволяет искать определенные слова или шаблоны.
  5. НЛП: основа для задач обработки естественного языка.

Вы увидите важность этого в действии, когда мы начнем классифицировать наши данные. Но пока вы можете токенизировать данные, используя следующий код. Не забудьте установить его в свой терминал или командный центр (если он у вас не установлен), используя:

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: полезные ресурсы для начинающих, чтобы раскрыть всю мощь языковых моделей

Это созданный список:

  1. Политика
  2. Виды спорта
  3. Технологии
  4. Бизнес
  5. Здоровье
  6. Развлечение

Затем я попросил ChatGPT включить связанные ключевые слова с каждой перечисленной категорией. Результат был следующим:

  1. Политика: политика, правительство, выборы, политика, законодательство, демократия
  2. Виды спорта: спорт, футбол, баскетбол, бейсбол, футбол, легкая атлетика
  3. Технологии: технологии, инновации, программное обеспечение, гаджеты, цифровые технологии, искусственный интеллект, кибербезопасность.
  4. Бизнес: бизнес, экономика, финансы, рынки, акции, предпринимательство, коммерция
  5. Здоровье: здоровье, хорошее самочувствие, медицина, здравоохранение, фитнес, медицина, питание
  6. Развлечения: развлечения, фильмы, музыка, знаменитости, телешоу, искусство, культура.

Вы даже можете попросить его отформатировать его в код, используя созданный вами пример, но вернемся к нашим шагам категоризации, используя наш список, мы можем использовать следующий код 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, подчеркивают согласованность модели при выполнении точных прогнозов по различным классам. Такие выдающиеся результаты подчеркивают эффективность шагов предварительной обработки и выбранного алгоритма машинного обучения, что делает эту модель отличным кандидатом для реального применения, особенно в задачах категоризации новостей.

Этот код представляет собой подробное пошаговое руководство по проекту классификации текста, включая предварительную обработку, токенизацию, определение категорий, категоризацию и построение/оценку модели.

Полный проект и дополнительные ресурсы можно найти здесь!

Поздравляем! Вы успешно завершили этот удобный для начинающих проект по очистке текста Python. Теперь у вас есть практический опыт очистки и обработки текстовых данных. Продолжайте исследовать, и вскоре вы будете готовы решать более сложные задачи анализа данных. Удачного кодирования! 🥳