分类模型评估:混淆矩阵、准确率、召回率、ROC

这篇具有很好参考价值的文章主要介绍了分类模型评估:混淆矩阵、准确率、召回率、ROC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 混淆矩阵

在二分类问题中,混淆矩阵被用来度量模型的准确率。因为在二分类问题中单一样本的预测结果只有Yes or No,即:真或者假两种结果,所以全体样本经二分类模型处理后,处理结果不外乎四种情况,每种情况都有一个专门称谓,如果用一个2行2列表格描述,得到的就是“混淆矩阵”,以下是遵循sklearn规范的混淆矩阵布局(本文地址:https://laurence.blog.csdn.net/article/details/129006571,转载请注明出处!):

  预测为’假’ 预测为’真’
实际为’假’ 真阴性 / TN (True Negative) 假阳性 / FP (False Positive)
实际为’真’ 假阴性 / FN (False Negative) 真阳性 / TP (True Positive)

助记:

  • 行:实际值,第1行:假,第2行:真;
  • 列:预测值,第1列:假,第2列:真
  • 主对角线:真阴、真阳,均以T开头
  • 副对角线:假阳、假阴,均以F开头
名称 缩写 解释(1) 解释(2)
真阴性 TN 预测为阴,实测也为阴 预测为假,实测也为假
假阳性 FP 预测为阳,实测为阴(错报) 预测为真,实测为假
假阴性 FN 预测为阴,实测为阳(漏报) 预测为假,实测为真
真阳性 TP 预测为阳,实测也为阳 预测为真,实测也为真

其中,假阳性(FP)又被称为“Type 1 Error”,就是“错报”,假阴性(FN)又被称为“Type 2 Error”,就是“漏报”。混淆矩阵的4个值定义清晰,没有任何歧义,容易让人搞混的是混淆矩阵的布局,因为业界没有统一规定过在混淆矩阵中实际值和预测值谁应该是行谁应该是列,也没规定真假值/正负值谁应是第一行谁应是第二行,所以在不同的资料和程序库中就会出现行列结构或顺序相反的情况,所以要特别留意一下混淆矩阵的布局。本文遵循的是sklearn中定义的混淆矩阵结构,使用公式描述就是:

C o n f u s i o n   M a t r i x = [ T N F P F N T P ] Confusion\ Matrix = \begin{bmatrix} {TN}&{FP}\\ {FN}&{TP}\\ \end{bmatrix} Confusion Matrix=[TNFNFPTP]

在《Hands-On ML》一书的第三章,就计算过针对图片(数字5)的二分类模型处理结果的混淆矩阵:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

上述案例使用的是MNIST数据集,训练数据6万张图片(使用6万张图片训练,同时再使用它们进行评估),根据红框中的混淆矩阵可知:

  • 实际不是数字5,模型预测也不是数字5(预测正确)的图片有:53892张
  • 实际不是数字5,模型预测是数字5(预测错误)的图片有:687张
  • 实际是数字5,模型预测不是数字5(预测错误)的图片有:1891张
  • 实际是数字5,模型预测也是数字5(预测正确)的图片有:3530张

2. 准确率与召回率

在混淆矩阵的四个数据基础之上,人们还设计了两种常用的度量指标,分别是准确率和召回率:

  • 准确率 ( Precision )

    在所有“预测为真”(TP+FP)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫准确率 ( Precision ),计算公式:
    P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP + FP} Precision=TP+FPTP

  • 召回率 ( Recall )

    在所有“实际为真”(TP + FN)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫召回率 ( Recall ),计算公式:
    R e c a l l = T P T P + F N Recall=\frac{TP}{TP + FN} Recall=TP+FNTP

在《Hands-On ML》一书的第三章,给出了一张图,清晰明了地阐述了混淆矩阵、准确率、召回率三者之间的关系:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

注意:该图4个象限的布局对应Sklearn中的混淆矩阵的布局。网上有的资料介绍混淆矩阵使用的4象限图表
未必与本图一致,它们对于行列是实际值还是预测值的定义可能是反的,对于真假值/正负值谁是第一行谁是二行的定义可能是反的,请一定注意区分!

3. 准确率与召回率之间的权衡

人们之所以会定义“准确率”和“召回率”这两个概念,是因为它们能从两个不同的维度(或者说角度)度量二分类模型的准确性,且在不同的场景里,人们对这两个指标的看重程度是不一样的。引用《Hands-On ML》一书给出的两个例子:

  • 案例一: 过滤少儿不宜的视频

    在这个场景中,模型的任务是:判定视频是否适合儿童观看,True表示健康视频,False表示少儿不宜。在该场景下模型应该追求的是:宁可将部分健康视频错误地认定为少儿不宜,也要最大限度地保证认定为健康的视频一定是健康的,这是典型的“优先保证高准确率,允许牺牲一定召回率”的场景。

  • 案例二:识别商超监控中的盗窃行为

    在这个场景中,模型的任务是:判定视频中的人是否有盗窃行为,True表示有,False表示无。在该场景下模型应该追求的是:宁可将部分正常行为的视频错误地认定为了盗窃,也要最大限度地保证所有盗窃行为都能被识别出来,这是典型的“优先保证高召回率,允许牺牲一定准确率”的场景。

很多时候,鱼和熊掌不可兼得,在模型调至最优状态时,依然要在“准确率”与“召回率”之间作出“权衡”,它们之间是“此消彼长”的博弈关系,通过调整阈值是可以调节两者的大小的。我们以《Hands-On ML》第三章“识别数字5”的图片二分类结果为例解释的“准确率”与“召回率”之间的“权衡”或者“博弈”关系:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

首先,图中12张数字图片的排序不是随机的,而是根据模型给它们的“评分”按从小到大的顺序在SROCe数轴上依次排列的。这里是“准确率”与“召回率”之间可调的关键,因为虽然二分类模型给出的是一个Yes or No的二元结果,但在模型内部其实为维护的是一个“量值”,通过调节“阈值”的大小,可以决定最终输出的是Yes还是No,这会影响一个“不是很容易分辨的样本”最后被划定成FP还是FN(TP和TN的分值一般会很高或很低,受阈值调整的影响不大,这很容易理解)。以图示的情况为例:

  • 情形一:阈值设定在数轴左侧图片9和5的得分之间(暂不考虑具体数值),则右侧8张图片均会被判定为True,8张图片中实际有两个数字2和6被错误判定了,所以准确率=6/8=75%;同时,在总计6张的数字5图片中,该阈值设定下,全部6张数字5的图片都被判定为True,所以召回率=6/6=100%

  • 情形二:阈值设定在数轴中间两张图片5的得分之间(暂不考虑具体数值),则右侧5张图片均会被判定为True,5张图片中实际有1个数字6被错误判定了,所以准确率=4/5=80%;同时,在总计6张的数字5图片中,该阈值设定下,只有4张数字5的图片都被判定为True,所以召回率=4/6=67%

  • 情形三:阈值设定在在数轴右侧图片6和5的得分之间(暂不考虑具体数值),则右侧3张图片均会被判定为True,3张图片全部正确判定,所以准确率=3/3=100%;同时,在总计6张的数字5图片中,该阈值设定下,只有3张数字5的图片都被判定为True,所以召回率=3/6=50%

从上述三次阈值的调节中我们可以清晰观察到:“准确率”和“召回率”之间此消彼长的博弈关系。

关于上述解释中所说的“评分”,专业名称叫“Confidence SROCe”,分值越高表示结果为True的可能性越大。在Sklearn中使用SGDClassifier.decision_function(X)方法可以计算出给定样本的评分,下图是书中针对某一个数字5的图片计算sROCe的示例代码:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

4. 如何设定期望的准确率与召回率?

就像前面介绍的两个案例一样,不同的情形下,人们对于模型的准确率与召回率的期望是不同的,而通过设定SROCe的阈值,我们就可以调整模型预测的准确率和召回率。我们可以自行推导一下寻找期望的准确率和召回率组合的方法:

假设有1000个样本,首先,计算出所有样本的Confidence SROCe,按分值从小到大排好,以每一个sROCe作为阈值,计算对应的准确率和召回率,这样就会得出准确率和召回率伴随阈值变化的曲线,可以想见:当阈值取最小的sROCe时,全部样本都会被判定为True,所以召回率将是100%,而准确率会非常低,而当阈值取到最大的sROCe时,全部样本都会被判定为False,此时召回率将降为0,准确率会趋向于无穷大。为此,Sklearn专门提供了一个函数sklearn.metrics.precision_recall_curve(官方文档)用于计算一组样本+对应成绩的准确率和召回率曲线,下图是《Hands-On ML》一书利用这个函数绘制的数字5的准确率和召回率变化曲线:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

这张图已经把阈值变化对准确率和召回率的影响描述地非常清晰了,从这张图上也能清晰地看出准确率和召回率之间的“此消彼长”的博弈关系。此外,我们还可以观察准确率和召回率之间的变化关系,就是以Recall为横坐标,Precision为纵坐标绘制的曲线,一般称之为Precision-Recall曲线,下图是《Hands-On ML》针对上述准确率和召回率数据绘制的两者变化关系,这张图提供了一些额外的“信息”,我们可以从中发现:一但准确率低于80%以后就会急剧下降,当然,这也意味着召回率是在急剧上升。

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

假设我们最终选择了:准确率90% + 召回率50% 的组合,接下来的工作就是找出它们所对应的阈值,然后将这个阈值设置给模型产出符合预期的预测结果。但是,这里有一个不问题,那就是:Sklearn其实并不提供修改其内部阈值的接口(不允许用户直接修改),怎么办呢?非常简单,我们只需要拿到sROCe数组,然后和自己设定的threshold值进行矩阵逻辑计算,就可以轻松获得最终的判定结果:布尔数组,就是下面的做法:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

5. ROC

ROC的全称是“受试者工作特征”(Receiver Operating Characteristic)曲线,是另一种评判分类模型结果好坏的方法。ROC曲线与Precision-Recall曲线类似,也是用两个比值作为横纵坐标绘制的曲线,这两个比值分别是:

  • 假阳性率 ( False Positice Rate,FPR )

    在所有“实际为假”(FP+TN)的样本中,有多少是“预测错了”(FP)的? 这个百分比叫假阳性率(FPR),计算公式:
    F a l s e   P o s i t i v e   R a t e   ( F P R ) = F P F P + T N False\ Positive \ Rate\ (FPR)= \frac{FP}{FP+TN} False Positive Rate (FPR)=FP+TNFP

  • 真阳性率 ( True Positive Rate,TPR )

    在所有“实际为真”(TP + FN)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫真阳性率(TPR),其实也就是召回率(Recall),计算公式:
    T r u e   P o s i t i v e   R a t e   ( T P R ) = T P T P + F N True \ Positive \ Rate\ (TPR)= \frac{TP}{TP+FN} True Positive Rate (TPR)=TP+FNTP

而ROC曲线就是以假阳性率(FPR)为横坐标,真阳性率(TPR)为纵坐标绘制的曲线:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion

要理解ROC曲线的含义,还是得从混淆矩阵的四象限图着手, 我们再次引用《Hands-On ML》中的那个数字图片5的混淆矩阵图,然后添加一些注解:

分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion
在这张四象限图中,样本(数字图片)是不能上下移动的,因为上下方向代表样本实际的真假,这是确定的事实,不会发生变更,但样本是可以左右移动的,至于是落在左边(1、3象限)还是右边(2、4象限),即被预测为假还是为真,恰恰就是通过阈值来调节的,而图中的红色竖线所代表的就是阈值!设想一下:

  • 如果调高阈值,就是调高了判定为真的门槛,就相当于红线右移,致使更多的图片从右侧(2、4象限)移动到了左侧(1、3象限),此时,真阳性率 ( TPR ) 和假阳性率 ( FPR ) 都会变小,但变小的幅度是不同的,当阈值调至最大值时,TPR和FPR都将变成0,此时就是ROC曲线上的 ( 0, 0 ) 点;
  • 如果调低阈值,就是调低了判定为真的门槛,就相当于红线左移,致使更多的图片从左侧(1、3象限)移动到了右侧(2、4象限),此时,真阳性率 ( TPR ) 和假阳性率 ( FPR ) 都会变大,但变大的幅度是不同的;当阈值调至最小值时,TPR和FPR都将变成1,此时就是ROC曲线上的 ( 1, 1 ) 点;

上述描述可以形象地解释ROC曲线的整体框架,即为什么它是从( 0, 0 ) 点到( 1, 1 ) 点的一段曲线,但是,它还不能解释曲线的形状,也就是TPR对FPR比值的变化趋势,其实也就是在调高和调低阈值的过程中,TPR和FPR变小和变大的规律是什么?我们继续借用上图来推导和解释这个问题。首先,不管是观察分类模型给出的样本评分还是我们的直观感受,都可以清晰印证这样一个事实,那就是:样本的评分并不是均匀分布的,而是接近于正态分布,即:大多数书写规范的数字5图片都会获得较高分数,并集中于某一高分区间内;大多数书写规范的非数字5图片都会获得较低分数,并集中于某一低分区间内,也就是说:如果我们把预测是数字5的图片得分和预测是非数字5的图片得分绘制成曲线,则大概率它们会形成两条正态分布曲线,并且还会有一定交叠区域,这张图看上去就是类似下面右侧子图的样子:
分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion
这个图是解释ROC曲线形状最好的一张图了,我们看右侧的样本得分曲线,X轴本应是得分,Y轴就是得此分数的样本数量,但是为了和左图呼应,X轴实际取的是得分的倒数,也就是说:当阈值θ自左向右移动时,其实是得分从大变小的过程,这一点从TP在左TN在右也能推断出来,所以不必在意,重要的是在阈值θ自左向右移动的过程中,首先是TP样本数量开始增加,并且增量迅速,这就意味着TPR在急速增长,所以映射到左图大概就是(0,0.1)这段区间上发生的事情,当θ越过了TP曲线的中点后,TP增速就开始放缓了,并且此时开始逐渐出现FP样本,这会导致左图中作为分子的TPR增速放缓,同时作为分母的FPR可以增长,这会导致曲线的增长速度加速放缓,反应到左图大概就是(0.1,0.2)这段区间上发生的事情,再之后,随着阈值θ移动到TN曲线的中心线位置,作为分子的TPR已经基本不会再变化了,而作为分母的FPR却进入了急速增长期,导致曲线基本接近一条水平直线,反应到左图大概就是(0.2,1)这段区间上发生的事情。同样的道理,换用下面这张图表一样能直观地解释曲线的形状的由来:
分类模型评估:混淆矩阵、准确率、召回率、ROC,AIML笔记,混淆矩阵,准确率,召回率,权衡,confusion
以上,是对ROC曲线的解释,这个曲线有一个很大的用处就是帮助我们找到收益最大的阈值。先抛开曲线不谈,在ROC平面上,最理想的点位无疑是(0,1)这个点,它代表着预测为真和预测为假的结果全对,没有任何误判,但实际上,这很难做到,所以一般的ROC曲线都不太可能经过该点,所以曲线上最佳的点无疑就是那个离(0,1)最近的点,也就是连线最短的那个点!而这个点在presion-recall曲线上是找不出来。当你的场景对准确率和召回率没有偏向性时,那么ROC曲线上的这个点就是一个最佳选择!

6. 概念汇总

  • 准确率 ( Precision )

    在所有“预测为真”(TP+FP)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫准确率 ( Precision ),计算公式:
    P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP + FP} Precision=TP+FPTP

  • 召回率 ( Recall )

    在所有“实际为真”(TP + FN)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫召回率 ( Recall ),其实也就是真阳性率 ( True Positive Rate,TPR ),计算公式:
    R e c a l l = T P T P + F N Recall=\frac{TP}{TP + FN} Recall=TP+FNTP

  • 真阳性率 ( True Positive Rate,TPR )

    在所有“实际为真”(FN + TP)的样本中,有多少是“预测对了”(TP)的? 这个百分比叫真阳性率(TPR),其实也就是召回率(Recall),计算公式:
    T r u e   P o s i t i v e   R a t e   ( T P R ) = T P F N + T P True \ Positive \ Rate\ (TPR)= \frac{TP}{FN + TP} True Positive Rate (TPR)=FN+TPTP

  • 真阴性率 ( True Negative Rate,TNR )

    在所有“实际为假”(TN + FP)的样本中,有多少是“预测对了”(TN)的? 这个百分比叫真阴性率(TNR),计算公式:
    T r u e   N e g a t i v e   R a t e   ( T P R ) = T N T N + F P True \ Negative \ Rate\ (TPR)= \frac{TN }{TN + FP} True Negative Rate (TPR)=TN+FPTN

  • 假阳性率 ( False Positice Rate,FPR )

    在所有“实际为假”(TN + FP)的样本中,有多少是“预测错了”(FP)的? 这个百分比叫假阳性率(FPR),计算公式:
    F a l s e   P o s i t i v e   R a t e   ( F P R ) = F P T N + F P False\ Positive \ Rate\ (FPR)= \frac{FP}{TN + FP} False Positive Rate (FPR)=TN+FPFP

  • 假阴性率 ( False Negative Rate,FNR )
    在所有“实际为真”(FN + TP)的样本中,有多少是“预测错了”(FN)的? 这个百分比叫假阴性率(TNR)
    F a l s e   N e g a t i v e   R a t e   ( F N R ) = F N F N + T P False\ Negative \ Rate\ (FNR)= \frac{FN}{FN+TP} False Negative Rate (FNR)=FN+TPFN

以上所有概念,只有准确率是以预测数据为参照(作分母)进行度量的,真阳性率、真阴性率、假阳性率、假阴性率都是以实际数据为参照(作分母)进行度量的。以下是它们之间存在的一些关系:

召回率 ( R e c a l l ) = 真阳性率 ( T P R ) 召回率 ( Recall ) = 真阳性率 ( TPR ) 召回率(Recall)=真阳性率(TPR)
真阳性率 ( T P R ) + 假阴性率 ( F N R ) = 1 真阳性率 ( TPR ) + 假阴性率( FNR )= 1 真阳性率(TPR)+假阴性率(FNR)=1
真阴性率 ( T N R ) + 假阳性率 ( F P R ) = 1 真阴性率 ( TNR ) + 假阳性率( FPR )= 1 真阴性率(TNR)+假阳性率(FPR)=1

参考资料:

机器学习之分类性能度量指标 : ROC曲线、AUC值、正确率、召回率文章来源地址https://www.toymoban.com/news/detail-737901.html

到了这里,关于分类模型评估:混淆矩阵、准确率、召回率、ROC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python计算分类问题的评价指标(准确率、精确度、召回率和F1值,Kappa指标)

    机器学习的分类问题常用评论指标有:准确率、精确度、召回率和F1值,还有kappa指标 。 每次调包去找他们的计算代码很麻烦,所以这里一次性定义一个函数,直接计算所有的评价指标。 每次输入预测值和真实值就可以得到上面的指标值,很方便。 下面是这些指标的计算公

    2024年01月21日
    浏览(37)
  • 在分类任务中准确率(accuracy)、精确率(precision)、召回率(recall)和 F1 分数是常用的性能指标,如何在python中使用呢?

    在机器学习和数据科学中,准确率(accuracy)、精确率(precision)、召回率(recall)和 F1 分数是常用的性能指标,用于评估分类模型的性能。 准确率是模型预测正确的样本数占总样本数的比例。 精确率是指在预测为正的样本中,实际为正的比例。它关注的是预测为正的样本

    2024年01月19日
    浏览(33)
  • 模型评估指标(一)Top-5和Top-1准确率

    在看论文里面提到Top-5和top-1错误率,看了有点懵,所以去了解了一下 举个例子: 我们在训练完某个分类网络后,假设我们需要分类的数量为50类,我们需要评估它的分类性能。输入测试集的每张图片,会得到它的50个类别的的概率。 Top-5准确率 就是:在这张测试的图片50的类

    2024年02月08日
    浏览(70)
  • 【超详细】机器学习sklearn之分类模型评估 混淆矩阵、ROC曲线、召回率与精度、F1分数

    机器学习之分类模型的评估 学习分类模型评估的方法: 1、混淆矩阵 2、分类结果汇总 3、ROC曲线 4、召回率与精度 5、F1分数 一、评估分类器性能的度量 1、真正(true positive, TP)或f++,对应的是被分类模型正确预测的正样本数。 2、假负(false negative, FN)或f±对应的是被分类模型错

    2023年04月08日
    浏览(78)
  • ML分类模型的评估量 —— 混淆矩阵、查准率、查全率、正确率、F1值

    Some Metrics suitable for machine learning classification model - Confusion Matrix, Precision Score, Recall Score and F1 Score. 本文意在介绍,监督学习(Supervised Learning)中,几个常被用于评估 分类模型 的 指标 (model metric),并讨论它们在二分类模型和多分类模型中的具体计算方法。 图 1 混淆矩阵(

    2024年02月07日
    浏览(32)
  • 【机器学习】准确率、精确度、召回率和 F1 定义

            数据科学家选择目标变量后 - 例如他们希望预测电子表格中的“列”,并完成了转换数据和构建模型的先决条件,最后步骤之一是评估模型的性能。         选择性能指标通常取决于要解决的业务问题。假设您的数据集中有 100 个示例,并且您已将每个示例输

    2024年02月12日
    浏览(32)
  • 准确率、精确率、召回率、F1-score

    TP(True Positives):真正例,即正例预测为真(预测为正例而且实际上也是正例); FP(False Positives):假正例,即负例预测为真(预测为正例然而实际上却是负例); FN(false Negatives):假负例,即正例预测为假(预测为负例然而实际上却是正例); TN(True Negatives):真负例,即

    2024年02月03日
    浏览(37)
  • 准确率,精准率,召回率,真正率,假正率,ROC/AUC

      最近在看到这些词得时候老是混淆,看了之后还很容易遗忘,于是查了些资料把他们记录下来。 我们在设计深度学习网络模型的时候经常要对其进行评估,评估就要用到这些东西,在接介绍这个率,那个率之前,我先来介绍下什么是混淆矩阵,如下表所示: 混淆矩阵:

    2024年02月06日
    浏览(44)
  • 谈谈召回率(R值),准确率(P值)及F值

    通俗解释机器学习中的召回率、精确率、准确率,一文让你一辈子忘不掉这两个词 赶时间的同学们看这里:提升精确率是为了不错报、提升召回率是为了不漏报 先说个题外话,暴击一下乱写博客的人,网络上很多地方分不清准确率和精确率,在这里先正确区分一下精确率和

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包