前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >scipy.sparse、pandas.sparse、sklearn稀疏矩阵的使用

scipy.sparse、pandas.sparse、sklearn稀疏矩阵的使用

作者头像
悟乙己
发布2021-12-07 14:37:18
1.7K0
发布2021-12-07 14:37:18
举报
文章被收录于专栏:素质云笔记素质云笔记

单机环境下,如果特征较为稀疏且矩阵较大,那么就会出现内存问题,如果不上分布式 + 不用Mars/Dask/CuPy等工具,那么稀疏矩阵就是一条比较容易实现的路。

文章目录

1 scipy.sparse

参考: SciPy 稀疏矩阵笔记 Sparse稀疏矩阵主要存储格式总结 Python数据分析----scipy稀疏矩阵

1.1 SciPy 几种稀疏矩阵类型

SciPy 中有 7 种存储稀疏矩阵的数据结构:

  • bsr_matrix: Block Sparse Row matrix
  • coo_matrix: COOrdinate format matrix
  • csc_matrix: Compressed Sparse Column matrix
  • csr_matrix: Compressed Sparse Row matrix
  • dia_matrix: Sparse matrix with DIAgonal storage
  • dok_matrix: Dictionary Of Keys based sparse matrix
  • lil_matrix: Row-based LInked List sparse matrix

各个类型的用途:

  • 如果想创建一个新的稀疏矩阵,lil_matrix,dok_matrix和coo_matrix会比高效,但是它们不适合做矩阵运算。
  • 如果想做矩阵运算,例如矩阵乘法、求逆等,应该用 CSC 或者 CSR 类型的稀疏矩阵。
  • 由于在内存中存储顺序的差异,csc_matrix 矩阵更适合取列切片,
  • 而 csr_matrix 矩阵更适合用来取行切片。
在这里插入图片描述
在这里插入图片描述

1.2 lil_matrix

这里只说lil_matrix,因为笔者用的这款,且比较方便。 lil_matrix 是第二直观的稀疏矩阵存储方式。它的全称是 row-based linked list sparse matrix 。它包含两个要素:rows 和 data

示例代码一:

代码语言:javascript
复制
>>> from scipy.sparse import lil_matrix
>>> l = lil_matrix((6,5))
>>> l[2,3] = 1
>>> l[3,4] = 2
>>> l[3,2] = 3
>>> print l.toarray()
[[ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  1.  0.]
 [ 0.  0.  3.  0.  2.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]]
>>> print l.data
[[] [] [1.0] [3.0, 2.0] [] []]
>>> print l.rows
[[] [] [3] [2, 4] [] []]

示例代码二:

代码语言:javascript
复制
# 原始矩阵为

array([[1., 0., 0., 0., 0.],
       [0., 0., 2., 0., 3.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 4., 0.],
       [0., 0., 0., 0., 5.]])

mat_lil = sparse.lil_matrix(mat_coo) # 几种稀疏矩阵之间可以相互转化

# mat_lil 的两要素

mat_lil.rows

array([list([0]), list([2, 4]), list([]), list([3]), list([4])],
      dtype=object)

mat_lil.data

array([list([1.0]), list([2.0, 3.0]), list([]), list([4.0]), list([5.0])],
      dtype=object)

示例代码三:

代码语言:javascript
复制
# 创建矩阵
lil = sparse.lil_matrix((6, 5), dtype=int)

# 设置数值
# set individual point
lil[(0, -1)] = -1
# set two points
lil[3, (0, 4)] = [-2] * 2
# set main diagonal
lil.setdiag(8, k=0)

# set entire column
lil[:, 2] = np.arange(lil.shape[0]).reshape(-1, 1) + 1

# 转为array
lil.toarray()
'''
array([[ 8,  0,  1,  0, -1],
       [ 0,  8,  2,  0,  0],
       [ 0,  0,  3,  0,  0],
       [-2,  0,  4,  8, -2],
       [ 0,  0,  5,  0,  8],
       [ 0,  0,  6,  0,  0]])
'''

# 查看数据
lil.data
'''
array([list([0, 2, 4]), list([1, 2]), list([2]), list([0, 2, 3, 4]),
       list([2, 4]), list([2])], dtype=object)
'''
lil.rows
'''
array([[list([8, 1, -1])],
       [list([8, 2])],
       [list([3])],
       [list([-2, 4, 8, -2])],
       [list([5, 8])],
       [list([6])]], dtype=object)
'''

1.3 矩阵的通用属性

矩阵属性

代码语言:javascript
复制
from scipy.sparse import csr_matrix

### 共有属性
mat.shape  # 矩阵形状
mat.dtype  # 数据类型
mat.ndim  # 矩阵维度
mat.nnz   # 非零个数
mat.data  # 非零值, 一维数组

### COO 特有的
coo.row  # 矩阵行索引
coo.col  # 矩阵列索引

### CSR\CSC\BSR 特有的
bsr.indices    # 索引数组
bsr.indptr     # 指针数组
bsr.has_sorted_indices  # 索引是否排序
bsr.blocksize  # BSR矩阵块大小

通用方法

代码语言:javascript
复制
import scipy.sparse as sp

### 转换矩阵格式
tobsr()、tocsr()、to_csc()、to_dia()、to_dok()、to_lil()
mat.toarray()  # 转为array
mat.todense()  # 转为dense
# 返回给定格式的稀疏矩阵
mat.asformat(format)
# 返回给定元素格式的稀疏矩阵
mat.astype(t)  

### 检查矩阵格式
issparse、isspmatrix_lil、isspmatrix_csc、isspmatrix_csr
sp.issparse(mat)

### 获取矩阵数据
mat.getcol(j)  # 返回矩阵列j的一个拷贝,作为一个(mx 1) 稀疏矩阵 (列向量)
mat.getrow(i)  # 返回矩阵行i的一个拷贝,作为一个(1 x n)  稀疏矩阵 (行向量)
mat.nonzero()  # 非0元索引
mat.diagonal()   # 返回矩阵主对角元素
mat.max([axis])  # 给定轴的矩阵最大元素

### 矩阵运算
mat += mat     # 加
mat = mat * 5  # 乘
mat.dot(other)  # 坐标点积


resize(self, *shape)
transpose(self[, axes, copy])

1.4 稀疏矩阵存取

存储 - save_npz

代码语言:javascript
复制
scipy.sparse.save_npz('sparse_matrix.npz', sparse_matrix)
sparse_matrix = scipy.sparse.load_npz('sparse_matrix.npz')

读取 - load_npz

代码语言:javascript
复制
# 从npz文件中读取
test_x = sparse.load_npz('./data/npz/test_x.npz')

存储大小比较

代码语言:javascript
复制
a = np.arange(100000).reshape(1000,100)
a[10: 300] = 0
b = sparse.csr_matrix(a)

# 稀疏矩阵压缩存储到npz文件
sparse.save_npz('b_compressed.npz', b, True)  # 文件大小:100KB

# 稀疏矩阵不压缩存储到npz文件
sparse.save_npz('b_uncompressed.npz', b, False)  # 文件大小:560KB

# 存储到普通的npy文件
np.save('a.npy', a)  # 文件大小:391KB

# 存储到压缩的npz文件
np.savez_compressed('a_compressed.npz', a=a)  # 文件大小:97KB• 1

2 pandas.sparse

Sparse data structures

2.1 SparseArray

代码语言:javascript
复制
In [1]: arr = np.random.randn(10)

In [2]: arr[2:-2] = np.nan

In [3]: ts = pd.Series(pd.arrays.SparseArray(arr))

In [4]: ts
Out[4]: 
0    0.469112
1   -0.282863
2         NaN
3         NaN
4         NaN
5         NaN
6         NaN
7         NaN
8   -0.861849
9   -2.104569
dtype: Sparse[float64, nan]

pandas中sparse变成一种格式,如dtype: Sparse[float64, nan]

2.2 新建SparseDataFrame

之前Pandas版本有:pd.SparseDataFrame(),不过这个在新版本被移除了。

SparseSeries and SparseDataFrame were removed in pandas 1.0.0. This migration guide is present to aid in migrating from previous versions.

一种方式:

代码语言:javascript
复制
# Previous way
>>> pd.SparseDataFrame({"A": [0, 1]})

# New way
In [31]: pd.DataFrame({"A": pd.arrays.SparseArray([0, 1])})
Out[31]: 
   A
0  0
1  1

The SparseDataFrame.default_kind and SparseDataFrame.default_fill_value attributes have no replacement.

另一种方式:

代码语言:javascript
复制
# Previous way
>>> from scipy import sparse
>>> mat = sparse.eye(3)
>>> df = pd.SparseDataFrame(mat, columns=['A', 'B', 'C'])

# New way
In [32]: from scipy import sparse

In [33]: mat = sparse.eye(3)

In [34]: df = pd.DataFrame.sparse.from_spmatrix(mat, columns=['A', 'B', 'C'])

In [35]: df.dtypes
Out[35]: 
A    Sparse[float64, 0]
B    Sparse[float64, 0]
C    Sparse[float64, 0]
dtype: object

第三种新建:

代码语言:javascript
复制
In [38]: dense = pd.DataFrame({"A": [1, 0, 0, 1]})

In [39]: dtype = pd.SparseDtype(int, fill_value=0)

In [40]: dense.astype(dtype)
Out[40]: 
   A
0  1
1  0
2  0
3  1

2.3 格式转化

代码语言:javascript
复制
# SparseDataFrame -> dataframe
In [36]: df.sparse.to_dense()
Out[36]: 
     A    B    C
0  1.0  0.0  0.0
1  0.0  1.0  0.0
2  0.0  0.0  1.0

# SparseDataFrame -> spacy.coo
In [37]: df.sparse.to_coo()
Out[37]: 
<3x3 sparse matrix of type '<class 'numpy.float64'>'
	with 3 stored elements in COOrdinate format>

2.4 稀疏矩阵的属性

Sparse-specific properties, like density, are available on the .sparse accessor.

代码语言:javascript
复制
In [41]: df.sparse.density
Out[41]: 0.3333333333333333

2.5 scipy.sparse与pandas.sparse

从scipy -> pandas pd.DataFrame.sparse.from_spmatrix 可以使用

代码语言:javascript
复制
In [47]: from scipy.sparse import csr_matrix

In [48]: arr = np.random.random(size=(1000, 5))

In [49]: arr[arr < .9] = 0

In [50]: sp_arr = csr_matrix(arr)

In [51]: sp_arr
Out[51]: 
<1000x5 sparse matrix of type '<class 'numpy.float64'>'
	with 517 stored elements in Compressed Sparse Row format>

In [52]: sdf = pd.DataFrame.sparse.from_spmatrix(sp_arr)

In [53]: sdf.head()
Out[53]: 
          0    1    2         3    4
0  0.956380  0.0  0.0  0.000000  0.0
1  0.000000  0.0  0.0  0.000000  0.0
2  0.000000  0.0  0.0  0.000000  0.0
3  0.000000  0.0  0.0  0.000000  0.0
4  0.999552  0.0  0.0  0.956153  0.0

In [54]: sdf.dtypes
Out[54]: 
0    Sparse[float64, 0]
1    Sparse[float64, 0]
2    Sparse[float64, 0]
3    Sparse[float64, 0]
4    Sparse[float64, 0]
dtype: object

从pandas -> scipy

代码语言:javascript
复制
In [61]: A, rows, columns = ss.sparse.to_coo(row_levels=['A', 'B'],
   ....:                                     column_levels=['C', 'D'],
   ....:                                     sort_labels=True)
   ....: 

In [62]: A
Out[62]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>'
	with 3 stored elements in COOrdinate format>

In [63]: A.todense()
Out[63]: 
matrix([[0., 0., 1., 3.],
        [3., 0., 0., 0.],
        [0., 0., 0., 0.]])

In [64]: rows
Out[64]: [(1, 1), (1, 2), (2, 1)]

In [65]: columns
Out[65]: [('a', 0), ('a', 1), ('b', 0), ('b', 1)]

3 sklearn

一般情况scipy.sparse可以直接使用,进行train_test_split, 如果pandas.sparse不行,那么就转成pandas x = x.sparse.to_dense()应该也是可以的:

代码语言:javascript
复制
fea_datasets = csr_matrix((data, (row, col)), shape=(row_index, max_col+1)).toarray()
#当特征维度过大时,选下面这种方式(加toarray()和不加都是对的),内存不容易爆掉
#fea_datasets = csr_matrix((data, (row, col)), shape=(row_index, max_col+1))

x_train, x_test, y_train, y_test = train_test_split(fea_datasets, target_list, test_size = 0.2, random_state = 0)
return x_train, x_test, y_train, y_test

笔者看到一般scipy中csr_matrix格式一般支持sklearn的模型训练; 如果是pandas.sparse可能会报错,所以,需要变成dataframe

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1 scipy.sparse
    • 1.1 SciPy 几种稀疏矩阵类型
      • 1.2 lil_matrix
        • 1.3 矩阵的通用属性
          • 1.4 稀疏矩阵存取
          • 2 pandas.sparse
            • 2.1 SparseArray
              • 2.2 新建SparseDataFrame
                • 2.3 格式转化
                  • 2.4 稀疏矩阵的属性
                    • 2.5 scipy.sparse与pandas.sparse
                    • 3 sklearn
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档