-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhw_07_svertoka_viktor.py
153 lines (123 loc) · 7.88 KB
/
hw_07_svertoka_viktor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# -*- coding: utf-8 -*-
"""hw_07_svertoka_viktor.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/1vYx1EHclx9Xb8Zw2_BNZeaMMa9I7H7uu
"""
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import re
import string
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, classification_report
from nltk.corpus import stopwords
import nltk
from nltk.stem import WordNetLemmatizer
# Завантаження бібліотек NLTK
nltk.download('stopwords')
nltk.download('punkt')
nltk.download('wordnet')
# Завантаження даних
!wget -O SpamEmailClassificationDataset.zip https://github.com/goitacademy/NUMERICAL-PROGRAMMING-IN-PYTHON/blob/main/SpamEmailClassificationDataset.zip?raw=true
!unzip -o SpamEmailClassificationDataset.zip
# Завантаження CSV файлу
df = pd.read_csv('./SpamEmailClassificationDataset/combined_data.csv')
# Перевірка кількості класів
print("Кількість повідомлень по класах:")
print(df['label'].value_counts())
# Візуалізація розподілу класів
plt.figure(figsize=(6, 6))
sns.countplot(data=df, x='label', palette='coolwarm')
plt.title('Розподіл повідомлень за класами')
plt.xlabel('Клас')
plt.ylabel('Кількість')
plt.show()
# Фільтрація для класів із мінімальною кількістю записів >= 2
df = df.groupby('label').filter(lambda x: len(x) >= 2)
# Перевірка після фільтрації
print("Кількість повідомлень по класах після фільтрації:")
filtered_counts = df['label'].value_counts()
print(filtered_counts)
if len(filtered_counts) < 2 or min(filtered_counts) < 2:
raise ValueError("Недостатньо даних для обох класів після фільтрації.")
# Функція для попередньої обробки тексту
def preprocess_text(text):
# Перетворення на малі літери
text = text.lower()
# Видалення пунктуації та чисел
text = ''.join([char for char in text if char not in string.punctuation and not char.isdigit()])
# Видалення зайвих пробілів
text = ' '.join(text.split())
return text
# Функція для тренування моделі на спамових листах
def train_spam(data, vectorizer, model):
spam_data = data[data['label'] == 'spam']['text']
spam_data = spam_data.apply(preprocess_text)
X_spam = vectorizer.fit_transform(spam_data)
y_spam = ['spam'] * len(spam_data)
model.fit(X_spam, y_spam)
# Функція для тренування моделі на нормальних (не спамових) листах
def train_ham(data, vectorizer, model):
ham_data = data[data['label'] == 'ham']['text']
ham_data = ham_data.apply(preprocess_text)
X_ham = vectorizer.transform(ham_data)
y_ham = ['ham'] * len(ham_data)
model.partial_fit(X_ham, y_ham, classes=['ham', 'spam'])
# Функція для тестування нових листів
def test_emails(data, vectorizer, model):
test_data = data['text'].apply(preprocess_text)
X_test = vectorizer.transform(test_data)
y_test = data['label']
predictions = model.predict(X_test)
return classification_report(y_test, predictions)
# Попередня обробка тексту: лематизація та видалення стоп-слів
stop_words = set(stopwords.words("english"))
lemmatizer = WordNetLemmatizer()
def preprocess_advanced_text(text):
text = re.sub("[^a-zA-Z]", " ", text).lower() # Видалення небуквових символів
words = text.split()
words = [lemmatizer.lemmatize(word) for word in words if word not in stop_words] # Лематизація
words = list(set(words)) # Видалення повторів
return " ".join(words)
df["text"] = df["text"].apply(preprocess_advanced_text)
# Поділ даних на тренувальні та тестові набори
train, test = train_test_split(df, test_size=0.2, random_state=42, stratify=df["label"])
# Ініціалізація векторизатора TF-IDF
vectorizer = TfidfVectorizer(max_features=5000)
# Векторизація тексту
X_train = vectorizer.fit_transform(train["text"])
X_test = vectorizer.transform(test["text"])
# Мітки класів
y_train = train["label"]
y_test = test["label"]
# Тренування моделі наївного Баєса
nb_classifier = MultinomialNB()
nb_classifier.fit(X_train, y_train)
# Прогнозування
predictions = nb_classifier.predict(X_test)
# Оцінка моделі
accuracy = accuracy_score(y_test, predictions)
print(f"Точність класифікації: {accuracy * 100:.2f}%")
# Повний звіт
print("\nПовний звіт про класифікацію:")
print(classification_report(y_test, predictions))
# Аналіз найбільш важливих слів
feature_names = np.array(vectorizer.get_feature_names_out())
sorted_indices_spam = np.argsort(nb_classifier.feature_log_prob_[1]) # Спам
sorted_indices_ham = np.argsort(nb_classifier.feature_log_prob_[0]) # Хем
# Топ 10 найбільш впливових слів для спаму
print("\nТоп 10 слів, характерних для спаму:")
for idx in sorted_indices_spam[-10:]:
print(f"{feature_names[idx]}: {np.exp(nb_classifier.feature_log_prob_[1][idx]):.4f}")
# Топ 10 найбільш впливових слів для хему
print("\nТоп 10 слів, характерних для звичайних повідомлень:")
for idx in sorted_indices_ham[-10:]:
print(f"{feature_names[idx]}: {np.exp(nb_classifier.feature_log_prob_[0][idx]):.4f}")
print("\nВисновки:")
print("1. Модель показала високу точність класифікації (94.92%), що вказує на ефективність використаного наївного класифікатора Баєса для задачі фільтрації спаму. Однак, можливо, доцільно додати варіанти для покращення цієї метрики, наприклад, за допомогою коригування гіперпараметрів або використання додаткових методів передобробки даних.")
print("2. TF-IDF дійсно показав кращі результати порівняно з простим лематизатором для цієї задачі. Проте варто зазначити, що обидва підходи (лематизація і TF-IDF) можуть використовуватися в комбінації, щоб досягти ще кращих результатів. Наприклад, можна спробувати покращити обробку текстів через інші методи, як, наприклад, використання n-grams (bigrams або trigrams).")
print("3. Додавання n-grams або аналізу контексту може значно підвищити точність моделі, особливо якщо додавати функціонал, що враховує залежності між словами в повідомленнях. Крім того, можна застосувати інші методи векторизації текстів, наприклад Word2Vec або FastText, що дозволяють моделі навчатися на глибших семантичних зв’язках між словами.")