机器学习入门的核心是掌握经典算法的原理与实战,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大易过拟合 | 低(模型简单) |
| 核心适用场景 | 小样本分类 | 高维/非线性分类 | 文本/概率类分类 |
选型原则:
- 小样本、特征维度低 → 选KNN;
- 高维数据(文本/图像)、非线性 → 选SVM;
- 文本分类、追求速度、样本量大 → 选朴素贝叶斯。
六、常见问题与解决方法
- KNN准确率低 :
- 原因:未标准化、K值不合适、特征维度太高;
- 解决:标准化数据、调优K值、降维(PCA)。
- SVM训练慢 :
- 原因:样本量大、用rbf核函数;
- 解决:用线性核、降维、采样减少样本量。
- 朴素贝叶斯文本分类效果差 :
- 原因:未去除停用词、TF-IDF参数不合适;
- 解决:去除停用词、调整TF-IDF的
max_features(限制特征数)。
- 模型过拟合 :
- KNN:增大K值;
- SVM:减小C值、增大gamma;
- 朴素贝叶斯:增大alpha值。