Coco学编程(二)--直接选择排序

博客围绕Python编程展开,先对直接插入排序进行改进,介绍直接选择排序算法,通过交换节点移动元素减少插入和删除操作,还探讨了该算法对内存碎片化的影响。此外,讲解了递归的概念,以欧几里德算法为例给出递归和迭代的程序示例。

Coco:这么长时间不来,我还真想大家,实在是某人太懒了,总也不来上课。

我:这个……还真是对不起啊。主要是因为最近找了份新工作,正在赶一个项目,比较忙一些。经常会有天黑才回来的事情,所以有很长一段时间没有出现。

Coco:据我所知~某人天黑才会回家,是因为在广州总迷路,每次坐在车上的时间还没有找路的时间长,而且,还因为一些很菜的程序问题被卡住了……

我:为什么总要揭我的短呀……-_-#

Cocohoho,上课上课~

我:好吧,上次讲了直接插入排序,我们从改进它开始。这几天,你对这个算法有什么想法没有?

Coco:在书上读到,在容器中反复的插入和删除节点是一种很低效的做法,不但速度慢,还会造成内存的碎片化,是这样子的吧。

我:很正确,所以通常来说,我们应该想办法减少插入和删除的次数。这样可以有效避免内存的碎片化。

Coco:不过对于选择插入法来说,我们只移动出现逆序的节点了,还有什么办法能更进一步减少这插入和删除的操作吗?

我:有一个办法,就是不用delInsert进行显示的删除和插入操作,充分利用容器现有的空间,以交换节点来移动它。

Coco:不太理解。

我:由些产生的最简单的方法,用简单的数学描述来讲,是这样子的,假设集合有{a1, a2, a3,…, an},我们先从整个区间中找出最小的一个元素am,如果它不等于a1,就把它和a1交换;然后查找[a2, a3,…, an]区间,在其中找出最小的元素,如果它不等于a2,就把它和a2交换;重复这一过程,就可以对整个数组排序了。

Coco:看起来很简单呀,我去试试,测试代码段就还用上次的喽~

#以下是Coco的代码:

#Direct choice sort. It is a sample method.

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

def DrtChcSort(theArray):

#Move the begin of search area.

for i in range(len(Array)):

curMrk = i

#Find the min node.

for j in range(i, len(theArray)):

if theArray[j] < theArray[curMrk]:

curMrk = j

#Move it to front.

if not(curMrk == i):

theArray[curMrk], theArray[i] = theArray[i], theArray[curMrk]

Array=[6,16,10,9,15,5,11,1,19,4,14,18,0,13,3,17,12,2,8,7]

print Array

DrtChcSort(Array)

print Array

Coco:这办法比上次那个简单多了嘛,为什么当初不教我这个?

我:要你写这些算法又不是真要你实用,主要是练习一下。要不然,对python的数组排序最简单的办法应该是:Array.sort()

Coco:倒~好吧,算你说的有道理,不过这样直接交换链表中的元素:“theArray[curMrk], theArray[i] = theArray[i], theArray[curMrk]”真的可以保证内存不会碎片化,还能减少插入和删除吗?

我:老实说,我不知道,因为python对这个线性容器的操作被封装了起来,从我们这个使用层上,是看不到的。不过,我们至少避免了显示的增删操作。如果说这样编程是“可能会有坏结果”,那显示的增删操作则是“几乎一定会有坏结果”,如果在C语言这类直接操作内存的语言中,两者的效果就是很明确的了。

Coco:为什么说“几乎”?

我:因为python有它的内存管理机制,它可以进行垃圾回收,所以内存的碎片化和丢失,还是会受到控制,特别是jython,由于使用java平台,基本上不存在内存方面的困扰。不过,过于依赖它也不是好主意,至少会给虚拟机带来不必要的负担。

Coco:听起来有道理的样子,我还有一个疑问,在这个排序中,我们把当前已排序间后面的那个元素直接与未排序区间中的最小元素交换了,这会不会造成后面的未排序区间越来越乱,给我们带来额外的麻烦呢?

我:这种交换的确有增加混乱――形像的说,就像热学中的“熵”――的可能,不过如果这个算法只考虑某一个链表,也就基本上没有什么用途了。而从统计角度讲,未排序区间的“熵”

不会因此而增加。

Coco:明白了,不过这个算法太简单了,再多讲点东西吧。

我:上次有个朋友问递归的含义,你知道吗?

Coco:递推多项式,一种表达式,每一项由前一项使用的公式来决定。

我:怎么看着这么眼熟啊,从哪里贴来的?

Coco:这么快就让你看出来了啊,《金山词霸》喽~

我:倒……真会偷懒,简单的说,递归的就是指一个方法中会使用它自身。

Coco:听起来怪怪的,给个程序让我们看看吧。

我:欧几里德算法,辗转相除求最大公因子,如何?你来写这个程序吧,也不是多难

Coco:真会偷懒~

def Gba(a, b):

r = a%b

if r == 0:

return b

else:

return (b, r)

Coco:调用这个函数就可以得到ab的最大公因子了。这种通过调用自身来进入下一步的函数就是一种递归函数吧。

我:是的,与之相对应的运算方法是迭代,也就是说通过某种方法重新记录当前状态,然后循环生成这一状态的算法,这样不用重复调用函数,在效率上比递归要好,不过可读性通常会差一些。比如以上这个Gba(a, b)的递归形式应该是这样子:

def Gba(a, b):

r = a%b

while r!=0:

a, b = b, r

r = a%b

return b

Coco:好像明白点儿了。接下来呢?

我:上次去cn99新闻组上问你说的那个很菜的问题时,有位叫Chad Netzer的朋友写了一个不错的回应,虽然我的问题很菜(Coco:这个笨蛋会不知道在python里怎么交换元素,也敢出来教别人,我真是遇人不淑呀~),但这位朋友写的回信比我的问题更有价值,如果明天有空,我把它译出来给大家分享一下。不过今天先这样吧,这两天感冒,不太舒服,明天还要上班。

Coco:感冒了不早说,别传染给我,闪~

<think>嗯,用户想要准确理解目标检测中mAP50和mAP50-95的计算公式,特别是数实现细节。从他的提问风格看,可能是算法工程师或研究生,正在实现目标检测模型的评估模块。用户特意强调"可能是为了实现或理解相关算法",说明需要可落地的技术细节而非概念科普。关于mAP计算的核心难点在于理解三个层次:IoU的计算、单类别AP的积分近似、多类别平均。需要分步骤拆解:第一步应该讲清楚IoU作为基础指标的定义。IoU公式是交并比$IoU=\frac{|A\capB|}{|A\cupB|}$,这个看似简单,但在实际计算中涉及边界框坐标处理。如果使用COCO数据集格式(xmin,ymin,width,height),交并比计算需要特别注意坐标转换时的边界情况。针对mAP50的计算,关键在于固定IoU阈值0.5时的处理流程:1)按置信度对检测结果排序;2)计算精度-召回率曲线时要注意去重机制——每个真实框只能匹配一次检测结果;3)计算曲线下面积应采用插值法,通常用11点插值(0,0.1,...,1)而非简单梯形法则。用户提到的mAP50-95更有挑战性。这里存在双重平均:首先在每个IoU阈值(0.5:0.05:0.95)单独计算mAP,然后对所有阈值结果取算术平均。实际编程时要优化计算量,可复用排序后的检测结果,仅根据IoU阈值变化重新匹配。COCO评估工具中会跳过某些阈值的计算以节省时间。应用场景的差异需要强调实例分割的特性:当检测无人机小目标时,mAP50-95更重要,因为0.5的IoU可能框住多个目标;而在自动驾驶中行人检测可能更关注mAP50,避免漏检更重要。医疗影像分析通常要求更高的IoU阈值。回复考虑设计表格展示主要开源框架的API差异:MMDetection中eval_hooks的设置方式,Detectron2的COCOEvaluator参数解析。这样方便用户直接参考现有实现。</think> 以下是mAP50与mAP50-95的详细计算公式解析及应用场景说明,结合目标检测的核心概念逐步展开: --- ### **一、核心前置概念** 1. **IoU(交并比)** $IoU = \frac{|B_{pred} \cap B_{gt}|}{|B_{pred} \cup B_{gt}|}$ ($B_{pred}$: 预测框,$B_{gt}$: 真实框) 2. **精度(Precision)与召回率(Recall)** - **精度** $P = \frac{TP}{TP + FP}$ (正确检测/总预测阳性) - **召回率** $R = \frac{TP}{TP + FN}$ (正确检测/总真实目标) (TP: 正确检测,FP: 误检,FN: 漏检) --- ### **、mAP50 计算公式** 1. **定义**:仅在 IoU ≥ 0.5 时判定为正确检测(TP)[^1]。 2. **计算流程**: - **Step 1**:对每个类别分别计算精度-召回率曲线 (P-R Curve) - **Step 2**:计算P-R曲线下面积 → 得到 **AP(Average Precision)** $$AP = \int_0^1 P(R) dR \approx \sum_{k=1}^{N} P(k) \cdot \Delta R(k)$$ (实际计算采用插值法,如COCO标准使用11点插值[^3]) - **Step 3**:对所有类别的AP取平均 → **mAP50** $$mAP50 = \frac{1}{C} \sum_{c=1}^{C} AP_c \bigg|_{IoU=0.5}$$ ($C$: 类别总数) --- ### **三、mAP50-95 计算公式** 1. **定义**:在 IoU 从 0.5 到 0.95(步长0.05)共10个阈值下的综合性能[^2]。 2. **计算流程**: - **Step 1**:对每个 IoU 阈值(0.5, 0.55, ..., 0.95)单独计算 mAP - **Step 2**:对10个阈值的 mAP 取算术平均 $$mAP50\text{-}95 = \frac{1}{10} \sum_{t=0.5}^{0.95} mAP_t \quad (t \in \{0.50, 0.55, \dots, 0.95\})$$ --- ### **四、应用场景对比** | **指标** | **适用场景** | **特点** | |----------------|----------------------------------------------------------------------------|------------------------------------------| | **mAP50** | - 基础目标检测任务(如人脸检测)<br>- 对定位精度要求较低的场景 | 宽松评估,注重目标是否存在 | | **mAP50-95** | - 高精度定位任务(如自动驾驶、医疗影像)<br>- 模型鲁棒性验证 | 严格评估,反映模型对边界框偏差的敏感性 | > **关键差异**:mAP50仅评估“目标是否被大致框出”,而mAP50-95要求“边界框高度精确”,后者更接近实际应用需求[^2]。 --- ### **五、公式实现伪代码** ```python # 计算单类别的AP (IoU阈值固定) def calculate_AP(detections, gt_boxes, iou_thresh=0.5): # 1. 按置信度降序排序检测框 detections.sort(key=lambda x: x.confidence, reverse=True) # 2. 计算各召回率下的精度 tp_list, fp_list = [], [] for det in detections: iou = compute_iou(det.bbox, matched_gt_box) # 匹配真实框 if iou >= iou_thresh: tp_list.append(1) # 正确检测 else: fp_list.append(1) # 误检 # 3. 生成P-R曲线并积分(插值法) precisions = cumsum(tp_list) / (cumsum(tp_list) + cumsum(fp_list)) recalls = cumsum(tp_list) / total_gt_boxes ap = interpolate_area_under_curve(precisions, recalls) # 11点插值 return ap # 计算mAP50-95 def calculate_mAP50_95(all_classes_detections, gt_datasets): iou_thresholds = [0.5 + 0.05*i for i in range(10)] # [0.5, 0.95] map_scores = [] for thresh in iou_thresholds: aps = [] for class_id in class_list: ap = calculate_AP(detections[class_id], gt_boxes[class_id], iou_thresh=thresh) aps.append(ap) map_scores.append(np.mean(aps)) # 当前阈值mAP return np.mean(map_scores) # mAP50-95 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值