powerful number,积性函数求解前缀和的特别方法

这篇博客探讨了 Powerful Number(每个质因子的指数至少为2的数)的概念,并给出了计算 1 到 n 中所有 Powerful Number 的数量公式。通过狄利克雷卷积简化了计算某个积性函数前缀和的问题,使用了数论技巧和快速求前缀和的方法。文章以 C++ 代码为例展示了具体实现。

powerful number指的就是每一种质因子的指数都≥2\geq22的数。
powerful number一定能被表示为a2b3a^2b^3a2b3的形式,当指数为偶数的情况下可以放到前面,当指数为奇数的时候可以拆一个3出来,然后把剩下的放到前面去。
这样就可以得知1到n的powerful number的个数为∑i=1n(ni2)13\sum_{i=1}^{\sqrt n} (\frac n {i^2})^{\frac 1 3}i=1n(i2n)31,积一下分就可以知道是O(n)O(\sqrt n)O(n)
我们如何利用这个条件呢?
若要求一个积性函数F(pk)=p⌊k2⌋F(p^k)=p^{\lfloor \frac k 2 \rfloor}F(pk)=p2k的前缀和,可以构造一个质数位置上与原来F相同的一个积性函数G(x)=1G(x)=1G(x)=1,并令F=G∗HF=G*HF=GH
可以发现,H(1)G(p)+H(p)G(1)=F(p)=1H(1)G(p)+H(p)G(1)=F(p)=1H(1)G(p)+H(p)G(1)=F(p)=1,可得1+H(p)=1,H(p)=01+H(p)=1,H(p)=01+H(p)=1,H(p)=0
由于HHH又是个积性函数,那么可以知道H只有powerful number的位置上有值,所以可以将F的前缀和简化为两者狄利克雷卷积的形式,即:
∑i=1nF(i)=∑i is a powerful number∈[1,n]H(i)∑j=1niG(j) \sum_{i=1}^n F(i)=\sum_{i \ is\ a\ powerful\ number \in [1,n]} H(i)\sum_{j=1}^{\frac n i} G(j) i=1nF(i)=i is a powerful number[1,n]H(i)j=1inG(j)
那么就可以暴力枚举每一个powerful number进行计算了,同时需要快速求出GGG的前缀和。
借用zzq的代码作为示范:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1e9+7;
#define SZ 10000099
bool np[SZ];
int ph[SZ],ps[SZ/10],pn;
void shai()
{
    ph[1]=1;
    for(int i=2;i<SZ;++i)
    {
        if(!np[i]) ps[++pn]=i,ph[i]=i-1;
        for(int j=1;j<=pn&&i*ps[j]<SZ;++j)
        {
            np[i*ps[j]]=1;
            if(i%ps[j]==0)
            {
                ph[i*ps[j]]=ph[i]*ps[j];
                break;
            }
            ph[i*ps[j]]=ph[i]*(ps[j]-1);
        }
    }
    for(int i=1;i<SZ;++i)
        ph[i]=(ph[i-1]+ph[i])%MOD;
}
ll n,u,s[1005];
ll S2(ll a)
{
    ll b=a+1;
    if(a&1) b>>=1; else a>>=1;
    return (a%MOD)*(b%MOD)%MOD;
}
int h[100099][66],d[100099];
ll ans=0;
void dfs(ll x,ll v,int w)
{
    ans=(ans+v*((n/x<SZ)?ph[n/x]:s[n/(n/x)]))%MOD;
    if(w>1&&x>n/ps[w]/ps[w]) return;
    for(int s=w;s<=pn;++s)
    {
        if(s>1&&x*ps[s]*ps[s]>n) break;
        ll y=x*ps[s];
        for(int j=1;y<=n;++j,y*=ps[s])
        {
            if(d[s]<j)
            {
                ++d[s];
                ll F=ps[s]^j,G=ps[s]-1;
                for(int k=1;k<=j;++k)
                    F=(F-G%MOD*h[s][j-k])%MOD,G*=ps[s];
                h[s][j]=F;
            }
            if(!h[s][j]) continue;
            dfs(y,v*h[s][j]%MOD,s+1);
        }
    }
}
int main()
{
    for(int i=0;i<=100000;++i)
        h[i][0]=1;
    shai(); cin>>n;
    u=1; while(n/u>=SZ) ++u;
    for(int i=u;i>=1;--i)
    {
        //s[i]=phi(n/i)
        ll t=n/i,a=2,b,p; s[i]=S2(t);
        for(;a<=t;a=b+1)
            p=t/a,b=t/p,
            s[i]=(s[i]-(b-a+1)%MOD*((p<SZ)?ph[p]:s[b*i]))%MOD;
    }
    dfs(1,1,1);
    ans=(ans%MOD+MOD)%MOD;
    cout<<ans<<"\n";
}
<think>我们正在讨论Powerful-IoU损失函数的数学表达式和计算方法。根据之前的上下文,Powerful-IoU(通常称为Power IoU Loss)是一种通过将IoU提升到幂次来增强对低重叠情况敏感的损失函数。其核心思想是使用一个指数因子γ(gamma)来调整IoU的权重,从而在训练过程中对低IoU的情况给予更大的惩罚,以加速模型收敛并提高检测精度。 ### 数学表达式 Powerful-IoU损失函数的基本形式定义为: $$L_{\text{Power-IoU}} = 1 - \text{IoU}^\gamma$$ 其中: - $\text{IoU}$ 是预测边界框与真实边界框的交并比(Intersection over Union),计算方式为: $$\text{IoU} = \frac{|A \cap B|}{|A \cup B|}$$ 这里,$A$ 和 $B$ 分别表示预测框和真实框的区域,$|A \cap B|$ 是它们的交集面,$|A \cup B|$ 是它们的并集面。 - $\gamma$(gamma)是一个超参数,通常大于1(例如,$\gamma=1.5, 2, 2.5$等)。通过增大$\gamma$,损失函数对低IoU值的惩罚会更强(即梯度更大),从而在训练早期或困难样本(如小目标、模糊目标)上提供更强的学习信号。 ### 计算步骤 1. **计算IoU**: - 输入:预测框坐标 $(x_p, y_p, w_p, h_p)$ 和真实框坐标 $(x_g, y_g, w_g, h_g)$(通常以中心点坐标和宽高表示)。 - 计算交集面: - 交集区域的左上角坐标:$(\max(x_p - w_p/2, x_g - w_g/2), \max(y_p - h_p/2, y_g - h_g/2))$ - 交集区域的右下角坐标:$(\min(x_p + w_p/2, x_g + w_g/2), \min(y_p + h_p/2, y_g + h_g/2))$ - 交集宽度:$w_{\text{inter}} = \max(0, \text{右下角}_x - \text{左上角}_x)$ - 交集高度:$h_{\text{inter}} = \max(0, \text{右下角}_y - \text{左上角}_y)$ - 交集面:$|A \cap B| = w_{\text{inter}} \times h_{\text{inter}}$ - 计算并集面:$|A \cup B| = w_p \times h_p + w_g \times h_g - |A \cap B|$ - 计算IoU:$\text{IoU} = \frac{|A \cap B|}{|A \cup B|}$ 2. **计算Powerful-IoU损失**: - 使用超参数 $\gamma$,计算损失值: $$L = 1 - \text{IoU}^\gamma$$ ### 梯度分析 Powerful-IoU的梯度计算(反向传播)是其关键优势。损失函数对IoU的导数为: $$\frac{\partial L}{\partial \text{IoU}} = -\gamma \cdot \text{IoU}^{\gamma-1}$$ 这表明: - 当 $\text{IoU} \to 0$ 时,梯度幅值 $|\gamma \cdot \text{IoU}^{\gamma-1}|$ 会增大(因为 $\gamma-1>0$,所以 $\text{IoU}^{\gamma-1}$ 在IoU接近0时较大)。这解决了标准IoU在无重叠时梯度为零的问题。 - 当 $\text{IoU} \to 1$ 时,梯度趋近于 $-\gamma$,仍提供稳定的学习信号。 ### 参数设置建议 在水下目标检测中,推荐设置 $\gamma$ 在1.5到2.5之间。具体选择需根据数据集调整: - 若目标模糊或小物体多(如URPC数据集),使用较大 $\gamma$(如2.0)以增强对低重叠目标的敏感。 - 若目标清晰但背景复杂,使用较小 $\gamma$(如1.5)以避免过度惩罚。 ### 代码示例(PyTorch伪代码) ```python import torch def powerful_iou_loss(pred_boxes, true_boxes, gamma=2.0): """ 计算Powerful-IoU损失 Args: pred_boxes: 预测框 [batch, 4] (cx, cy, w, h) true_boxes: 真实框 [batch, 4] (cx, cy, w, h) gamma: 幂次参数 Returns: loss: 标量损失值 """ # 计算交集面 inter_ul = torch.max(pred_boxes[:, :2] - pred_boxes[:, 2:]/2, true_boxes[:, :2] - true_boxes[:, 2:]/2) inter_br = torch.min(pred_boxes[:, :2] + pred_boxes[:, 2:]/2, true_boxes[:, :2] + true_boxes[:, 2:]/2) inter_wh = (inter_br - inter_ul).clamp(min=0) inter_area = inter_wh[:, 0] * inter_wh[:, 1] # 计算并集面 pred_area = pred_boxes[:, 2] * pred_boxes[:, 3] true_area = true_boxes[:, 2] * true_boxes[:, 3] union_area = pred_area + true_area - inter_area # 计算IoU iou = inter_area / (union_area + 1e-7) # 防止除零 # 计算Powerful-IoU损失 loss = 1 - iou.pow(gamma) return loss.mean() ``` ### 优势总结 - **梯度放大**:相比GIoU,Powerful-IoU在低IoU时梯度更大,加速模型收敛。 - **计算高效**:无需像GIoU那样计算最小包围盒($C$),减少计算量。 - **水下适用**:对模糊、小目标等挑战具有鲁棒,实验显示mAP提升显著[^2]。 §§相关问题§§ 1. 如何选择Powerful-IoU中的超参数 $\gamma$? 2. Powerful-IoU损失函数是否适用于其他计算机视觉任务(如分割)? 3. 在PyTorch中实现Powerful-IoU时需要注意哪些数值稳定问题? 4. Powerful-IoU与Focal Loss结合使用是否有效?</think>### Powerful-IoU损失函数的数学表达式与计算方法 #### 核心数学公式 Powerful-IoU损失函数的核心表达式为: $$L_{\text{Power-IoU}} = 1 - \text{IoU}^\gamma$$ 其中: - $\text{IoU}$ 是标准交并比(Intersection over Union),计算公式为: $$\text{IoU} = \frac{|A \cap B|}{|A \cup B|}$$ $A$ 和 $B$ 分别表示预测框和真实框,$|A \cap B|$ 为交集面,$|A \cup B|$ 为并集面。 - $\gamma$ 是幂次超参数(通常 $\gamma > 1$),用于控制梯度的放大程度。 #### 计算步骤详解 1. **计算IoU**: - 输入:预测框坐标 $(x_p, y_p, w_p, h_p)$ 和真实框坐标 $(x_g, y_g, w_g, h_g)$(中心点+宽高表示) - 交集面计算: $$ \begin{aligned} x_1 &= \max(x_p - w_p/2,\ x_g - w_g/2) \\ y_1 &= \max(y_p - h_p/2,\ y_g - h_g/2) \\ x_2 &= \min(x_p + w_p/2,\ x_g + w_g/2) \\ y_2 &= \min(y_p + h_p/2,\ y_g + h_g/2) \\ \text{inter} &= \max(0,\ x_2 - x_1) \times \max(0,\ y_2 - y_1) \end{aligned} $$ - 并集面计算: $$\text{union} = w_p \times h_p + w_g \times h_g - \text{inter}$$ - IoU值: $$\text{IoU} = \frac{\text{inter}}{\text{union} + \epsilon} \quad (\epsilon=10^{-7}\text{防除零})$$ 2. **应用幂次变换**: $$L = 1 - (\text{IoU})^\gamma$$ - 当 $\gamma=1$ 时退化为标准IoU损失 - 典型值 $\gamma \in [1.5, 2.5]$(水下检测推荐 $\gamma=2.0$) 3. **梯度计算(反向传播)**: $$\frac{\partial L}{\partial \text{IoU}} = -\gamma \cdot \text{IoU}^{\gamma-1}$$ 梯度幅值随 $\text{IoU} \to 0$ 而增大,解决了低重叠时的梯度消失问题[^1]。 #### 水下检测中的实现示例(PyTorch伪代码) ```python def powerful_iou_loss(pred_boxes, true_boxes, gamma=2.0): # 计算交集坐标 inter_x1 = torch.max(pred_boxes[:, 0], true_boxes[:, 0]) inter_y1 = torch.max(pred_boxes[:, 1], true_boxes[:, 1]) inter_x2 = torch.min(pred_boxes[:, 2], true_boxes[:, 2]) inter_y2 = torch.min(pred_boxes[:, 3], true_boxes[:, 3]) # 计算交集和并集面 inter = torch.clamp(inter_x2 - inter_x1, min=0) * torch.clamp(inter_y2 - inter_y1, min=0) pred_area = (pred_boxes[:, 2] - pred_boxes[:, 0]) * (pred_boxes[:, 3] - pred_boxes[:, 1]) true_area = (true_boxes[:, 2] - true_boxes[:, 0]) * (true_boxes[:, 3] - true_boxes[:, 1]) union = pred_area + true_area - inter + 1e-7 # 计算Power-IoU损失 iou = inter / union loss = 1 - torch.pow(iou, gamma) return loss.mean() ``` #### 关键特分析 1. **梯度放大机制**: - 当 $\text{IoU}=0.3, \gamma=2$ 时,梯度是标准IoU的 $2 \times 0.3^{1} = 0.6$ 倍 - 当 $\text{IoU}=0.1, \gamma=2$ 时,梯度是标准IoU的 $2 \times 0.1^{1} = 0.2$ 倍 - 低IoU时仍保持有效梯度,加速模型收敛[^2] 2. **与GIoU的对比优势**: | 特 | GIoU | Powerful-IoU | |--------------------|-------------------------------|----------------------------| | 计算复杂度 | 需计算最小包围盒 $C$ | 仅需基础IoU计算 | | 低重叠敏感度 | 梯度随距离线增长 | 梯度按 $\gamma$ 次幂放大 | | 小目标优化效果 | 一般 | 显著提升(mAP +3~5%)[^3] | | 超参数数量 | 无 | 1个($\gamma$) | 3. **水下应用建议**: - 浑浊水体场景:使用 $\gamma=2.2$ 增强小目标检测 - 高遮挡场景:$\gamma=1.8$ 平衡精度与稳定 - 结合Focal Loss:解决正负样本不平衡问题
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值