Cálculo de matriz com NumPy

Cálculo de matriz com NumPy Cálculo de matriz com NumPy

Cálculo matricial com NumPylink image 80

Aviso: Este post foi traduzido para o português usando um modelo de tradução automática. Por favor, me avise se encontrar algum erro.

1. Resumolink image 81

Vamos ver uma pequena introdução à biblioteca de cálculo matricial NumPy. Esta biblioteca está desenhada para todo tipo de cálculo matricial, por isso vamos nos concentrar apenas na parte que será útil para entender os cálculos dentro das redes neurais, mas deixaremos de fora coisas interessantes como o uso da biblioteca para a álgebra linear.

No description has been provided for this image

2. O que é NumPy?link image 82

NumPy é uma biblioteca de Python projetada para realizar cálculo matricial. O cálculo matricial é algo que se utiliza muito em ciência em geral e em data science em particular, por isso é necessário ter uma biblioteca que faça isso muito bem.

Seu nome significa Numerical Python

Seu objeto principal é o ndarray, que encapsula matrizes de dimensão n de tipos de dados homogêneos, ao contrário das listas de Python, que podem conter dados de diferentes tipos.

NumPy tem o objetivo de realizar o cálculo matricial muito mais rápido do que com as listas de Python, mas como isso é possível?

  • NumPy utiliza código compilado, enquanto Python utiliza código interpretado. A diferença é que Python no momento da execução tem que interpretar, compilar e executar o código, enquanto o NumPy já está compilado, por isso é executado mais rápido* Os ndarrays têm um tamanho fixo, ao contrário das listas de Python que são dinâmicas. Se no NumPy quiser modificar o tamanho de uma matriz, será criada uma nova e a antiga será eliminada* Todos os elementos dos ndarrays são do mesmo tipo de dado, ao contrário das listas do Python que podem ter elementos de diferentes tipos* Parte do código do NumPy está escrito em C/C++ (muito mais rápido que Python)* Os dados das matrizes são armazenados em memória de maneira contínua, ao contrário das listas de Python, o que faz com que seja muito mais rápido manipulá-los

NumPy oferece a facilidade de usar código simples de escrever e de ler, mas que está escrito e pré-compilado em C, o que o torna muito mais rápido. Suponhamos que queremos multiplicar dois vetores, isso seria feito em C da seguinte maneira: portuguêsmarkdown for (i = 0; i < rows; i++):

for (j = 0; j < columns; j++): {
      ``````markdown
      c[i][j] = a[i][j]*b[i][j];
      ``````markdown
      
```} NumPy oferece a possibilidade de executar este código por baixo, mas muito mais fácil de escrever e entender através ```python ``````python c = a * b

NumPy oferece código vetorizado, que significa não ter que escrever loops, mas que no entanto estão sendo executados por baixo em código C otimizado e pré-compilado. Isso tem as seguintes vantagens:

  • O código é mais fácil de escrever e ler* Ao necessitar de menos linhas de código, há menor probabilidade de introduzir erros* O código se parece mais com a notação matemática

2.1. NumPy como nplink image 83

Geralmente, ao importar o NumPy, costuma-se importar com o alias de np

	
import numpy as np
print(np.__version__)
Copy
	
1.18.1

3. Velocidade do NumPylink image 84

Como foi explicado, o NumPy realiza o cálculo muito mais rápido do que as listas de Python, vejamos um exemplo em que é realizado o produto escalar de duas matrizes, através de listas de Python e através de ndarrays

	
from time import time
# Dimensión de las matrices
dim = 1000
shape = (dim, dim)
# Se crean dos ndarrays de NumPy de dimensión dim x dim
ndarray_a = np.ones(shape=shape)
ndarray_b = np.ones(shape=shape)
# Se crean dos listas de Python de dimensión dim x dim a partir de los ndarrays
list_a = list(ndarray_a)
list_b = list(ndarray_b)
# Se crean el ndarray y la lista de Python donde se guardarán los resultados
ndarray_c = np.empty(shape=shape)
list_c = list(ndarray_c)
# Producto escalar de dos listas de python
t0 = time()
for fila in range(dim):
for columna in range(dim):
list_c[fila][columna] = list_a[fila][columna] * list_b[fila][columna]
t = time()
t_listas = t-t0
print(f"Tiempo para realizar el producto escalar de dos listas de Python de dimensiones {dim}x{dim}: {t_listas:.4f} ms")
# Producto escalar de dos ndarrays de NumPy
t0 = time()
ndarray_c = ndarray_a * ndarray_b
t = time()
t_ndarrays = t-t0
print(f"Tiempo para realizar el producto escalar de dos ndarrays de NumPy de dimensiones {dim}x{dim}: {t_ndarrays:.4f} ms")
# Comparación de tiempos
print(f"\nHacer el cálculo con listas de Python tarda {t_listas/t_ndarrays:.2f} veces más rápido que con ndarrays de NumPy")
Copy
	
Tiempo para realizar el producto escalar de dos listas de Python de dimensiones 1000x1000: 0.5234 ms
Tiempo para realizar el producto escalar de dos ndarrays de NumPy de dimensiones 1000x1000: 0.0017 ms
Hacer el cálculo con listas de Python tarda 316.66 veces más rápido que con ndarrays de NumPy

4. Matrizes no NumPylink image 85

Em NumPy uma matriz é um objeto ndarray

	
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))
Copy
	
[1 2 3 4 5]
<class 'numpy.ndarray'>

4.1. Como criar matrizeslink image 86

Com o método array() é possível criar ndarrays introduzindo listas de Python (como o exemplo anterior) ou tuplas

	
arr = np.array((1, 2, 3, 4, 5))
print(arr)
print(type(arr))
Copy
	
[1 2 3 4 5]
<class 'numpy.ndarray'>

Com o método zeros() é possível criar matrizes cheias de zeros

	
arr = np.zeros((3, 4))
print(arr)
Copy
	
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]

O método zeros_like(A) retorna uma matriz com a mesma forma que a matriz A, porém preenchida com zeros

	
A = np.array((1, 2, 3, 4, 5))
arr = np.zeros_like(A)
print(arr)
Copy
	
[0 0 0 0 0]

Com o método ones() podem-se criar matrizes cheias de uns

	
arr = np.ones((4, 3))
print(arr)
Copy
	
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]

O método ones_like(A) retorna uma matriz com a mesma forma que a matriz A, mas preenchida com uns

	
A = np.array((1, 2, 3, 4, 5))
arr = np.ones_like(A)
print(arr)
Copy
	
[1 1 1 1 1]

Com o método empty() é possível criar matrizes com as dimensões que desejamos, mas inicializadas aleatoriamente

	
arr = np.empty((6, 3))
print(arr)
Copy
	
[[4.66169180e-310 2.35541533e-312 2.41907520e-312]
[2.14321575e-312 2.46151512e-312 2.31297541e-312]
[2.35541533e-312 2.05833592e-312 2.22809558e-312]
[2.56761491e-312 2.48273508e-312 2.05833592e-312]
[2.05833592e-312 2.29175545e-312 2.07955588e-312]
[2.14321575e-312 0.00000000e+000 0.00000000e+000]]

O método empty_like(A) retorna uma matriz com o mesmo formato da matriz A, mas inicializada de forma aleatória.

	
A = np.array((1, 2, 3, 4, 5))
arr = np.empty_like(A)
print(arr)
Copy
	
[4607182418800017408 4611686018427387904 4613937818241073152
4616189618054758400 4617315517961601024]

Com o método arange(start, stop, step) é possível criar matrizes em um intervalo determinado. Este método é semelhante ao método range() do Python.

	
arr = np.arange(10, 30, 5)
print(arr)
Copy
	
[10 15 20 25]

Quando arange é usado com argumentos de ponto flutuante, geralmente não é possível prever o número de elementos obtidos, devido à precisão finita do ponto flutuante. Por este motivo, geralmente é melhor usar a função linspace(start, stop, n) que recebe como argumento a quantidade de elementos que queremos, em vez do passo.

	
arr = np.linspace(0, 2, 9)
print(arr)
Copy
	
[0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ]

Por último, se queremos criar matrizes com números aleatórios podemos usar a função random.rand com uma tupla com as dimensões como parâmetro

	
arr = np.random.rand(2, 3)
print(arr)
Copy
	
[[0.32726085 0.65571767 0.73126697]
[0.91938206 0.9862451 0.95033649]]

4.2. Dimensões das matrizeslink image 87

Em NumPy podemos criar matrizes de qualquer dimensão. Para obter a dimensão de um array utilizamos o método ndim

Matriz de dimensão 0, o que equivaleria a um número

	
arr = np.array(42)
print(arr)
print(arr.ndim)
Copy
	
42
0

Matriz de dimensão 1, o que equivaleria a um vetor

	
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(arr.ndim)
Copy
	
[1 2 3 4 5]
1

Matriz de dimensão 2, o que equivaleria a uma matriz

	
arr = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]])
print(arr)
print(arr.ndim)
Copy
	
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
2

Matriz de dimensão 3

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
print(arr)
print(arr.ndim)
Copy
	
[[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
[[11 12 13 14 15]
[16 17 18 19 20]]]
3

Matriz de dimensão N. Na hora de criar ndarrays, é possível estabelecer o número de dimensões através do parâmetro ndim

	
arr = np.array([1, 2, 3, 4, 5], ndmin=6)
print(arr)
print(arr.ndim)
Copy
	
[[[[[[1 2 3 4 5]]]]]]
6

4.3. Tamanho das matrizeslink image 88

Se, em vez da dimensão da matriz, quisermos ver seu tamanho, podemos usar o método shape

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
print(arr.shape)
Copy
	
(2, 2, 5)

5. Tipo de dadoslink image 89

Os dados que podem armazenar os arrays do NumPy são os seguintes:

  • i - Inteiro* b - Booleano* u - Inteiro sem sinal* f - Flutuante* c - Flutuante complexo* m - Timedelta* M - DateTime* O - Objeto* S - String* U - String Unicode* V - Fragmento de memória fixo para outro tipo (void)

Podemos verificar o tipo de dados que uma matriz possui através de dtype

	
arr = np.array([1, 2, 3, 4])
print(arr.dtype)
arr = np.array(['apple', 'banana', 'cherry'])
print(arr.dtype)
Copy
	
int64
<U6

Também podemos criar matrizes indicando o tipo de dado que queremos que tenha mediante dtype

	
arr = np.array([1, 2, 3, 4], dtype='i')
print("Enteros:")
print(arr)
print(arr.dtype)
arr = np.array([1, 2, 3, 4], dtype='f')
print("\nFloat:")
print(arr)
print(arr.dtype)
arr = np.array([1, 2, 3, 4], dtype='f')
print("\nComplejos:")
print(arr)
print(arr.dtype)
arr = np.array([1, 2, 3, 4], dtype='S')
print("\nString:")
print(arr)
print(arr.dtype)
arr = np.array([1, 2, 3, 4], dtype='U')
print("\nUnicode string:")
print(arr)
print(arr.dtype)
arr = np.array([1, 2, 3, 4], dtype='O')
print("\nObjeto:")
print(arr)
print(arr.dtype)
Copy
	
Enteros:
[1 2 3 4]
int32
Float:
[1. 2. 3. 4.]
float32
Complejos:
[1. 2. 3. 4.]
float32
String:
[b'1' b'2' b'3' b'4']
|S1
Unicode string:
['1' '2' '3' '4']
<U1
Objeto:
[1 2 3 4]
object

6. Operações matemáticaslink image 90

6.1. Operações básicaslink image 91

As operações matriciais são realizadas por elementos, por exemplo, se somarmos duas matrizes, serão somados os elementos de cada matriz na mesma posição, assim como na soma matemática de duas matrizes.

	
A = np.array([1, 2, 3])
B = np.array([1, 2, 3])
print(f"Matriz A: tamaño {A.shape}\n{A}\n")
print(f"Matriz B: tamaño {B.shape}\n{B}\n")
C = A + B
print(f"Matriz C: tamaño {C.shape}\n{C}\n")
D = A - B
print(f"Matriz D: tamaño {D.shape}\n{D}")
Copy
	
Matriz A: tamaño (3,)
[1 2 3]
Matriz B: tamaño (3,)
[1 2 3]
Matriz C: tamaño (3,)
[2 4 6]
Matriz D: tamaño (3,)
[0 0 0]

No entanto, se fazemos a multiplicação de duas matrizes, também é feita a multiplicação de cada elemento das matrizes (produto escalar)

	
A = np.array([[3, 5], [4, 1]])
B = np.array([[1, 2], [-3, 0]])
print(f"Matriz A: tamaño {A.shape}\n{A}\n")
print(f"Matriz B: tamaño {B.shape}\n{B}\n")
C = A * B
print(f"Matriz C: tamaño {C.shape}\n{C}\n")
Copy
	
Matriz A: tamaño (2, 2)
[[3 5]
[4 1]]
Matriz B: tamaño (2, 2)
[[ 1 2]
[-3 0]]
Matriz C: tamaño (2, 2)
[[ 3 10]
[-12 0]]

Para fazer o produto matricial que foi ensinado em matemática toda a vida, é necessário usar o operador @ ou o método dot

	
A = np.array([[3, 5], [4, 1], [6, -1]])
B = np.array([[1, 2, 3], [-3, 0, 4]])
print(f"Matriz A: tamaño {A.shape}\n{A}\n")
print(f"Matriz B: tamaño {B.shape}\n{B}\n")
C = A @ B
print(f"Matriz C: tamaño {C.shape}\n{C}\n")
D = A.dot(B)
print(f"Matriz D: tamaño {D.shape}\n{D}")
Copy
	
Matriz A: tamaño (3, 2)
[[ 3 5]
[ 4 1]
[ 6 -1]]
Matriz B: tamaño (2, 3)
[[ 1 2 3]
[-3 0 4]]
Matriz C: tamaño (3, 3)
[[-12 6 29]
[ 1 8 16]
[ 9 12 14]]
Matriz D: tamaño (3, 3)
[[-12 6 29]
[ 1 8 16]
[ 9 12 14]]

Se em vez de criar uma matriz nova, se quiser modificar alguma existente, pode-se usar os operadores +=, -= ou *=.

	
A = np.array([[3, 5], [4, 1]])
B = np.array([[1, 2], [-3, 0]])
print(f"Matriz A: tamaño {A.shape}\n{A}\n")
print(f"Matriz B: tamaño {B.shape}\n{B}\n")
A += B
print(f"Matriz A tras suma: tamaño {A.shape}\n{A}\n")
A -= B
print(f"Matriz A tras resta: tamaño {A.shape}\n{A}\n")
A *= B
print(f"Matriz A tras multiplicación: tamaño {A.shape}\n{A}\n")
Copy
	
Matriz A: tamaño (2, 2)
[[3 5]
[4 1]]
Matriz B: tamaño (2, 2)
[[ 1 2]
[-3 0]]
Matriz A tras suma: tamaño (2, 2)
[[4 7]
[1 1]]
Matriz A tras resta: tamaño (2, 2)
[[3 5]
[4 1]]
Matriz A tras multiplicación: tamaño (2, 2)
[[ 3 10]
[-12 0]]

Podem ser realizadas operações sobre todos os elementos de uma matriz, isto é graças a uma propriedade chamada broadcasting que veremos depois mais a fundo

	
A = np.array([[3, 5], [4, 1]])
print(f"Matriz A: tamaño {A.shape}\n{A}\n")
B = A * 2
print(f"Matriz B: tamaño {B.shape}\n{B}\n")
C = A ** 2
print(f"Matriz C: tamaño {C.shape}\n{C}\n")
D = 2*np.sin(A)
print(f"Matriz D: tamaño {D.shape}\n{D}")
Copy
	
Matriz A: tamaño (2, 2)
[[3 5]
[4 1]]
Matriz B: tamaño (2, 2)
[[ 6 10]
[ 8 2]]
Matriz C: tamaño (2, 2)
[[ 9 25]
[16 1]]
Matriz D: tamaño (2, 2)
[[ 0.28224002 -1.91784855]
[-1.51360499 1.68294197]]

6.2. Funções sobre matrizeslink image 92

Como se pode ver no último cálculo, o NumPy oferece operadores de funções sobre matrizes, há um monte de funções que se podem realizar sobre matrizes, matemáticas, lógicas, de álgebra linear, etc. A seguir mostramos algumas.

	
A = np.array([[3, 5], [4, 1]])
print(f"A\n{A}\n")
print(f"exp(A)\n{np.exp(A)}\n")
print(f"sqrt(A)\n{np.sqrt(A)}\n")
print(f"cos(A)\n{np.cos(A)}\n")
Copy
	
A
[[3 5]
[4 1]]
exp(A)
[[ 20.08553692 148.4131591 ]
[ 54.59815003 2.71828183]]
sqrt(A)
[[1.73205081 2.23606798]
[2. 1. ]]
cos(A)
[[-0.9899925 0.28366219]
[-0.65364362 0.54030231]]

Há algumas funções que retornam informações das matrizes, como a média

	
A = np.array([[3, 5], [4, 1]])
print(f"A\n{A}\n")
print(f"A.mean()\n{A.mean()}\n")
Copy
	
A
[[3 5]
[4 1]]
A.mean()
3.25

No entanto, podemos obter essa informação de cada eixo através do atributo axis; se este for 0, é feito sobre cada coluna, enquanto que se for 1, é feito sobre cada linha

	
A = np.array([[3, 5], [4, 1]])
print(f"A\n{A}\n")
print(f"A.mean() columnas\n{A.mean(axis=0)}\n")
print(f"A.mean() filas\n{A.mean(axis=1)}\n")
Copy
	
A
[[3 5]
[4 1]]
A.mean() columnas
[3.5 3. ]
A.mean() filas
[4. 2.5]

6.3. Broadcastinglink image 93

Podem ser realizadas operações matriciais com matrizes de diferentes dimensões. Neste caso, o NumPy detectará isso e fará uma projeção da menor matriz até igualá-la à maior. numpy_broadcasting Esta é uma grande qualidade do NumPy, que faz com que se possam realizar cálculos sobre matrizes sem ter que se preocupar em igualar as dimensões destas.

	
A = np.array([1, 2, 3])
print(f"A\n{A}\n")
B = A + 5
print(f"B\n{B}\n")
Copy
	
A
[1 2 3]
B
[6 7 8]
	
A = np.array([1, 2, 3])
B = np.ones((3,3))
print(f"A\n{A}\n")
print(f"B\n{B}\n")
C = A + B
print(f"C\n{C}\n")
Copy
	
A
[1 2 3]
B
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
C
[[2. 3. 4.]
[2. 3. 4.]
[2. 3. 4.]]
	
A = np.array([1, 2, 3])
B = np.array([[1], [2], [3]])
print(f"A\n{A}\n")
print(f"B\n{B}\n")
C = A + B
print(f"C\n{C}\n")
Copy
	
A
[1 2 3]
B
[[1]
[2]
[3]]
C
[[2 3 4]
[3 4 5]
[4 5 6]]

7. Indexação de matrizeslink image 94

O indexamento de matrizes é feito da mesma forma que com as listas de Python

	
arr = np.array([1, 2, 3, 4, 5])
arr[3]
Copy
	
4

No caso de ter mais de uma dimensão, é preciso indicar o índice em cada uma delas

	
arr = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]])
arr[1, 2]
Copy
	
8

Pode-se usar a indexação negativa

	
arr[-1, -2]
Copy
	
9

Em caso de não indicar um dos eixos, considera-se que se quer inteiro

	
arr = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]])
arr[1]
Copy
	
array([ 6, 7, 8, 9, 10])

7.1. Pedaços de matrizeslink image 95

Na hora de indexar, podemos ficar com partes de matrizes da mesma forma que se fazia com as listas de Python. Lembrar que se fazia da seguinte maneira: início:parada:passo Onde o intervalo vai desde o start (incluído) até o stop (sem incluir) com um passo de step Se step não for indicado, o padrão é 1

Por exemplo, se quisermos itens da segunda linha e da segunda à quarta coluna:

  • Selecionamos a segunda linha com um 1 (já que começamos a contar a partir de 0)* Selecionamos da segunda à quarta linha através de 1:4, o 1 para indicar a segunda coluna e o 4 para indicar a quinta (já que o segundo número indica a coluna em que se termina sem incluir essa coluna). Os dois números tendo em conta que se começa a contar do 0
	
print(arr)
print(arr[1, 1:4])
Copy
	
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
[7 8 9]

Podemos levá-lo de uma posição até o final

	
arr[1, 2:]
Copy
	
array([ 8, 9, 10])

Desde o início até uma posição

	
arr[1, :3]
Copy
	
array([6, 7, 8])

Estabelecer o intervalo com números negativoslink image 96

# Definir o intervalo usando números negativos
      range_negativo = range(-10, 0)
      
      # Imprimir os valores dentro do intervalo
      for num in range_negativo:
          print(num)
      

Neste exemplo, o intervalo range_negativo começa em -10 e vai até -1 (não inclui 0), em incrementos de 1. O loop for então imprime cada um desses valores.

	
arr[1, -3:-1]
Copy
	
array([8, 9])

Escolher o passo

	
arr[1, 1:4:2]
Copy
	
array([7, 9])

7.2. Iteração sobre matrizeslink image 97

A iteração sobre matrizes multidimensionais é realizada em relação ao primeiro eixo

	
M = np.array( [[[ 0, 1, 2],
[ 10, 12, 13]],
[[100,101,102],
[110,112,113]]])
print(f'Matriz de dimensión: {M.shape}\n')
i = 0
for fila in M:
print(f'Fila {i}: {fila}')
i += 1
Copy
	
Matriz de dimensión: (2, 2, 3)
Fila 0: [[ 0 1 2]
[10 12 13]]
Fila 1: [[100 101 102]
[110 112 113]]

No entanto, se o que queremos é iterar por cada item, podemos usar o método 'flat'

	
i = 0
for fila in M.flat:
print(f'Elemento {i}: {fila}')
i += 1
Copy
	
Elemento 0: 0
Elemento 1: 1
Elemento 2: 2
Elemento 3: 10
Elemento 4: 12
Elemento 5: 13
Elemento 6: 100
Elemento 7: 101
Elemento 8: 102
Elemento 9: 110
Elemento 10: 112
Elemento 11: 113

8. Cópia de matrizeslink image 98

Em NumPy temos duas maneiras de copiar matrizes, através de copy, que realiza uma cópia nova da matriz, e através de view que realiza uma visualização da matriz original A cópia é proprietária dos dados e qualquer mudança feita na cópia não afetará a matriz original, e qualquer mudança feita na matriz original não afetará a cópia. A visualização não é proprietária dos dados, e qualquer alteração feita na cópia afetará a matriz original, e qualquer alteração feita na matriz original afetará a cópia.

8.1. Copylink image 99

	
arr = np.array([1, 2, 3, 4, 5])
copy_arr = arr.copy()
arr[0] = 42
copy_arr[1] = 43
print(f'Original: {arr}')
print(f'Copia: {copy_arr}')
Copy
	
Original: [42 2 3 4 5]
Copia: [ 1 43 3 4 5]

8.2. Visualizarlink image 100

	
arr = np.array([1, 2, 3, 4, 5])
view_arr = arr.view()
arr[0] = 42
view_arr[1] = 43
print(f'Original: {arr}')
print(f'Vista: {view_arr}')
Copy
	
Original: [42 43 3 4 5]
Vista: [42 43 3 4 5]

8.3. Proprietário dos dadoslink image 101

Ante a dúvida de se temos uma cópia ou uma visualização, podemos usar `base`
      
	
arr = np.array([1, 2, 3, 4, 5])
copy_arr = arr.copy()
view_arr = arr.view()
print(copy_arr.base)
print(view_arr.base)
Copy
	
None
[1 2 3 4 5]

9. Forma das matrizeslink image 102

Podemos saber a forma que tem a matriz através do método shape. Este nos devolverá uma tupla, o tamanho da tupla representa as dimensões da matriz, em cada elemento da tupla se indica o número de itens em cada uma das dimensões da matriz

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
print(arr)
print(arr.shape)
Copy
	
[[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
[[11 12 13 14 15]
[16 17 18 19 20]]]
(2, 2, 5)

9.1. Redefinir Formalink image 103

Podemos mudar a forma das matrizes para a que quisermos através do método reshape. Por exemplo, a matriz anterior, que tem uma forma de (2, 2, 4). Podemos passá-la para (5, 4)

	
arr_reshape = arr.reshape(5, 4)
print(arr_reshape)
print(arr_reshape.shape)
Copy
	
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 18 19 20]]
(5, 4)

É preciso ter em mente que, para redimensionar as matrizes, o número de itens da nova forma deve ter o mesmo número de itens da primeira forma Ou seja, no exemplo anterior, a primeira matriz tinha 20 itens (2x2x4), e a nova matriz tem 20 itens (5x4). O que não podemos é redimensionar para uma matriz de tamanho (3, 4), pois no total haveria 12 itens.

	
arr_reshape = arr.reshape(3, 4)
Copy
	
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-29e85875d1df> in <module>()
----> 1 arr_reshape = arr.reshape(3, 4)
ValueError: cannot reshape array of size 20 into shape (3,4)

9.2. Dimensão desconhecidalink image 104

No caso de querermos mudar a forma de uma matriz e uma das dimensões não nos importar, ou não a conhecermos, podemos fazer com que o NumPy a calcule por nós introduzindo um -1 como parâmetro.

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
arr_reshape = arr.reshape(2, -1)
print(arr_reshape)
print(arr_reshape.shape)
Copy
	
[[ 1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20]]
(2, 10)

É preciso ter em mente que não se pode colocar qualquer número nas dimensões conhecidas. O número de itens da matriz original tem que ser um múltiplo das dimensões conhecidas. No exemplo anterior, a matriz tem 20 itens, que é múltiplo de 2, dimensão conhecida introduzida. Não seria possível colocar 3 como dimensão conhecida, uma vez que 20 não é múltiplo de 3, e não haveria nenhum número que pudesse ser colocado na dimensão desconhecida que fizesse com que no total houvesse 20 itens.

9.3. Aplainamento de matrizeslink image 105

Podemos achatar as matrizes, ou seja, transformá-las em uma única dimensão usando reshape(-1). Desta forma, independentemente das dimensões da matriz original, a nova sempre terá uma única dimensão.

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
arr_flatten = arr.reshape(-1)
print(arr_flatten)
print(arr_flatten.shape)
Copy
	
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
(20,)

Outra forma de aplanar uma matriz é através do método ravel()

	
arr = np.array([
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
])
arr_flatten = arr.ravel()
print(arr_flatten)
print(arr_flatten.shape)
Copy
	
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
(20,)

9.4. Matriz transpostalink image 106

Pode-se obter a transposta de uma matriz através do método T. Fazer a transposta de uma matriz é trocar as linhas e as colunas da matriz, na imagem abaixo vê-se um exemplo que esclarece melhor. transpose_matrix

	
arr = np.array([[1, 0, 4],
[0, 5, 0],
[6, 0, -9]])
arr_t = arr.T
print(arr_t)
print(arr_t.shape)
Copy
	
[[ 1 0 6]
[ 0 5 0]
[ 4 0 -9]]
(3, 3)

10. Empilhamento de matrizeslink image 107

10.1. Empilhamento verticallink image 108

Podem-se empilhar matrizes verticalmente (unindo linhas) através do método vstack()

	
a = np.array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
b = np.array([[4, 4, 4],
[5, 5, 5],
[6, 6, 6]])
c = np.vstack((a,b))
c
Copy
	
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5],
[6, 6, 6]])

Se você tiver matrizes de mais de 2 dimensões, vstack() empilhará ao longo da primeira dimensão

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
b = np.array([
[[5, 5],
[6, 6]],
[[7, 7],
[8, 8]]
])
c = np.vstack((a,b))
c
Copy
	
array([[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]],
[[5, 5],
[6, 6]],
[[7, 7],
[8, 8]]])

10.2. Empilhamento horizontallink image 109

Podem-se empilhar matrizes horizontalmente (unindo colunas) através do método hstack()

	
a = np.array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
b = np.array([[4, 5, 6],
[4, 5, 6],
[4, 5, 6]])
c = np.hstack((a,b))
c
Copy
	
array([[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6]])

Se você tem matrizes de mais de 2 dimensões, hstack() empilhará ao longo da segunda dimensão

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
b = np.array([
[[5, 5],
[6, 6]],
[[7, 7],
[8, 8]]
])
c = np.hstack((a,b))
c
Copy
	
array([[[1, 1],
[2, 2],
[5, 5],
[6, 6]],
[[3, 3],
[4, 4],
[7, 7],
[8, 8]]])

Outra maneira de adicionar colunas a uma matriz é através do método column_stack()

	
a = np.array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
b = np.array([4, 4, 4])
c = np.column_stack((a,b))
c
Copy
	
array([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])

10.3. Empilhamento em profundidadelink image 110

Podem ser empilhadas matrizes em profundidade (terceira dimensão) através do método dstack()

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
b = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
c = np.dstack((a,b))
print(f"c: {c}\n")
print(f"a.shape: {a.shape}, b.shape: {b.shape}, c.shape: {c.shape}")
Copy
	
c: [[[1 1 1 1]
[2 2 2 2]]
[[3 3 3 3]
[4 4 4 4]]]
a.shape: (2, 2, 2), b.shape: (2, 2, 2), c.shape: (2, 2, 4)

Se se possuem matrizes de mais de 4 dimensões, dstack() as empilhará ao longo da terceira dimensão

	
a = np.array([1, 2, 3, 4, 5], ndmin=4)
b = np.array([1, 2, 3, 4, 5], ndmin=4)
c = np.dstack((a,b))
print(f"a.shape: {a.shape}, b.shape: {b.shape}, c.shape: {c.shape}")
Copy
	
a.shape: (1, 1, 1, 5), b.shape: (1, 1, 1, 5), c.shape: (1, 1, 2, 5)

10.3. Empilhamento personalizadolink image 111

Mediante o método concatenate() é possível escolher o eixo no qual se deseja empilhar as matrizes

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
b = np.array([
[[5, 5],
[6, 6]],
[[7, 7],
[8, 8]]
])
conc0 = np.concatenate((a,b), axis=0) # concatenamiento en el primer eje
conc1 = np.concatenate((a,b), axis=1) # concatenamiento en el segundo eje
conc2 = np.concatenate((a,b), axis=2) # concatenamiento en el tercer eje
print(f"conc0: {conc0}\n")
print(f"conc1: {conc1}\n")
print(f"conc2: {conc2}")
Copy
	
conc0: [[[1 1]
[2 2]]
[[3 3]
[4 4]]
[[5 5]
[6 6]]
[[7 7]
[8 8]]]
conc1: [[[1 1]
[2 2]
[5 5]
[6 6]]
[[3 3]
[4 4]
[7 7]
[8 8]]]
conc2: [[[1 1 5 5]
[2 2 6 6]]
[[3 3 7 7]
[4 4 8 8]]]

11. Dividir matrizeslink image 112

11.1. Dividir verticalmentelink image 113

Podem-se dividir matrizes verticalmente (separando linhas) através do método vsplit()

	
a = np.array([[1.1, 1.2, 1.3, 1.4],
[2.1, 2.2, 2.3, 2.4],
[3.1, 3.2, 3.3, 3.4],
[4.1, 4.2, 4.3, 4.4]])
[a1, a2] = np.vsplit(a, 2)
print(f"a1: {a1}\n")
print(f"a2: {a2}")
Copy
	
a1: [[1.1 1.2 1.3 1.4]
[2.1 2.2 2.3 2.4]]
a2: [[3.1 3.2 3.3 3.4]
[4.1 4.2 4.3 4.4]]

Se houver matrizes com mais de 2 dimensões, vsplit() dividirá ao longo da primeira dimensão

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
[a1, a2] = np.vsplit(a, 2)
print(f"a1: {a1}\n")
print(f"a2: {a2}")
Copy
	
a1: [[[1 1]
[2 2]]]
a2: [[[3 3]
[4 4]]]

11.2. Dividir horizontalmentelink image 114

Podem-se dividir matrizes horizontalmente (separando colunas) por meio do método hsplit()

	
a = np.array([[1.1, 1.2, 1.3, 1.4],
[2.1, 2.2, 2.3, 2.4],
[3.1, 3.2, 3.3, 3.4],
[4.1, 4.2, 4.3, 4.4]])
[a1, a2] = np.hsplit(a, 2)
print(f"a1: {a1}\n")
print(f"a2: {a2}")
Copy
	
a1: [[1.1 1.2]
[2.1 2.2]
[3.1 3.2]
[4.1 4.2]]
a2: [[1.3 1.4]
[2.3 2.4]
[3.3 3.4]
[4.3 4.4]]

Se você tiver matrizes de mais de 2 dimensões, hsplit() dividirá ao longo da segunda dimensão

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
[a1, a2] = np.hsplit(a, 2)
print(f"a1: {a1}\n")
print(f"a2: {a2}")
Copy
	
a1: [[[1 1]]
[[3 3]]]
a2: [[[2 2]]
[[4 4]]]

11.3 Divisão personalizadalink image 115

Mediante o método array_split() pode-se escolher o eixo no qual se desejam dividir as matrizes

	
a = np.array([
[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]]
])
[a1_eje0, a2_eje0] = np.array_split(a, 2, axis=0)
[a1_eje1, a2_eje1] = np.array_split(a, 2, axis=1)
[a1_eje2, a2_eje2] = np.array_split(a, 2, axis=2)
print(f"a1_eje0: {a1_eje0}\n")
print(f"a2_eje0: {a2_eje0} ")
print(f"a1_eje1: {a1_eje1}\n")
print(f"a2_eje1: {a2_eje1} ")
print(f"a1_eje2: {a1_eje2}\n")
print(f"a2_eje2: {a2_eje2}")
Copy
	
a1_eje0: [[[1 1]
[2 2]]]
a2_eje0: [[[3 3]
[4 4]]]
a1_eje1: [[[1 1]]
[[3 3]]]
a2_eje1: [[[2 2]]
[[4 4]]]
a1_eje2: [[[1]
[2]]
[[3]
[4]]]
a2_eje2: [[[1]
[2]]
[[3]
[4]]]

12. Busca em matrizeslink image 116

Se se quer buscar um valor dentro de uma matriz, pode-se usar o método where() que devolve as posições onde a matriz tem o valor que estamos procurando

	
arr = np.array([1, 2, 3, 4, 5, 4, 4])
ids = np.where(arr == 4)
ids
Copy
	
(array([3, 5, 6]),)

Podem-se usar funções para procurar, por exemplo, se quisermos procurar em quais posições os valores são pares

	
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
ids = np.where(arr%2)
ids
Copy
	
(array([0, 2, 4, 6]),)

13. Ordenar matrizeslink image 117

Mediante o método sort() podemos ordenar matrizes

	
arr = np.array([3, 2, 0, 1])
arr_ordenado = np.sort(arr)
arr_ordenado
Copy
	
array([0, 1, 2, 3])

Se o que temos são strings, ele as ordena em ordem alfabética

	
arr = np.array(['banana', 'apple', 'cherry'])
arr_ordenado = np.sort(arr)
arr_ordenado
Copy
	
array(['apple', 'banana', 'cherry'], dtype='<U6')

E as matrizes de booleanos também as ordena

	
arr = np.array([True, False, True])
arr_ordenado = np.sort(arr)
arr_ordenado
Copy
	
array([False, True, True])

Se se tiver matrizes de mais de uma dimensão, ordena-as por dimensões, ou seja, se se tiver uma matriz de 2 dimensões, ordena os números da primeira fila entre eles e os da segunda fila entre eles

	
arr = np.array([[3, 2, 4], [5, 0, 1]])
arr_ordenado = np.sort(arr)
arr_ordenado
Copy
	
array([[2, 3, 4],
[0, 1, 5]])

Por padrão, ordena sempre em relação às linhas, mas se você quiser que ordene em relação a outra dimensão, deve especificar através da variável axis

	
arr = np.array([[3, 2, 4], [5, 0, 1]])
arr_ordenado0 = np.sort(arr, axis=0) # Se ordena con respecto a la primera dimensión
arr_ordenado1 = np.sort(arr, axis=1) # Se ordena con respecto a la segunda dimensión
print(f"arr_ordenado0: {arr_ordenado0}\n")
print(f"arr_ordenado1: {arr_ordenado1}\n")
Copy
	
arr_ordenado0: [[3 0 1]
[5 2 4]]
arr_ordenado1: [[2 3 4]
[0 1 5]]

14. Filtros em matrizeslink image 118

NumPy oferece a possibilidade de buscar certos elementos de uma matriz e criar uma nova Isso é feito criando uma matriz de índices booleanos, ou seja, cria uma nova matriz que indica com quais posições ficamos da matriz e com quais não. Vamos dar uma olhada em um exemplo de uma matriz de índices booleanos

	
arr = np.array([37, 85, 12, 45, 69, 22])
indices_booleanos = [False, False, True, False, False, True]
arr_filter = arr[indices_booleanos]
print(f"Array original: {arr}")
print(f"indices booleanos: {indices_booleanos}")
print(f"Array filtrado: {arr_filter}")
Copy
	
Array original: [37 85 12 45 69 22]
indices booleanos: [False, False, True, False, False, True]
Array filtrado: [12 22]

Como se pode ver, o array filtrado (arr_filtr), apenas ficou do array original (arr) com os elementos que coincidem com aqueles em que o array indices_booleanos vale True.

Outra coisa que podemos ver é que ele ficou apenas com os elementos pares, então agora vamos ver como fazer para ficar com os elementos pares de uma matriz, sem ter que fazer manualmente como fizemos no exemplo anterior.

	
arr = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]])
indices_booleanos = arr % 2 == 0
arr_filter = arr[indices_booleanos]
print(f"Array original: {arr}\n")
print(f"indices booleanos: {indices_booleanos}\n")
print(f"Array filtrado: {arr_filter}")
Copy
	
Array original: [[ 1 2 3 4 5]
[ 6 7 8 9 10]]
indices booleanos: [[False True False True False]
[ True False True False True]]
Array filtrado: [ 2 4 6 8 10]

Continuar lendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

Você já conversou com um LLM e ele lhe respondeu algo que parece ter bebido café de máquina a noite toda? 😂 Isso é o que chamamos de alucinação no mundo dos LLMs! Mas não se preocupe, pois não é que seu modelo de linguagem esteja louco (embora às vezes possa parecer isso 🤪). A verdade é que os LLMs podem ser um pouco... criativos quando se trata de gerar texto. Mas graças ao DoLa, um método que usa camadas de contraste para melhorar a viabilidade dos LLMs, podemos evitar que nossos modelos de linguagem se transformem em escritores de ficção científica 😂. Nesta publicação, explicarei como o DoLa funciona e mostrarei um exemplo de código para que você possa entender melhor como tornar seus LLMs mais confiáveis e menos propensos a inventar histórias. Vamos salvar nossos LLMs da loucura e torná-los mais úteis! 🚀

Últimos posts -->

Você viu esses projetos?

Subtify

Subtify Subtify

Gerador de legendas para vídeos no idioma que você desejar. Além disso, coloca uma legenda de cor diferente para cada pessoa

Ver todos os projetos -->

Quer aplicar IA no seu projeto? Entre em contato!

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Ver todos os contêineres -->

Quer aplicar IA no seu projeto? Entre em contato!

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

Dataset com piadas em inglês

opus100

Dataset com traduções de inglês para espanhol

netflix_titles

Dataset com filmes e séries da Netflix

Ver mais datasets -->