Spam — классификация текста (TF-IDF)
Классификация SMS: спам (1) или нет (0). Baseline — TF-IDF + sklearn; для сравнения с нейросетями — практикум тональности.
Зависимости: pip install pandas scikit-learn
1. Загрузка
import pandas as pd
url = "https://raw.githubusercontent.com/justmarkham/pycon-2016-tutorial/master/data/sms.tsv"
df = pd.read_csv(url, sep="\t", header=None, names=["label", "message"])
df["target"] = (df["label"] == "spam").astype(int)
print(df["target"].value_counts())
print(df.head(2))
Аналог задачи на Kaggle — spam or not spam.
2. Train / test
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
df["message"], df["target"], test_size=0.2, random_state=42, stratify=df["target"]
)
3. TF-IDF + логистическая регрессия
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
pipe = Pipeline([
("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))),
("clf", LogisticRegression(max_iter=1000)),
])
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
print(classification_report(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
ngram_range=(1, 2) добавляет словосочетания («free entry», «click here»).
4. Сравнение с CountVectorizer (мешок слов)
from sklearn.feature_extraction.text import CountVectorizer
bow_pipe = Pipeline([
("bow", CountVectorizer(max_features=3000)),
("clf", LogisticRegression(max_iter=1000)),
])
bow_pipe.fit(X_train, y_train)
print("BoW accuracy:", bow_pipe.score(X_test, y_test))
print("TF-IDF accuracy:", pipe.score(X_test, y_test))
TF-IDF обычно лучше подавляет частые «пустые» слова.
5. Дерево решений на тех же признаках
from sklearn.tree import DecisionTreeClassifier
tree_pipe = Pipeline([
("tfidf", TfidfVectorizer(max_features=2000)),
("clf", DecisionTreeClassifier(max_depth=20, random_state=42)),
])
tree_pipe.fit(X_train, y_train)
print("Tree accuracy:", tree_pipe.score(X_test, y_test))
На разреженных текстовых матрицах чаще выигрывает логистическая регрессия или линейный SVM.
6. Проверка на своём тексте
samples = [
"Win a free iPhone now!!! click here",
"See you at the meeting tomorrow",
]
for text, pred in zip(samples, pipe.predict(samples)):
print("spam" if pred else "ham", "→", text[:50])
Самопроверка: обучите модель на датасете эмоций (6 классов): сначала LabelEncoder для y, затем TfidfVectorizer + LogisticRegression(multinomial).
Дальше
- Текст в Keras — TextVectorization — нейросетевой текст
- Трансформеры и NLP