目录
[(1)VarianceThreshold 低方差过滤特征选择](#(1)VarianceThreshold 低方差过滤特征选择)
[二、KNN算法 - 分类](#二、KNN算法 - 分类)
(2)K-折交叉验证 (K-fold Cross-Validation)
[(3)分层 K-折交叉验证 (Stratified K-fold Cross-Validation)](#(3)分层 K-折交叉验证 (Stratified K-fold Cross-Validation))
2、超参数搜索 (Hyperparameter Tuning)
[四、朴素贝叶斯 - 分类](#四、朴素贝叶斯 - 分类)
一、特征降维
特征降维是机器学习和数据科学中常用的一种技术,主要用于 减少数据集的特征维度,从而简化模型、提高计算效率、避免过拟合,并且有助于可视化高维数据。
1、特征选择
特征选择是一种通过筛选原始特征子集来降低维度的方法。它基于某些标准(如方差、相关性等)来保留对目标变量最有影响力的特征。
(1)VarianceThreshold 低方差过滤特征选择
-
原理:
-
方差是衡量一个特征分布离散程度的指标。如果某个特征的方差非常小,说明该特征的值几乎不变,对模型的 贡献很小,可以被移除。
-
VarianceThreshold
是一种简单的特征选择方法,它会移除方差低于指定阈值的特征。
-
-
特点:
-
简单易用,计算成本低。
-
适用于去除无意义或冗余的特征。
-
不考虑特征之间的相关性。
-
-
API 使用:
python
from sklearn.feature_selection import VarianceThreshold
# 自定义一个简单的二维矩阵,三条数据,每条数据四个特征
data = [[0, 2, 0, 3],
[0, 1, 4, 3],
[0, 1, 1, 3]]
# 创建转换器
transfer = VarianceThreshold(threshold=0.1)
data = transfer.fit_transform(data)
print(data)
结果展示:

(2)根据相关系数的特征选择
-
原理:
-
相关系数(如皮尔逊相关系数)用于衡量两个特征之间的线性相关性。如果两个特征高度相关,它们提供的信息重叠较多,可以选择其中一个特征而移除另一个。
-
可以通过计算特征矩阵的相关系数矩阵,然后根据阈值移除相关性较高的特征。
-
-
特点:
-
能够识别并移除冗余特征。
-
需要计算特征之间的相关性,计算成本较高。
-
仅适用于线性相关性。
-
-
API 使用(以pearsonr皮尔逊为例):
python
from scipy.stats import pearsonr
x = [1,2,3,4,5]
y = [2,3,5,7,9]
# 获取皮尔逊相关系数 statistic 为相关系数 p 为 概率值
p = pearsonr(x,y)
print(p)

statistic是相关系数,范围是[ -1 , 1 ],1表示完全正相关,-1表示完全负相关,0则表示不相关
p值是在原假设为真的前提下,观察到当前样本结果或更极端结果的概率。换句话说:
-
如果p值很小,说明在原假设为真的情况下,观察到当前数据的可能性非常低,因此我们有理由怀疑原假设的真实性,从而倾向于拒绝原假设。
-
如果p值较大,说明当前数据在原假设为真的情况下是合理的,因此我们没有足够的证据拒绝原假设。
2、主成分分析(PCA)
主成分分析 (Principal Component Analysis, PCA) 是一种线性降维技术,通过将数据投影到新的正交基上,保留尽可能多的原始数据方差。
(a) 原理
-
核心思想:
-
PCA 将原始特征空间转换为一个新的正交坐标系,新坐标轴称为"主成分"。
-
第一主成分是数据方差最大的方向,第二主成分是与第一主成分正交且方差次大的方向,依此类推。
-
通过选择前
k
个主成分,可以实现降维,同时保留大部分数据的方差。
-
-
数学表示:
-
假设原始数据矩阵为 X ,经过中心化处理后,PCA 的目标是最小化投影误差,即找到一组正交基向量 U ,使得投影后的数据方差最大化。
-
主成分可以通过数据的协方差矩阵的特征值分解得到。
-
(b) 步骤
-
数据预处理:对数据进行标准化(归一化),确保每个特征具有相同的尺度。
-
计算协方差矩阵:计算数据矩阵 X 的协方差矩阵 Σ 。
-
特征值分解:对协方差矩阵进行特征值分解,得到特征值 λ 和对应的特征向量 v 。
-
选择主成分:按照特征值从大到小排序,选择前 k 个特征向量作为新的基。
-
投影数据:将原始数据投影到新的基上,得到降维后的数据。
API 使用:
python
from sklearn.decomposition import PCA
import numpy as np
# 自定义一个随机的数据集
data = np.random.randint(0,10,(10,10))
print(data)
# 创建PCA,设置n_components=0.8,表示保留80%的信息
pca = PCA(n_components=0.8)
data = pca.fit_transform(data)
print(data)

n_components:
-
设置为小数: 如果将
n_components
设置为一个小于 1 的浮点数(如 0.95),则 PCA 会自动选择足够的主成分,保留95%的信息,使得累计解释的方差比例达到该阈值。 -
设置为整数: 如果将
n_components
设置为一个整数(如 2),则 PCA 会直接选择前k
(2)个特征。
二、KNN算法 - 分类
1、样本距离判断
KNN(K-Nearest Neighbors)算法的核心是基于样本之间的距离进行分类或回归。因此,距离度量的选择至关重要。
(1)欧氏距离
-
定义:在n维空间中,两个点的欧式距离为:
-
特点:最常用的距离度量,适用于连续型特征。
-
适用场景:数据分布较为均匀时效果较好。
(2)曼哈顿距离
-
定义:在n维空间中,两个点的曼哈顿距离为:
-
特点:计算简单,适合处理具有明显边界的数据。
-
适用场景:当特征之间相互独立时,曼哈顿距离表现更好。
2、KNN算法
KNN是一种基于实例的学习方法,其核心思想是"近朱者赤,近墨者黑"。具体步骤如下:
-
计算距离:对于一个待分类的样本,计算它与训练集中所有样本的距离。
-
选择最近的K个邻居:根据距离从小到大排序,选择距离最小的K个样本。
-
投票或加权平均:
-
分类任务:统计这K个邻居中出现次数最多的类别,作为待分类样本的类别。
-
回归任务:计算这K个邻居的目标值的平均值,作为待预测的值。
-


python
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import numpy as np
import joblib
# 加载数据集
iris = load_iris()
x = iris.data
y = iris.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=22)
# 特征工程标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 构建模型 设置模型参数 n_neighbors=5 意味最近5个样本
model = KNeighborsClassifier(n_neighbors=5)
model.fit(x_train, y_train)
# 评估
y_predict = model.predict(x_test)
print(y_predict)
print(y_test)
print(y_predict == y_test)
score = np.sum(y_predict == y_test)/len(y_test)
print(score)
# 模型保存
joblib.dump(model, '../src/model/KNN.pkl')
joblib.dump(transfer, '../src/model/transfer.pkl')
# 预测
x_new = [[4.2, 2.6, 1.8, 0.9],
[1.2, 1.1, 4.8, 0.9 ]]
x_new = transfer.transform(x_new)
y = model.predict(x_new)
print(y)
result = iris.target_names[y]
print(result)
3、KNN算法的缺点
-
对于 大规模数据集 ,计算量大,因为需要计算测试样本与所有训练样本的距离。
-
对于 高维数据,距离度量可能变得不那么有意义,这就是所谓的"维度灾难"
-
需要 选择合适的k值和距离度量,这可能需要一些实验和调整
三、模型选择与调优
1、交叉验证 (Cross-Validation)
交叉验证是一种评估机器学习模型性能的方法,主要用于 避免 过拟合 和 欠拟合,同时提供更可靠的模型泛化能力评估。以下是图中提到的几种交叉验证方法:
(1)保留交叉验证 (HoldOut)
-
定义:将数据集分为两部分:
-
训练集 (Training Set):用于训练模型。
-
测试集 (Test Set):用于评估模型的性能。
-
-
特点:
-
简单易用,实现方便。
-
测试集只使用一次,可能导致评估结果不稳定,尤其是当数据量较小时。
-
-
适用场景:数据量较大时,可以有效评估模型性能。
(2)K-折交叉验证 (K-fold Cross-Validation)
-
定义:将数据集划分为 K 个大小相近的子集(称为"折叠"),每次使用 K−1 个子集作为训练集,剩余的 1 个子集作为测试集,重复 K 次。
-
过程:
-
将数据集随机分成 K 个子集。
-
每次选择一个子集作为测试集,其余 K−1 个子集作为训练集。
-
重复 K 次,最终取 K 次评估结果的平均值作为最终性能指标。
-
-
优点:
-
每个样本都有机会被用作测试集,充分利用了数据。
-
评估结果更加稳定,尤其是当数据量有限时。
-
-
缺点:
- 计算成本较高,需要训练 K 次模型。
-
常见参数:
- K=5 或 K=10 是常见的选择。
(3)分层 K-折交叉验证 (Stratified K-fold Cross-Validation)
-
定义:在 K-折交叉验证的基础上,确保每个折叠中的类别分布与整体数据集的类别分布一致。
-
应用场景:适用于分类问题,尤其是类别不平衡的数据集。
-
特点:
-
避免某些折叠中缺少某些类别的样本,导致评估结果偏差。
-
更加公平地评估模型在不同类别上的表现。
-
-
示例: 如果数据集中有两类样本,比例为 80% 和 20%,分层 K-折交叉验证会确保每个折叠中也保持 80% 和 20% 的比例。
代码示例1:
python
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
x, y = load_iris(return_X_y=True)
# stratify=y表示按y的分布进行分层
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=22,shuffle=True, stratify=y)
print(y_test)
print(y_train)
结果展示:

代码示例2:
python
from sklearn.datasets import load_iris
from sklearn.model_selection import KFold,StratifiedKFold
x, y = load_iris(return_X_y=True)
# 创建K折交叉验证 n_splits=5 表示5折
k = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# 获取数据集的索引
re = k.split(x, y)
# 迭代 获取数据集
for train_index, test_index in re:
x_train, x_test = x[train_index], x[test_index]
y_train, y_test = y[train_index], y[test_index]
print(y_test)
结果展示:

2、超参数搜索 (Hyperparameter Tuning)
超参数是模型训练过程中需要手动设置的参数,例如学习率、正则化强度等。超参数搜索的目标是找到最优的超参数组合,以提高模型性能。
常用方法:
-
网格搜索 (Grid Search):
-
枚举所有可能的超参数组合,并逐一评估模型性能。
-
优点:全面搜索,能找到全局最优解。
-
缺点:计算成本高,尤其是超参数空间较大时。
-
scikit-learn
提供了GridSearchCV
实现网格搜索。
-
-
随机搜索 (Random Search):
-
在超参数空间中随机采样一组超参数进行评估。
-
优点:计算成本较低,适合高维超参数空间。
-
缺点:可能无法找到全局最优解。
-
scikit-learn
提供了RandomizedSearchCV
实现随机搜索。
-
-
贝叶斯优化 (Bayesian Optimization):
-
使用概率模型(如高斯过程)来指导超参数搜索,逐步缩小搜索范围。
-
优点:效率高,适合复杂超参数空间。
-
工具库:
hyperopt
、optuna
等。
-
我们这里以网格搜索为例:
示例代码:
python
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
x, y = load_iris(return_X_y=True)
# 创建模型
knn = KNeighborsClassifier()
# 设置超参数可选范围, cv = 5 ,5折交叉验证
model = GridSearchCV(knn, param_grid={'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, cv=5)
model.fit(x, y)
# 获取结果
print(model.best_params_)
# 获取准确率
print(model.best_score_)
# 获取模型
print(model.best_estimator_)
model.predict(x)
结果展示:

四、朴素贝叶斯 - 分类
朴素贝叶斯分类是一种基于概率论的简单而有效的分类方法,其核心思想是利用贝叶斯定理计算后验概率,并通过朴素假设(特征条件独立)简化计算。虽然其独立性假设在现实中可能不完全成立,但它在文本分类、垃圾邮件检测等任务中表现出色。
1、贝叶斯分类理论
贝叶斯分类是一种基于概率论的分类方法,其核心思想是利用贝叶斯定理来计算后验概率,并根据后验概率进行分类。
贝叶斯定理公式:

-
P(Y∣X) :后验概率,表示在观测到特征 X 的条件下,样本属于类别 Y 的概率。
-
P(X∣Y) :似然概率,表示在类别 Y 的条件下,观测到特征 X 的概率。
-
P(Y) :先验概率,表示类别 Y 出现的概率。
-
P(X) :证据概率,表示观测到特征 X 的概率(通常可以忽略,因为它是常数)。
贝叶斯分类的目标是找到使后验概率 P(Y∣X) 最大的类别 Y :

2、条件概率
条件概率是贝叶斯分类中的重要概念,用于描述在某个事件发生的情况下,另一个事件发生的概率。
定义:

其中:
-
P(A∣B) :在事件 B 发生的条件下,事件 A 发生的概率。
-
P(A∩B) :事件 A 和事件 B 同时发生的联合概率。
-
P(B) :事件 B 发生的概率。
在贝叶斯分类中,条件概率用于计算特征 X 在类别 Y 下出现的概率 P(X∣Y) 。
3、全概率公式
全概率公式是贝叶斯定理的基础之一,用于计算一个事件发生的总概率,通过将其分解为不同情况下的条件概率来实现。
公式:

其中:
-
P(X) :事件 X 发生的总概率。
-
P(X∣Yi) :在类别 Yi 的条件下,事件 X 发生的概率。
-
P(Yi) :类别 Yi 的先验概率。
全概率公式在贝叶斯分类中用于计算证据概率 P(X) ,但通常可以直接忽略,因为它是一个常数。
4、贝叶斯推断
贝叶斯推断是贝叶斯统计的核心思想,它通过结合先验知识和观测数据,更新对参数或模型的信念。
在贝叶斯分类中,贝叶斯推断的过程如下:
-
先验分布:根据已有知识,设定类别 Y 的先验概率 P(Y) 。
-
似然函数:根据观测数据 X ,计算特征在不同类别下的概率 P(X∣Y) 。
-
后验分布:利用贝叶斯定理,计算后验概率 P(Y∣X) 。
-
决策:选择使后验概率最大的类别作为预测结果。
5、朴素贝叶斯推断
朴素贝叶斯分类是一种简化版的贝叶斯分类,其核心假设是:特征之间是条件独立的,即在给定类别 Y 的条件下,特征 X1,X2,...,Xn 是相互独立的。
公式:



这意味着,在计算特征的联合概率时,可以将特征的概率相乘。
朴素贝叶斯分类的优点是计算简单、效率高,尽管其独立性假设在现实中可能不完全成立,但在许多实际问题中仍然表现良好。
6、拉普拉斯平滑系数
在朴素贝叶斯分类中,如果某个特征在训练集中没有出现过,会导致其概率为 0,从而影响整个分类结果。为了避免这种情况,引入了拉普拉斯平滑(Laplace Smoothing)。
拉普拉斯平滑公式: 假设特征 Xi 可以取 k 种不同的值,那么在计算特征 Xi 在类别 Y 下的概率时,使用以下公式:

-
count(Xi=v,Y) :特征 Xi 取值 v 且类别为 Y 的样本数量。
-
count(Y) :类别 Y 的样本总数。
-
α :平滑系数,通常取 1(拉普拉斯平滑)。
-
k :特征 Xi 的可能取值个数。
拉普拉斯平滑确保了即使某个特征没有出现在训练集中,其概率也不会为 0。
7、API
代码示例:
python
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
x, y = load_iris(return_X_y=True)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=22)
# 创建模型
model = MultinomialNB()
model.fit(x_train, y_train)# 训练模型(统计先验概率)
# 打印模型准确率
score = model.score(x_test, y_test)
print(score)
# 创建预测数据
x_new = [[5.1, 3.5, 1.4, 0.2],
[5.9, 3.0, 5.1, 1.8],
[5, 5, 4, 2]]
# 预测
y_predict = model.predict(x_new)
print(y_predict)
结果展示:

五、总结
通过这篇博客,大家应该能清晰地了解到特征降维的目的和技巧,在我们后面学习回归的时候都是用的这个思想。除此之外,大家可以通过这两个经典的分类算法来体会到机器学习中分类这一操作的大致内容!
希望这篇博客对你有所帮助!如果有任何问题,欢迎留言讨论。