2013-10-11 2 views
6

Есть ли простой/встроенный способ получить максимальный размер элемента из двух (или идеально большего) разреженных матриц? То есть редкий эквивалент np.maximum.Элементарный максимум двух разреженных матриц

+0

Что именно вы подразумеваете под «элементарно»? Если я перейду на редкую страницу coo_matrix, я вижу такие функции, как 'arcsin() \t Element-wise arcsin.' Но не' max'. Вы хотите наибольшее значение в каждой матрице; самый большой по некоторому размеру; самый большой по множеству матриц? – hpaulj

+1

Не обижайтесь, но я думаю, что элементный мудрый недвусмыслен. В: две матрицы A, B с одинаковыми размерами. Out: матрица C, где C [i, j] = max (A [i, j], B [i, j]) – Maarten

ответ

3

Это сделал трюк:

def maximum (A, B): 
    BisBigger = A-B 
    BisBigger.data = np.where(BisBigger.data < 0, 1, 0) 
    return A - A.multiply(BisBigger) + B.multiply(BisBigger) 
+0

Контрпример: 'A = coo_matrix ([1,1]); B = coo_matrix ([0,2]); максимум (A, B) .A' дает 'array ([[0, 2]])'. –

+0

Хорошо, я думаю, теперь это должно сработать. – Maarten

0
from scipy import sparse 
from numpy import array 
I = array([0,3,1,0]) 
J = array([0,3,1,2]) 
V = array([4,5,7,9]) 
A = sparse.coo_matrix((V,(I,J)),shape=(4,4)) 

A.data.max() 
9 

Если вы еще не сделали, вы должны попробовать ipython, вы могли бы спасти вашу уверенность время мой делая свободное матрицу A затем просто набрав A. затем вкладку, это напечатает список методов, которые вы можете позвоните по телефону A. Из этого вы увидите, что A.data дает ненулевые записи в виде массива и, следовательно, вы просто хотите максимум этого.

+0

Спасибо, что ответили, но вы неправильно поняли вопрос. Я отредактировал его, чтобы сделать его более понятным. – Maarten

+0

Посредством элемента вы подразумеваете матрицу A и B, которая имеет больший максимальный элемент? – Greg

+0

как http://docs.scipy.org/doc/numpy/reference/generated/numpy.maximum.html – Maarten

2

Нет, нет встроенного способа сделать это в scipy.sparse. Простое решение является

np.maximum(X.A, Y.A) 

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

# convert to COO, if necessary 
X = X.tocoo() 
Y = Y.tocoo() 

Xdict = dict(((i, j), v) for i, j, v in zip(X.row, X.col, X.data)) 
Ydict = dict(((i, j), v) for i, j, v in zip(Y.row, Y.col, Y.data)) 

keys = list(set(Xdict.iterkeys()).union(Ydict.iterkeys())) 

XmaxY = [max(Xdict.get((i, j), 0), Ydict.get((i, j), 0)) for i, j in keys] 
XmaxY = coo_matrix((XmaxY, zip(*keys))) 

Обратите внимание, что это использует чистый Python вместо векторизованных идиомы. Вы можете попытаться избавиться от частичного времени, векторизируя его части.

+0

Возможно, я должен был упомянуть, что я пробовал это раньше, и он разбил мой MacBook, потому что мне не хватило места на диске для файла подкачки. – Maarten

+0

@Maarten: см. Обновленный ответ. –

1

Вот другой памяти эффективное решение, которое должно быть немного быстрее, чем larsmans'. Он основан на нахождении набора уникальных индексов для ненулевых элементов в двух массивах с использованием кода от Jaime's excellent answer here.

import numpy as np 
from scipy import sparse 

def sparsemax(X, Y): 

    # the indices of all non-zero elements in both arrays 
    idx = np.hstack((X.nonzero(), Y.nonzero())) 

    # find the set of unique non-zero indices 
    idx = tuple(unique_rows(idx.T).T) 

    # take the element-wise max over only these indices 
    X[idx] = np.maximum(X[idx].A, Y[idx].A) 

    return X 

def unique_rows(a): 
    void_type = np.dtype((np.void, a.dtype.itemsize * a.shape[1])) 
    b = np.ascontiguousarray(a).view(void_type) 
    idx = np.unique(b, return_index=True)[1] 
    return a[idx] 

Тестирование:

def setup(n=1000, fmt='csr'): 
    return sparse.rand(n, n, format=fmt), sparse.rand(n, n, format=fmt) 

X, Y = setup() 
Z = sparsemax(X, Y) 
print np.all(Z.A == np.maximum(X.A, Y.A)) 
# True 

%%timeit X, Y = setup() 
sparsemax(X, Y) 
# 100 loops, best of 3: 4.92 ms per loop 
+1

Ах, забудьте об этом - решение Маартен на много порядков быстрее, чем мое! –

1

Последние scipy (13.0) определяет поэлементно булевы для разреженных матриц,. Итак:

BisBigger = B>A 
A - A.multiply(BisBigger) + B.multiply(BisBigger) 

np.maximum нет (пока) работы, поскольку он использует np.where, который до сих пор пытается получить truth value of an array.

Любопытно B>A возвращает булевский тип, а B>=A - float64.

+0

Слишком плохо scipy 13.0 еще не в PyPi. – Maarten

+0

Я не уверен, что такое 'B> = A'. Но если он будет делать то, что вам нужно, кроме этого, и у вас есть две очень редкие матрицы A и B, в результате вы получите очень плотную матрицу. – Maarten

+0

Хорошая точка. Это объясняет предупреждение, которое я получаю: '' SparseEfficiencyWarning: сравнение разреженных матриц с использованием> = и <= неэффективно, попробуйте вместо этого использовать <, > или! =. "' – hpaulj

Смежные вопросы