稀疏矩阵用于python的keras和theano

作者: JxKing | 来源:发表于2016-06-02 22:13 被阅读2739次

    稀疏矩阵

    稀疏矩阵(sparse matrix)是由于矩阵中存在大量0,从而可以采用特别的存储技巧来压缩内存。
    由于在工作需要将一个150666569x9860的超大矩阵作为数据,来训练NN模型,所以采用稀疏矩阵的方式,将这个超大矩阵压缩,从而使得能够放入内存中。
    python的稀疏矩阵在scipy包中,而theano同时支持的是csc_matrix,和csr_matrix。

    from scipy.sparse import csc_matrix,csr_matrix
    

    这两种稀疏矩阵的选择取决于要稀疏的矩阵的情况,如果row比column多,就用csc_matrix,反之则用csr_matrix,更具体的可以看这里。我们当然就选择scs_matrix

    构建稀疏矩阵

    有两种方法构建矩阵,一种方法是用3个list,分别记录非0元素的行序列, 列序列,还有该元素本身。

    row = np.array([0, 2, 2, 0, 1, 2])
    col = np.array([0, 0, 1, 2, 2, 2])
    data = np.array([1, 2, 3, 4, 5, 6])
    sparse_matrix=csc_matrix((data, (row, col)), shape=(3, 3))
    sparse_matrix.toarray()
    output:array([[1, 0, 4], 
                  [0, 0, 5], 
                  [2, 3, 6]])
    

    另一种方法也是用3个list,看例子来详解下

    indptr = np.array([0, 2, 3, 6])
    indices = np.array([0, 2, 2, 0, 1, 2])
    data = np.array([1, 2, 3, 4, 5, 6])
    csc_matrix((data, indices, indptr), shape=(3, 3)).toarray()
    output:
    array([[1, 0, 4], 
          [0, 0, 5],
          [2, 3, 6]])
    

    在csc_matrix中indptr的差值代表每列有几个非0元素,比如2-0=2,代表第一列有2个非0元素,在哪里是看indices这个list,它记录了行的序列,元素本身则在data list中。
    知道这个原理,我们可以自己写一个合并两个csc_matrix的函数:

    def concatenate_csc_matrices_by_columns(matrix1, matrix2):
        new_data = np.concatenate((matrix1.data, matrix2.data))
        new_indices = np.concatenate((matrix1.indices, matrix2.indices))
        new_ind_ptr = matrix2.indptr + len(matrix1.data)
        new_ind_ptr = new_ind_ptr[1:]
        new_ind_ptr = np.concatenate((matrix1.indptr, new_ind_ptr))
        return csc_matrix((new_data, new_indices, new_ind_ptr))
    

    很明显的看到,第二种存储稀疏矩阵的方式,更节省空间。但是第一种更浅显易懂。

    将稀疏矩阵用于theano

    以deeplearning tutorial的mlp为例,如果输入的training_x数据为稀疏矩阵,那么需要改一下几个地方:

    1. Symbolic declaration:
      将原来的x = T.matrix('x')改成:
    x = theano.sparse.csc_matrix('x')
    
    1. 将Hiddenlayer的lin_out改成:
     lin_output = theano.sparse.dot(input, self.W) + self.b
    

    其他只要跟原来的模型保持一致就可以了。

    theano改起来还是很容易的,这主要是因为theano本身支持稀疏矩阵。

    将稀疏矩阵用于keras

    Keras is a minimalist, highly modular neural networks library, written in Python and capable of running on top of either TensorFlow or Theano.
    keras是一个高度模块化的深度学习框架,用起来非常方便,只需要关注模型本身就行。
    要使得稀疏矩阵能在keras中用,只需要对keras的training.py这个文件做些修改就行。

    1. 将所有len(ins[0])替换成ins[0].shape[0]
    2. 在用SGD的时候,将每批batch选出来的样本还原成正常的矩阵,这样的方式,使得内存不会被占用很多。要实现这个,只需要在每次调用slice_X这个函数之后,插入如下代码,将ins_batch变成正常矩阵就可以。
      代码如下:
    if sps.issparse(ins_batch[0]):    
          ins_batch[0] = ins_batch[0].toarray()
    if sps.issparse(ins_batch[1]):    
          ins_batch[1] = ins_batch[1].toarray()
    

    总结

    1. keras很好用
    2. keras是用python实现的,查看源代码很方便,修改起来也很方便
    3. 这次因为这个稀疏矩阵的需求,研究了下theano和keras,收获颇丰,以后有机会还是应该多看看源代码

    相关文章

      网友评论

      • 我像风筝寻一个梦:楼主最后是怎么将一个150666569x9860的超大矩阵读进内存的或者存储起来的,我申请python或者matlab内的矩阵空间都会out of memory。

        东大老实人:sparse.save_npz函数

      本文标题:稀疏矩阵用于python的keras和theano

      本文链接:https://www.haomeiwen.com/subject/gwlkdttx.html