项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

在各种算法中,向量计算是最常用的一种操作之一。传统的向量计算,学过中学数学的同学也能明白怎么做。但在现在的大数据环境下,数据一般都会比较稀疏,因此稀疏向量的计算,跟普通向量计算,还是存在一些不同。

首先,我们定义两个向量:
A=[x1,x2,⋯,xn]A=[x_1, x_2,\cdots,x_n]A=[x1​,x2​,⋯,xn​]
B=[y1,y2,⋯,yn]B=[y_1, y_2,\cdots,y_n]B=[y1​,y2​,⋯,yn​]
定义A、B的点积为A∗BA*BA∗B,要求A∗B=?A*B=?A∗B=?

最简单粗暴的方式

最直接的方式,当然就是按中学时候就学过的方法:
A∗B=x1∗y1+x2∗y2+⋯+xn∗ynA*B=x_1*y1 + x_2*y_2 + \cdots + x_n*y_nA∗B=x1​∗y1+x2​∗y2​+⋯+xn​∗yn​
先不考虑乘法与加法的区别,也不考虑计算精度问题。如果按上述方式进行计算,总共进行了n次乘法,n-1次加法,总复杂度为2n-1。矩阵乘法的基本计算单元是向量之间的乘法,复杂度为n3n^3n3。
在现在的大数据环境之下,n可能会很大,比如在计算广告,或者文本分类中,上百万维都是很正常的。而且这种向量都有一个特点,那就是很稀疏。如果没有很稀疏这个特点,那后面自然就无从谈起了。。。

第一种思路

对于稀疏向量,自然而然的可以想到按一下方式进行存储:
A:{<x1:location1>,<x2:location2>,⋯,<xi,locationi>}A:\{<x1:location1>,<x2:location2>,\cdots,<x_i,locationi>\}A:{<x1:location1>,<x2:location2>,⋯,<xi​,locationi>}
B:{<y1:location1>,<y2:location2>,⋯,<yj,locationj>}B:\{<y1:location1>,<y2:location2>,\cdots,<y_j,locationj>\}B:{<y1:location1>,<y2:location2>,⋯,<yj​,locationj>}
因为是稀疏向量,所以 i≪n,j≪ni \ll n,j \ll ni≪n,j≪n

具体在计算A*B的时候,可以在向量A中循环,然后在向量B中进行二分查找。例如,在向量A中取出第一个非零元素,假设为<x1,location1><x1,location1><x1,location1>,在B中对location1进行二分。如果找到,计算乘积,如果找不到,自然为0.
那我们来估算一下算法的复杂度。在B中二分的复杂度为logjlogjlogj,A的长度为iii,则这部分的总复杂度为ilogjilogjilogj,加法的最大情况为min(i,j)−1min(i,j)-1min(i,j)−1,总的复杂度为ilogj+min(i,j)−1ilogj+min(i,j)-1ilogj+min(i,j)−1

继续优化

当然,如果我们知道iii , jjj 的大小,可以在小的向量上循环,在大的向量上二分,这样复杂度可以降低为 min(i,j)log(max(i,j))+min(i,j)−1min(i,j)log(max(i,j))+min(i,j)-1min(i,j)log(max(i,j))+min(i,j)−1
如果咱们不用二分查找,而是使用hash,则二分查找部分可以变为hash。假设hash的复杂度为1,那么总的复杂度为2min(i,j)2min(i,j)2min(i,j)。当然,我们忽略了创建hash的复杂度,以及hash碰撞的复杂度。
这样,总的复杂度就由最初的2n−12n-12n−1降到了2min(i,j)2min(i,j)2min(i,j)。

并行

如果n特别特别大,比如凤巢系统动不动就是号称上亿维度。这样i,j也不会特别小。如果是两个矩阵相乘,咱们前面提到的,复杂度为n3n^3n3,这样就必须上并行计算了。搞数据的同学,对并行肯定不陌生,这里不再细述了。

代码验证

以上都是理论分析,为了验证实际中的运行效果,特意编写了一部分测试代码。测试代码如下

#!/usr/bin/env python
#coding:utf-8'''
Created on 2016年4月22日@author: lei.wang
'''import time#二分查找
def bin_search(num,list):low = 0high = len(list) - 1while(low <= high):middle = (low + high) / 2if list[middle] > num:high = middle - 1elif list[middle] < num:low = middle + 1else:return middlereturn -1def t1():all = 1000000sparse_rate = 1000vec_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] = 1sum = 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:",sumdef t2():all = 1000000sparse_rate = 1000vec_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] = 1sum = 0start = 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()printprintt2()

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

cost time is: 0.002319
sum is: 1000cost time is: 0.123861
sum is: 1000

可以看出,遍历的方式是二分查找的方式的54倍!按上述咱们的分析方式,遍历的方式应该是2∗1062*10^62∗106 的复杂度,二分查找的方式应该是103∗log100010^3 * log1000103∗log1000,即10410^4104 左右的复杂度。二分查找的方式比遍历的方式应该要快100倍左右。根据咱们实验的结果来看,数量级上来说基本是差不多的。如果采取一些优化方式,比如用python自带的binset模块,应该会有更快的速度。

如果改变上述代码中的稀疏度,即改变sparse_rate的数值,例如将sparse_rate由1000改为10000,运行的结果如下:

cost time is: 0.000227
sum is: 100cost time is: 0.118492
sum is: 100

如果将sparse_rate改为100,运行的结果为:

cost time is: 0.034885
sum is: 10000cost time is: 0.124176
sum is: 10000

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

稀疏向量计算优化小结相关推荐

  1. lucene索引文件大小优化小结

    lucene索引文件大小优化小结 1 数值数据类型索引优化 1.1 数值类型索引问题 lucene本质上是一个全文检索引擎而非传统的数据库系统,它基于倒排索引,非常适合处理文本,而处理数值类型却不是强 ...

  2. HBase在淘宝的应用和优化小结

    本文来自于NoSQLFan联合作者@koven2049,他在淘宝从事Hadoop及HBase相关的应用和优化.对Hadoop.HBase都有深入的了解,本文就是其在工作中对HBase的应用优化小结,分 ...

  3. 参观中央财经大学机房安装centos6.4及优化小结

    老男孩教育外包项目带领学生实战练兵,由老男孩老师规划设计方案,内部学生师兄执行实施,内部学生参与实践的项目! 参观中央财经大学机房并安装centos6.4及优化小结 今天老男孩老师安排莫XX同学带我去 ...

  4. 代码测试,调试与优化小结

    http://www.cppblog.com/cuijixin/default.html?page=8 代码测试.调试与优化的小结 by falcon<zhangjinw@gmail.com&g ...

  5. 随机生成稀疏矩阵_面向异构众核超级计算机的大规模稀疏计算性能优化研究

    点击上方蓝字关注我们 面向异构众核超级计算机的大规模稀疏计算性能优化研究 胡正丁, 薛巍 清华大学计算机科学与技术系,北京 100084 论文引用格式: 胡正丁, 薛巍.面向异构众核超级计算机的大规模 ...

  6. 面向异构众核超级计算机的大规模稀疏计算性能优化研究

    点击上方蓝字关注我们 面向异构众核超级计算机的大规模稀疏计算性能优化研究 胡正丁, 薛巍 清华大学计算机科学与技术系,北京 100084 论文引用格式: 胡正丁, 薛巍.面向异构众核超级计算机的大规模 ...

  7. 移动 web 开发问题和优化小结

    [转] 作者:守候 segmentfault.com/a/1190000011338800 1.前言 到目前为止,互联网行业里,手机越来越智能化,移动端占有的比例越来越高,尤其实在电商,新闻,广告,游 ...

  8. 移动web开发问题和优化小结

    1.前言 到目前为止,互联网行业里,手机越来越智能化,移动端占有的比例越来越高,尤其实在电商,新闻,广告,游戏领域.用户要求越来越高,网站功能越来越好,效果越来越炫酷,这就要求我们产品质量越来越高,w ...

  9. SQL Server 2016 查询存储性能优化小结

    SQL Server 2016已经发布了有半年多,相信还有很多小伙伴还没有开始使用,今天我们来谈谈SQL Server 2016 查询存储性能优化,希望大家能够喜欢 作为一个DBA,排除SQL Ser ...

  10. javascript --- [读书笔记] 回流与重绘 前端优化小结

    1. 浏览器渲染原理 请说出: 从用户在浏览器地址输入网址,到看整个页面,中间都发生了哪些事情? HTTP请求阶段 HTTP响应阶段 浏览器渲染阶段 1.1 可能用到的知识 1.1.1 进程 Proc ...

最新文章

  1. 汇编语言随笔(10)-内中断及实验12(返回到dos的中断处理程序)
  2. Apache 2,4版本 编译与安装 RedHat enterprises 6.2
  3. 【控制】传递函数拉氏变化如何与时间域结合使用举例
  4. Python:列表、集合等交集、并集、差集、非集简介及其代码实现之详细攻略
  5. java 手风琴二级菜单_jQuery多级手风琴菜单实例讲解
  6. IP层:尽力交付,可能丢包,可能重包,可能无序
  7. 鸿蒙系统怎么换windows,求助~鸿蒙系统windows环境搭建(hpm-cli安装失败)!
  8. kafkatemplate无法注入_Spring-Kafka(三)-KafkaTemplate发送消息及结果回调
  9. ANDROID窗体跳转
  10. Linux中的sh+source+export
  11. 5.1、python remove和del的区别,python 循环删除元素
  12. 正则表达式:JS在一段HTML文字中找出所有img标签的src属性
  13. Landsat-8 介绍
  14. Duplicate zip entry
  15. Python 五个知识点搞定作用域
  16. 轻松在线绘制进化树和增加热图注释
  17. win10+centOS7双系统安装步骤记录
  18. 一些前端的开发环境配置
  19. 怎么开启linux的dhcp,怎么开启DHCP服务器啊
  20. 李子柒方面否认年入1.68亿,造谣者居然这样回应...

热门文章

  1. linux系统--C语言程序开发的基本步骤(包含gcc的基本步骤)
  2. 4-MSP430定时器_定时器中断
  3. fg、bg、jobs、、nohup、ctrl + z命令
  4. phpmyadmin误删表后如何恢复
  5. Postgresql 插入json数据
  6. Python自然语言处理学习笔记(64): 7.5 命名实体识别
  7. T-SQL数据类型的细微差别(四)
  8. python BeautifulSoup对应关系
  9. java循环练习:输出1+2+3....+100的和
  10. DataRow[] /数组转换datatable!