Сохранение / загрузка составляющей разреженные матрицы КСО в портативный формат данных
как вы сохраняете / загружаете scipy sparse csr_matrix
в портативном формате? Разреженная матрица scipy создается на Python 3 (Windows 64-bit) для запуска на Python 2 (Linux 64-bit). Первоначально я использовал pickle (с протоколом=2 и fix_imports=True), но это не сработало, перейдя от Python 3.2.2 (Windows 64-bit) к Python 2.7.2 (Windows 32-bit) и получил ошибку:
TypeError: ('data type not understood', <built-in function _reconstruct>, (<type 'numpy.ndarray'>, (0,), '[98]')).
далее пробовал numpy.save
и numpy.load
а также scipy.io.mmwrite()
и scipy.io.mmread()
и ни один из этих методов работал любой.
8 ответов:
edit: SciPy 1.19 теперь имеет
scipy.sparse.save_npz
иscipy.sparse.load_npz
.from scipy import sparse sparse.save_npz("yourmatrix.npz", your_matrix) your_matrix_back = sparse.load_npz("yourmatrix.npz")
для функций
file
аргумент может также быть файл-как объект (т. е. результатopen
) вместо имени.
получил ответ от группы пользователей Scipy:
csr_matrix имеет 3 атрибута данных, которые имеют значение:
.data
,.indices
и.indptr
. Все это простые ndarrays, так чтоnumpy.save
будет работать на них. Сохраните три массива с помощьюnumpy.save
илиnumpy.savez
загрузить их обратно сnumpy.load
, а затем воссоздать разреженные матрицы с:new_csr = csr_matrix((data, indices, indptr), shape=(M, N))
например:
def save_sparse_csr(filename, array): np.savez(filename, data=array.data, indices=array.indices, indptr=array.indptr, shape=array.shape) def load_sparse_csr(filename): loader = np.load(filename) return csr_matrix((loader['data'], loader['indices'], loader['indptr']), shape=loader['shape'])
хоть ты пиши,
scipy.io.mmwrite
иscipy.io.mmread
не работает для вас, я просто хочу добавить, как они работают. Этот вопрос является хитом Google № 1, поэтому я сам начал сnp.savez
иpickle.dump
перед переключением на простые и очевидные scipy-функции. Они работают на меня и не должны контролироваться теми, кто еще не пробовал их.from scipy import sparse, io m = sparse.csr_matrix([[0,0,0],[1,0,0],[0,1,0]]) m # <3x3 sparse matrix of type '<type 'numpy.int64'>' with 2 stored elements in Compressed Sparse Row format> io.mmwrite("test.mtx", m) del m newm = io.mmread("test.mtx") newm # <3x3 sparse matrix of type '<type 'numpy.int32'>' with 2 stored elements in COOrdinate format> newm.tocsr() # <3x3 sparse matrix of type '<type 'numpy.int32'>' with 2 stored elements in Compressed Sparse Row format> newm.toarray() # array([[0, 0, 0], [1, 0, 0], [0, 1, 0]], dtype=int32)
вот сравнение производительности трех самых популярных ответов с помощью Jupyter notebook. Вход представляет собой 1M x 100K случайную разреженную матрицу с плотностью 0.001, содержащую 100M ненулевых значений:
from scipy.sparse import random matrix = random(1000000, 100000, density=0.001, format='csr') matrix <1000000x100000 sparse matrix of type '<type 'numpy.float64'>' with 100000000 stored elements in Compressed Sparse Row format>
io.mmwrite
/io.mmread
from scipy.sparse import io %time io.mmwrite('test_io.mtx', matrix) CPU times: user 4min 37s, sys: 2.37 s, total: 4min 39s Wall time: 4min 39s %time matrix = io.mmread('test_io.mtx') CPU times: user 2min 41s, sys: 1.63 s, total: 2min 43s Wall time: 2min 43s matrix <1000000x100000 sparse matrix of type '<type 'numpy.float64'>' with 100000000 stored elements in COOrdinate format> Filesize: 3.0G.
(обратите внимание, что формат был изменен с csr на coo).
np.savez
/np.load
import numpy as np from scipy.sparse import csr_matrix def save_sparse_csr(filename, array): # note that .npz extension is added automatically np.savez(filename, data=array.data, indices=array.indices, indptr=array.indptr, shape=array.shape) def load_sparse_csr(filename): # here we need to add .npz extension manually loader = np.load(filename + '.npz') return csr_matrix((loader['data'], loader['indices'], loader['indptr']), shape=loader['shape']) %time save_sparse_csr('test_savez', matrix) CPU times: user 1.26 s, sys: 1.48 s, total: 2.74 s Wall time: 2.74 s %time matrix = load_sparse_csr('test_savez') CPU times: user 1.18 s, sys: 548 ms, total: 1.73 s Wall time: 1.73 s matrix <1000000x100000 sparse matrix of type '<type 'numpy.float64'>' with 100000000 stored elements in Compressed Sparse Row format> Filesize: 1.1G.
cPickle
import cPickle as pickle def save_pickle(matrix, filename): with open(filename, 'wb') as outfile: pickle.dump(matrix, outfile, pickle.HIGHEST_PROTOCOL) def load_pickle(filename): with open(filename, 'rb') as infile: matrix = pickle.load(infile) return matrix %time save_pickle(matrix, 'test_pickle.mtx') CPU times: user 260 ms, sys: 888 ms, total: 1.15 s Wall time: 1.15 s %time matrix = load_pickle('test_pickle.mtx') CPU times: user 376 ms, sys: 988 ms, total: 1.36 s Wall time: 1.37 s matrix <1000000x100000 sparse matrix of type '<type 'numpy.float64'>' with 100000000 stored elements in Compressed Sparse Row format> Filesize: 1.1G.
Примечание: cPickle не работает с очень большие объекты (см. ответ). По моему опыту, это не сработало для матрицы 2.7 M x 50k с ненулевыми значениями 270M.
np.savez
решение хорошо работал.вывод
(на основе этого простого теста для матриц CSR)
cPickle
это самый быстрый способ, но он не работает с очень большими матрицами,np.savez
лишь немного медленнее, в то время какio.mmwrite
гораздо медленнее, производит большой файл и восстанавливает в неправильном формате. Так чтоnp.savez
победитель здесь.
теперь вы можете использовать
scipy.sparse.save_npz
: https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.save_npz.html
предполагая, что у вас есть scipy на обеих машинах, вы можете просто использовать
pickle
.однако не забудьте указать двоичный протокол при травлении массивов numpy. В противном случае вы получите огромный файл.
В любом случае, вы должны быть в состоянии сделать это:
import cPickle as pickle import numpy as np import scipy.sparse # Just for testing, let's make a dense array and convert it to a csr_matrix x = np.random.random((10,10)) x = scipy.sparse.csr_matrix(x) with open('test_sparse_array.dat', 'wb') as outfile: pickle.dump(x, outfile, pickle.HIGHEST_PROTOCOL)
затем вы можете загрузить его с:
import cPickle as pickle with open('test_sparse_array.dat', 'rb') as infile: x = pickle.load(infile)
начиная с scipy 0.19.0, вы можете сохранять и загружать разреженные матрицы следующим образом:
from scipy import sparse data = sparse.csr_matrix((3, 4)) #Save sparse.save_npz('data_sparse.npz', data) #Load data = sparse.load_npz("data_sparse.npz")
Это то, что я использовал, чтобы сохранить
lil_matrix
.import numpy as np from scipy.sparse import lil_matrix def save_sparse_lil(filename, array): # use np.savez_compressed(..) for compression np.savez(filename, dtype=array.dtype.str, data=array.data, rows=array.rows, shape=array.shape) def load_sparse_lil(filename): loader = np.load(filename) result = lil_matrix(tuple(loader["shape"]), dtype=str(loader["dtype"])) result.data = loader["data"] result.rows = loader["rows"] return result
Я должен сказать, я нашел и NumPy в НП.нагрузка.(.) быть очень медленно. Это мое текущее решение, я чувствую, работает гораздо быстрее:
from scipy.sparse import lil_matrix import numpy as np import json def lil_matrix_to_dict(myarray): result = { "dtype": myarray.dtype.str, "shape": myarray.shape, "data": myarray.data, "rows": myarray.rows } return result def lil_matrix_from_dict(mydict): result = lil_matrix(tuple(mydict["shape"]), dtype=mydict["dtype"]) result.data = np.array(mydict["data"]) result.rows = np.array(mydict["rows"]) return result def load_lil_matrix(filename): result = None with open(filename, "r", encoding="utf-8") as infile: mydict = json.load(infile) result = lil_matrix_from_dict(mydict) return result def save_lil_matrix(filename, myarray): with open(filename, "w", encoding="utf-8") as outfile: mydict = lil_matrix_to_dict(myarray) json.dump(mydict, outfile)
меня попросили отправить матрицу в простом и общем формате:
<x,y,value>
в итоге:
def save_sparse_matrix(m,filename): thefile = open(filename, 'w') nonZeros = np.array(m.nonzero()) for entry in range(nonZeros.shape[1]): thefile.write("%s,%s,%s\n" % (nonZeros[0, entry], nonZeros[1, entry], m[nonZeros[0, entry], nonZeros[1, entry]]))