本帖最后由 Aclicee 于 2024-8-22 21:55 编辑
本书的第二部分为机器学习模块,介绍了一些经典的机器学习算法。机器学习与深度学习,二者虽同根生,却各有千秋。个人的理解上,机器学习算法,如KNN、随机森林和支持向量机等,它们是依赖于严格的数学计算的。这些算法的精髓在于其算法本身的设计,而非依赖于人工介入的超参数调整。不像深度学习需要炼丹那样,精心调配各种网络结构和参数,以期达到最佳的训练效果。
本书在这一部分中,为我们详细介绍了以下几个关键的机器学习算法:
-
PCA(主成分分析):一种通过正交变换将数据转换到新的坐标系统中,使得数据的任何投影的第一大方差在第一个坐标(称为第一主成分)上,第二大方差在第二个坐标上,依此类推的算法。它不仅帮助我们降维,更让我们能够洞察数据的本质。
-
Kmeans:一种经典的聚类算法,通过迭代优化,将数据点划分为K个簇,使得每个簇内的点尽可能相似,而簇间的点尽可能不同。它简单而高效,是探索数据结构的有力工具。
-
KNN(K近邻算法):一种基于距离的分类算法,通过测量不同特征值之间的距离来进行分类。它的简洁和直观,使得KNN在多种应用场景中都表现出了不俗的效果。
-
线性回归与多项式回归:回归算法是预测数值型数据的重要工具。线性回归以其直观的模型和易于理解的特性,为我们提供了数据预测的基础。而多项式回归则在此基础上增加了模型的复杂度,以适应更复杂的数据关系。
对这一部分的总体评价:
有一说一,这本书的介绍逻辑比较奇怪,之前学习其他课程往往会从回归问题开始讲解,因为线性回归是后面很多算法的前置(比如支持向量机,甚至是推导梯度下降时最简单情形的案例),不明白为什么编者要放在最后,反而在最前面花了大量的篇幅讲PCA。
一方面,对初学者而言,初次接触机器学习便直接学习PCA可能会感到困惑,因为它属于是数据降维和特征工程相关的内容,有点像是锦上添花的作用,并不直接关联到具体的分类或回归任务。如果读者在没有充分理解机器学习基本概念的情况下学习PCA,可能会对其作用和重要性缺乏直观的认识。
另一方面,在PCA推导过程中利用到了梯度的概念以及梯度上升算法,此时读者根本不知道什么是梯度,也不知道梯度下降算法,强行插入对梯度上升算法的介绍,完全不合逻辑(并且推导也是没头没尾的,又要去参考十万八千里以外的梯度下降法)。
一些个人浅薄之见,欢迎各位批评指正,阅读下来总觉得编者这样剑走偏锋安排的讲解方式对读者尤其是初学者十分不友好,建议编者考虑是否重新安排一下逻辑和数学上的连贯性。
回到评测计划上来,我之前在计划中也提到过,我目前在做一个预测电池容量衰退情况的工作。简单介绍一下任务的背景,在当今快速发展的新能源领域,锂离子电池作为核心能量存储单元,其性能稳定性和寿命预测显得尤为重要。电池的循环充放电过程中,不可避免地会出现电解液浓度降低、内阻增大等现象,这些因素共同作用导致电池容量逐渐衰退。因此我们通过采集锂离子电池在不同充放电周期的关键特征数据,建立一个模型,以评估电池的衰退情况。
为了构建一个具有代表性的数据集,我们从马里兰大学提供的公开电池数据(Battery Research Data | Center for Advanced Life Cycle Engineering (umd.edu))中挑选了几组电池数据。在每节电池的充放电周期中,我们选取了电池的一些充放电表现作为特征。因为我实际项目的数据集暂时不能公开,所以我胡诌了一个数据集,仅作为演示使用,每个样本为某一节电池某一周期随意选择充电曲线上的五个位置(作为特征),标签为是否出现衰退的二元标签(0-Negative表示未衰退,1-Positive表示已衰退)。然后生成了训练集和测试集,本质上就是一个二元分类的问题。
1.数据处理(使用了PCA进行降维)
对数据集进行初步探索性分析时,绘制了一下其中两个特征的关系图。由于特征我是随意选择的,可以看到其中第一个和第二个特征(如图1)之间存在非常强烈的线性关系,且有大量数据点彼此重叠。这种重叠的情况暗示了这两个特征可能在区分样本方面并不具有足够的能力。进一步观察其他特征,比如第一个特征和第三个特征(如图2),也发现了一定程度的线性相关性,这表明数据中存在冗余。
为了解决这一问题,可以使用PCA方法对数据进行降维处理。书中虽然提供了使用梯度上升法手动实现PCA的方法和详细的推导过程,也可以参考其他作者发表的阅读报告。但为了简化流程并提高效率,我选择直接使用Python内置的PCA工具。考虑到可视化的便利性,我决定仅保留前两个主成分。具体代码如下:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(X_train)
X_train_norm = scaler.transform(X_train)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X_train_norm)
X_Rtrain = pca.fit_transform(X_train_norm)
通过PCA转换后的特征分布图,我们可以看到大部分数据点现在分布在了水平方向上,原先的线性关系得到了有效的消解。这表明主成分分析成功地捕捉了数据中分布方差最大的方向。此外,原本重叠的数据区域也有所减少,这进一步证实了所选主成分在表示样本差异性方面的有效性。
在完成训练集的PCA降维处理后,我们面临着对测试集进行相同操作的任务。至关重要的一点是,我们必须确保测试集的处理方式与训练集保持完全一致。这样做不仅有助于避免数据泄露,确保模型评估的公正性。我们首先使用训练集的最大值-最小值归一化测试集,然后将训练集上学习到的主成分分析模型直接应用于测试集的归一化数据。具体的代码如下:
X_test_norm = scaler.transform(X_test)
X_Rtest = pca.transform(X_test_norm)
在对测试集进行PCA降维处理后,我们观察到正负样本的分布形态与训练集保持了高度的一致性。这种一致性对于确保模型评估的准确性至关重要,因为它意味着我们的数据预处理步骤没有引入偏差,模型在训练集和测试集上的表现将是可比的。
2.分类问题(使用了逻辑回归和KNN两种方法)
接下来就是使用书中介绍的机器学习算法,来完成这个二元分类任务。
从样本分布的形状可以看出,存在一定的交叠,最好的方法一定是支持向量机或者神经网络了,但是书中既然没有提到支持向量机,我们就试试别的方法。
首先是回归的方法,逻辑回归是一种特殊的线性回归,它通过引入sigmoid函数将线性回归的输出映射到0和1之间,从而实现二元分类。这一变换不仅保留了线性模型的直观解释性,而且通过引入非线性,增强了模型对复杂数据分布的适应能力。具体来说,当预测值小于0.5时,我们将其分类为0;当预测值大于0.5时,我们将其分类为1。这种方法为我们提供了一种既简单又有效的二元分类界面。逻辑回归的内容书中没有讲,实际只是在线性回归的基础上套一个sigmoid函数,应该是很简单的。具体推导的过程也可以参考其他作者的阅读报告,我这里就直接调用Python的工具了,具体代码如下:
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
log_reg = LogisticRegression(max_iter=1000)
log_reg.fit(X_Rtrain, y_train)
y_pred = log_reg.predict(X_Rtest)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
输出:Accuracy: 0.8097643097643098
通过逻辑回归模型的初步分类尝试,我们观察到分类界面(如上图)呈现出明显的线性特征,其实际表现比较一般,正确率大约是80%左右。
为了进一步提升分类效果,书中推荐了KNN(K近邻算法)作为另一种经典的分类算法。KNN的核心思想在于,通过计算测试集中每个样本与训练集中样本的距离,找出最近的K个邻居。这些邻居的多数投票结果将决定测试样本的类别。这种方法能够提供更加灵活的非线性决策边界,从而有望提高分类的准确性。书中给出了手动计算的过程(也非常简单),但我依旧选择是直接调用了Python中的KNN工具,设置用于投票的邻居数量k=3,如下:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_Rtrain, y_train)
y_pred = knn.predict(X_Rtest)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
输出:Accuracy: 0.9124579124579124
可以看到这一结果(如上图)不仅在数值上更加接近实际的分类情况,而且在视觉上也更加符合我们的预期,正确率大约在91%左右。
为了进一步探究特征选择和降维对模型性能的影响,我们还尝试了不进行PCA降维,直接使用原始的五个特征进行KNN分类。由于高维数据的可视化难度较大,我们无法直观地展示分类界面,但通过模型评估,我们发现正确率大约为87%左右,略低于经过PCA降维后的结果。
这一对比实验强调了PCA在特征工程中的重要性。通过PCA降维,我们不仅减少了特征间的冗余,还去除了可能影响模型性能的噪声。更重要的是,PCA帮助我们捕捉了特征间的本质差异性,这在高维数据中尤为重要。降维后的数据更加精炼,使得KNN算法能够更加聚焦于数据的关键信息,从而提高了分类的准确性。