Vetorização e transmissão em Python

Publicados: 2020-12-01

Vetorização e transmissão são maneiras de acelerar o tempo de computação e otimizar o uso de memória ao fazer operações matemáticas com o Numpy. Esses métodos são cruciais para garantir que a complexidade do tempo seja reduzida para que os algoritmos não enfrentem gargalos. Essa operação otimizada é necessária para que os aplicativos sejam escaláveis. Analisaremos essas duas técnicas e implementaremos alguns exemplos.

Ao final deste tutorial, você terá o seguinte conhecimento:

  • Como a vetorização é tratada pelo Numpy
  • Diferenças de tempo com e sem vetorização
  • O que é radiodifusão
  • Como a transmissão é diferente da multiplicação de matrizes usual

Vetorização

Muitas vezes precisamos de operações matemáticas em arrays – como multiplicação de arrays. Agora, uma maneira não vetorizada seria fazer a multiplicação por elementos usando um loop. Implementá-lo dessa maneira resultaria na mesma operação de multiplicação a ser feita várias vezes, o que seria um desperdício de recursos de computação se o tamanho dos dados fosse muito grande. Vamos dar uma olhada rápida.

Forma não vetorizada:

Importar aleatório

a = [random.randint( 1 , 100 ) for _ in range( 10000 )]
b = [random.randint( 1 , 100 ) for _ in range( 10000 )]
%timeit [i*j para i, j em zip(a,b)]

#Saída:
>> 1000 loops, melhor de 3 : 658 µs por loop

Forma vetorizada:

importar numpy como np
a = np.array([random.randint( 1 , 100 ) for _ in range( 10000 )])
b = np.array([random.randint( 1 , 100 ) for _ in range( 10000 )])
%timeit a*b

#Saída:
>> 100.000 loops, melhor de 3 : 7,25 µs por loop

Como vemos, o tempo decorrido passou de 658 microssegundos para apenas 7,25 microssegundos. Isso ocorre porque quando dizemos a = np.array([]) , todas as operações são tratadas internamente pelo numpy. E quando fazemos a*b , numpy multiplica internamente a matriz completa de uma só vez por meio de vetorização.

Aqui usamos o comando mágico %timeit para cronometrar a execução do processo que pode ser diferente em sua máquina.

Vamos dar uma olhada em outro exemplo de produtos externos de 2 vetores com dimensões (nx1) e (1xm). A saída será (nxm).

tempo de importação
importar numpy
importar matriz
a = array.array( 'i' , [random.randint( 1 , 100 ) for _ in range( 100 )])
b = array.array( 'i' , [random.randint( 1 , 100 ) for _ in range( 100 )])

T1 = time.process_time()
c = numpy.zeros(( 200 , 200 ))

para i no intervalo(len(a)):
para j no intervalo(len(b)):
c[i][j]= a[i]*b[j]

T2 = time.process_time()

print( f"Tempo de computação = { 1000 *(T2-T1)} ms" )

#Saída:
>> Tempo de computação = 6,819299000000001 ms

Agora, vamos fazer isso com Numpy,

T1 = time.process_time()
c = numpy.exter(a, b)
T2 = time.process_time()

print( f"Tempo de computação = { 1000 *(T2-T1)} ms" )

#Saída:
>> Tempo de computação = 0,2256630000001536 ms

Como vemos novamente, o Numpy processa a mesma operação de maneira mais rápida por vetorização.

Deve ler: aplicativos Python fascinantes no mundo real

Transmissão

Até agora, vimos exemplos em que arrays do mesmo tamanho eram usados. E se os tamanhos dos arrays forem diferentes? Aqui é onde outro grande recurso do Numpy, Broadcasting, entra em cena.

Broadcasting é outra extensão da vetorização onde os arrays não precisam ser do mesmo tamanho para que operações sejam realizadas neles como adição, subtração, multiplicação, etc. Vamos entender isso com um exemplo bem simples de adição de um array e um escalar.

a = np.array([ 1 , 1 , 1 , 1 ])
a+ 5

#Saída:
array([ 6 , 6 , 6 , 6 ])

Como vemos, o escalar 5 foi adicionado a todos os elementos. Então, como isso aconteceu?

Para imaginar o processo, você pode pensar que o escalar 5 é repetido 4 vezes para fazer um array que é então adicionado ao array a. Mas lembre-se de que o Numpy não cria nenhum desses arrays que ocupam apenas memória. Numpy apenas “transmite” ou duplica o escalar de 5 para 4 lugares para adicioná-lo ao array a.

Vamos dar outro exemplo fácil.

a = np.ones(( 3 , 3 ))
b = np.ones( 3 )
a+b

#Saída:
>> array([[ 2. , 2. , 2. ],
[ 2. , 2. , 2. ],
[ 2. , 2. , 2. ]])

No exemplo acima, a matriz de forma (3,1) foi transmitida para (3,3) para corresponder à matriz a.

Mas isso significa que qualquer array com qualquer dimensão pode ser transmitido para corresponder a um array com qualquer dimensão?

NÃO!

Regras de transmissão

O Numpy segue um conjunto de regras fáceis para garantir que apenas as matrizes que seguem os critérios sejam transmitidas. Vamos dar uma olhada.

A regra de transmissão diz que os 2 arrays que devem ser operados devem ter as mesmas dimensões ou se algum deles for 1.

Vamos ver isso em ação.

Exemplo 1:

Considere abaixo matrizes de dimensões:

a = 3 x 4 x 7

b = 3 x 4 x 1

Aqui, a última dimensão de b será transmitida para corresponder à de a a 7.

Portanto, resultado = 3 x 4 x 7

Exemplo 2:

a = 3 x 4 x 7

b = 4

Agora, o número de dimensões de a e b são desiguais. Nesses casos, o array com menor número de dimensões será preenchido com 1.

Então, aqui, a primeira e a última dimensão de b são 1, então elas serão transmitidas para combinar com a de a para 3 e 7.

Portanto, resultado = 3 x 4 x 7.

Leia: Tutorial Python

Exemplo 3:

a = 3 x 4 x 1 x 5

b = 3 x 1 x 7 x 1

Aqui, novamente, a segunda e a última dimensão de b serão transmitidas para corresponder às de a a 4 e 5. Além disso, a terceira dimensão de a será transmitida para corresponder à de b a 7.

Portanto, resultado = 3 x 4 x 7 x 5

Agora vamos ver quando a condição falha:

Exemplo 4:

a = 3 x 4 x 7 x 5

b = 3 x 3 x 7 x 4

Aqui, a segunda e quarta dimensões de b não combinam com a e nem são 1. Nesse caso, o Python lançará um erro de valor:

ValueError: operandos não puderam ser transmitidos junto com formas ( 3 , 4 , 7 , 5 ) ( 3 , 3 , 7 , 4 )

Exemplo 5:

a = 3 x 4 x 1 x 5

b = 3 x 2 x 3

Resultado: ValueError

Aqui também, a segunda dimensão não corresponde e não é 1 para nenhuma delas.

Antes de você ir

Vetorização e Broadcasting, ambos, são métodos como o Numpy torna seu processamento otimizado e mais eficiente. Esses conceitos devem ser lembrados principalmente quando se trata de matrizes e arrays n-dimensionais, muito comuns em dados de imagem e Redes Neurais.

Se você está curioso para aprender sobre python, ciência de dados, confira o PG Diploma in Data Science do IIIT-B & upGrad, criado para profissionais que trabalham e oferece mais de 10 estudos de caso e projetos, workshops práticos práticos, orientação com especialistas do setor, 1-on-1 com mentores do setor, mais de 400 horas de aprendizado e assistência de trabalho com as principais empresas.

O que é vetorização em Python?

Numpy é um pacote Python que fornece várias funções matemáticas padrão que permitem operações rápidas em grandes matrizes de dados sem a necessidade de loops, incluindo vetorização. A vetorização é usada para acelerar programas Python sem o uso de loops. Usar esse método pode ajudar a reduzir a quantidade de tempo que o código leva para ser executado. Existem várias operações que são realizadas em vetores, como o produto escalar de vetores, também conhecido como produto escalar, pois produz uma única saída, produtos externos, que resulta em uma matriz quadrada de dimensão igual ao comprimento x comprimento do vetores, multiplicação elemento a elemento, que produz elementos com os mesmos índices.

O que é transmissão em Python?

A palavra broadcasting refere-se a como o Numpy gerencia arrays com dimensões diferentes durante operações aritméticas que resultam em restrições específicas; a matriz menor é transmitida pela matriz enorme para que suas formas sejam consistentes. A transmissão permite vetorizar operações de matriz de modo que o loop ocorra em C em vez de Python, como o Numpy faz. Ele faz isso sem criar cópias desnecessárias de dados, resultando em implementações eficientes de algoritmos. Em certas situações, a transmissão é uma ideia negativa, pois resulta em um desperdício de consumo de memória, o que retarda o processamento.

Quais são os usos do NumPy em Python?

NumPy ou Numerical Python é uma biblioteca Python gratuita e de código aberto utilizada por quase todos os ramos de pesquisa e engenharia. A biblioteca NumPy inclui array multidimensional e estruturas de dados de matriz e oferece métodos para operar eficientemente em um array, um objeto de array n-dimensional homogêneo. Os usuários podem usar o NumPy para executar uma ampla variedade de operações matemáticas em matrizes. Ele aprimora o Python com estruturas de dados fortes que fornecem cálculos eficientes com matrizes e matrizes, bem como uma enorme biblioteca de funções matemáticas de alto nível que funcionam nessas matrizes e matrizes.