7.6 KiB
7.6 KiB
In [ ]:
from pathlib import Path
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.model_selection import train_test_split
DATA_PATH = Path("data/SMSSpamCollection")
RANDOM_STATE = 42
if not DATA_PATH.exists():
raise FileNotFoundError(
"Missing data/SMSSpamCollection. Follow data/README.md to download the official dataset."
)
In [ ]:
tiny_messages = [
"free prize now",
"free meeting today",
"project meeting today",
]
# TODO 1: fit a CountVectorizer on tiny_messages and transform the messages.
count_vectorizer = None
tiny_bow = None
# TODO 2: create a DataFrame whose columns are the learned feature names.
tiny_bow_df = None
tiny_bow_df
In [ ]:
df = pd.read_csv(DATA_PATH, sep="\t", header=None, names=["label", "message"])
df["label"] = df["label"].astype("string").str.strip().str.lower()
df["message"] = df["message"].astype("string").str.strip()
df = df.dropna(subset=["label", "message"])
df = df[df["label"].isin(["ham", "spam"]) & df["message"].ne("")]
conflicts = df.groupby("message")["label"].nunique()
conflict_texts = conflicts[conflicts.gt(1)].index
df = df[~df["message"].isin(conflict_texts)]
df = df.drop_duplicates(subset=["label", "message"]).reset_index(drop=True)
X = df["message"]
y = df["label"].map({"ham": 0, "spam": 1}).astype(int)
print("Clean messages:", len(df))
In [ ]:
# TODO 3: split message and target into 80% training and 20% test data.
# Use random_state=42 and stratify=y.
X_train, X_test, y_train, y_test = None, None, None, None
# TODO 4: fit TfidfVectorizer on X_train only and transform X_test.
tfidf_vectorizer = None
X_train_tfidf = None
X_test_tfidf = None
print("Training matrix shape:", None)
print("Test matrix shape:", None)
print("Training density:", None)
In [ ]:
# TODO 5: calculate each term's mean TF-IDF weight across training messages.
mean_tfidf = None
# TODO 6: build a descending Series and keep the 15 highest-weight terms.
top_terms = None
top_terms
In [ ]:
# TODO 7: fit a second TF-IDF vectorizer with unigrams and bigrams.
ngram_vectorizer = None
X_train_ngram = None
print("Unigram features:", None)
print("Unigram + bigram features:", None)
print("Example bigrams:", None)
In [ ]:
assert tiny_bow.shape == (3, len(count_vectorizer.get_feature_names_out()))
assert tiny_bow_df.loc["message_1", "free"] == 1
assert len(X_train) + len(X_test) == len(df)
assert X_train_tfidf.shape[0] == len(X_train)
assert X_test_tfidf.shape[0] == len(X_test)
assert X_train_tfidf.shape[1] == X_test_tfidf.shape[1]
assert X_train_tfidf.nnz < X_train_tfidf.shape[0] * X_train_tfidf.shape[1]
assert X_train_ngram.shape[1] >= X_train_tfidf.shape[1]
assert len(top_terms) == 15
print("✓ Lab 2 completed")