Python机器学习三大经典算法:KNN、SVM、朴素贝叶斯

机器学习入门的核心是掌握经典算法的原理与实战,K近邻(KNN)、支持向量机(SVM)、朴素贝叶斯作为分类任务的三大基础算法,覆盖了"基于距离""基于超平面""基于概率"三种核心思路,是入门机器学习的必学内容。

一、核心前置知识与环境准备

1. 算法核心定位(快速选对算法)

算法 核心思想 优势 劣势 适用场景
KNN(K近邻) 近朱者赤:按最近邻样本分类 原理简单、无需训练、适合多分类 高维数据慢、对异常值敏感 小样本分类、推荐系统、数据补全
SVM(支持向量机) 找最优超平面分隔样本 高维数据表现好、泛化能力强 大样本训练慢、参数调优复杂 文本分类、图像识别、特征维度高的场景
朴素贝叶斯 基于概率公式(贝叶斯)分类 训练速度极快、适合文本数据 假设特征独立(实际难满足) 垃圾邮件过滤、文本分类、情感分析

2. 环境安装(Scikit-learn核心库)

bash 复制代码
# 安装核心库(Python 3.8~3.10版本最佳)
pip install scikit-learn numpy pandas matplotlib
  • Scikit-learn:封装三大算法的核心API,调用统一;
  • NumPy:处理数值计算,支撑算法底层;
  • Matplotlib:可视化数据分布和分类效果。

3. 验证安装

python 复制代码
import sklearn
import numpy as np
import matplotlib.pyplot as plt
print("Scikit-learn版本:", sklearn.__version__)  # 输出≥1.0.0即可
print("环境准备完成!")

二、K近邻(KNN)算法:最简单的"邻居投票"分类

1. 算法原理(通俗理解)

KNN的核心逻辑:"物以类聚,人以群分"------给一个新样本,找它最近的K个样本(邻居),这K个邻居中占比最多的类别,就是新样本的类别。

  • K值是核心参数:K太小易过拟合(受异常值影响),K太大易欠拟合(分类模糊)。

2. 实战:鸢尾花品种分类(KNN实现)

以经典的鸢尾花数据集为例,实现KNN分类:

python 复制代码
# 步骤1:加载数据集并划分训练集/测试集
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 加载数据(特征:花萼/花瓣的长宽,标签:3类鸢尾花)
iris = load_iris()
X = iris.data  # 特征矩阵
y = iris.target  # 标签向量

# 划分数据集:训练集70%,测试集30%
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42  # random_state保证结果可复现
)

# 步骤2:数据标准化(KNN基于距离,必须标准化)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 步骤3:初始化并训练KNN模型
from sklearn.neighbors import KNeighborsClassifier

# 初始化模型:K=5(常用默认值)
knn_model = KNeighborsClassifier(n_neighbors=5)
# KNN无需"训练",仅存储训练集数据(预测时计算距离)
knn_model.fit(X_train_scaled, y_train)

# 步骤4:模型预测与评估
from sklearn.metrics import accuracy_score, classification_report

# 预测测试集
y_pred = knn_model.predict(X_test_scaled)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print("KNN模型准确率:", accuracy)  # 鸢尾花数据集上≈0.98
# 详细分类报告(精确率、召回率、F1值)
print("\n分类报告:")
print(classification_report(y_test, y_pred))

# 步骤5:K值调优(找到最优K)
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]  # 中文显示

# 测试K=1到20的准确率
k_range = range(1, 21)
accuracy_list = []
for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train_scaled, y_train)
    accuracy_list.append(accuracy_score(y_test, knn.predict(X_test_scaled)))

# 可视化K值与准确率关系
plt.figure(figsize=(10, 6))
plt.plot(k_range, accuracy_list, marker='o', color='blue')
plt.xlabel('K值(邻居数量)')
plt.ylabel('准确率')
plt.title('KNN算法K值调优')
plt.grid(linestyle='--', alpha=0.7)
plt.savefig('knn_k_tuning.png')
plt.close()

3. KNN关键技巧

  • 标准化必做 :特征单位不同(如花萼长度cm,花瓣宽度mm)会导致距离计算偏差,必须用StandardScaler标准化;
  • K值选择:通过遍历测试(如K=1~20)找到准确率最高的K,或用"肘部法则"(准确率提升放缓的点);
  • 距离度量 :默认用欧氏距离,高维数据可尝试曼哈顿距离(metric='manhattan')。

三、支持向量机(SVM):找"最优分隔线"的分类器

1. 算法原理(通俗理解)

SVM的核心是在特征空间中找一条"最优超平面",将不同类别的样本分隔开,且超平面到两边样本的"间隔"最大------间隔越大,模型泛化能力越强。

  • 线性可分:直接找线性超平面;
  • 线性不可分:通过"核函数"将数据映射到高维空间,实现线性分隔(常用核函数:高斯核rbf、线性核linear)。

2. 实战:手写数字分类(SVM实现)

以手写数字数据集为例,实现SVM分类(适合高维特征场景):

python 复制代码
# 步骤1:加载手写数字数据集
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split

# 加载数据(8x8像素的手写数字,共10类)
digits = load_digits()
X = digits.data  # 特征:64维(8*8)
y = digits.target  # 标签:0-9

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

# 步骤2:数据标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 步骤3:初始化并训练SVM模型
from sklearn.svm import SVC

# 初始化模型:核函数rbf(处理非线性数据),C=1.0(正则化系数)
svm_model = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
# 训练模型(SVM训练耗时比KNN长,尤其大样本)
svm_model.fit(X_train_scaled, y_train)

# 步骤4:模型评估
from sklearn.metrics import accuracy_score, confusion_matrix

y_pred = svm_model.predict(X_test_scaled)
accuracy = accuracy_score(y_test, y_pred)
print("SVM模型准确率:", accuracy)  # 手写数字数据集上≈0.98

# 混淆矩阵(查看数字分类错误情况)
cm = confusion_matrix(y_test, y_pred)
print("\n混淆矩阵:")
print(cm)

# 步骤5:SVM参数调优(网格搜索找最优C和gamma)
from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {
    'C': [0.1, 1, 10],  # 正则化系数:越大容错率越低
    'gamma': ['scale', 'auto', 0.001, 0.01],  # 核函数系数
    'kernel': ['rbf', 'linear']
}

# 网格搜索(5折交叉验证)
grid_search = GridSearchCV(SVC(random_state=42), param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train_scaled, y_train)

# 输出最优参数
print("\nSVM最优参数:", grid_search.best_params_)
print("交叉验证最优准确率:", grid_search.best_score_)

# 用最优模型预测
best_svm = grid_search.best_estimator_
print("最优模型测试集准确率:", accuracy_score(y_test, best_svm.predict(X_test_scaled)))

3. SVM关键技巧

  • 核函数选择 :线性数据用linear(速度快),非线性数据用rbf(效果好);
  • 参数调优:C(正则化)越大,模型越"硬"(易过拟合);gamma越大,核函数影响范围越小(易过拟合);
  • 样本量限制 :SVM适合中小样本(万级以内),大样本建议用SGDClassifier(随机梯度下降版SVM)。

四、朴素贝叶斯:基于概率的"文本分类神器"

1. 算法原理(通俗理解)

朴素贝叶斯基于"贝叶斯公式",核心假设是"特征之间相互独立"(朴素性),通过计算样本属于每个类别的概率,选择概率最大的类别作为预测结果。

  • 文本分类中,特征是"单词出现次数",通过词频计算概率,速度极快。

2. 实战:垃圾邮件分类(朴素贝叶斯实现)

以经典的20NewsGroups文本数据集为例,实现朴素贝叶斯文本分类:

python 复制代码
# 步骤1:加载文本数据集并预处理
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer

# 加载数据集(仅选4个类别,简化任务)
categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med']
# 加载训练集和测试集
train_data = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)
test_data = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)

# 文本特征提取:TF-IDF(将文本转为数值特征)
tfidf = TfidfVectorizer(stop_words='english')  # 去除英文停用词(the/a/an等)
X_train = tfidf.fit_transform(train_data.data)
X_test = tfidf.transform(test_data.data)
y_train = train_data.target
y_test = test_data.target

# 步骤2:初始化并训练朴素贝叶斯模型
from sklearn.naive_bayes import MultinomialNB

# 多项式朴素贝叶斯(适合文本分类,处理离散特征)
nb_model = MultinomialNB(alpha=1.0)  # alpha:平滑系数,避免概率为0
nb_model.fit(X_train, y_train)

# 步骤3:模型评估
from sklearn.metrics import accuracy_score, classification_report

y_pred = nb_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("朴素贝叶斯模型准确率:", accuracy)  # 文本数据集上≈0.84

# 详细分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=train_data.target_names))

# 步骤4:实战预测新文本
def predict_text(text):
    # 文本转为TF-IDF特征
    text_tfidf = tfidf.transform([text])
    # 预测类别
    pred = nb_model.predict(text_tfidf)[0]
    # 返回类别名称
    return train_data.target_names[pred]

# 测试预测
test_text1 = "GPU performance for 3D rendering"  # 计算机图形学
test_text2 = "Medical treatment for diabetes"  # 医学
print("\n文本1分类结果:", predict_text(test_text1))
print("文本2分类结果:", predict_text(test_text2))

3. 朴素贝叶斯关键技巧

  • 特征提取:文本分类必须用TF-IDF/词袋模型将文本转为数值特征;
  • 平滑系数alpha:alpha越大,平滑越强(避免因某个单词未出现导致概率为0);
  • 适用场景:优先用于文本/序列数据,不适合特征高度相关的场景(违背"朴素"假设)。

五、三大算法对比与选型指南

维度 KNN SVM 朴素贝叶斯
训练速度 无训练(极快) 中-慢(尤其大样本) 极快(概率计算)
预测速度 慢(计算距离) 极快
高维数据 效果差(维度灾难) 效果好 效果好(文本高维)
超参数调优 仅K值 C、gamma、核函数 仅alpha
过拟合风险 K小易过拟合 C大易过拟合 低(模型简单)
核心适用场景 小样本分类 高维/非线性分类 文本/概率类分类

选型原则:

  1. 小样本、特征维度低 → 选KNN;
  2. 高维数据(文本/图像)、非线性 → 选SVM;
  3. 文本分类、追求速度、样本量大 → 选朴素贝叶斯。

六、常见问题与解决方法

  1. KNN准确率低
    • 原因:未标准化、K值不合适、特征维度太高;
    • 解决:标准化数据、调优K值、降维(PCA)。
  2. SVM训练慢
    • 原因:样本量大、用rbf核函数;
    • 解决:用线性核、降维、采样减少样本量。
  3. 朴素贝叶斯文本分类效果差
    • 原因:未去除停用词、TF-IDF参数不合适;
    • 解决:去除停用词、调整TF-IDF的max_features(限制特征数)。
  4. 模型过拟合
    • KNN:增大K值;
    • SVM:减小C值、增大gamma;
    • 朴素贝叶斯:增大alpha值。
相关推荐
盼哥PyAI实验室2 小时前
Python 爬虫实战:从 Ajax 到 POST 请求,完整爬取汉堡王门店与产品数据
爬虫·python·ajax
TheSumSt2 小时前
Python丨课程笔记Part2:方法论进阶部分
开发语言·笔记·python
知远同学2 小时前
使用virtualenv 和 anaconda 创建管理虚拟环境的区别
python
山沐与山2 小时前
【设计模式】Python状态模式:从入门到实战
python·设计模式·状态模式
Swizard2 小时前
别让你的密钥在互联网上“裸奔”!用 python-dotenv 优雅管理你的敏感配置
python
无心水2 小时前
【Stable Diffusion 3.5 FP8】8、生产级保障:Stable Diffusion 3.5 FP8 伦理安全与问题排查
人工智能·python·安全·docker·stable diffusion·ai镜像开发·镜像实战开发
深蓝海拓3 小时前
PySide6从0开始学习的笔记(十八) MVC(Model-View-Controller)模式的图形渲染体系
笔记·python·qt·学习·pyqt
一招定胜负3 小时前
杂记:cv2.imshow显示中文乱码解决过程
python·opencv
唐叔在学习3 小时前
Pyinstaller进阶之构建管理大杀器-SPEC文件
后端·python·程序员