前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何使用python处理稀疏矩阵

如何使用python处理稀疏矩阵

作者头像
用户3578099
发布2020-05-20 16:08:41
3.4K0
发布2020-05-20 16:08:41
举报
文章被收录于专栏:AI科技时讯AI科技时讯

大多数机器学习从业者习惯于在将数据输入机器学习算法之前采用其数据集的矩阵表示形式。矩阵是一种理想的形式,通常用行表示数据集实例,用列表示要素。

稀疏矩阵是其中大多数元件是零矩阵。这与稠密矩阵相反,稠密矩阵元素多。

通常,我们的数据是密集的,拥有的每个实例填充特征列。如果使用有限的列来可靠地描述某些事物,则通常为给定数据点分配的描述性值已被剪掉,以提供有意义的表示:一个人,一张图像,一个虹膜,房价,潜在的信用风险等。

但是某些类型的数据在其表示中不需要这种冗长的描述。比如关系。可能需要捕获大量潜在事物以获取其关系状态,但是在这些事物的交集处,可能需要简单地记录是,存在关系或不存在。

此人是否购买了该物品?那句话中有这个词吗?任何给定的句子中都有很多可能出现的单词,但实际上并不是很多。同样,可能有很多物品要出售,但是任何个人都不会购买很多物品。

这是稀疏矩阵在机器学习中起作用的一种方式。将一栏描绘成要销售的商品,将行描绘成购物者。对于每个给定购物者未购买给定项目的路口,将有一个“ no”(空)表示形式,例如0。只有给定购物者所购买给定项目的路口才需要有一个“是”表示形式,例如1。给定句子中给定单词的出现也是如此。你会看到为什么这样的矩阵包含多个零,这意味着它们将是稀疏的。

稀疏矩阵带来的一个问题是,它们可能会占用很大的内存。假设采用标准的方法来表示2x2矩阵,则尽管没有捕获到有用的信息,也需要在内存中为每个空表示进行分配。此内存分配也继续用于永久存储。在矩阵表示的标准方法中,也不得不记录事物的不存在,而不是简单地记录事物的存在。

事实上,一定有更好的方法!

碰巧有。稀疏矩阵不必以标准矩阵形式表示。有很多方法可以缓解这种标准形式给我们的计算系统带来的压力,而且恰恰是这种情况使得流行的Python机器学习主力Scikit-learn中的某些算法接受了这些稀疏表示中的一些作为输入。熟悉可以节省时间,精力。

我们如何更好地表示这些稀疏矩阵?我们需要一种方法来跟踪零不在哪里。那么关于列表,我们在其中一个列中跟踪row,col非零项目的存在以及在另一列中其对应值的情况呢?请记住,稀疏矩阵不必只包含零和一。只要大多数元素为零,无论非零元素中存在什么,矩阵都是稀疏的。

我们还需要创建稀疏矩阵的顺序, 我们是一行一行地行进,在遇到每个非零元素时存储它们,还是一列一列地进行?如果我们决定逐行进行,那么刚刚创建了一个压缩的稀疏矩阵。如果按列,则现在有一个压缩的稀疏矩阵。方便地,Scipy对两者都支持。

让我们看一下如何创建这些矩阵。首先,我们在Numpy中创建一个简单矩阵。

代码语言:javascript
复制
import numpy as np
from scipy import sparse

X = np.random.uniform(size=(6, 6))
print(X)
代码语言:javascript
复制
[[0.79904211 0.76621075 0.57847599 0.72606798 0.10008544 0.90838851]
 [0.45504345 0.10275931 0.0191763  0.09037216 0.14604688 0.02899529]
 [0.92234613 0.78231698 0.43204239 0.61663291 0.78899765 0.44088739]
 [0.50422356 0.72221353 0.57838041 0.30222171 0.25263237 0.55913311]
 [0.191842   0.07242766 0.17230918 0.31543582 0.90043157 0.8787012 ]
 [0.71360049 0.45130523 0.46687117 0.96148004 0.56777938 0.40780967]]

然后,我们需要将大多数矩阵元素归零,使其稀疏。

代码语言:javascript
复制
X[X < 0.7] = 0
print(X)

代码语言:javascript
复制
[[0.79904211 0.76621075 0.         0.72606798 0.         0.90838851]
 [0.         0.         0.         0.         0.         0.        ]
 [0.92234613 0.78231698 0.         0.         0.78899765 0.        ]
 [0.         0.72221353 0.         0.         0.         0.        ]
 [0.         0.         0.         0.         0.90043157 0.8787012 ]
 [0.71360049 0.         0.         0.96148004 0.         0.        ]]

现在,我们将标准矩阵X存储为压缩的稀疏行矩阵。为此,要从左到右逐行遍历元素,并在遇到它们时将其输入到此压缩矩阵表示中。

压缩稀疏矩阵又如何呢?为了创建它,元素被逐列从上到下遍历,并在遇到它们时输入到压缩表示中,

代码语言:javascript
复制
X_csr = sparse.csr_matrix(X)
print(X_csr)

代码语言:javascript
复制
  (0, 0)  0.799042106215471
  (0, 1)  0.7662107548809229
  (0, 3)  0.7260679774297479
  (0, 5)  0.9083885095042665
  (2, 0)  0.9223461264672205
  (2, 1)  0.7823169848589594
  (2, 4)  0.7889976504606654
  (3, 1)  0.7222135307432606
  (4, 4)  0.9004315651436953
  (4, 5)  0.8787011979799789
  (5, 0)  0.7136004887949333
  (5, 3)  0.9614800409505844

注意所得的稀疏矩阵表示之间的差异,特别是相同元素值的位置差异。

代码语言:javascript
复制
X_csc = sparse.csc_matrix(X)
print(X_csc)

代码语言:javascript
复制
  (0, 0)  0.799042106215471
  (2, 0)  0.9223461264672205
  (5, 0)  0.7136004887949333
  (0, 1)  0.7662107548809229
  (2, 1)  0.7823169848589594
  (3, 1)  0.7222135307432606
  (0, 3)  0.7260679774297479
  (5, 3)  0.9614800409505844
  (2, 4)  0.7889976504606654
  (4, 4)  0.9004315651436953
  (0, 5)  0.9083885095042665
  (4, 5)  0.8787011979799789

如前所述,许多Scikit学习算法都接受scipy.sparse形状矩阵在[num_samples, num_features]Numpy数组中的位置,因此,目前并没有迫切要求将它们转换回标准Numpy表示形式。可能还有内存限制阻止这样做(请记住,这是采用此方法的主要原因之一)。但是,仅出于演示目的,这里介绍了如何将稀疏的Scipy矩阵表示形式转换回Numpy多维数组。

代码语言:javascript
复制
print(X_csr.toarray())

代码语言:javascript
复制
[[0.79904211 0.76621075 0.         0.72606798 0.         0.90838851]
 [0.         0.         0.         0.         0.         0.        ]
 [0.92234613 0.78231698 0.         0.         0.78899765 0.        ]
 [0.         0.72221353 0.         0.         0.         0.        ]
 [0.         0.         0.         0.         0.90043157 0.8787012 ]
 [0.71360049 0.         0.         0.96148004 0.         0.        ]]

两种表示形式在内存需求上的区别又如何呢?让我们再次进行该过程,首先从标准Numpy形式的较大矩阵开始,然后计算每个表

代码语言:javascript
复制
import numpy as np
from scipy import sparse

X = np.random.uniform(size=(10000, 10000))
X[X < 0.7] = 0
X_csr = sparse.csr_matrix(X)

print(f"Size in bytes of original matrix: {X.nbytes}")
print(f"Size in bytes of compressed sparse row matrix: {X_csr.data.nbytes + X_csr.indptr.nbytes + X_csr.indices.nbytes}")
代码语言:javascript
复制
Size in bytes of original matrix: 800000000
Size in bytes of compressed sparse row matrix: 360065312

从上述可以看到, 压缩矩阵形式在标准Numpy表示形式上享有的显着内存节省,大约从原先的800m变为360m。鉴于格式之间的转换得到了高度优化,这节省了440 MB,且几乎没有时间开销。显然,也可以直接创建这些稀疏的SciPy矩阵,从而节省了临时的占用内存的步骤。

总结

之后遇到处理一个大的数据集,并考虑通过适当地使用稀疏矩阵格式节省内存。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技时讯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档