说明
L1算法中的核心公式简明易懂,但是从核心的优化式向复杂的迭代式的推导却不是那么简单。本文将针对相关公式进行一次推导,最后根据验证的迭代式进行代码实现。
公式推导
L1核心公式如下:
(1)中 代表sample point集合和单个点,代表原本的点云点集和单个点,代表对应的平衡常数(balancing constants),代表的有向度(directionality degree)。
将看做函数中的变量,则有以下式子
偏微分:
偏微分:
由于式(1.2)和(1.3)中的系数 和在实际运算中近似为1和-1,所以系数可以直接去掉,直接保留符号即可。
最终去掉系数的化简式如下:
P.S. 原论文,但是按照(1.3)计算,此处采用的是3次方的这个定义。
化简式又可以提取为:
根据新的斥力系数定义(刊误:原论文里使用公式为,经分析应为笔误),可将(2.2)化简为:
简单移项后可得:
使用不动点迭代[1]推导出迭代公式:
可以看到,(3.1)和迭代公式(4)已经基本一毛一样了。
代码实现
整个迭代的流程包括:
- 计算邻居(self neighbor 和origin neighbor)
- 计算项(computeAlphasTerms)和项(computeBetasTerms)
- 根据和计算新的迭代坐标(公式4)
- 重复上述步骤直到满足停止条件
迭代函数
double L1median::iterateReturnError()
{
/*位置迭代更新*/
paraPtr->add("neighborhood_size", h);
for (int i = 0; i < sampleInfo.size(); ++i) {
sampleInfo[i].kind = (sampleInfo[i].kind == pi::Candidate) ? pi::Sample : sampleInfo[i].kind;
}
computeAlphasTerms();
computeBetasTerms();
double error = updateSamplePos();
emit infoSignal("RMS:" + QString::number(error, 'f', 6)+'\n');
/*位置同步*/
if (synSampleWithInfo()) {
emit iterateSignal();
} else {
emit errorSignal(QString("fail to synchronize sample info"));
return 0.0;
}
/*位置更新后的预备信息计算*/
computeNeighbors();
computeSigmas();
return error;
}
其它具体实现部分过于复杂,此处按下不表,有时间可能另开一章进行说明。