Extraer valores máximos de cada uno de los subconjuntos de una matriz -- python campo con array campo con numpy campo con vectorization camp codereview Relacionados El problema

Extracting maximum values from each of the subsets of an array


2
vote

problema

Español

Descripción del problema:

Tengo una matriz adorable cps a partir de la cual quiero extraer el valor máximo en cada uno de los Los subconjuntos de la matriz (un subconjunto se define como valores no cero que caen entre ceros). La entrada y la forma en que se debe mostrar la salida se ilustran en la siguiente figura.

Nota: cps solo contiene valores positivos y ceros.

la entrada y la salida deseada

Por el momento, estoy haciendo esto como se muestra a continuación:

  ## cps is a numpy array which contains values as observed in the figure  idx = np.nonzero(cps) subsets = np.array_split(idx[0],np.where(np.diff(idx[0])!=1)[0]+1)   lst = np.full(len(cps), 0)   for subset in subsets:     min = subset[0]   ## index of the start of subset (the smallest index number)     max = subset[-1]  ## index of the end of subset (the largest index number)      index_of_change_point_with_max_value = min + np.argmax(cps[min:max+1])              lst[index_of_change_point_with_max_value] = cps[index_of_change_point_with_max_value]   

Sin embargo, me preguntaba si hay alguna otra parte para hacer esto de una manera vectorizada y conseguir deshacerse de la bucle FOR?

Original en ingles

Problem description:

I have a numpy array cps from which I want to extract the maximum value in each of the subsets of the array (a subset is defined as non-zero values which fall between zeros). The input and how the output should look like are illustrated in the following figure.

Note: cps only contains positive values and zeros.

The input and the desired output

for the moment, I am doing this as below:

## cps is a numpy array which contains values as observed in the figure  idx = np.nonzero(cps) subsets = np.array_split(idx[0],np.where(np.diff(idx[0])!=1)[0]+1)   lst = np.full(len(cps), 0)   for subset in subsets:     min = subset[0]   ## index of the start of subset (the smallest index number)     max = subset[-1]  ## index of the end of subset (the largest index number)      index_of_change_point_with_max_value = min + np.argmax(cps[min:max+1])              lst[index_of_change_point_with_max_value] = cps[index_of_change_point_with_max_value] 

However, I was wondering if there is anyway to do this in a vectorized manner and getting rid of the for loop?

           
         
         

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

Encontré una forma ordenada de hacer el truco utilizando el argrelmax () Función de initBombs4 Módulo. Sin embargo, parece que no aumenta el rendimiento en mi código, el código se vuelve más legible.

la solución:

  initBombs5  
 

I found a neat way to do the trick by using the argrelmax() function from scipy.signal module. It seems that it does not increase the performance in my code, however, the code becomes more readable.

The solution:

import scipy.signal as sig lst = np.full(len(cps), 0)     indices = sig.argrelmax(cps) lst[indices] = cps[indices]   
 
 
       
       
1
 
vote

Algoritmo de paso único (~ 2N)

Puede hacerlo con un solo paso sobre la matriz (que denotaré como lst ).

  1. Mantener un valor máximo (Denificaré esto como max_val ) Una vez que llegue a un valor distinto de cero. Cuando lleguemos a un cero, agregue (i, max_val) a la lista de valores máximos y restablecer el valor máximo.
  2. construir la nueva lista con la lista de valores máximos.

Esto debería darle un rendimiento bastante bueno (~ 2n, ya que itera 2 veces). Sin embargo, si necesita una versión paralela ...

algoritmo paralelo

Este es el primer algoritmo paralelo que he diseñado, así que perdíme si me arruinaba en alguna parte. Utilizamos el Mapreduce Model que es bastante simple de escribir.

Permitir k3 BE El número de procesos que desea dividir el trabajo entre y 9988776655544334 es el número de cada proceso donde 9988777665544335 .

en el procedimiento Map() :

  1. Cada proceso comienza en n/k * i INDIETE Y ITERATES HACE n/k * (i+1) .
  2. Siga el algoritmo como se describe en el Paso 1 del algoritmo de paso único.
  3. Si el primer o último valor es distinto de cero, indica que los valores que hemos obtenido pueden no ser los valores máximos del subconjunto, ya que podemos haber monitoreado solo una parte del subconjunto. Por lo tanto, lo agregamos a la lista de porciones.

Cuando nos enjuagamos, marcamos el inicio y finalización de los indicadores que hemos escaneado y el valor máximo, para indicar que no hemos terminado de escanear ese Subarrio.

para k = 3 y nuestra matriz max_val0 con una longitud de 15 (dividida en 3 segmentos para su conveniencia):

  max_val1  

En el procedimiento max_val2 , fusionamos las matrices que tenemos juntos para formar dos listas:

  max_val3  

Ahora obtenemos max_val4 . ¡Construimos la lista usando el Paso 2 y hemos terminado!

La complejidad del tiempo debe estar alrededor de ~ 2N si elige un buen valor 998877666554443315 .

 

Single pass algorithm (~2n)

You can do it with a single pass over the array (which I shall denote as lst).

  1. Maintain a maximum value (I shall denote this as max_val) once you hit a non-zero value. When we reach a zero, add (i, max_val) to the list of maximum values and reset the maximum value.
  2. Build the new list using the list of maximum values.

This should give you pretty good performance (~2n since you iterate 2 times). However, if you need a parallel version...

Parallel algorithm

This is the first parallel algorithm I've ever designed, so pardon me if I screwed up somewhere. We use the MapReduce model which is quite simple to write.

Let k be the number of processes which you want to divide the work among and i be the number of each process where 0 <= i < k.

In the Map() procedure:

  1. Each process starts at n/k * i indice and iterates till it hits n/k * (i+1).
  2. Follow the algorithm as described in step 1 of the single pass algorithm.
  3. If the first or last value is non-zero, it indicates that the values we have obtained may not be the maximum values of the subset as we may have only monitored a portion of the subset. Hence, we add it to the portions list.

When we flush, we mark the start and end indice that we have scanned and the maximum value, so as to indicate that we have not finished scanning that subarray.

For k = 3 and our array being [0, 0, 0, 0, 1] + [2, 3, 4, 0, 0] + [0, 2, 1, 0, 2] with a length of 15 (split into 3 segments for convenience):

i = 0: lst[0] = 0        lst[1] = 0        lst[2] = 0        lst[3] = 0        lst[4] = 1 # is_portion = True, max_val = 1                   # add (4, 5, (4, 1)) to the list of portions        return [] and [(4, 5, (4, 1))] i = 1: lst[5] = 2 # is_portion = True, max_val = 2        lst[6] = 3 # max_val = 3        lst[7] = 4 # max_val = 4        lst[8] = 0 # add (5, 8, (8, 4)) to the list of portions        lst[9] = 0        return [] and [(5, 8, (8, 4))] i = 2: lst[10] = 0        lst[11] = 2 # max_val = 2        lst[12] = 1        lst[13] = 0 # add (11, 2) to the list of maximum values        lst[14] = 2 # is_portion = True, max_val = 2                    # add (14, 15, (14, 2)) to the list of portions        return [(11, 2)] and [(14, 15, (14, 2))] 

In the Reduce() procedure, we merge the arrays we have together to form two lists:

1. Maximum values: [(11, 2)] 2. Portions not yet finished scanning: [(4, 5, (4, 1)), (5, 8, (8, 4)), (14, 15, (14, 2))]   We merge the tuples (4, 5, (4, 1)) and (5, 8, (8, 4)) together and compare the maximum value found. (8, 4) > (4, 1), so we get a maximum value (8, 4).   The last tuple, (14, 15, (14, 2)), ends at the boundary of the array, so we immediately return the maximum value (14, 2). 

We now get [(11, 2), (8, 4), (14, 2)]. We build the list using step 2 and we're done!

The time complexity should be around ~2n if you choose a good k value.

 
 
   
   

Relacionados problema

2  Escalado e incremento de elementos no cero de una matriz adorable  ( Scaling and incrementing non zero elements of a numpy matrix ) 
Tengo una matriz adorable C y desea crear una copia cPrime , que tiene algún funcionamiento de la matriz original a todos los valores no cero. En el código...

4  Vectorizando un bucle de conversión de coordenadas polares en un proceso de coincidencia de huellas dactilares  ( Vectorizing a polar coordinate conversion loop in a fingerprint matching process ) 
Estoy trabajando en una técnica de coincidencia de huellas dactilares y se necesita mucho tiempo de computación para obtener el resultado. Estoy tratando de i...

6  Cálculo de estacionamientos y estadísticas de carga para un servicio compartido de automóviles  ( Calculating parking and charging statistics for a car sharing service ) 
Estoy buscando ayuda para diseñar mi código de manera más eficiente y también en mantener la pendiente de mi curva de aprendizaje personal empinada: Para un...

5  Evaluando una serie de polinomios legendra  ( Evaluating a series of legendre polynomials ) 
La siguiente función representa el potencial electrostático, en coordenadas esféricas, debido a un anillo de carga $ Q = 1 $ y RADIUS $ R = 1 $, colocado ...

1  Vectorizamos gradiente 2D con contenedores espacialmente variables  ( Vectorize 2d gradient with spatially varying bins ) 
El siguiente código lleva a algunos valores ssh y resuelve las ecuaciones para el movimiento geostrófico (diapositiva 8 aquí ). La parte principal del Có...

2  Encuentra el primer umbral de cruce en la matriz NUTPY  ( Find first threshold crossing in numpy array ) 
Dado los siguientes datos generados artificialmente: t_steps = 30 data = np.array([ np.arange(t_steps) * .05, np.arange(t_steps) * .1, np.aran...

3  Generar vectores de la unidad aleatoria alrededor del círculo  ( Generate random unit vectors around circle ) 
Estoy tratando de generar un montón de vectores de unidad de distribución uniformemente alrededor del círculo de la unidad. Aquí está mi código, que está func...

5  Vectorización para simulación de temperatura  ( Vectorization for temperature simulation ) 
Soy nuevo en Matlab y me gustaría saber consejos para reducir el tiempo de procesamiento de dicho programa. El esquema del código real es muy similar al códig...

4  Crosstabulación vectorizada en Python para dos matrices con dos categorías cada una  ( Vectorized crosstabulation in python for two arrays with two categories each ) 
Tengo dos listas de Python, label y presence1 . Quiero hacer la tabulación cruzada y obtener el recuento para cada bloque de cuatro, como A, B, C y D en ...

6  ¿Cómo hacer que mis operaciones de Groupby y Transponen eficientes?  ( How to make my groupby and transpose operations efficient ) 
Tengo un DataFrame 3,745,802 filas y 30 columnas. Me gustaría realizar cierto 9988776665544331 y 9988776655544332 terminará finalmente con más columnas ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos