ML基础——分类模型的评估指标

以鸢尾花的分类分析为例:

首先我们对于3类分类做了个数字编码,012对应3个分类,

所以这就是3个分类下的预测结果指标:
分类为0的准确率、召回率、F1-score,以及support

因为前面我们数据集划分为了105 train:45 test,所以右边这里的support是每个类别都有多少样本,比如说0的support是17,就是说这45样本的test集中,实际标签为0的样本有17个。

F1-score是precision和recall的调和平均。
最后三行是各个指标计算结果的平均值,宏平均和加权平均(最后一列除外);

accuracy不用说了,看下文部分的定义,可以通过相关模块进行评估;

至于macro或weighted等指标计算,其实很简单,

可以参考:
https://mp.weixin.qq.com/s/2Sw_YpDZWGEi4bA2R0VsVw

解释如下:

一,分类:准确率、召回率、精确率和相关指标

真正例、假正例和假负例用于计算评估模型的几个实用指标。哪些评估指标最有意义,取决于具体模型和具体任务、不同错误分类的代价,以及数据集是平衡的还是不平衡的。

本部分中的所有指标均基于单个固定阈值计算得出,并且会随阈值的变化而变化。很多时候,用户会调整阈值以优化其中某个指标。

参考https://developers.google.com/machine-learning/crash-course/classification/accuracy-precision-recall?hl=zh-cn

1,准确率(Accuracy)

准确性是指所有分类(无论是正类还是负类)正确分类的比例。其数学定义为:

在垃圾邮件分类示例中,准确度衡量的是所有电子邮件正确分类所占的比例

完美的模型没有假正例和假负例,因此准确率为 1.0,即 100%。

由于精度包含混淆矩阵中的所有四种结果(TP、FP、TN、FN),因此在数据集平衡且两个类别中的示例数量相近的情况下,精度可以用作衡量模型质量的粗略指标。因此,它通常是执行通用或未指定任务的通用或未指定模型使用的默认评估指标。

不过,如果数据集不平衡,或者一种错误(假负例或假正例)的代价高于另一种错误(大多数实际应用中都是如此),则最好改为针对其他指标进行优化。

对于严重不均衡的数据集(其中一个类别出现的频率非常低,例如 1%),如果模型 100% 都预测为负类,则准确率得分为 99%,尽管该模型毫无用处。

注意:在机器学习 (ML) 中,recallprecisionaccuracy 等字词的数学定义可能与这些字词的常用含义不同,或更具体。

from sklearn.metrics import accuracy_score
accuracy = accuracy_score(Y_test, pre_res)
print(f'Accuracy: {accuracy}')

2,召回率或真正例率/真阳性率(Recall)

真正例率 (TPR,真阳性),即所有实际正例(正确分类的就是TP,错误分类的就是FN)正确分类为正例的比例,也称为召回率。

在数学上,召回率的定义为:

假负例(假阴性)是指被误分类为负例的实际正例,因此会出现在分母中。在垃圾邮件分类示例中,召回率衡量的是被正确分类为垃圾邮件的垃圾邮件电子邮件的比例。因此,召回率的另一个名称是检测概率:它可以回答“此模型检测到垃圾邮件的比例是多少?”这一问题。

假设一个完美的模型,其假负例率(假阴性)为 0,因此召回率 (TPR) 为 1.0,也就是说,检测率为 100%。

在实际正例数量非常少(例如总共 1-2 个样本)的不均衡数据集中,召回率作为指标的意义不大,作用不大。

from sklearn.metrics import recall_score

recall = recall_score(Y_test, pre_res)
print(f'Recall: {recall}')

和下面的precision一样,对于二分类可以像上面那样处理,但是多分类的话需要加其他参数;

from sklearn.metrics import recall_score

recall_micro = recall_score(Y_test, pre_res, average='micro')
print(f'Recall: {recall_micro}')

recall_macro = recall_score(Y_test, pre_res, average='macro')
print(f'Recall: {recall_macro}')

recall_weighted = recall_score(Y_test, pre_res, average='weighted')
print(f'Recall: {recall_weighted}')

3,假正例率/假阳性率

假正例率 (FPR) 是指被错误地归类为正例的在所有实际负例所占的比例,在所有实际负样本中假阳性所占的比例,也称为误报概率。其数学定义为:

假正例是被错误分类的实际负例,因此会出现在分母中。在垃圾邮件分类示例中,FPR 用于衡量被错误分类为垃圾邮件的合法电子邮件的比例,或模型的误报率。

完美的模型没有假正例,因此 FPR 为 0.0,也就是说,假警报率为 0%。

在实际负例数量非常少(例如总共 1-2 个示例)的不平衡数据集中,FPR 作为一个指标就没有那么有意义和实用。

4,精确率(Precision)

精确率是指模型所有正分类分类中实际正分类的比例,所有被分成阳性的样本中真阳性的比例。在数学上,其定义为:

在垃圾邮件分类示例中,精确率衡量的是被归类为垃圾邮件的电子邮件中实际是垃圾邮件的比例

假设有一个完美的模型,则该模型没有假正例(假阳性率),因此精确率为 1.0。

在实际正例数量非常少(例如总共 1-2 个示例)的不平衡数据集中,精确率作为指标的意义和实用性较低。

from sklearn.metrics import precision_score
precision = precision_score(Y_test, pre_res)
print(f'Precision: {precision}')

如果是2分类可以参照上面的方法进行操作,否则:

多分类问题:

precision_micro = precision_score(Y_test,pre_res,average='micro')
print(f'Precision (micro): {precision_micro}')

precision_macro = precision_score(Y_test, pre_res, average='macro')
print(f'Precision (macro): {precision_macro}')

precision_weighted = precision_score(Y_test, pre_res, average='weighted')
print(f'Precision (weighted): {precision_weighted}')

5,关于精确率precision和召回率recall:

随着假正例的减少,精确率会提高;随着假负例的减少,召回率会提高。

但正如前面所述,提高分类阈值往往会减少假正例的数量并增加假负例的数量,而降低阈值则会产生相反的效果。

所以,改变分类阈值——》影响FP、FN数目——》共轭影响precision和recall,且两个是呈反函数关系

因此,精确率和召回率通常呈反函数关系,其中一个提高improve会恶化另一个worsen

(1)可视化总结

(2)指标的选择和权衡

在评估模型和选择阈值时,您选择优先处理的指标取决于特定问题的费用、收益和风险。在垃圾邮件分类示例中,通常最好优先考虑召回率(抓取所有垃圾邮件)或准确率(尝试确保被标记为垃圾邮件的电子邮件实际上是垃圾邮件),或者在达到某个最低准确性水平的情况下,兼顾这两者。

指标指南
准确率作为平衡数据集的模型训练进度/收敛情况的粗略指标。
对于模型效果,请仅与其他指标搭配使用。
避免使用不平衡的数据集。考虑使用其他指标。
召回率 (真正例率)在假负例比假正例开销更高时使用。
假正例率在假正例比假负例开销更高时使用。
精确率当正例预测的准确性非常重要时,请使用此方法。

(3)F1-score

调和平均值大家中学学均值不等式应该都了解,上链接:
https://zh.wikipedia.org/wiki/%E8%B0%83%E5%92%8C%E5%B9%B3%E5%9D%87%E6%95%B0

所以F1-score就是recall和precision的二数的调和平均数,也就是鱼与熊掌兼得

同样的,需要区分是2分类还是多分类任务:否则会报错

from sklearn.metrics import f1_score
f1 = f1_score(Y_test, pre_res, average='macro')
print("F1-score:", f1)

from sklearn.metrics import f1_score

f1_micro = f1_score(Y_test, pre_res, average='micro')
print("F1-score:", f1_micro)

f1_macro = f1_score(Y_test, pre_res, average='macro')
print("F1-score:", f1_macro)

f1_weighted = f1_score(Y_test, pre_res, average='weighted')
print("F1-score:", f1_weighted)

一些练习用来掌握回顾:

二,wiki中的分类模型评估指标扩展

1,ROC曲线

完美的模型是没有Fx率的(也就是没有F开头的比率的),所以套进去公式看看,加上一点简单的数学

参考https://zh.wikipedia.org/wiki/ROC%E6%9B%B2%E7%BA%BF

受试者操作特征曲线,ROC曲线

这里就不得不提混淆矩阵了,基本上本科低年级学过数理统计的都应该倒背如流相应的概念

ROC曲线:假阳x,真阳y

x轴是假阳性率(FPR,假阳,那就是从阴性样本来考虑——》所有实际为阴性的样本中,被错误归类为阳性的样本FP比例)

y轴是真阳性率(TPR,真阳,那就是从阳性样本来考虑——》所有实际为阳性的样本中,被正确归类为阳性的样本TP比例)

然后在训练过程中,模型会迭代,

对于过程中的某一个模型+某一个阈值,我们都能计算出它的混淆矩阵等所有分类评估指标,那自然就能算出x轴以及y轴代表的模型指标,也就是说每个过程中的模型都能计算出1个坐标点(x,y);

然后完美的模型是没有F开头的比率的(就是完美的模型是不会产出假阳性假阴性假xxx的),所以结合x轴以及y轴的定义:

完美的模型就是TPR(y轴)=1,FPR(x轴)=0,也就是完美的模型的结果坐标点是(0,1),也就是左上角的点

然后非常差的模型就是没有T开头的比例,就是没有真阳真阴,都是假阳假阴,只有F开头的比例,

那就是(1,0),就是右下角;

如果是随机的预测,那就是55开,也就是说混淆矩阵中每一列(注意是列)下面的值应该是55开,

那再结合x轴以及y轴定义,那就是TP/FN 55开,FP/TN 55开,那就是(0.5,0.5),

准确来说,如果是无识别的话,那么TPR=FPR(这里需要意译理解,联合上面的0.5),

也就是对角线;

如果模型分类效果好,比随机好,那就是TPR会好点>FPR(T开头的比率比F开头的比率好),也就是y>x,在对角线上,反之下;

然后上面是指模型+阈值定下来之后绘制的单个点,考虑不同模型不同阈值,会有各种可能性;

如果我们只考虑某种模型,然后将阈值进行修改(一般高于阈值是P阳性,低于阈值是N阴性)
那某个模型在阈值改动之后绘制出来的(x,y)模型评估指标坐标,就是该模型的ROC曲线

上面的这个分布图很好理解,上面蓝色的是所有实际上为阴性的样本,下面红色的是所有实际为阳性的样本;

然后竖线是阈值,阈值往上、右边是阳性(预测、评估为阳性),阈值左边为阴性;

那对于上面的蓝色图,在阈值竖线左边的就是实际为阴性,然后预测为阴性的,那就是真阴性;阈值竖线右边的就是实际为阴性,但是根据阈值预测为阳性的,也就是假阳性。

下面红色同样分类,竖线左侧是实际为阳性,被分类、被预测为阴性,假阴性;竖线右侧是实际上为阳性也被分类为阳性,就是真阳性。

下面的图也好理解:
阈值改动之后,如何理解ROC曲线中的(x,y)模型预测坐标如何移动;

如果阈值很高时,比如说是A点,或者是往阈值很高方向移动时

我们分别看竖线阈值左右两侧的数目比例,TP会变小,FP会变大,TN增大,FP减小,

然后总的分母FP+TN=all N不变(就是蓝色的总面积),同样红色的总面积,对应分母TP+FN=all P不变。

那么分母不变,我们看分子,TP和FP都会变小,所以会向(0,0)移动;

也就是说阈值变高,ROC曲线中的坐标点会偏向(0,0)左下角移动;

阈值变低,同样分析趋势,就是偏向(1,1)右上角移动;

====》

AUC,其实就是ROC曲线下的面积,严谨来说应该是AUC ROC

就是将面积积分起来

具体如何从数学意义上去理解AUC,可以在后续博客中深入

如果是2分类的话,绘制ROC曲线可以是:

import numpy as np
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt

# 假设 y_true 是真实标签,y_prob 是预测的正类概率
y_true = np.array([0, 1, 1, 0, 1, 0])
y_prob = np.array([0.1, 0.4, 0.35, 0.8, 0.7, 0.2])

# 计算ROC曲线
fpr, tpr, thresholds = roc_curve(y_true, y_prob)

# 计算AUC值
auc = roc_auc_score(y_true, y_prob)

# 绘制ROC曲线
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()

print(f'AUC: {auc}')

我们现在主要是看多分类:
多分类的话需要从multiclass中导入OneVsRestClassifier函数,就是搞1 vs rest,强行凑2分类

from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.multiclass import OneVsRestClassifier
import matplotlib.pyplot as plt

# 使用OneVsRestClassifier处理多分类问题
classifier = OneVsRestClassifier(ldc)
y_prob = classifier.fit(X_train_spca, Y_train).predict_proba(X_test_spca)

# 计算每个类别的ROC曲线和AUC
for i in range(y_prob.shape[1]):
	fpr, tpr, _ = roc_curve(Y_test == i, y_prob[:, i])
	auc = roc_auc_score(Y_test == i, y_prob[:, i])
	plt.plot(fpr, tpr, label='Class {} (AUC = {:.2f})'.format(i, auc))

plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.show()

获取元祖的1索引,也就是列数

然后每一列,首先roc_curve提供真实y标签(test set)以及评估

本质上绘制的就是散点图,可以参考我的上一篇博客:
https://blog.csdn.net/weixin_62528784/article/details/145360599?spm=1001.2014.3001.5501

总之代码解释如下:

2,其他指标:

阳性 (P, positive)

阴性 (N, Negative)

真阳性 (TP, true positive)

正确的肯定。又称:命中 (hit)

真阴性 (TN, true negative)

正确的否定。又称:正确拒绝 (correct rejection)

伪阳性 (FP, false positive)

错误的肯定,又称:假警报 (false alarm),第一型错误

伪阴性 (FN, false negative)

错误的否定,又称:未命中 (miss),第二型错误

真阳性率 (TPR, true positive rate)

又称:命中率 (hit rate)、敏感度(sensitivity)

TPR = TP / P = TP / (TP+FN)

伪阳性率(FPR, false positive rate)

又称:错误命中率,假警报率 (false alarm rate)

FPR = FP / N = FP / (FP + TN)

准确度 ****(ACC, accuracy)

ACC = (TP + TN) / (P + N)

即:(真阳性+真阴性) / 总样本数

真阴性率 (TNR)

又称:特异度 (SPC, specificity)

SPC = TN / N = TN / (FP + TN) = 1 - FPR

阳性预测值 (PPV)

PPV = TP / (TP + FP)

阴性预测值 (NPV)

NPV = TN / (TN + FN)

假发现率 (FDR)

FDR = FP / (FP + TP)

Matthews相关系数 (MCC),即 Phi相关系数

F1评分

F1 = 2TP/(P+P’)

交叉熵损失:这个在DL深度学习多分类中就很常见了,softmax之后用cross entropy

如果是二分类,类似

from sklearn.metrics import log_loss
y_true = [0, 1, 1, 0, 1, 0]
y_prob = [0.2, 0.8, 0.9, 0.4, 0.7, 0.3]

loss = log_loss(y_true, y_prob)
print(f'Log Loss: {loss}')

多分类:

from sklearn.metrics import log_loss

# 计算交叉熵损失
loss = log_loss(Y_test, pd.get_dummies(pre_res), labels=[0, 1, 2])
print(f'Log Loss: {loss}')

3,上述指标的实现

(1)混淆矩阵:

from sklearn.metrics import confusion_matrix
cm = confusion_matrix(Y_test, pre_res)
print(cm)

这个混淆矩阵大家都很熟悉了,三分类的

当然只是个array难看,最常见的就是可视化,用seaborn

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix


# 计算混淆矩阵
cm = confusion_matrix(Y_test, pre_res)
print(cm)

# 可视化混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Class 0', 'Class 1', 'Class 2'], yticklabels=['Class 0', 'Class 1', 'Class 2'])
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.title('Confusion Matrix')
plt.show()

(2)AUC/ROC的可视化见前面

(3)最基本的统计指标的分析也见前面

总结

指标适用场景特点
准确率(Accuracy)适用于类别平衡数据集简单直观,但在类别不平衡时不可靠
精确率(Precision)偏重减少假正例(FP)的场景,如垃圾邮件检测关注正类预测的精确性
召回率(Recall)偏重减少假负例(FN)的场景,如疾病诊断关注正类样本的识别率
F1值(F1 Score)当精确率和召回率同等重要时平衡精确率和召回率的权衡
AUC-ROC适合类别不平衡的数据集,评估模型整体性能显示模型的分类能力,尤其适用于不平衡数据集
混淆矩阵直观展示分类结果,适用于二分类和多分类问题展示每个类的分类情况,特别适合多分类问题
交叉熵损失(Cross Entropy Loss)主要用于多分类任务衡量概率分布差异,通常在深度学习中使用

每个分类评估指标都有特定的应用场景,选择合适的指标有助于更好地理解模型性能并针对问题进行优化。

参考:
https://developers.google.com/machine-learning/crash-course/classification/accuracy-precision-recall?hl=zh-cn

https://zh.wikipedia.org/wiki/ROC%E6%9B%B2%E7%BA%BF

https://mp.weixin.qq.com/s/YyzU67doaB_btbnUE6Q_Bg

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安装Office自定义项,安装期间出错

个人博客地址:安装Office自定义项,安装期间出错 | 一张假钞的真实世界 卸载PowerDesigner后,打开“WPS文字”时出现下图错误: 解决方法: 按“WinR”快捷键,打开【运行】框,在对话框中输入“re…

Arouter详解・常见面试题

前言:ARouter是一个用于 Android App 进行组件化改造的路由框架 —— 支持模块间的路由、通信、解耦。 一、路由简介: 路由:就是通过互联的网络把信息从源地址传输到目的地址的活动。完成路由这个操作的实体设备就是 路由器(Rout…

能量提升法三:赞美

前情回顾: 《能量提升法二:感恩》 片段:“感恩,就像是在跟世界说:谢谢你,我收到了,我很喜欢,请多来点” 把它归还人海,就当作每一个人,都有可能是曾经帮助…

翼星求生服务器搭建【Icarus Dedicated Server For Linux】

一、前言 本次搭建的服务器为Steam平台一款名为Icarus的沙盒、生存、建造游戏,由于官方只提供了Windows版本服务器导致很多热爱Linux的小伙伴无法释怀,众所周知Linux才是专业服务器的唯一准则。虽然Github上已经有大佬制作了容器版本但是容终究不够完美,毕竟容器无法与原生L…

Java编程语言:辉煌的历史与未来前景

如果将软件开发世界比喻成一个宇宙,Java 无疑是其中最亮的星星之一。它从诞生起就改变了软件开发世界的格局。发展到今天,Java仍然是这个世界上最重要的编程语言之一。当然,它也面临着新的挑战。 Java的诞生 回溯到 1991 年,在 …

为什么噪声不是过拟合的原因?

直观解释:为什么噪声不是过拟合的原因?又什么只要没有过拟合就一定有噪声?_哔哩哔哩_bilibili

【JavaWeb06】Tomcat基础入门:架构理解与基本配置指南

文章目录 🌍一. WEB 开发❄️1. 介绍 ❄️2. BS 与 CS 开发介绍 ❄️3. JavaWeb 服务软件 🌍二. Tomcat❄️1. Tomcat 下载和安装 ❄️2. Tomcat 启动 ❄️3. Tomcat 启动故障排除 ❄️4. Tomcat 服务中部署 WEB 应用 ❄️5. 浏览器访问 Web 服务过程详…

C语言【基础篇】之流程控制——掌握三大结构的奥秘

流程控制 🚀前言🦜顺序结构💯 定义💯执行规则 🌟选择结构💯if语句💯switch语句💯case穿透规则 🤔循环结构💯for循环💯while循环💯do -…

sunrays-framework配置重构

文章目录 1.common-log4j2-starter1.目录结构2.Log4j2Properties.java 新增两个属性3.Log4j2AutoConfiguration.java 条件注入LogAspect4.ApplicationEnvironmentPreparedListener.java 从Log4j2Properties.java中定义的配置读取信息 2.common-minio-starter1.MinioProperties.…

【Elasticsearch】内置分词器和IK分词器

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

简易版RAG实现

之前玩过一次RAG(检索增强生成),链接,十分简陋,现在已经无用了,时隔1年半以后又再需要实现一次。其实现在做RAG已经算相对成熟了,要求不高的话甚至可以直接跑langchain-chatchat这类现成的。因为…

指针的介绍2后

1.二级指针 1.1二级指针的介绍 二级指针是指向指针的指针 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {int a 100;int* pa &a;int** ppa &pa;printf("a %d\n", a);printf("&a(pa) %p\n", pa);prin…

Android开发基础知识

1 什么是Android&#xff1f; Android&#xff08;读音&#xff1a;英&#xff1a;[ndrɔɪd]&#xff0c;美&#xff1a;[ˈnˌdrɔɪd]&#xff09;&#xff0c;常见的非官方中文名称为安卓&#xff0c;是一个基于Linux内核的开放源代码移动操作系统&#xff0c;由Google成立…

【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)

羑悻的小杀马特.-CSDN博客羑悻的小杀马特.擅长C/C题海汇总,AI学习,c的不归之路,等方面的知识,羑悻的小杀马特.关注算法,c,c语言,青少年编程领域.https://blog.csdn.net/2401_82648291?typebbshttps://blog.csdn.net/2401_82648291?typebbs 在本篇文章中&#xff0c;博主将带…

一个基于Python+Appium的手机自动化项目~~

本项目通过PythonAppium实现了抖音手机店铺的自动化询价&#xff0c;可以直接输出excel&#xff0c;并带有详细的LOG输出。 1.excel输出效果: 2. LOG效果: 具体文件内容见GitCode&#xff1a; 项目首页 - douyingoods:一个基于Pythonappium的手机自动化项目&#xff0c;实现了…

【Unity3D】实现Decal贴花效果,模拟战旗游戏地形效果

目录 一、基础版 二、Post Process 辉光Bloom效果 矩形渐隐 涉及知识点&#xff1a;Decal贴花、屏幕后处理Bloom、屏幕空间构建世界空间、ChracterController物体移动、Terrain地形创建 一、基础版 Unity 2019.4.0f1 普通渲染管线&#xff08;非URP、非HDRP&#xff09; UR…

03:Heap代码的分析

Heap代码的分析 1、内存对齐2、Heap_1.c文件代码分析3、Heap_2.c文件代码分析4、Heap_4.c文件代码分析5、Heap_5.c文件代码分析 1、内存对齐 内存对齐的作用是为了CPU更快的读取数据。对齐存储与不对齐存储的情况如下&#xff1a; 计算机读取内存中的数据时是一组一组的读取的…

javascript-es6 (一)

作用域&#xff08;scope&#xff09; 规定了变量能够被访问的“范围”&#xff0c;离开了这个“范围”变量便不能被访问 局部作用域 函数作用域&#xff1a; 在函数内部声明的变量只能在函数内部被访问&#xff0c;外部无法直接访问 function getSum(){ //函数内部是函数作用…

自动驾驶中的多传感器时间同步

目录 前言 1.多传感器时间特点 2.统一时钟源 2.1 时钟源 2.2 PPSGPRMC 2.3 PTP 2.4 全域架构时间同步方案 3.时间戳误差 3.1 硬件同步 3.2 软件同步 3.2.3 其他方式 ① ROS 中的 message_filters 包 ② 双端队列 std::deque 参考&#xff1a; 前言 对多传感器数据…

方豆子(递归)

方豆子 思路&#xff1a;很典的一道递归题&#xff0c;但当时没想到怎么递归/(ㄒoㄒ)/~~。赛后看了大佬的讲解知道要将这个图形看成由四个小正方形组成的大正方形&#xff0c;递归参数可以设置成&#xff08;r1,c1,r2,c2,good)表示正方形的左上角坐标和右下角坐标以及当前这个正…