【机器学习】决策树(基础篇)

news2025/1/4 15:37:37

决策树(基础篇---分类问题,回归问题会另出一篇博客,但也是基础篇)

  • 思维导图
  • 前言
    • 了解决策树(前后观看)
    • 使用决策树(感性的认识)
    • 如何生成决策树(原理部分,此部分有局限性,主要是针对分类问题)
      • ID3算法生成决策树(基于信息增益的决策树算法)
        • 举例:小明出去玩?
      • CART算法生成决策树(基于基尼系数|MSE的决策树算法)
        • 举例:

思维导图

前言

  • 本节将以例子为主,详细介绍生成决策树的原理部分,代码将不做重点介绍。

了解决策树(前后观看)

决策树算法被广泛应用于数据挖掘、自然语言处理、图像处理等领域。它的优点包括易于理解和解释、计算复杂度低、具有较高的准确性等。

使用决策树(感性的认识)

给定决策树:

给定数据:

年龄收入学历是否购买
25本科
35硕士
45初中
20大专
30博士
依据决策树我们可以判定的下表是否购买项的数据
年龄收入学历是否购买
25本科
35硕士
45初中
20大专
30博士

如何生成决策树(原理部分,此部分有局限性,主要是针对分类问题)

通过上面的例子,我们将相关决策树的名词,给出以下定义:

  • 最佳属性(最佳特征):在节点上,我们需要找到一个将数据集划分为最有利于分类的子集的属性。这个属性被称为最佳属性,

    • 上例中根节点的年龄属性,蓝色字段是为什么不选其他的属性的原因
  • 划分准则:划分准则是指用来衡量每个属性将数据集分成不同子集的优劣程度的方法。

    • 例如信息增益、基尼系数等
  • 子集:将数据集根据最佳属性划分后得到的数据子集。

  • 叶节点:决策树的终止节点,表示该节点下的所有数据都属于同一类别。叶节点不再进行划分。

要生成一颗决策树,通常需要考虑以下几个方面:

  1. 数据集的选择:需要先选定用于训练决策树的数据集。这个数据集应该包含足够多的样本,能够覆盖待分类问题中的所有可能情况。

  2. 最佳属性选择:在数据集中选择最佳的属性(特征),作为节点划分准则,通常会使用信息增益、基尼不纯度等指标来衡量每个属性(特征)的重要性,以便确定最佳划分属性。

  3. 剪枝:生成的决策树可能存在过拟合的问题,需要进行剪枝以提高泛化能力。

上图针对分类问题所作的图,显然,属性选择的不同会带来分类的不同效果,从我们感官上来分析,选择特征X1要优于选择特征X2。

决策树学习采用分而治之的策略,通过贪婪搜索来识别树中的最佳分割点。然后以自上而下的递归方式重复此拆分过程,直到所有或大多数记录都已分类到特定的类别标签下。

特征的选取不同,生成的子集不同,从图上我们可以看得出来选择特征X1要强于选择特征X2,但是如何量化的划分子集的效果,通过量化后数值大小来确定特征的选择呢,哎嘿!这就需要划分准则所做的事情。

暂不考虑数据集的选择和剪枝操作,对于最佳属性选择操作所使用的划分准则不同,可以将决策树算法分为以下4种:

  1. ID3算法:使用信息增益作为属性选择的判据,这种算法通常用于处理分类问题。
  2. C4.5算法:与ID3算法类似,但是使用信息增益比作为属性选择的依据,同时还支持处理缺失数据。
  3. CART算法:使用基尼指数或者均方误差(MSE)等判据作为属性选择依据,该算法既可以用于分类问题,也可以用于回归问题。
  4. CHAID算法:使用卡方检验作为属性选择判据,主要用于分类问题。

下面详细介绍下ID3和CART算法去生成决策树

ID3算法生成决策树(基于信息增益的决策树算法)

信息增益在我另一篇博客:(引流一下)【机器学习】信息量、香农熵、信息增益

信息增益的基本思想是:选择一个能够最大化训练数据集中信息增益的特征作为划分标准。信息增益的计算公式如下:
G a i n ( D , A ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ D H ( D v ) Gain(D,A)=H(D)-\sum_{v=1}^{V}\frac{|D_v|}{D}H(D_v) Gain(D,A)=H(D)v=1VDDvH(Dv)
其中, D D D 表示训练数据集, f f f 表示要计算信息增益的特征, V V V 表示特征 f f f 的取值个数, D v D^v Dv 表示在特征 f f f 取值为 v v v 时,训练数据集 D D D 的子集。 E n t ( D ) Ent(D) Ent(D) 表示训练数据集 D D D 的熵, E n t ( D v ) Ent(D^v) Ent(Dv) 表示在特征 f f f 取值为 v v v 时,训练数据集 D v D^v Dv 的熵。

那么利用信息增益,生成决策树流程为:

  1. 收集数据集,并确定每个样本的分类标签。
  2. 利用信息增益确定用来分裂数据集的最佳特征。
  3. 根据选择的特征将数据集分为子集,每个子集都具有相同的特征值。
  4. 对于每个子集,递归地重复步骤2-3,直到所有子集中的样本属于同一类别或达到预定义的停止条件。 构建决策树,
  5. 并将最终的分类结果与测试数据进行比较以评估决策树的准确性。

信息增益确定用来分裂数据集的最佳特征的过程如下:

  1. 计算训练数据集 D D D 的熵 E n t ( D ) Ent(D) Ent(D)
  2. 对于每个特征 f f f,计算特征 f f f 对训练数据集 D D D 的条件熵 E n t ( D ∣ f ) Ent(D|f) Ent(Df)
  3. 计算特征 f f f 对训练数据集 D D D 的信息增益 G a i n ( D , f ) Gain(D, f) Gain(D,f),即 G a i n ( D , f ) = E n t ( D ) − E n t ( D ∣ f ) Gain(D, f) = Ent(D) - Ent(D|f) Gain(D,f)=Ent(D)Ent(Df)
  4. 选择信息增益最大的特征作为划分标准。

最后,根据选择的最佳特征,将训练数据集 D D D 分成若干个子集,每个子集对应于最佳特征的一个取值。这个过程就是数据集的划分。这些子集成为决策树的分支节点,它们继续递归地执行上述过程,直到满足预定义的停止条件,例如树的深度达到一定值,节点中的样本数量小于一定值等。

接下来,需要确定决策树的叶子节点的类别。有几种方法可以实现:

  • 选取叶子节点中出现最多的类别作为该节点的类别。
  • 对于叶子节点中的每个类别,计算该类别在训练数据集中出现的频率,选择频率最高的类别作为该节点的类别。
  • 对于叶子节点中的每个类别,计算该类别在训练数据集中出现的概率,选择概率最高的类别作为该节点的类别。

最终,得到的决策树就可以用于对新样本进行分类。

举例:小明出去玩?

数据拟定背景:小明想出去玩?

IDClassWindTempOutlook
1PlayWeakHotSunny
2PlayStrongHotSunny
3StayWeakHotRain
4PlayWeakMidOvercast
5StayStrongColdRain
6PlayWeakColdOvercast
7StayStrongColdRain
8PlayWeakMidSunny
9PlayWeakColdSunny
10PlayStrongMidOvercast
11StayWeakMidSunny
12StayStrongMidRain
13PlayWeakHotOvercast
14PlayWeakColdRain
  • 对于系统香农熵 H ( D ) H(D) H(D)
ClassCount
play6
stay4

H ( D ) = − ∑ p ( x ) ⋅ l o g 2 p ( x ) = − ( 9 14 l o g 2 9 14 + 5 14 l o g 2 5 14 ) = 0.94 H(D)=-\sum p(x)·log_2{p(x)}=-(\frac{9}{14}log_2\frac{9}{14}+\frac{5}{14}log_2\frac{5}{14})=0.94 H(D)=p(x)log2p(x)=(149log2149+145log2145)=0.94

  • 计算关于Wind的信息增益
WeakStrong
Play72
Stay23

H ( D w e a k ) = − ( 7 9 l o g 2 7 9 + 2 9 l o g 2 2 9 ) = 0.764 H(D_{weak})=-(\frac{7}{9}log_2\frac{7}{9}+\frac{2}{9}log_2\frac{2}{9})=0.764 H(Dweak)=(97log297+92log292)=0.764
H ( D s t r o n g ) = − ( 2 5 l o g 2 2 5 + 3 5 l o g 2 3 5 ) = 0.970 H(D_{strong})=-(\frac{2}{5}log_2\frac{2}{5}+\frac{3}{5}log_2\frac{3}{5})=0.970 H(Dstrong)=(52log252+53log253)=0.970
G a i n ( D , W i n d ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ D H ( D v ) = H ( D ) − ( 9 14 H ( D w e a k ) + 5 14 H ( D s t r o n g ) ) = 0.102 Gain(D,Wind)=H(D)-\sum_{v=1}^{V}\frac{|D_v|}{D}H(D_v)=H(D)-(\frac{9}{14}H(D_{weak})+\frac{5}{14}H(D_{strong}))=0.102 Gain(D,Wind)=H(D)v=1VDDvH(Dv)=H(D)(149H(Dweak)+145H(Dstrong))=0.102

  • 计算关于Temperature的信息增益
HotMidCold
Play333
Stay122

H ( D H o t ) = − ( 3 4 l o g 2 3 4 + 1 4 l o g 2 1 4 ) = 0.811 H(D_{Hot})=-(\frac{3}{4}log_2\frac{3}{4}+\frac{1}{4}log_2\frac{1}{4})=0.811 H(DHot)=(43log243+41log241)=0.811
H ( D M i d ) = − ( 3 5 l o g 2 3 5 + 2 5 l o g 2 2 5 ) = 0.970 H(D_{Mid})=-(\frac{3}{5}log_2\frac{3}{5}+\frac{2}{5}log_2\frac{2}{5})=0.970 H(DMid)=(53log253+52log252)=0.970
H ( D C o l d ) = − ( 3 5 l o g 2 3 5 + 2 5 l o g 2 2 5 ) = 0.970 H(D_{Cold})=-(\frac{3}{5}log_2\frac{3}{5}+\frac{2}{5}log_2\frac{2}{5})=0.970 H(DCold)=(53log253+52log252)=0.970
G a i n ( D , T e m p ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ D H ( D v ) = H ( D ) − ( 4 14 H ( D H o t ) + 5 14 H ( D M i d ) + 5 14 H ( D C o l d ) ) = 0.008 Gain(D,Temp)=H(D)-\sum_{v=1}^{V}\frac{|D_v|}{D}H(D_v)=H(D)-(\frac{4}{14}H(D_{Hot})+\frac{5}{14}H(D_{Mid})+\frac{5}{14}H(D_{Cold}))=0.008 Gain(D,Temp)=H(D)v=1VDDvH(Dv)=H(D)(144H(DHot)+145H(DMid)+145H(DCold))=0.008

  • 计算关于Outlook的信息增益
SunnyOvercastRain
Play441
Stay104

H ( D S u n n y ) = − ( 4 5 l o g 2 4 5 + 1 5 l o g 2 1 5 ) = 0.722 H(D_{Sunny})=-(\frac{4}{5}log_2\frac{4}{5}+\frac{1}{5}log_2\frac{1}{5})=0.722 H(DSunny)=(54log254+51log251)=0.722
H ( D O v e r c a s t ) = − ( 4 4 l o g 2 4 4 + 0 4 l o g 2 0 4 ) = 0 H(D_{Overcast})=-(\frac{4}{4}log_2\frac{4}{4}+\frac{0}{4}log_2\frac{0}{4})=0 H(DOvercast)=(44log244+40log240)=0
H ( D R a i n ) = − ( 1 5 l o g 2 1 5 + 4 5 l o g 2 4 5 ) = 0.722 H(D_{Rain})=-(\frac{1}{5}log_2\frac{1}{5}+\frac{4}{5}log_2\frac{4}{5})=0.722 H(DRain)=(51log251+54log254)=0.722
G a i n ( D , O u t l o o k ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ D H ( D v ) = H ( D ) − ( 5 14 H ( D S u n n y ) + 4 14 H ( D O v e r c a s t ) + 5 14 H ( D R a i n ) ) = 0.424 Gain(D,Outlook)=H(D)-\sum_{v=1}^{V}\frac{|D_v|}{D}H(D_v)=H(D)-(\frac{5}{14}H(D_{Sunny})+\frac{4}{14}H(D_{Overcast})+\frac{5}{14}H(D_{Rain}))=0.424 Gain(D,Outlook)=H(D)v=1VDDvH(Dv)=H(D)(145H(DSunny)+144H(DOvercast)+145H(DRain))=0.424

  • 信息增益汇总
windTempOutlook
信息增益0.1020.0080.424

不难看出,小明去不去玩啊,温度只能减少0.008的不确定性,但是天气景观(Outlook)可以减少0.424的不确定性,那我们是不是说Outlook更重要一些,更适合作为重要决策节点。

选择标准就是:信息增益最大的那个作为决策属性,

经过第一轮的比较我们可以知道根节点就是最佳决策属性就是Outlook

接下来的步骤就是,将划分好的3个数据子集( D S u n n y 、 D O v e r c a s t 、 D R a i n D_{Sunny}、D_{Overcast}、D_{Rain} DSunnyDOvercastDRain)分别作为下一次的数据集合,进行上述操作,直至划分的子集纯度为1(其实就是不可在分,在数据的表现就是信息增益为0),这样我们就能得到一个完整的决策树。

如果数据集中有连续变量,可以将其转换为离散变量,例如将年龄按照一定的区间划分为不同的类别。这样做可以简化计算,并且能够更好地处理离散数据。

CART算法生成决策树(基于基尼系数|MSE的决策树算法)

在CART算法中,基尼系数和均方误差(MSE)都被用作度量划分质量的指标,选择最佳特征时,算法计算每个特征的基尼系数或者MSE,选择最小值对应的特征进行划分。

  1. 基尼系数用于分类问题,它表示从数据集中随机选取两个样本,其类别不一致的概率,基尼系数越小表示数据集纯度越高。
  2. 均方误差(MSE)用于回归问题,它表示预测值与实际值之间的平均误差的平方,均方误差越小表示预测值与实际值的差距越小。在回归问题中,CART算法选择平均值作为叶子节点的预测值。

假设数据集 D D D K K K 个类别, p k p_k pk 表示属于第 k k k 类的样本在数据集 D D D 中的比例,那么 D D D 的基尼系数可以表示为:
G i n i ( D ) = ∑ k = 1 K p k ( 1 − p k ) Gini(D)=\sum_{k=1}^Kp_k(1-p_k) Gini(D)=k=1Kpk(1pk) D D D 中只有一种类别时,基尼系数最小,为 0。因为此时 p k = 1 p_k=1 pk=1,而其他 p j p_j pj 都等于 0,因此 1 − p k = 0 1-p_k=0 1pk=0,整个求和式中只有一项,结果为 0。而当 D D D 中所有类别都出现相同的次数时,基尼系数最大,为 1 − 1 / K 1-1/K 11/K。因为此时 p k = 1 / K p_k=1/K pk=1/K,每一项的值都相等,最终求和的结果为 K × ( 1 / K ) ( 1 − 1 / K ) = 1 − 1 / K K \times (1/K)(1-1/K) = 1-1/K K×(1/K)(11/K)=11/K
 在决策树算法中,我们可以通过计算选择某个特征进行分割后子集的基尼系数来评估分割的质量,选取基尼系数最小的分割方法作为最终选择。
那么利用基尼系数,生成决策树流程为:

  1. 收集数据集,并确定每个样本的分类标签。
  2. 利用基尼系数确定用来分裂数据集的最佳特征。
  3. 根据选择的特征将数据集分为子集,每个子集都具有相同的特征值。
  4. 对于每个子集,递归地重复步骤2-3,直到所有子集中的样本属于同一类别或达到预定义的停止条件。 构建决策树,
  5. 并将最终的分类结果与测试数据进行比较以评估决策树的准确性。

基于基尼系数确定用来分裂数据集的最佳特征的具体步骤如下:

  1. 计算训练数据集 D D D 的基尼指数 G i n i ( D ) Gini(D) Gini(D)
    Gini ⁡ ( D ) = ∑ k = 1 ∣ Y ∣ ∑ k ′ ≠ k p k p k ′ = ∑ k = 1 ∣ Y ∣ p k ( 1 − p k ) \operatorname{Gini}(D)=\sum_{k=1}^{|\mathcal{Y}|} \sum_{k^{\prime} \neq k} p_{k} p_{k^{\prime}}=\sum_{k=1}^{|\mathcal{Y}|} p_{k}\left(1-p_{k}\right) Gini(D)=k=1Yk=kpkpk=k=1Ypk(1pk)

其中, ∣ Y ∣ |\mathcal{Y}| Y 是类别的个数, p k p_k pk 是第 k k k 个类别在数据集 D D D 中出现的概率。

  1. 对于每个特征 A A A,对数据集 D D D 按特征 A A A 的不同取值进行划分,计算每个划分的基尼指数
    G i n i A ( D ) Gini_A(D) GiniA(D)。划分的方式有多种,比如对于离散特征可以按取值分别划分,对于连续特征可以按阈值划分。
  2. 选择基尼指数最小的划分作为最优划分特征。最小基尼指数的定义如下:
    G i n i _ i n d e x ( D , A ) = ∑ v = 1 V D v D G i n i ( D v ) Gini\_index(D,A)=\sum_{v=1}^V\frac{D_v}{D}Gini(D_v) Gini_index(D,A)=v=1VDDvGini(Dv)

其中, V V V 是特征 A A A 的取值个数, D v D_v Dv 是数据集 D D D 中特征 A A A 取值为 v v v 的样本集合, ∣ D v ∣ |D_v| Dv D v D_v Dv 中的样本个数。

  1. 对于上一步得到的最优划分,将数据集 D D D 划分成若干个子集
    D 1 , D 2 , ⋯   , D k D_1,D_2,\cdots,D_k D1,D2,,Dk,并将每个子集分别作为一个子节点,递归地生成决策树。

举例:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/515457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一次失败的面试经历:我只想找个工作,你却用面试题羞辱我

金三银四就要来了,即将又是一波求职月,面对跳槽的高峰期,很多软件测试人员都希望能拿一个满意的高薪offer,但是随着招聘职位的不断增多,面试的难度也随之加大,而面试官更是会择优录取 小王最近为面试已经焦…

redis与mysql事务区别

mysql事务具有原子性,隔离性,一致性的特点。 redis提供multi, exec,watch来支持事务: 原子性,一致性: redis保证在multi,exec之间的语句作为一个整体执行,redis在exec后&…

【Linux进阶之路】基本指令(上)

文章目录 * —— 通配符与ls搭配使用与 rm 搭配使用 ctrl C——终止当前操作man——指令的指南man manman printfman pwd echo ——输出指定内容echo 字符串 cat ——打印文件呢内容cat 文件名常用选项 moreless常用 head——查看文件的前N行内容tail| ——管道cp——拷贝文…

【Android车载系列】第13章 车载渲染-OpenGL实现屏幕渲染

1 OpenGL渲染 上一章节我们通过SurfaceFlinger拿到Surface进行图像绘制,这节课我们通过GLSurfaceView来进行绘制,把摄像头的数据采集后展示渲染在屏幕上,这种方式是在GPU进行处理和绘制。 1.1 渲染使用GLSurfaceView 自定义CarView继承GLS…

考研数学武忠祥 高等数学0基础课笔记 函数和映射

常见的函数 取整函数的基本性质 函数的有界性 例题 sinx 是从-1到1的,但是x是无界的 遇到这种带sin的,就要试着取特殊值,让它为1或者为0 函数的单调性 函数的奇偶性 函数的周期性 举例 数学中Q表示有理数集,下面那个符号表示…

Linux 部署 Nexus (下载、安装、使用)

----仅供学习 如有侵权 联系删除----- 1、下载 下载方式1:官网下载 //建议用迅雷 https://help.sonatype.com/repomanager3/product-information/download/download-archives—repository-manager-3下载方式2:百度云盘下载 文件名:nexus-3…

一个让阿里面试官都说好软件测试简历模板

作为软件测试的垂直领域深耕者,面试或者被面试都是常有的事,可是不管是啥,总和简历有着理不清的关系,面试官要通过简历了解面试者的基本信息、过往经历等,面试者希望通过简历把自己最好的一面体现给面试官,…

数据库表设计规范—三范式、反范式

1.第一范式: 表中的属性不可分割 改为: 2.第二范式: 非主属性必须完全依赖主属性,不能部分依赖,比如只依赖联合主键中的其中一个主键就能拿到数据,这是不符合第二范式的 3.第三范式: 非主…

【Linux】缓存数据库Memcached、Memcached 安装、Memcached应用实例配置

一、 什么是缓存 缓存是指可以进行高速数据交换的存储器,它先于内存与CPU交换数据,因此速率很快。 从性能分析: CPU缓存>内存>磁盘>数据库 从性能来看内存是介于CPU和磁盘,在实际中内存是CPU和磁盘的桥梁。buffer和cache…

一、 JSP01 初识动态网页

一、 JSP01 初识动态网页 1.1 Web 应用程序开发 1.1.1 C/S 架构 客户端(Client)/服务器(Server)架构(即 C/S 架构)的系统主其分为客户端和用户端两层用户需要在本地安装客户端软件,通过网络与…

白话文讲计算机视觉-第十一讲-Harris算子

Moravec算子 说白了就是求两个像素点之间的差,然后平方一下给它变成正值。 其中,x,y表示像素点,u、v表示水平竖直方向的偏移量;w(x,y)为滤波函数,一般直接等于常数1。 I(xu,xv)、I(x,y )表示像素点(xu,xv)、…

基于zemax的折叠光路的激光扩束系统设计

激光扩束系统是激光干涉仪、激光测距仪、激光雷达等诸多仪器设备的重要组成部分,其光学系统多采用通过倒置的望远系统,来实现对激光的扩束,其主要作用是压缩激光束的空间发散角,使扩束后的激光束口径满足其他系统的要求。 激光器…

MySQL-图形化界面工具 (上)

♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️树高千尺,落叶归根人生不易&…

【sorting+双指针+数学】CF845div2 C. Quiz Master

和我一开始想的不太一样 一开始想的也是排序,然后双指针,但是我想的双指针是l1,rn的,因为我没注意到极差尽可能小这个条件可以转化为区间长度最短 其实就是尺取法,然后合法性就是这个区间内的数的所有因子能填满1~m这些格子 找…

Vue2 Vue3 Scoped 样式穿透

概念 主要是用于修改很多 Vue 常用的组件库(Element, Vant, AntDesigin),虽然配好了样式但是还是需要更改其他的样式, 因为添加了 scoped 实现 css 模块化 就需要用到 样式穿透 ,更改组件的样式 scoped 的原理 Vue …

route详解

一、前言 个人主页: ζ小菜鸡大家好我是ζ小菜鸡,让我们一起学习route。如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连) 二、什么是route Route就是用来显示、人工添加和修改路由表项目的。大多数主机一般都是驻留在只连接一台路由器的网段上。由于只有一台路…

1000个已成功入职的软件测试工程师简历经验总结:软件测试工程师简历项目经验怎么写?(含真实简历模板)

一、前言:浅谈面试 面试是我们进入一个公司的门槛,通过了面试才能进入公司,你的面试结果和你的薪资是息息相关的。那如何才能顺利的通过面试,得到公司的认可呢?面试软件测试要注意哪些问题呢?下面和笔者一起来看看吧。这里分享一…

【面试常见】链表带环

前言 一、什么是环形链表 二、判断链表是否带环 三、(问题1)slow和fast一定会相遇吗? 四、(问题2)fast一次走3/4/n步,还会相遇吗? 五、总结 前言 链表是面试中常见的一类题。分为单链表&#x…

Maven详细教程(图文并茂)

一、maven概述 1.1、项目开发中的问题 1、我的项目依赖一些jar包,我把他们放在哪里?直接拷贝到项目的lib文件夹中?如果我开发的第二个项目还是需要上面的那些jar包,再把它们复制到我当前项目lib中?那如果现在是第三次了&#xf…

ALSA子系统(十八)------指纹解锁动画提示声卡顿问题解析

你好!这里是风筝的博客, 欢迎和我一起交流。 很久没写kernel相关的东西了,主要是来到手机厂之后,大部分还是在Android上,Kernel虽然也有涉及,但毕竟只是有所涉及,主要业务逻辑还是在HAL之上&am…