问题解决策略基础算法实现训练1
2026/4/10 4:22:30
第一次做“垃圾邮件过滤”毕设,很多同学把 80% 时间花在“调包”上,结果答辩时被老师一句“为什么把‘FREE’和‘free’当成两个词?”问得哑口无言。我总结了四个高频误区,提前打个预防针:
CountVectorizer完就甩给模型,结果测试集里一旦出现训练集没见过的词,概率乘积瞬间变 0,整条邮件被判错。我把 SVM、逻辑回归、Random Forest 都试了一遍,结论写在下面,时间紧的同学直接抄作业即可。
一句话:毕设周期 8 周,电脑只有 8 G 内存,朴素贝叶斯是最省心的“保底方案”。
下面用 SpamAssassin 公开数据集(公版 6000 封、垃圾/正常各半)为例,手把手过一遍。每一步我都拆成独立函数,方便你后期换特征、换模型。
import pandas as pd, os, email, re, string from pathlib import Path def load_spamassassin(path): """返回 DataFrame:columns=['text','label'],label 1=spam, 0=ham""" rows = [] for label, sub in [('spam', 1), ('ham', 0)]: for file in (Path(path)/label).rglob('*'): if file.is_file(): text = file.read_text(encoding='utf-8', errors='ignore') rows.append({'text': text, 'label': sub}) return pd.DataFrame(rows)def normalize(text): text = text.lower() text = re.sub(r'<[^>]+>', ' ', text) # 去 HTML 标签 text = re.sub(r'http\S+|www\S+', ' URL ', text) text = text.translate(str.maketrans('', '', string.punctuation)) text = re.sub(r'\d+', ' NUM ', text) # 数字统一成 NUM return ' '.join(text.split()) # 去多余空白from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split def make_vectorizer(df, min_df=2, ngram_range=(1,2)): vect = TfidfVectorizer(min_df=min_df, stop_words='english', preprocessor=normalize, ngram_range=ngram_range) X = vect.fit_transform(df['text']) return X, vectfrom sklearn.naive_bayes import MultinomialNB from sklearn.pipeline import Pipeline from sklearn.metrics import f1_score, classification_report def build_model(): return Pipeline([ ('tfidf', TfidfVectorizer(min_df=2, preprocessor=normalize)), ('nb', MultinomialNB(alpha=1.0)) # alpha 就是拉普拉斯平滑 λ ]) def train_evaluate(df): X_train, X_test, y_train, y_test = train_test_split( df['text'], df['label'], test_size=0.2, random_state=42, stratify=df['label']) model = build_model() model.fit(X_train, y_train) pred = model.predict(X_test) print(classification_report(y_test, pred, digits=3)) return modeldef predict_raw_email(raw: str, model) -> int: return model.predict([raw])[0]partial_fit接口 3 行代码就能实现,记得把alpha调小一点(0.01),否则旧知识被稀释。max_features=30000,再加 L2 等价于调小alpha,交叉验证里一起搜就行。Pipeline能强制帮你隔离。random_state、numpy、sklearn、pandas版本写进 README,附requirements.txt;答辩老师复现不出结果,直接扣印象分。FastText预训练词向量做平均池化,再和 TF-IDF 拼接,输入给逻辑回归,对比实验章节秒变“深度学习结合传统特征”。StratifiedKFold=5调alpha+max_features+ngram_range,画热力图,老师一看就知道你做过网格搜索。partial_fit更新,把 F1 曲线画 30 天,论文“在线学习”章节就有了。整个毕设做下来,最大的感受是:朴素贝叶斯虽然简单,却把“概率 + 特征工程”的套路展现得淋漓尽致。把数据洗干净、平滑处理好、评估看全了,就能跑赢很多 fancy 模型。建议你先把上面的 baseline 跑通,再一点点替换特征、加交叉验证、写在线学习脚本,边做边记录,每周 git commit 一次,答辩时打开 GitHub 时间线,老师自然能看到你的成长。动手改起来,下一封被拦截的垃圾邮件,也许就藏着你的毕业勋章。