前言
提醒:
文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。
其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展及意见建议,欢迎评论区讨论交流。
分类与回归算法
机器学习中的分类与回归算法是两种主要的监督学习任务,它们分别用于解决不同类型的问题。以下是这两种算法的总结:
分类算法:
分类算法用于将数据分成不同的类别,适用于输出为离散标签的问题。常见的分类算法包括:
- 逻辑回归:使用逻辑函数来估计概率,用于二分类问题,也可以扩展到多分类问题。
- 支持向量机(SVM):通过找到最优的决策边界来最大化样本的分类准确率,适用于高维数据。
- 决策树:通过树结构来进行决策,每个节点代表一个特征的选择,叶子节点代表分类结果。
- 随机森林:由多个决策树组成的集成学习方法,通过投票来决定最终分类结果。
- 梯度提升决策树(GBDT):通过构建和结合多个弱学习器来形成强学习器,适用于分类和回归问题。
- 朴素贝叶斯:基于贝叶斯定理,假设特征之间相互独立,适用于文本分类等场景。
- K近邻(KNN):根据样本之间的距离进行分类,适用于小规模数据集。
- 神经网络:通过多层感知机学习数据的复杂模式,适用于图像、语音等复杂分类问题。
回归算法:
回归算法用于预测连续数值输出,适用于输出为连续变量的问题。常见的回归算法包括:
- 线性回归:通过拟合一条直线来预测目标变量的值,是最简单的回归方法。
- 岭回归:线性回归的扩展,通过引入L2正则化项来防止过拟合。
- Lasso回归:线性回归的另一种扩展,通过引入L1正则化项来进行特征选择。
- 弹性网回归:结合了岭回归和Lasso回归,同时引入L1和L2正则化项。
- 决策树回归:使用决策树结构来进行回归预测,适用于非线性关系。
- 随机森林回归:由多个决策树组成的集成学习方法,通过平均来决定最终回归结果。
- 梯度提升决策树回归(GBDT回归):通过构建和结合多个弱学习器来形成强学习器,适用于回归问题。
- 支持向量回归(SVR):支持向量机在回归问题上的应用,通过找到最优的决策边界来最大化样本的回归准确率。
- 神经网络回归:通过多层感知机学习数据的复杂模式,适用于复杂的回归问题。
分类与回归算法的比较:
- 输出类型:分类算法输出离散标签,回归算法输出连续数值。
- 评估指标:分类算法常用准确率、召回率、F1分数等指标,回归算法常用均方误差(MSE)、均方根误差(RMSE)等指标。
- 问题类型:分类算法适用于类别预测问题,如垃圾邮件检测;回归算法适用于数值预测问题,如房价预测。 在实际应用中,选择分类还是回归算法取决于问题的性质和需求。有时,可以将回归问题转化为分类问题,或者将分类问题转化为回归问题,具体取决于问题的特点和目标。
K近邻(KNN)
KNN分类算法
KNN分类算法的步骤:
-
选择K: 确定最近邻的数量。选择过小的K可能会使算法对噪声过于敏感,而选择过大的K可能会平滑掉重要的模式。选择合适的K至关重要。
-
计算距离: 确定如何测量数据点之间的距离。常用的距离度量包括欧氏距离、曼哈顿距离和余弦相似性。使用欧氏距离时:
d ( x ′ , x i ) = ∑ j = 1 m ( x j ′ − x i , j ) 2 d(x', x_i) = \sqrt{\sum_{j=1}^{m} (x'_j - x_{i,j})^2} d(x′,xi)=j=1∑m(xj′−xi,j)2
其中 m m m 是特征的数量。 -
找到K个最近邻: 根据选定的距离度量,检索K个最近的点 N K = { ( x i 1 , y i 1 ) , … , ( x i K , y i K ) } N_K = \{ (x_{i_1}, y_{i_1}), \dots, (x_{i_K}, y_{i_K}) \} NK={(xi1,yi1),…,(xiK,yiK)}。
-
多数投票: 在 N K N_K NK 中统计每个类别的出现次数。具有最高频率的类别 y ^ \hat{y} y^ 将被分配给 x ′ x' x′。数学上:
y ^ = argmax c { ∑ k = 1 K δ ( y i k , c ) } \hat{y} = \text{argmax}_{c} \left\{ \sum_{k=1}^{K} \delta(y_{i_k}, c) \right\} y^=argmaxc{k=1∑Kδ(yik,c)}
其中 δ \delta δ 是克罗内克δ函数,当 y i k = c y_{i_k} = c yik=c 时为1,否则为0。 -
返回预测: 预测完成。
KNN的变体和改进
KNN的变体和改进:
-
加权KNN: 不同的邻居可以根据它们的距离对分类进行不同的加权。例如,赋予较近的邻居更高的权重:
y ^ = argmax c { ∑ k = 1 K δ ( y i k , c ) d ( x ′ , x i k ) } \hat{y} = \text{argmax}_{c} \left\{ \sum_{k=1}^{K} \frac{\delta(y_{i_k}, c)}{d(x', x_{i_k})} \right\} y^=argmaxc{k=1∑Kd(x′,xik)δ(yik,c)} -
自适应K: 不是全局固定K,而是根据局部数据密度自适应地选择K。
-
特征加权距离度量: 根据特征的重要性对它们进行加权。
实施中的挑战:
-
选择K: 通过交叉验证来选择最优的K。将数据分成几折,对每个 K 值进行训练和验证,选择验证性能最好的 K。
-
距离度量: 根据数据选择合适的距离度量。有时需要进行数据归一化以避免某些特征主导距离计算。
-
计算效率: 对于大型数据集,计算所有距离可能是计算密集型的。使用数据结构如kd树或近似最近邻方法可以提高效率。
实际示例
示例:
假设我们有一个数据集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x 6 , y 6 ) } D = \{ (x_1, y_1), (x_2, y_2), \dots, (x_6, y_6) \} D={(x1,y1),(x2,y2),…,(x6,y6)},具体如下:
- x 1 = ( 1 , 2 ) , y 1 = A x_1 = (1, 2), y_1 = A x1=(1,2),y1=A
- x 2 = ( 2 , 3 ) , y 2 = A x_2 = (2, 3), y_2 = A x2=(2,3),y2=A
- x 3 = ( 3 , 3 ) , y 3 = B x_3 = (3, 3), y_3 = B x3=(3,3),y3=B
- x 4 = ( 6 , 2 ) , y 4 = B x_4 = (6, 2), y_4 = B x4=(6,2),y4=B
- x 5 = ( 7 , 1 ) , y 5 = C x_5 = (7, 1), y_5 = C x5=(7,1),y5=C
- x 6 = ( 8 , 1 ) , y 6 = C x_6 = (8, 1), y_6 = C x6=(8,1),y6=C
需要对 x ′ = ( 4 , 2 ) x' = (4, 2) x′=(4,2) 进行分类,假设 K = 3 K = 3 K=3。
计算距离:
采用欧氏距离公式:
d
(
x
′
,
x
i
)
=
(
4
−
x
i
,
1
)
2
+
(
2
−
x
i
,
2
)
2
d(x', x_i) = \sqrt{(4 - x_{i,1})^2 + (2 - x_{i,2})^2}
d(x′,xi)=(4−xi,1)2+(2−xi,2)2
具体计算如下:
- d ( x ′ , x 1 ) = ( 4 − 1 ) 2 + ( 2 − 2 ) 2 = 3 d(x', x_1) = \sqrt{(4-1)^2 + (2-2)^2} = 3 d(x′,x1)=(4−1)2+(2−2)2=3
- d ( x ′ , x 2 ) = ( 4 − 2 ) 2 + ( 2 − 3 ) 2 = 5 ≈ 2.236 d(x', x_2) = \sqrt{(4-2)^2 + (2-3)^2} = \sqrt{5} \approx 2.236 d(x′,x2)=(4−2)2+(2−3)2=5≈2.236
- d ( x ′ , x 3 ) = ( 4 − 3 ) 2 + ( 2 − 3 ) 2 = 2 ≈ 1.414 d(x', x_3) = \sqrt{(4-3)^2 + (2-3)^2} = \sqrt{2} \approx 1.414 d(x′,x3)=(4−3)2+(2−3)2=2≈1.414
- d ( x ′ , x 4 ) = ( 4 − 6 ) 2 + ( 2 − 2 ) 2 = 2 d(x', x_4) = \sqrt{(4-6)^2 + (2-2)^2} = 2 d(x′,x4)=(4−6)2+(2−2)2=2
- d ( x ′ , x 5 ) = ( 4 − 7 ) 2 + ( 2 − 1 ) 2 = 10 ≈ 3.162 d(x', x_5) = \sqrt{(4-7)^2 + (2-1)^2} = \sqrt{10} \approx 3.162 d(x′,x5)=(4−7)2+(2−1)2=10≈3.162
- d ( x ′ , x 6 ) = ( 4 − 8 ) 2 + ( 2 − 1 ) 2 = 17 ≈ 4.123 d(x', x_6) = \sqrt{(4-8)^2 + (2-1)^2} = \sqrt{17} \approx 4.123 d(x′,x6)=(4−8)2+(2−1)2=17≈4.123
找到3个最近邻:
将距离从小到大排序:
- x 3 x_3 x3:≈1.414
- x 2 x_2 x2:≈2.236
- x 4 x_4 x4:2
因此,3个最近邻分别是 x 3 x_3 x3, x 2 x_2 x2,和 x 4 x_4 x4。
多数投票:
- x 3 x_3 x3:B
- x 2 x_2 x2:A
- x 4 x_4 x4:B
统计频率:
- B:2
- A:1
因此, y ^ = B \hat{y} = B y^=B。
经典应用案例
更复杂的应用:
MNIST数据集:
- 数据集描述: 包含 70,000 个手写数字的灰度图像(0-9),每个图像大小为 28x28 像素,flatten 后结果为 784 个特征。
- 挑战:
- 高维数据:每个样本有 784 个特征,计算密集型。
- 大型数据集:70,000 个样本,使用标准方法计算距离耗时较长。
- 距离度量:选择适合图像数据的距离度量。
- 方法:
- 降维: 应用 PCA 将维数降低到更易管理的数量,例如 50 个主成分。
- 优化 KNN 实现: 使用基于 kd 树的 KNN 实现,可以高效处理大量数据点。
- 选择 K: 通过交叉验证,确定最优的 K 值。例如,从 K=1, 3, 5, 7, 9 中选择。
- 距离度量: 尝试不同的距离度量,如欧氏距离和曼哈顿距离,以查看哪种在该数据集上表现更好。
- 性能评估: 在测试集上评估性能,使用准确率、召回率、精确度和 F1 分数。
实施步骤:
- 加载数据: 将 MNIST 数据集加载到训练集和测试集中。
- 预处理:
- 将图像 flatten 为 1D 数组。
- 归一化像素值,范围为 0-1。
- 应用 PCA 降维到 50 个成分。
- 初始化 KNN: 使用基于 kd 树的 KNN 实现,以提高效率。
- 交叉验证: 对每个 K 候选值,进行交叉验证以评估性能并选择最佳 K。
- 训练 KNN: 使用最佳 K 在整个训练集上训练 KNN。
- 预测: 使用训练的 KNN 对测试集进行预测。
- 评估: 计算并报告性能指标。
算法实现
K近邻(KNN)手动实现
import numpy as np
import matplotlib.pyplot as plt
# 定义欧氏距离函数
def euclidean_distance(x1, x2):
return np.sqrt(np.sum((x1 - x2) ** 2))
# 定义 KNN 分类器类
class KNN:
def __init__(self, k=3):
self.k = k
def fit(self, X, y):
self.X_train = X
self.y_train = y
def predict(self, X):
y_pred = [self._predict(x) for x in X]
return np.array(y_pred)
def _predict(self, x):
# 计算距离
distances = [euclidean_distance(x, x_train) for x_train in self.X_train]
# 获取距离最近的 K 个样本的索引
k_indices = np.argsort(distances)[:self.k]
# 获取这些样本的标签
k_nearest_labels = [self.y_train[i] for i in k_indices]
# 统计各类别的数量
most_common = np.bincount(k_nearest_labels).argmax()
return most_common
# 生成示例数据
X_train = np.array([[1, 2], [2, 3], [3, 1], [6, 5], [7, 7], [8, 6]])
y_train = np.array([0, 0, 0, 1, 1, 1])
# 创建 KNN 分类器实例
knn = KNN(k=3)
# 拟合数据
knn.fit(X_train, y_train)
# 待分类的样本
X_test = np.array([[3, 2], [7, 6]])
# 进行预测
predictions = knn.predict(X_test)
# 可视化部分
# 定义颜色映射
colors = {0: 'blue', 1: 'red'}
# 绘制训练数据点
for label in np.unique(y_train):
indices = np.where(y_train == label)
plt.scatter(X_train[indices, 0], X_train[indices, 1], c=colors[label], label=f'Class {label} (Train)')
# 绘制测试数据点及预测结果
for i, test_point in enumerate(X_test):
plt.scatter(test_point[0], test_point[1], c=colors[predictions[i]], marker='x', s=100, label=f'Class {predictions[i]} (Test)' if i == 0 else "")
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('KNN Classification Visualization')
plt.legend()
plt.show()
运行结果:
KNN python函数库实现
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import datasets, neighbors
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 1. 加载数据
# 使用鸢尾花数据集 (iris),只取前两个特征
iris = datasets.load_iris()
X = iris.data[:, :2] # 取前两个特征(萼片长度和萼片宽度)
y = iris.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 2. 训练 KNN 分类器
k = 15 # 选择 K=15
knn = neighbors.KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train, y_train)
# 3. 预测测试集
y_pred = knn.predict(X_test)
# 4. 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.2f}")
# 5. 可视化决策边界
# 定义颜色映射
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
# 创建网格点来绘制决策边界
h = 0.02 # 网格点的步长
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
# 对每个网格点进行预测
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
# 将预测结果重新整形为网格形状
Z = Z.reshape(xx.shape)
# 绘制决策边界和数据点
plt.figure(figsize=(8, 6))
plt.pcolormesh(xx, yy, Z, cmap=cmap_light, shading='auto') # 决策边界
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=50) # 数据点
plt.xlabel('Sepal Length (cm)')
plt.ylabel('Sepal Width (cm)')
plt.title(f'KNN Classification (k = {k}, Accuracy = {accuracy:.2f})')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.show()
运行结果: