大数据技术 稀疏向量学习
沉沙 2018-10-12 来源 : 阅读 1225 评论 0

摘要:本篇教程探讨了大数据技术 稀疏向量学习,希望阅读本篇文章以后大家有所收获,帮助大家对大数据技术的理解更加深入。

本篇教程探讨了大数据技术 稀疏向量学习,希望阅读本篇文章以后大家有所收获,帮助大家对大数据技术的理解更加深入。

<


在各种算法中,向量计算是最常用的一种操作之一。传统的向量计算,学过中学数学的同学也能明白怎么做。但在现在的大数据环境下,数据一般都会比较稀疏,因此稀疏向量的计算,跟普通向量计算,还是存在一些不同。
首先,我们定义两个向量: A=[x1,x2,?,xn] B=[y1,y2,?,yn] 定义A、B的点积为A?B,要求A?B=?
最简单粗暴的方式
最直接的方式,当然就是按中学时候就学过的方法: A?B=x1?y1+x2?y2+?+xn?yn 先不考虑乘法与加法的区别,也不考虑计算精度问题。如果按上述方式进行计算,总共进行了n次乘法,n-1次加法,总复杂度为2n-1。矩阵乘法的基本计算单元是向量之间的乘法,复杂度为n3。 在现在的大数据环境之下,n可能会很大,比如在计算广告,或者文本分类中,上百万维都是很正常的。而且这种向量都有一个特点,那就是很稀疏。如果没有很稀疏这个特点,那后面自然就无从谈起了。。。
第一种思路
对于稀疏向量,自然而然的可以想到按一下方式进行存储: A:{,,?,} B:{,,?,} 因为是稀疏向量,所以 i?n,j?n
具体在计算A*B的时候,可以在向量A中循环,然后在向量B中进行二分查找。例如,在向量A中取出第一个非零元素,假设为,在B中对location1进行二分。如果找到,计算乘积,如果找不到,自然为0. 那我们来估算一下算法的复杂度。在B中二分的复杂度为logj,A的长度为i,则这部分的总复杂度为ilogj,加法的最大情况为min(i,j)?1,总的复杂度为ilogj+min(i,j)?1
继续优化
当然,如果我们知道i , j 的大小,可以在小的向量上循环,在大的向量上二分,这样复杂度可以降低为 min(i,j)log(max(i,j))+min(i,j)?1 如果咱们不用二分查找,而是使用hash,则二分查找部分可以变为hash。假设hash的复杂度为1,那么总的复杂度为2min(i,j)。当然,我们忽略了创建hash的复杂度,以及hash碰撞的复杂度。 这样,总的复杂度就由最初的2n?1降到了2min(i,j)。
并行
如果n特别特别大,比如凤巢系统动不动就是号称上亿维度。这样i,j也不会特别小。如果是两个矩阵相乘,咱们前面提到的,复杂度为n3,这样就必须上并行计算了。搞数据的同学,对并行肯定不陌生,这里不再细述了。
代码验证
以上都是理论分析,为了验证实际中的运行效果,特意编写了一部分测试代码。测试代码如下
#!/usr/bin/env python
#coding:utf-8


import time

#二分查找
def bin_search(num,list):
    low = 0
    high = len(list) - 1
    while(low <= high):
        middle = (low + high) / 2
        if list[middle] > num:
            high = middle - 1
        elif list[middle] < num:
            low = middle + 1
        else:
            return middle
    return -1

def t1():
    all = 1000000
    sparse_rate = 1000
    vec_a = [0 for i in range(all)]
    vec_b = [0 for i in range(all)]

    list_none_zero = [sparse_rate*i for i in range(all / sparse_rate)]
    for i in list_none_zero:
        vec_a[i] = vec_b[i] = 1

    sum = 0

    #a,b分别不为0的位置
    location_a = [i for i in range(0,all,sparse_rate)]
    location_b = [i for i in range(0,all,sparse_rate)]

    start = time.clock()
    for i in location_a:
        location = bin_search(i, location_b) #对应a不为0的位置,在b不为0的位置数组中查找是否存在
        if location != -1:
            sum += vec_a[i] * vec_b[location_b[location]] #如果存在,将结果相加
    end = time.clock()

    print "cost time is:",(end-start)
    print "sum is:",sum

def t2():
    all = 1000000
    sparse_rate = 1000
    vec_a = [0 for i in range(all)]
    vec_b = [0 for i in range(all)]

    list_of_none_zero = [sparse_rate*i for i in range(all / sparse_rate)]
    for i in list_of_none_zero:
        vec_a[i] = vec_b[i] = 1

    sum = 0

    start = time.clock()
    for i in range(all):
        sum += vec_a[i] * vec_b[i]
    end = time.clock()

    print "cost time is:",(end-start)
    print "sum is:",sum       

if __name__ == ‘__main__‘:
    t1()
    print
    print
    t2()


bin_search是自己实现的二分查找,t1方法是用上面说到的二分查找的方式,t2方法就是最简单的直接遍历相乘的方式。 在mac上运行以上代码,结果如下:
cost time is: 0.002319
sum is: 1000


cost time is: 0.123861
sum is: 1000



可以看出,遍历的方式是二分查找的方式的54倍!按上述咱们的分析方式,遍历的方式应该是2?106 的复杂度,二分查找的方式应该是103?log1000,即104 左右的复杂度。二分查找的方式比遍历的方式应该要快100倍左右。根据咱们实验的结果来看,数量级上来说基本是差不多的。如果采取一些优化方式,比如用python自带的binset模块,应该会有更快的速度。
如果改变上述代码中的稀疏度,即改变sparse_rate的数值,例如将sparse_rate由1000改为10000,运行的结果如下:
cost time is: 0.000227
sum is: 100


cost time is: 0.118492
sum is: 100



如果将sparse_rate改为100,运行的结果为:
cost time is: 0.034885
sum is: 10000


cost time is: 0.124176
sum is: 10000


很容易看出来,对于遍历的方式来说,不管稀疏度为多少,耗时都是基本不变的。但是对于我们采用二分查找的方式来说,稀疏度越高,节省的计算资源,就越可观。
   

本文由职坐标整理发布,学习更多的大数据技术相关知识,请关注职坐标大技术云计算大技术技术频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程