Норма разреженных векторов питона

Можно ли эффективно получить норму разреженного вектора в питоне?

Я попробовал следующее:

from scipy import sparse
from numpy.linalg import norm

vector1 = sparse.csr_matrix([ 0 for i in xrange(4000000) ], dtype = float64)

#just to test I set a few points to a value higher than 0

vector1[ (0, 10) ] = 5
vector1[ (0, 1500) ] = 80
vector1[ (0, 2000000) ] = 6

n = norm(t1)

но тогда я получаю ошибку:

ValueError: dimension mismatch

Функция нормы работает только с массивами, поэтому, вероятно, именно поэтому csr_matrix не работает, но тогда я не нашел другого способа эффективного вычисления нормы. Одним из возможных решений будет вычисление:

norm(asarray(vector1.todense()))

но тогда это сначала убивает цель использования разреженных векторов. И в качестве последнего подхода я мог бы пройтись по каждому элементу вектора и вручную вычислить норму, но, поскольку эффективность действительно важна, я искал что-то более быстрое и простое в реализации.

Заранее благодарю за любую помощь!

РЕДАКТИРОВАТЬ: Я попробовал все, что было предложено, и лучшее решение:

(vector1.data ** 2).sum()

из Дугала. Но решение Cython также очень хорошо и работает лучше, так как вектор растет в количестве элементов, отличных от нуля. Спасибо всем за помощь!

3 ответа

Решение
  1. Я надеюсь, что вы на самом деле не инициализируете и не настраиваете подобные элементы, эти предупреждения появляются по определенной причине, а временный список 4M подтверждает, что у вас достаточно ресурсов;).
  2. Вычисление нормы вручную очень просто, просто используя базовые данные vector1.data непосредственно. Вы также можете использовать такие вещи, как vector1.multiply(vector1) плюс .sum или же vector1.dot(vector1.T) но, как указал Дугал, в этом простом случае это может быть намного медленнее.
  3. Я предполагаю, что вы хотите сделать больше, но если вы хотите только векторные нормы, прохождение разреженных матриц кажется большой ненужной работой.

У меня просто была та же проблема, я реализовал функцию в Cython для увеличения скорости этой простой операции. Я проверил это с разреженным вектором 4M двойных чисел с ненулевыми элементами 100k. Метод с использованием sqrt(vector.multiply(vector).sum()) использовал 874us и мою функцию 205us.

# sparseLib.pyx
#cython: boundscheck=False
from cython.parallel cimport prange
from cython.view cimport array as cvarray

import numpy as np

from libc.math cimport sqrt

cpdef double sparseNorm2(double [:] data) nogil:
  cdef long i
  cdef double value = 0.0
  for i in xrange(data.shape[0]):
    value += data[i]*data[i]
  return sqrt(value)

Я не думаю, что ваша инициализация делает то, что вы думаете.

Чтобы норма работала, вам нужно иметь квадратный массив. Если вы пытаетесь создать квадратный массив с 4 миллионами элементов, вы хотите сделать

csr_matrix( (2000,2000), dtype=float64)

полная документация для инициализации у scipy

Другие вопросы по тегам