论文《Neighbor-Sensitive Hashing》读后感(四)

来源:互联网 发布:淘宝静物拍摄技巧 编辑:程序博客网 时间:2024/05/16 09:22

参数m的选取

原算法中通过m = c * b (b为哈希码的位数),将c从1~10不断在部分测试数据项上进行尝试,进而选取最合适的参数m。

但是这样会导致以下两个问题:

1.    在所有情况下都要进行10次尝试:时间效率低;

2.    在部分数据项上进行测试,结果未必适用于所有数据项整体。

 

改进的方案:

使用二分法进行参数的测试,减少测试的次数,提高算法的时间效率;

结合k-means算法,区分出多个点群,按照点群的规模,以相应的比例选取测试点,使得选取的参数m更加适合数据项整体。

 

具体的实现:

1.    对所有数据项进行以b为参数了k-means算法,得到b个点群,按照每个点群的规模,成正比例的在每个点群中选取相应数量的随机点,作为测试数据项;

2.    选取c = 5,即m = 5 * b,在测试数据项上运行代码,记录下耗时t5;

3.    选取c = 6,即m = 6 * b,在测试数据项上运行代码,记录下耗时t6;

4.    若t5 > t6,则再次使用二分法,在6~10中选取合适的c的值;否则,在1~5中选取合适的c的值。

 

显然,通过这种方案,我们只需要进行3~4次测试就可以选择出合适的m值,相比于原先在任何情况下进行10次测试而言,即使加上了运行k-means算法的时间,依然可以有效的改进算法的时间效率,另外,通过k-means算法选取出来的测试数据点,也使得参数m的值可以更加适合所有数据项整体。而且,k-means算法可以为下一步改进枢纽点的选取,打下一个良好的基础。

 

枢纽点的选取

在原论文的测试中,k-means策略拥有较高的准确性,但是时间效率相对平均策略而言较低。所以我们的目标,就是让这个算法兼具这两个策略各自的优势。

 

改进的方案:

在上一步中,我们对所有数据项进行了以b为参数的k-means处理,划分了b个点群,虽然b有极大的可能小于真实的参数m,但我们依然可以利用它得到的结果,提高枢纽点选取的准确度和时间效率。

 

具体的实现:

1.    我们将我们得到的b个点群的种子点收录为枢纽点;

2.    在每两个种子点之间,采用平均策略,分别选取c-1个枢纽点;

3.    在最外侧的两个种子点和数据项边界之间,分别平均选取c/2、(c/2 - 1)个枢纽点。

则我们一共得到 c/2 + (c/2 – 1) + b + (b - 1) * (c - 1) = b * c = m 个枢纽点。

 

    显然,在这一步中,我们并没有再次运行k-means算法,而是借用了上一部中的结果,因此这个代码时间效率可以有明显的提升。另外,相比于原先的平均算法,我们枢纽点的分布更加贴合原始数据点的分布,每个枢纽点都可以尽可能大的发挥作用,这提高了选取枢纽点的准确性。

 

不适用于k值较大的情况

哈希码的位数b,是所有kNN算法的一个重要参数。B的值越大,则算法的准确度越高,但是时间效率越低,b的值越小,则算法的时间效率越高,但是准确度越低。

当我们认为选取了一个合适的参数b,即参数b固定时,原算法将更多的位数用来区分邻近的数据项,这必然导致了远端的数据项难以区分,即当参数k的值较大时,算法失效。

 

改进的方案:

按照算法的设计,每个数据项都至少有一个邻近的枢纽点,即不存在某一个数据项,它位于所有枢纽点的远端,因此我们可以通过一个二维数组,记录所有数据项在每个枢纽点的大致方向,当需要处理查询点远端的数据项时,我们可以一圈圈地由内向外地通过枢纽点来猜测该数据项相对于查询点的位置和距离,进而对他们进行区分与选择。

但是,显然这样的算法时间效率很低,占用空间很多(因为往往数据项的数量非常大),且准确度不高(因为我们无法精确的计算方向,而当距离很远时,方向上的一点小偏离都有可能引起很大的误差),所以这不是一个优秀的方案。

 

当然,在我门的面前有另一条十分方便的路可以走,就是利用前人留下的其他优秀的kNN算法,如LSH等。

 

具体的实现:

1.    判断参数k的值,当k较小时,执行步骤2;否则执行步骤3.

2.    运行NSH算法求解;

3.    运行LSH算法求解。

 

显然,这样的组合算法,就可以应对各种各样k的取值了。

0 0
原创粉丝点击