Numpy

È la libreria di riferimento per il calcolo scientifico in python.

Array

È una griglia di valori n-dimensionale (tensore) tutti dello stesso tipo. È indicizzata da una tupla di numeri interi non negativi. Il numero di dimensione è detto rango dell’array, mentre la sua shape è una tupla di interi che indica la dimensione del tensore lungo ogni dimensione.

Ci sono molti modi per creare un array:

  • a = numpy.zeros((2, 2)): crea un array tutto 0
  • a = numpy.ones((2, 2)): crea un array tutto 1
  • a = numpy.full((2, 2), 3): crea un array tutto 3
  • a = numpy.eye((2, 2)): crea una matrice identità
  • a = numpy.random.random((2, 2)): crea un array random

Slicing

Gli array possono essere indicizzati. Dato che possono essere multidimensionali, si deve specificare una sezione per ogni dimensione della matrice.

numpy.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])

Uno slice è un subarray. a[:2, 1:3] ritorna [[2, 3], [6, 7]]. Gli slice, se modificati, modificano l’array di partenza.

Avendo un array di questo tipo: np.array([[1,2], [3, 4], [5, 6]]) Si può ricavare lo slice [1 4 5] tramite a[[0, 1, 2], [0, 1, 0]]

Boolean indexing

Spesso utilizzato per selezionare elementi di una matrice che soddisfano alcune condizioni.

a = numpy.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2)
 
print(a[bool_idx])     # [3 4 5 6]
# equivalentemente
print(a[a > 2])

Array datatypes

Il tipo di dati è solitamente indovinato da numpy, ma se si vuole avere un controllo maggiore, si può passare il tipo di dato al momento della creazione.

a = numpy.array([1, 2])
print(a.dtype)
 
b = numpy.array([1, 2], dtype=numpy.int64)
print(b.dtype)

Operations between arrays

Le classiche operazioni tra array sono tutte elementwise. Quindi +, -, *, / con le rispettive funzioni add(x, y), subtract(x, y), multiply(x, y), divide(x, y). Anche sqrt(x, y) è elementwise.

Tutti i metodi appartengono al namespace numpy.

Per eseguire una moltiplicazione matriciale, si può utilizzare il metodo dot(x, y)

Trasposta

Per calcolare la trasposta di una matrice basta chiamare il suo attributo T. a.T restituisce la trasposta di a.

Broadcasting

Potente meccanismo che consente a numpy di fare operazioni con matrici di forme diverse.

Ad esempio proviamo ad aggiungere un array [1, 0, 1] a tutte le righe di una matrice più grande.

x = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
v = numpy.array([1, 0, 1])
 
# Esempio 1:
vv = numpy.tile(v, (4, 1))   # impila il vettore v 4 volte, quindi crea una matrice simile a x
y = x + vv
 
# Esempio 2:
y = x + v

Nell’esempio 1 prima si crea una matrice della stessa dimensione di x, e poi si esegue la somma elementwise.

Nell’esempio 2, invece, si utilizza il broadcasting per eseguire la somma tra due matrici di dimensione differente.

Il broadcasting segue queste regole:

  1. Se i due array non hanno lo stesso rango, vengono anteposti alla shape dell’array di rango inferiore degli 1 fino a quando entrambe le shape hanno la stessa lunghezza.
  2. I due array vengono detti compatibili lungo una dimensione, se hanno lo stesso numero di elementi su quella dimensione, o se uno dei due ha 1 solo elemento lungo quella dimensione.
  3. Il broadcasting si può applicare solo se i due array sono compatibili su tutte le dimensioni.
  4. Dopo il broadcasting, ogni array si comporta come se avesse shape uguale al massimo elementwise delle shape dei due array di input
  5. Nella dimensione in cui uno dei due array ha lunghezza 1, il primo array si comporta come se fosse stato copiato lungo tale dimensione.

Lavorare con le immagini

Le immagini sono solitamente memorizzate in formati compressi (jpg, bmp, png…), e la compressione può essere lossy, o non lossy (png).

Per leggere un’immagine quindi abbiamo bisogno di un decodificatore in grado di leggere l’immagine e restituire i pixel.

I pixel sono di solito rappresentati con interi senza segno a 8 bit (np.uint8), che hanno range 0-255.

sva_s05