机器学习算法——分类任务

算法:

1、决策树

2、随机森林

3、梯度提升树

4、逻辑回归

5、支持向量机SVM

6、K近邻 KNN

7、朴素贝叶斯

8、多层感知机

9、统一分类

10、比较总结

11、完整代码

1、决策树

1.1 Decision Tree Analysis (C4.5,CART,CHAID)决策树

算法 树结构 特征选择 连续值处理 缺失值处理 剪枝
ID3 多叉树 信息增益 不支持 不支持 不支持
C4.5 多叉树 信息增益比 支持 支持 支持
CART 二叉树 基尼系数 支持 支持 支持
CHAID 多叉树 卡方检验 支持 支持 支持

1.2 决策树核心思想

决策树是一个树结构(可以是二叉树或非二叉树),其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个输出类别。使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。

决策树学习通常包含这几个方面:特征选择、决策树生成、决策树剪枝、缺失值/异常值处理、决策树集成学习。(由于决策树算法非常容易过拟合,因此对于生成的决策树必须要进行剪枝。)

可把连续取值的数据值域划分为多个区间,并将每个区间视为该特征的一个取值,如此就完成了从连续性数据到离散性数据的转变。

1.3 决策算法

1.3.1 ID3

ID3算法就是用信息增益大小来判断当前节点应该用什么特征来构建决策树,用计算出的信息增益最大的特征来建立决策树的当前节点。

缺点:

不能处理连续特征(只能处理离散值);

在相同条件下,取值比较多的特征比取值少的特征信息增益大。使用信息增益作为标准容易偏向于取值较多的特征;

对于缺失值的情况没有做考虑;

没有考虑过拟合的问题;

1.3.2 C4.5

对ID3算法进行改进。将连续的特征离散化、引入信息增益比(信息增益和特征熵的比值)进行特征选择、缺失值处理:一是在样本某些特征缺失的情况下选择划分的属性,二是选定了划分属性,对于在该属性上缺失特征的样本的处理。引入了正则化系数进行初步剪枝防止过拟合。

缺点:

剪枝算法待优化;

生成的是多叉树,效率没有二叉树优;

只能用于分类,不能用于回归;

使用了熵模型,有大量耗时的对数运算,如果是连续值还有大量的排序运算。

1.3.3 CART

无论是ID3还是C4.5,都是基于信息论的熵模型的,这里面会涉及大量的对数运算。CART使用基尼系数来代替信息增益比(可以做为熵模型的一个近似替代)。建立二叉树,而不是多叉树(每次仅仅对某个特征的值进行二分,而不是多分)。同样将连续的特征离散化。样本输出是离散值,就是一颗分类树。如果果样本输出是连续值,就是一颗回归树。采用的办法是后剪枝法,即先生成决策树,然后产生所有可能的剪枝后的CART树,然后使用交叉验证来检验各种剪枝的效果,选择泛化能力最好的剪枝策略。

缺点:

选择最优的一个特征来做分类决策,但是大多数,分类决策不应该是由某一个特征决定的,而是应该由一组特征决定的。

对异常值比较敏感。

构建的树可能会比较复杂,容易出现过拟合现象,需要进行剪枝处理。

1.3.4 CHAID

基于卡方检验进行特征选择。通常采用预剪枝方法。预剪枝是在树的生长过程中提前停止分裂,以防止过拟合。

缺点:

计算卡方统计量和进行假设检验相对复杂,当数据量较大时,计算成本较高。对于连续型变量要先进行离散化才能应用卡方检验。

1.4 剪枝

对于决策树而言,当不断向下划分,以构建一棵足够大的决策树时(直到所有叶子结点熵值均为0),理论上就能将近乎所有数据全部区分开。所以,决策树的过拟合风险非常大。为此,需要对其进行剪枝处理。

常用的剪枝策略主要有两个:

预剪枝:构建决策树的同时进行剪枝处理(更常用)。预剪枝策略可以通过限制树的深度、叶子结点个数、叶子结点含样本数以及最低信息增益来完成。

后剪枝:构建决策树后再进行剪枝处理。后剪枝法,即先生成决策树,然后产生所有可能的剪枝后的树,然后使用交叉验证来检验各种剪枝的效果,选择泛化能力最好的剪枝策略。

python 复制代码
# 1 决策树分类
dt = DecisionTreeClassifier(
    criterion='gini',       # 分裂标准:'gini'(基尼系数)或 'entropy'(信息熵)
    max_depth=5,            # 树的最大深度(防止过拟合)
    random_state=42         # 随机种子(确保结果可复现)
)

2、随机森林

解决决策树泛化能力弱的特点。随机森林是一种基于树模型的Bagging(自助聚合)的优化版本,一棵树的生成肯定还是不如多棵树,因此就有了随机森林。

决策过程:

1随机选择样本(放回抽样,行抽样。从样本集中通过重采样的方式产生n个样本)。

2构建决策树(假设样本特征数目为a,对n个样本选择a中的k个特征,用建立决策树的方式获得最佳分割点)。

3随机选择特征(列抽样,重复m次,产生m棵决策树)。

4随机森林投票(平均,多数投票机制来进行预测)。

优点:

无需修剪决策树;

过拟合不是问题;

对训练数据中的异常值不太敏感;

能够处理很高维度(feature很多)的数据,并且不用做特征选择(因为特征子集是随机选择的);

训练速度快,容易做成并行化方法(训练时树与树之间是相互独立的);

对于不平衡的数据集来说,它可以平衡误差;

如果有很大一部分的特征遗失,仍可以维持准确度。

缺点:

回归无法预测训练数据范围外的值;

在回归中,经常无法准确预测极端值--低估了高点,高估了低点。

python 复制代码
# 2. 随机森林分类
rf = RandomForestClassifier(
    n_estimators=100,       # 决策树的数量
    criterion='gini',       # 分裂标准
    max_depth=5,            # 单棵树的最大深度
    random_state=42         # 随机种子
)

3、梯度提升树

一种基于集成学习的算法,旨在通过组合多个弱学习器来构建一个强学习器。其核心思想是逐步优化模型,通过每一步的学习来纠正前一步的错误。弱学习器是指在某一特定任务上表现稍好的模型。通常,单个弱学习器的预测能力有限,但通过集成多个弱学习器,可以显著提高整体模型的性能。最终模型是初始模型与所有弱学习器的加权和。残差反映了模型在当前阶段的预测误差。新树的目标是捕捉当前模型未能解释的部分。

随机森林 VS 梯度提升树

随机森林:

并行构建:多棵决策树独立构建,互不影响,适合并行化处理。

随机性:每棵树使用不同的随机子样本和随机特征子集,增加模型多样性。

目标:通过"多数投票"(分类)或"平均值"(回归)组合结果,降低方差,提高泛化能力。

复杂度较低:训练过程简单,适合并行化,训练时间通常较快,尤其是在多核处理器上。

梯度提升树:

序贯构建:每棵树在前一棵树的基础上优化,目标是修正前一棵树的残差。

优化目标:通过最小化损失函数逐步优化模型,降低偏差,最终得到强预测模型。

复杂度较高:训练过程序贯,无法并行化,训练时间随树的数量增加而显著增加。

python 复制代码
# 3. 梯度提升树分类
gb = GradientBoostingClassifier(
    n_estimators=100,       # 树的数量
    learning_rate=0.1,      # 学习率(控制每棵树的贡献)
    max_depth=3,            # 单棵树的最大深度
    random_state=42
)

4、逻辑回归

逻辑回归,虽然叫做回归,但它却是分类算法。逻辑回归就是解决二分类问题的利器。逻辑回归是广义的线性模型,就是在线性回归基础上加了一个非线性映射。

假设有如下图所示的一个数据集,使用线性回归算法,可以找到大致如黑线的一个线性模型对其进行拟合。对数据集中每一个xi,都能通过模型找到一个yi(预测值)与之对应。获得了预测值,就可以做很多事情,例如:分类。可以对yi进行分段。这就实现了以回归的思路来实现分类。

线性回归有一个很致命的缺陷------对异常值很敏感,如果数据集中出现异常值,拟合出来的线性模型也将出现很大变化,预测出来的结果也将不在那么准确,从而到导致分类错误。逻辑回归算法对线性回归对异常数据敏感的不足进行了优化改进。用sigmod函数与线性函数进行复合。

sigmoid函数也叫Logistic函数,函数表达式:

sigmoid函数可以很好地将(-∞,+∞)内的数映射到(0,1)上,于是可以将g(z)≥0.5时将该条数据标记为1类,g(z)<0.5时标记为0类。

python 复制代码
# 4. 逻辑回归分类
lr = LogisticRegression(
    penalty='l2',           # 正则化类型:'l1'(Lasso)或 'l2'(Ridge)
    C=1.0,                  # 正则化强度的倒数(值越小,正则化越强)
    solver='lbfgs'          # 优化算法(如 'lbfgs', 'saga', 'liblinear')
)

5、支持向量机SVM

将向量映射到一个高维空间里,在这个空间里建立一个最大间隔超平面。在分开数据的超平面的两边建有两个互相平行的超平面,分隔超平面使两个平行超平面的距离最大化。假定平行超平面间的距离或差距越大,分类器的总误差越小。

线性:

最优分类平面的条件是使间隔最大化。通过任一类(星形或圆形标志)与超平面距离最近的点,基于其与超平面距离的最大化来判定最优超平面,这个距离称为边距(Margin)。相比较于A、B,超平面C的边距最大,且具有鲁棒性,也就是说与任一类别的边距都最大,而不像A、B泛化性较差。

非线性:

需要让空间从原本的线性空间变成一个更高维的空间,在这个高维的线性空间下,再用一个超平面进行划分。

SVM有一种称为核函数的技术。这些函数采用低维输入空间并将其转换为更高维空间,即将不可分离问题转换为可分离问题,这些函数称为内核。它主要用于非线性分离问题。

python 复制代码
# 5. 支持向量机 (SVM)
svm = SVC(
    kernel='rbf',           # 核函数:'linear', 'poly', 'rbf', 'sigmoid'
    C=1.0,                  # 正则化参数(值越大,对误分类容忍度越低)
    gamma='scale'           # 核函数的系数('scale' 或 'auto')
)

6、KNN

找出挨着自己最近的K个邻居,并且根据邻居的类别来确定自己的类别情况。

比如红色点,挨着其最近的5个点(K=5时)如上图,如果该5个点中多数均为A类,那么红色点就归为A类。k近邻的三个要素:①距离度量,②k(邻居数)的选择,③分类决策规则。

距离度量可以是一般的L_p距离(或Minkowski、闵可夫斯基、闵氏距离)。通常情况下K值为奇数,通常建议介于3~20之间。分类决策规则一般用多数表决规则。

缺点:KNN是一种"懒惰学习"算法(Lazy Learning),在训练阶段几乎不进行任何计算,而是将所有数据存储起来。在预测阶段,需要对每个测试样本计算其与所有训练样本之间的距离,然后找到最近的K个邻居。因此,当数据量较大时,计算成本非常高。

影响:在大规模数据集上,KNN的预测速度会非常慢,不适合实时或在线预测场景。

噪声数据:KNN对噪声数据和异常值非常敏感,因为这些数据点可能会影响最近邻的判断。

数据不平衡:在类别不平衡的数据集中,KNN的性能可能会受到严重影响。少数类的样本可能被多数类的样本"淹没",导致分类错误。

python 复制代码
# 6. K近邻分类 (KNN)
knn = KNeighborsClassifier(
    n_neighbors=5,          # 使用的邻居数量
    weights='uniform'       # 权重计算方式:'uniform' 或 'distance'
)

7、朴素贝叶斯

利用贝叶斯公式根据某特征的先验概率计算出其后验概率,然后选择具有最大后验概率的类作为该特征所属的类。它的优点是简单高效,尤其适用于特征维度较高的数据集。

之所以称之为"朴素",是因为贝叶斯分类只做最原始、最简单的假设:所有的特征之间是统计独立的。

在scikit-learn中,一共有3个朴素贝叶斯的分类算法:

GaussianNB:先验为高斯分布(正态分布)的朴素贝叶斯,假设每个标签的数据都服从简单的正态分布。

MultinomialNB:先验为多项式分布的朴素贝叶斯。它假设特征是由一个简单多项式分布生成的。多项分布可以描述各种类型样本出现次数的概率,因此多项式朴素贝叶斯非常适合用于描述出现次数或者出现次数比例的特征。

BernoulliNB:先验为伯努利分布的朴素贝叶斯。

python 复制代码
# 7. 朴素贝叶斯分类
nb = GaussianNB()           # 默认使用高斯分布

总结:

如果样本特征的分布大部分是连续值,使用GaussianNB会比较好。

如果样本特征的分布大部分是多元离散值,使用MultinomialNB比较合适(常用于文本分类)。

如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用BernoulliNB。

8、多层感知机

是一种前馈神经网络模型,它由一个输入层、一个输出层以及至少一层隐藏层组成。多层感知器模型即为多个单层感知器的叠加。

python 复制代码
# 8. 多层感知机 (MLP)
mlp = MLPClassifier(
    hidden_layer_sizes=(100,),  # 隐藏层结构(如 (100, 50) 表示两层)
    activation='relu',      # 激活函数:'relu', 'tanh', 'logistic'
    solver='adam',          # 优化算法:'adam', 'lbfgs', 'sgd'
    max_iter=1000,          # 最大迭代次数
    random_state=42
)

工作原理:

  1. 前向传播:输入数据通过网络从输入层传递到输出层,在每一层中,数据都被转换为新的表示形式。
  2. 损失计算:根据输出层产生的预测值和实际目标值之间的差异来计算损失(或误差)。
  3. 反向传播:使用梯度下降法(或其变体)来更新网络中的权重和偏置,以便最小化损失函数。

9、Unified Classification统一分类

旨在通过一个统一的模型或框架来解决多种分类问题,而不是为每个任务单独设计模型。

百度构建了"任务架构统一、通用能力共享"的通用文本分类技术UTC,其实现了良好的零/少样本迁移性能。PaddleNLP结合文心ERNIE,基于UTC技术开源了首个面向通用文本分类的产业级技术方案。

对于简单任务,通过调用 paddlenlp.Taskflow API,仅用三行代码即可实现零样本(Zero-shot)通用文本分类,可支持情感分析、意图识别、语义匹配、蕴含推理等各种可转换为分类问题的NLU任务。对于复杂任务,可以标注少量数据(Few-shot)进行模型训练,以进一步提升模型分类效果。

UTC具有低资源迁移能力,可以支持通用分类、评论情感分析、语义相似度计算、蕴含推理、多项式阅读理解等多种"泛分类"任务。这使得开发者可以更加轻松高效地实现多任务文本分类数据标注、训练、调优和上线,从而降低文本分类技术门槛。

Github:
https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/taskflow/zero_shot_text_classification.py

参考文章:https://aistudio.csdn.net/644b39106beb9e262918b1cb.html

流程:

1、数据

安装Label Studio为数据打标签、导出JSON文件。通过label_studio.py脚本可转为UTC的数据格式。生成训练/验证集文件。

2、模型微调与评估

推荐使用PromptTrainer API对模型进行微调,该API封装了提示定义功能,且继承自Trainer API。只需输入模型、数据集等就可以使用Trainer API高效快速地进行预训练、微调等任务,可以一键启动多卡训练、混合精度训练、梯度累积、断点重启、日志显示等功能,Trainer API还针对训练过程的通用训练配置做了封装,比如:优化器、学习率调度等。

3、预测

paddlenlp.Taskflow装载定制模型,通过task_path指定模型权重文件的路径,路径下需要包含训练好的模型权重文件model_state.pdparams。

python 复制代码
from pprint import pprint
from paddlenlp import Taskflow
schema = ["病情诊断", "治疗方案", "病因分析", "指标解读", "就医建议", "疾病表述", "后果表述", "注意事项", "功效作用", "医疗费用", "其他"]
my_cls = Taskflow("zero_shot_text_classification", model="utc-base", schema=schema, task_path='/home/aistudio/checkpoint/model_best/plm')
pprint(my_cls(["老年斑为什么都长在面部和手背上","老成都市哪家内痔医院比较好怎么样最好?","中性粒细胞比率偏低"]))

10、比较总结

在选择合适的分类算法时,需要综合考虑数据的规模、特征维度、任务复杂度以及计算资源等因素。

场景需求 推荐模型
线性可分、概率解释 逻辑回归
高维稀疏、小样本 朴素贝叶斯、SVM
非线性、可解释性 决策树、随机森林
复杂非线性、高精度 梯度提升树、多层感知机
局部模式、小数据集 KNN
多模态/序列数据、大规模任务 统一大模型
实时预测、轻量级部署 逻辑回归、轻量决策树

11、完整代码

python 复制代码
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn.metrics import accuracy_score

# 导入数据集
iris = datasets.load_iris()
# 切分数据集,将数据的内容余目标切分成训练集和测试集
Xtrain, Xtest, ytrain, ytest = train_test_split(iris.data,iris.target,random_state=12)

# 1. 决策树分类
dt = DecisionTreeClassifier(
    criterion='gini',       # 分裂标准:'gini'(基尼系数)或 'entropy'(信息熵)
    max_depth=5,            # 树的最大深度(防止过拟合)
    random_state=42         # 随机种子(确保结果可复现)
)

# 2. 随机森林分类
rf = RandomForestClassifier(
    n_estimators=100,       # 决策树的数量
    criterion='gini',       # 分裂标准
    max_depth=5,            # 单棵树的最大深度
    random_state=42         # 随机种子
)

# 3. 梯度提升树分类
gb = GradientBoostingClassifier(
    n_estimators=100,       # 树的数量
    learning_rate=0.1,      # 学习率(控制每棵树的贡献)
    max_depth=3,            # 单棵树的最大深度
    random_state=42
)

# 4. 逻辑回归分类
lr = LogisticRegression(
    penalty='l2',           # 正则化类型:'l1'(Lasso)或 'l2'(Ridge)
    C=1.0,                  # 正则化强度的倒数(值越小,正则化越强)
    solver='lbfgs'          # 优化算法(如 'lbfgs', 'saga', 'liblinear')
)

# 5. 支持向量机 (SVM)
svm = SVC(
    kernel='rbf',           # 核函数:'linear', 'poly', 'rbf', 'sigmoid'
    C=1.0,                  # 正则化参数(值越大,对误分类容忍度越低)
    gamma='scale'           # 核函数的系数('scale' 或 'auto')
)

# 6. K近邻分类 (KNN)
knn = KNeighborsClassifier(
    n_neighbors=5,          # 使用的邻居数量
    weights='uniform'       # 权重计算方式:'uniform' 或 'distance'
)

# 7. 朴素贝叶斯分类
nb = GaussianNB()           # 默认使用高斯分布(无需特殊参数)

# 8. 多层感知机 (MLP)
mlp = MLPClassifier(
    hidden_layer_sizes=(100,),  # 隐藏层结构(如 (100, 50) 表示两层)
    activation='relu',      # 激活函数:'relu', 'tanh', 'logistic'
    solver='adam',          # 优化算法:'adam', 'lbfgs', 'sgd'
    max_iter=1000,          # 最大迭代次数
    random_state=42
)

# 训练模型(假设已有 X_train, y_train)
models = [dt, rf, gb, lr, svm, knn, nb, mlp]
for model in models:
    model.fit(Xtrain, ytrain)
    # 在测试集上执行预测,proba导出的是每个样本属于某类的概率
    pre_result = model.predict(Xtest)  # 预测结果

    # 测试准确率
    accuracy_value = accuracy_score(ytest, pre_result)
    # 打印输出结果
    print(accuracy_value)  # 最后预测准确率
相关推荐
平凡而伟大(心之所向)11 分钟前
机器学习的发展史
机器学习
龚大龙11 分钟前
机器学习(李宏毅)——Domain Adaptation
人工智能·机器学习
AAA顶置摸鱼18 分钟前
机器学习·NLP中的文本分类
机器学习·自然语言处理·分类
AIGC_ZY18 分钟前
扩散模型中三种加入条件的方式:Vanilla Guidance,Classifier Guidance 以及 Classifier-Free Guidance
深度学习·机器学习·计算机视觉
原来是猿38 分钟前
蓝桥备赛(13)- 链表和 list(上)
开发语言·数据结构·c++·算法·链表·list
项目申报小狂人1 小时前
高性能算法NGO!北方苍鹰优化算法(Northern Goshawk Optimization,NGO)
算法·数学建模
且听风吟ayan1 小时前
leetcode day26 重复的子字符串
算法·leetcode·c#
仟濹1 小时前
【算法 C/C++】二维差分
c语言·c++·算法
*星星之火*1 小时前
【GPT入门】第9课 思维树概念与原理
gpt·算法·深度优先
xiangzhihong82 小时前
GitHub神秘组织3小时极速复刻Manus
人工智能·深度学习·机器学习