Python és adattudomány alapok · Lecke 04

NumPy és a tömbök

A numerikus munka alapja a NumPy tömb, amely azonos típusú elemeket tárol és gyors, vektorizált műveleteket enged. Ebben a leckében a tömb létrehozását, jellemzőit, az indexelést, a vektorizációt és a tengely fogalmát vesszük végig.

Vissza a tananyaghoz


Miért nem elég a lista

A Python lista sokféle elemet tárolhat, és ez rugalmas, de nagy számhalmazon lassú és körülményes. A numerikus munka alapja ezért a NumPy, amelynek központi adatszerkezete a tömb, angolul array. A tömb azonos típusú elemeket tárol egy összefüggő memóriaterületen, és a rajtuk végzett műveletek gyors, C nyelven írt kódban futnak. A NumPy szokásos importja a np rövidítéssel történik.

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6])
print(a)              # [1 2 3 4 5 6]
print(a.dtype)       # int64   (az elemek tipusa)

A tömböt a np.array függvénnyel hozzuk létre egy listából. A dtype az elemek közös típusa.

A tömb jellemzői

Egy tömbnek több leíró tulajdonsága van. A shape megadja a méretet minden dimenzió mentén egy tuple formájában, az ndim a dimenziók számát, a size az összes elem darabszámát, a dtype pedig az elemek közös típusát. Ezek a tulajdonságok segítenek ellenőrizni, hogy az adat a várt alakú-e, ami a gépi tanulásban gyakori hibaforrás.

a = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8],
              [9, 10, 11, 12]])
print(a.shape)       # (3, 4)   3 sor, 4 oszlop
print(a.ndim)        # 2        ket dimenzio
print(a.size)        # 12       elemek szama

Egy kétdimenziós tömb alakja (3, 4), vagyis három sor és négy oszlop, összesen tizenkét elem.


Tömbök gyors előállítása

Gyakran nem kézzel soroljuk fel az elemeket, hanem generáljuk a tömböt. A np.zeros csupa nullát, a np.ones csupa egyest ad. A np.arange egy egyenletes lépésközű egész sorozatot állít elő, a megadott stop értéket nem éri el. A np.linspace pedig két végpont között ad meg adott számú, egyenletesen elosztott értéket.

print(np.zeros(3))            # [0. 0. 0.]
print(np.ones(2))             # [1. 1.]
print(np.arange(2, 9, 2))     # [2 4 6 8]
print(np.linspace(0, 10, num=5))  # [ 0.   2.5  5.   7.5 10. ]

Négy tipikus generátor. Az arange lépésközzel, a linspace pedig fix darabszámmal állít elő értékeket.


Indexelés és szeletelés

A tömb elemeit ugyanúgy indexeljük, mint a listát, nullától indulva. Kétdimenziós tömbnél a sor és az oszlop indexét vesszővel adjuk meg. A logikai indexelés a NumPy egyik legerősebb eszköze. Egy feltétel egy logikai tömböt ad, és ezzel egyetlen lépésben kiválaszthatók a feltételnek megfelelő elemek, ciklus nélkül.

a = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8],
              [9, 10, 11, 12]])
print(a[1, 3])       # 8    masodik sor, negyedik elem
print(a[a < 5])      # [1 2 3 4]   a felteteltnek megfelelo elemek

A logikai indexelés egy feltétellel választja ki az elemeket. Itt az ötnél kisebbeket kapjuk vissza.


Vektorizáció, a lényeg

A NumPy igazi ereje a vektorizáció. Egy művelet nem elemenként, ciklusban fut, hanem egyszerre az egész tömbön. Két azonos alakú tömb összeadása elemenként adja össze az értékeket, egy tömb és egy szám művelete pedig minden elemre ugyanazt a számot alkalmazza. Ez utóbbit hívják broadcastingnak. A vektorizált kód rövidebb és sokkal gyorsabb, mint a kézi ciklus.

data = np.array([1, 2, 3, 4])
print(data + 10)     # [11 12 13 14]   minden elemhez hozzaad
print(data * 2)      # [2 4 6 8]       minden elemet megszoroz

masik = np.array([10, 20, 30, 40])
print(data + masik)  # [11 22 33 44]   elemenkenti osszeadas

A művelet az egész tömbön egyszerre fut. Egy tömb és egy szám esetén a szám minden elemre alkalmazódik, ez a broadcasting.

Python ciklussal

  • Elemenként végigjárjuk a listát
  • Több sor kód, könnyebb elrontani
  • Nagy adaton érezhetően lassabb

NumPy vektorizálással

  • Egyetlen művelet az egész tömbön
  • Rövid, olvasható kifejezés
  • Gyors, mert C kódban fut

Összesítések és a tengely

A tömbökön összesítő műveleteket végezhetünk, például sum, min, max és mean. Kétdimenziós tömbnél megadhatjuk, melyik tengely mentén összesítsen. Az axis egyenlő nulla az oszlopok mentén, tehát a sorokon lefelé összesít, az axis egyenlő egy pedig a soron belül, az oszlopok mentén. A tengely fogalma a pandas és a gépi tanulás könyvtárakban is végig visszatér.

b = np.array([[1, 1],
              [2, 2]])
print(b.sum())        # 6            minden elem osszege
print(b.sum(axis=0))  # [3 3]        oszloponkent (soron lefele)
print(b.sum(axis=1))  # [2 4]        soronkent (oszlopok menten)

Az axis paraméter dönti el, melyik tengely mentén összesít. Ez a fogalom a pandasban is ugyanígy működik.

axis = 0 oszloponként, soron lefelé 1 1 2 2 3 3 axis = 1 soronként, oszlopok mentén 1 1 2 2 2 4
Az axis nulla az oszlopok mentén, soronként lefelé összesít, az axis egy pedig soronként, az oszlopok mentén. A kimenet alakja ennek megfelelően más.
1

Egy szerkezet, ami mindent visz. A tömb azonos típusú elemeket tárol, és a rajta végzett vektorizált művelet gyors és tömör. Az alak, az indexelés és a tengely fogalma innentől a pandasban és a gépi tanulás könyvtárakban is végig visszatér.


← Előző lecke Következő lecke →

Workshop

AI Transformation Day

Egésznapos, vezetőknek szóló program. Feltérképezzük, hol tart a szervezet, mi az első reális lépés, és milyen belső feltételek szükségesek a sikerhez. A nap végén konkrét, prioritizált cselekvési lista.

Érdekel a program →