ApgÅ«stiet Python NumPy pÄrraidīŔanu ar Å”o visaptveroÅ”o rokasgrÄmatu. Uzziniet noteikumus, progresÄ«vas tehnikas un praktiskus pielietojumus efektÄ«vai masÄ«vu formas manipulÄcijai datu zinÄtnÄ un maŔīnmÄcÄ«bÄ.
NumPy SpÄka AtklÄÅ”ana: PadziļinÄta IepazīŔanÄs ar PÄrraidīŔanu un MasÄ«vu Formas ManipulÄcijÄm
Laipni lÅ«dzam augstas veiktspÄjas skaitliskÄs skaitļoÅ”anas pasaulÄ Python valodÄ! Ja jÅ«s nodarbojaties ar datu zinÄtni, maŔīnmÄcīŔanos, zinÄtnisko pÄtniecÄ«bu vai finanÅ”u analÄ«zi, jÅ«s neapÅ”aubÄmi esat saskÄruÅ”ies ar NumPy. Tas ir Python zinÄtniskÄs skaitļoÅ”anas ekosistÄmas pamatakmens, kas nodroÅ”ina jaudÄ«gu N-dimensiju masÄ«va objektu un sarežģītu funkciju kopumu darbam ar to.
Viens no biežÄkajiem ŔķÄrŔļiem iesÄcÄjiem un pat vidÄja lÄ«meÅa lietotÄjiem ir pÄreja no tradicionÄlÄs, uz cikliem balstÄ«tÄs domÄÅ”anas standarta Python valodÄ uz vektorizÄtu, uz masÄ«viem orientÄtu domÄÅ”anu, kas nepiecieÅ”ama efektÄ«vam NumPy kodam. Å Ä«s paradigmas maiÅas centrÄ ir spÄcÄ«gs, taÄu bieži pÄrprasts mehÄnisms: PÄrraidīŔana (Broadcasting). TÄ ir "maÄ£ija", kas ļauj NumPy veikt jÄgpilnas darbÄ«bas ar dažÄdu formu un izmÄru masÄ«viem, turklÄt bez veiktspÄjas zuduma, ko rada skaidri definÄti Python cikli.
Å Ä« visaptveroÅ”Ä rokasgrÄmata ir paredzÄta globÄlai izstrÄdÄtÄju, datu zinÄtnieku un analÄ«tiÄ·u auditorijai. MÄs vienkÄrÅ”oti izskaidrosim pÄrraidīŔanu no paÅ”iem pamatiem, izpÄtÄ«sim tÄs stingros noteikumus un demonstrÄsim, kÄ apgÅ«t masÄ«vu formas manipulÄciju, lai izmantotu tÄs pilno potenciÄlu. BeigÄs jÅ«s ne tikai sapratÄ«siet, *kas* ir pÄrraidīŔana, bet arÄ«, *kÄpÄc* tÄ ir kritiski svarÄ«ga tÄ«ra, efektÄ«va un profesionÄla NumPy koda rakstīŔanai.
Kas ir NumPy PÄrraidīŔana? Pamatkoncepcija
SavÄ bÅ«tÄ«bÄ pÄrraidīŔana ir noteikumu kopums, kas apraksta, kÄ NumPy apstrÄdÄ masÄ«vus ar dažÄdÄm formÄm aritmÄtisko darbÄ«bu laikÄ. TÄ vietÄ, lai izraisÄ«tu kļūdu, tÄ mÄÄ£ina atrast saderÄ«gu veidu, kÄ veikt darbÄ«bu, virtuÄli "izstiepjot" mazÄko masÄ«vu, lai tas atbilstu lielÄkÄ masÄ«va formai.
ProblÄma: DarbÄ«bas ar NesaderÄ«giem MasÄ«viem
IedomÄjieties, ka jums ir 3x3 matrica, kas, piemÄram, attÄlo maza attÄla pikseļu vÄrtÄ«bas, un jÅ«s vÄlaties palielinÄt katra pikseļa spilgtumu par vÄrtÄ«bu 10. Standarta Python valodÄ, izmantojot sarakstu sarakstus, jÅ«s, iespÄjams, rakstÄ«tu ligzdotu ciklu:
Python Cikla Pieeja (LÄnais Veids)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
result = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for i in range(len(matrix)):
for j in range(len(matrix[0])):
result[i][j] = matrix[i][j] + 10
# result will be [[11, 12, 13], [14, 15, 16], [17, 18, 19]]
Tas strÄdÄ, bet ir gari un, kas ir vÄl svarÄ«gÄk, neticami neefektÄ«vi lieliem masÄ«viem. Python interpretatoram ir liela virsizmaksa katrai cikla iterÄcijai. NumPy ir izstrÄdÄts, lai novÄrstu Å”o vÄjo vietu.
RisinÄjums: PÄrraidīŔanas MaÄ£ija
Ar NumPy tÄ pati darbÄ«ba kļūst par vienkÄrŔības un Ätruma paraugu:
NumPy PÄrraidīŔanas Pieeja (Ätrais Veids)
import numpy as np
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
result = matrix + 10
# result will be:
# array([[11, 12, 13],
# [14, 15, 16],
# [17, 18, 19]])
KÄ tas darbojÄs? MasÄ«va `matrix` forma ir `(3, 3)`, savukÄrt skalÄra `10` forma ir `()`. NumPy pÄrraidīŔanas mehÄnisms saprata mÅ«su nolÅ«ku. Tas virtuÄli "izstiepa" jeb "pÄrraidÄ«ja" skalÄru `10`, lai tas atbilstu matricas `(3, 3)` formai, un pÄc tam veica saskaitīŔanu pa elementiem.
BÅ«tiski, ka Ŕī izstiepÅ”ana ir virtuÄla. NumPy atmiÅÄ neizveido jaunu 3x3 masÄ«vu, kas piepildÄ«ts ar desmitniekiem. Tas ir ļoti efektÄ«vs process, kas tiek veikts C lÄ«meÅa implementÄcijÄ un atkÄrtoti izmanto vienu skalÄro vÄrtÄ«bu, tÄdÄjÄdi ietaupot ievÄrojamu atmiÅu un aprÄÄ·inu laiku. TÄ ir pÄrraidīŔanas bÅ«tÄ«ba: veikt darbÄ«bas ar dažÄdu formu masÄ«viem tÄ, it kÄ tie bÅ«tu saderÄ«gi, bez atmiÅas izmaksÄm, kas rastos, faktiski padarot tos saderÄ«gus.
PÄrraidīŔanas Noteikumi: VienkÄrÅ”oti Izskaidroti
PÄrraidīŔana var Ŕķist maÄ£iska, bet to regulÄ divi vienkÄrÅ”i, stingri noteikumi. Veicot darbÄ«bas ar diviem masÄ«viem, NumPy salÄ«dzina to formas pa elementiem, sÄkot no labÄs puses (beigu) dimensijÄm. Lai pÄrraidīŔana bÅ«tu veiksmÄ«ga, Å”iem diviem noteikumiem jÄbÅ«t izpildÄ«tiem katrÄ dimensiju salÄ«dzinÄÅ”anÄ.
1. Noteikums: Dimensiju IzlÄ«dzinÄÅ”ana
Pirms dimensiju salÄ«dzinÄÅ”anas NumPy konceptuÄli izlÄ«dzina abu masÄ«vu formas pÄc to beigu dimensijÄm. Ja vienam masÄ«vam ir mazÄk dimensiju nekÄ otram, tas tiek papildinÄts no kreisÄs puses ar 1. izmÄra dimensijÄm, lÄ«dz tam ir tikpat daudz dimensiju kÄ lielÄkajam masÄ«vam.
PiemÄrs:
- Masīva A forma ir `(5, 4)`
- Masīva B forma ir `(4,)`
NumPy to uztver kÄ salÄ«dzinÄjumu starp:
- A forma: `5 x 4`
- B forma: ` 4`
TÄ kÄ B ir mazÄk dimensiju, tas netiek papildinÄts Å”ajÄ pa labi izlÄ«dzinÄtajÄ salÄ«dzinÄjumÄ. TomÄr, ja mÄs salÄ«dzinÄtu `(5, 4)` un `(5,)`, situÄcija bÅ«tu atŔķirÄ«ga un novestu pie kļūdas, ko mÄs izpÄtÄ«sim vÄlÄk.
2. Noteikums: Dimensiju Saderība
PÄc izlÄ«dzinÄÅ”anas katram salÄ«dzinÄmajam dimensiju pÄrim (no labÄs uz kreiso) ir jÄatbilst vienam no Å”iem nosacÄ«jumiem:
- Dimensijas ir vienÄdas.
- Viena no dimensijÄm ir 1.
Ja Å”ie nosacÄ«jumi ir spÄkÄ visiem dimensiju pÄriem, masÄ«vi tiek uzskatÄ«ti par "pÄrraidīŔanai saderÄ«giem". RezultÄjoÅ”Ä masÄ«va formai katrÄ dimensijÄ bÅ«s izmÄrs, kas ir maksimÄlais no ievades masÄ«vu dimensiju izmÄriem.
Ja kÄdÄ brÄ«dÄ« Å”ie nosacÄ«jumi netiek izpildÄ«ti, NumPy padodas un izraisa `ValueError` ar skaidru ziÅojumu, piemÄram, `"operands could not be broadcast together with shapes ..."`.
Praktiski PiemÄri: PÄrraidīŔana DarbÄ«bÄ
NostiprinÄsim savu izpratni par Å”iem noteikumiem ar virkni praktisku piemÄru, sÄkot no vienkÄrÅ”iem lÄ«dz sarežģītiem.
1. PiemÄrs: VienkÄrÅ”Äkais GadÄ«jums ā SkalÄrs un MasÄ«vs
Å is ir piemÄrs, ar kuru mÄs sÄkÄm. AnalizÄsim to caur mÅ«su noteikumu prizmu.
A = np.array([[1, 2, 3], [4, 5, 6]]) # Forma: (2, 3)
B = 10 # Forma: ()
C = A + B
Analīze:
- Formas: A ir `(2, 3)`, B ir faktiski skalÄrs.
- 1. noteikums (IzlÄ«dzinÄÅ”ana): NumPy uzskata skalÄru par jebkuras saderÄ«gas dimensijas masÄ«vu. MÄs varam iedomÄties, ka tÄ forma tiek papildinÄta lÄ«dz `(1, 1)`. SalÄ«dzinÄsim `(2, 3)` un `(1, 1)`.
- 2. noteikums (Saderība):
- Beigu dimensija: `3` pret `1`. 2. nosacījums ir izpildīts (viena ir 1).
- NÄkamÄ dimensija: `2` pret `1`. 2. nosacÄ«jums ir izpildÄ«ts (viena ir 1).
- RezultÄta Forma: MaksimÄlais no katra dimensiju pÄra ir `(max(2, 1), max(3, 1))`, kas ir `(2, 3)`. SkalÄrs `10` tiek pÄrraidÄ«ts pa visu Å”o formu.
2. PiemÄrs: 2D MasÄ«vs un 1D MasÄ«vs (Matrica un Vektors)
Å is ir ļoti izplatÄ«ts lietoÅ”anas gadÄ«jums, piemÄram, pievienojot nobÄ«di katrai iezÄ«mei datu matricÄ.
A = np.arange(12).reshape(3, 4) # Forma: (3, 4)
# A = array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
B = np.array([10, 20, 30, 40]) # Forma: (4,)
C = A + B
Analīze:
- Formas: A ir `(3, 4)`, B ir `(4,)`.
- 1. noteikums (IzlÄ«dzinÄÅ”ana): MÄs izlÄ«dzinÄm formas pa labi.
- A forma: `3 x 4`
- B forma: ` 4`
- 2. noteikums (Saderība):
- Beigu dimensija: `4` pret `4`. 1. nosacÄ«jums ir izpildÄ«ts (tÄs ir vienÄdas).
- NÄkamÄ dimensija: `3` pret `(nekas)`. Ja mazÄkajÄ masÄ«vÄ trÅ«kst dimensijas, tas ir tÄ, it kÄ Å”Ä«s dimensijas izmÄrs bÅ«tu 1. TÄtad mÄs salÄ«dzinÄm `3` pret `1`. 2. nosacÄ«jums ir izpildÄ«ts. VÄrtÄ«ba no B tiek izstiepta jeb pÄrraidÄ«ta pa Å”o dimensiju.
- RezultÄta Forma: RezultÄjoÅ”Ä forma ir `(3, 4)`. 1D masÄ«vs `B` tiek faktiski pievienots katrai `A` rindai.
# C will be: # array([[10, 21, 32, 43], # [14, 25, 36, 47], # [18, 29, 40, 51]])
3. PiemÄrs: Kolonnas un Rindas Vektoru KombinÄcija
Kas notiek, kad mÄs apvienojam kolonnas vektoru ar rindas vektoru? Å eit pÄrraidīŔana rada spÄcÄ«gu, ÄrÄjam reizinÄjumam lÄ«dzÄ«gu uzvedÄ«bu.
A = np.array([0, 10, 20]).reshape(3, 1) # Forma: (3, 1) kolonnas vektors
# A = array([[ 0],
# [10],
# [20]])
B = np.array([0, 1, 2]) # Forma: (3,). Var būt arī (1, 3)
# B = array([0, 1, 2])
C = A + B
Analīze:
- Formas: A ir `(3, 1)`, B ir `(3,)`.
- 1. noteikums (IzlÄ«dzinÄÅ”ana): MÄs izlÄ«dzinÄm formas.
- A forma: `3 x 1`
- B forma: ` 3`
- 2. noteikums (Saderība):
- Beigu dimensija: `1` pret `3`. 2. nosacÄ«jums ir izpildÄ«ts (viena ir 1). MasÄ«vs `A` tiks izstiepts pa Å”o dimensiju (kolonnÄm).
- NÄkamÄ dimensija: `3` pret `(nekas)`. KÄ iepriekÅ”, mÄs to uzskatÄm par `3` pret `1`. 2. nosacÄ«jums ir izpildÄ«ts. MasÄ«vs `B` tiks izstiepts pa Å”o dimensiju (rindÄm).
- RezultÄta Forma: MaksimÄlais no katra dimensiju pÄra ir `(max(3, 1), max(1, 3))`, kas ir `(3, 3)`. RezultÄts ir pilna matrica.
# C will be: # array([[ 0, 1, 2], # [10, 11, 12], # [20, 21, 22]])
4. PiemÄrs: PÄrraidīŔanas Kļūme (ValueError)
Tikpat svarÄ«gi ir saprast, kad pÄrraidīŔana neizdosies. MÄÄ£inÄsim pievienot 3 elementu garu vektoru katrai 3x4 matricas kolonnai.
A = np.arange(12).reshape(3, 4) # Forma: (3, 4)
B = np.array([10, 20, 30]) # Forma: (3,)
try:
C = A + B
except ValueError as e:
print(e)
Å is kods izdrukÄs: operands could not be broadcast together with shapes (3,4) (3,)
Analīze:
- Formas: A ir `(3, 4)`, B ir `(3,)`.
- 1. noteikums (IzlÄ«dzinÄÅ”ana): MÄs izlÄ«dzinÄm formas pa labi.
- A forma: `3 x 4`
- B forma: ` 3`
- 2. noteikums (Saderība):
- Beigu dimensija: `4` pret `3`. Neizdodas! Dimensijas nav vienÄdas, un neviena no tÄm nav 1. NumPy nekavÄjoties apstÄjas un izraisa `ValueError`.
Å Ä« kļūme ir loÄ£iska. NumPy nezin, kÄ izlÄ«dzinÄt 3 elementu vektoru ar 4 elementu rindÄm. MÅ«su nolÅ«ks, iespÄjams, bija pievienot *kolonnas* vektoru. Lai to izdarÄ«tu, mums ir skaidri jÄmanipulÄ ar masÄ«va B formu, kas mÅ«s noved pie nÄkamÄs tÄmas.
MasÄ«vu Formas ManipulÄcijas ApgūŔana PÄrraidīŔanai
Bieži vien jÅ«su dati nav ideÄlÄ formÄ, lai veiktu vÄlamo darbÄ«bu. NumPy nodroÅ”ina bagÄtÄ«gu rÄ«ku komplektu, lai pÄrveidotu un manipulÄtu ar masÄ«viem, padarot tos saderÄ«gus pÄrraidīŔanai. TÄ nav pÄrraidīŔanas neveiksme, bet gan funkcija, kas liek jums bÅ«t skaidriem par saviem nodomiem.
np.newaxis SpÄks
VisbiežÄk izmantotais rÄ«ks masÄ«va saderÄ«bas nodroÅ”inÄÅ”anai ir `np.newaxis`. To izmanto, lai palielinÄtu esoÅ”a masÄ«va dimensiju par vienu 1. izmÄra dimensiju. Tas ir `None` aizstÄjvÄrds, tÄpÄc varat izmantot arÄ« `None`, lai sintakse bÅ«tu kodolÄ«gÄka.
Salabosim iepriekÅ”Äjo neveiksmÄ«go piemÄru. MÅ«su mÄrÄ·is ir pievienot vektoru `B` katrai `A` kolonnai. Tas nozÄ«mÄ, ka `B` ir jÄuztver kÄ kolonnas vektors ar formu `(3, 1)`.
A = np.arange(12).reshape(3, 4) # Forma: (3, 4)
B = np.array([10, 20, 30]) # Forma: (3,)
# Izmanto newaxis, lai pievienotu jaunu dimensiju, pÄrvÄrÅ”ot B par kolonnas vektoru
B_reshaped = B[:, np.newaxis] # Forma tagad ir (3, 1)
# B_reshaped tagad ir:
# array([[10],
# [20],
# [30]])
C = A + B_reshaped
Labojuma analīze:
- Formas: A ir `(3, 4)`, B_reshaped ir `(3, 1)`.
- 2. noteikums (Saderība):
- Beigu dimensija: `4` pret `1`. OK (viena ir 1).
- NÄkamÄ dimensija: `3` pret `3`. OK (tÄs ir vienÄdas).
- RezultÄta Forma: `(3, 4)`. `(3, 1)` kolonnas vektors tiek pÄrraidÄ«ts pa visÄm 4 A kolonnÄm.
# C will be: # array([[10, 11, 12, 13], # [24, 25, 26, 27], # [38, 39, 40, 41]])
`[:, np.newaxis]` sintakse ir standarta un ļoti labi lasÄma idioma NumPy valodÄ, lai pÄrveidotu 1D masÄ«vu par kolonnas vektoru.
reshape() Metode
VispÄrÄ«gÄks rÄ«ks masÄ«va formas maiÅai ir `reshape()` metode. TÄ Ä¼auj jums pilnÄ«bÄ norÄdÄ«t jauno formu, ja vien kopÄjais elementu skaits paliek nemainÄ«gs.
MÄs varÄjÄm sasniegt to paÅ”u rezultÄtu, kas iepriekÅ”, izmantojot `reshape`:
B_reshaped = B.reshape(3, 1) # Tas pats, kas B[:, np.newaxis]
`reshape()` metode ir ļoti spÄcÄ«ga, Ä«paÅ”i ar tÄs speciÄlo `-1` argumentu, kas liek NumPy automÄtiski aprÄÄ·inÄt Ŕīs dimensijas izmÄru, pamatojoties uz masÄ«va kopÄjo izmÄru un citÄm norÄdÄ«tajÄm dimensijÄm.
x = np.arange(12)
# PÄrveidot par 4 rindÄm un automÄtiski izrÄÄ·inÄt kolonnu skaitu
x_reshaped = x.reshape(4, -1) # Forma būs (4, 3)
TransponÄÅ”ana ar `.T`
MasÄ«va transponÄÅ”ana apmaina tÄ asis. 2D masÄ«vam tÄ apmaina rindas un kolonnas. Tas var bÅ«t vÄl viens noderÄ«gs rÄ«ks formu saskaÅoÅ”anai pirms pÄrraidīŔanas operÄcijas.
A = np.arange(12).reshape(3, 4) # Forma: (3, 4)
A_transposed = A.T # Forma: (4, 3)
Lai gan tas ir mazÄk tieÅ”s risinÄjums mÅ«su konkrÄtajai pÄrraidīŔanas kļūdai, transponÄÅ”anas izpratne ir bÅ«tiska vispÄrÄjai matricas manipulÄcijai, kas bieži notiek pirms pÄrraidīŔanas operÄcijÄm.
ProgresÄ«vi PÄrraidīŔanas Pielietojumi un GadÄ«jumi
Tagad, kad mums ir stingra izpratne par noteikumiem un rÄ«kiem, apskatÄ«sim dažus reÄlÄs pasaules scenÄrijus, kuros pÄrraidīŔana nodroÅ”ina elegantus un efektÄ«vus risinÄjumus.
1. Datu NormalizÄÅ”ana (StandartizÄcija)
FundamentÄls priekÅ”apstrÄdes solis maŔīnmÄcÄ«bÄ ir iezÄ«mju standartizÄÅ”ana, parasti atÅemot vidÄjo vÄrtÄ«bu un dalot ar standartnovirzi (Z-vÄrtÄ«bas normalizÄcija). PÄrraidīŔana padara to triviÄlu.
IedomÄjieties datu kopu `X` ar 1000 paraugiem un 5 iezÄ«mÄm, kas dod tai formu `(1000, 5)`.
# Ä¢enerÄsim dažus parauga datus
np.random.seed(0)
X = np.random.rand(1000, 5) * 100
# AprÄÄ·inÄsim vidÄjo vÄrtÄ«bu un standartnovirzi katrai iezÄ«mei (kolonnai)
# axis=0 nozÄ«mÄ, ka mÄs veicam operÄciju pa kolonnÄm
mean = X.mean(axis=0) # Forma: (5,)
std = X.std(axis=0) # Forma: (5,)
# Tagad normalizÄsim datus, izmantojot pÄrraidīŔanu
X_normalized = (X - mean) / std
Analīze:
- `X - mean` gadÄ«jumÄ mÄs darbojamies ar formÄm `(1000, 5)` un `(5,)`.
- Tas ir tieÅ”i kÄ mÅ«su 2. piemÄrÄ. `mean` vektors ar formu `(5,)` tiek pÄrraidÄ«ts uz augÅ”u pa visÄm 1000 `X` rindÄm.
- TÄ pati pÄrraidīŔana notiek, dalot ar `std`.
Bez pÄrraidīŔanas jums bÅ«tu jÄraksta cikls, kas bÅ«tu par vairÄkÄm kÄrtÄm lÄnÄks un garÄks.
2. Režģu Ä¢enerÄÅ”ana AttÄloÅ”anai un AprÄÄ·iniem
Ja vÄlaties novÄrtÄt funkciju pÄr 2D punktu režģi, piemÄram, lai izveidotu siltuma karti vai kontÅ«ru grafiku, pÄrraidīŔana ir ideÄls rÄ«ks. Lai gan Å”im nolÅ«kam bieži tiek izmantots `np.meshgrid`, jÅ«s varat sasniegt to paÅ”u rezultÄtu manuÄli, lai saprastu pamatÄ esoÅ”o pÄrraidīŔanas mehÄnismu.
# Izveidojam 1D masīvus x un y asīm
x = np.linspace(-5, 5, 11) # Forma (11,)
y = np.linspace(-4, 4, 9) # Forma (9,)
# Izmantojam newaxis, lai sagatavotu tos pÄrraidīŔanai
x_grid = x[np.newaxis, :] # Forma (1, 11)
y_grid = y[:, np.newaxis] # Forma (9, 1)
# Funkcija novÄrtÄÅ”anai, piem., f(x, y) = x^2 + y^2
# PÄrraidīŔana izveido pilnu 2D rezultÄtu režģi
z = x_grid**2 + y_grid**2 # RezultÄjoÅ”Ä forma: (9, 11)
Analīze:
- MÄs pievienojam masÄ«vu ar formu `(1, 11)` masÄ«vam ar formu `(9, 1)`.
- IevÄrojot noteikumus, `x_grid` tiek pÄrraidÄ«ts uz leju pa 9 rindÄm, un `y_grid` tiek pÄrraidÄ«ts pa 11 kolonnÄm.
- RezultÄts ir `(9, 11)` režģis, kas satur funkcijas vÄrtÄ«bu katrÄ `(x, y)` punktu pÄrÄ«.
3. PÄru AttÄlumu MatriÄu AprÄÄ·inÄÅ”ana
Å is ir sarežģītÄks, bet neticami spÄcÄ«gs piemÄrs. Doti `N` punkti `D`-dimensiju telpÄ (masÄ«vs ar formu `(N, D)`), kÄ jÅ«s varat efektÄ«vi aprÄÄ·inÄt `(N, N)` attÄlumu matricu starp katru punktu pÄri?
AtslÄga ir gudrs triks, izmantojot `np.newaxis`, lai iestatÄ«tu 3D pÄrraidīŔanas operÄciju.
# 5 punkti 2-dimensiju telpÄ
np.random.seed(42)
points = np.random.rand(5, 2)
# Sagatavojam masÄ«vus pÄrraidīŔanai
# PÄrveidojam punktus uz (5, 1, 2)
P1 = points[:, np.newaxis, :]
# PÄrveidojam punktus uz (1, 5, 2)
P2 = points[np.newaxis, :, :]
# PÄrraidot P1 - P2, bÅ«s formas:
# (5, 1, 2)
# (1, 5, 2)
# RezultÄjoÅ”Ä forma bÅ«s (5, 5, 2)
diff = P1 - P2
# Tagad aprÄÄ·inÄm kvadrÄtisko EiklÄ«da attÄlumu
# MÄs summÄjam kvadrÄtus pa pÄdÄjo asi (D dimensijas)
dist_sq = np.sum(diff**2, axis=-1)
# IegÅ«stam galÄ«go attÄlumu matricu, izvelkot kvadrÄtsakni
distances = np.sqrt(dist_sq) # GalÄ«gÄ forma: (5, 5)
Å is vektorizÄtais kods aizstÄj divus ligzdotus ciklus un ir masÄ«vi efektÄ«vÄks. Tas apliecina, kÄ domÄÅ”ana masÄ«vu formu un pÄrraidīŔanas terminos var eleganti atrisinÄt sarežģītas problÄmas.
Ietekme uz VeiktspÄju: KÄpÄc PÄrraidīŔana ir SvarÄ«ga
MÄs esam vairÄkkÄrt apgalvojuÅ”i, ka pÄrraidīŔana un vektorizÄcija ir ÄtrÄka par Python cikliem. PierÄdÄ«sim to ar vienkÄrÅ”u testu. MÄs saskaitÄ«sim divus lielus masÄ«vus, vienreiz ar ciklu un vienreiz ar NumPy.
VektorizÄcija pret Cikliem: Ätruma Tests
MÄs varam izmantot Python iebÅ«vÄto `time` moduli demonstrÄcijai. ReÄlÄ scenÄrijÄ vai interaktÄ«vÄ vidÄ, piemÄram, Jupyter Notebook, jÅ«s varÄtu izmantot `%timeit` maÄ£isko komandu, lai veiktu rÅ«pÄ«gÄkus mÄrÄ«jumus.
import time
# Izveidojam lielus masīvus
a = np.random.rand(1000, 1000)
b = np.random.rand(1000, 1000)
# --- 1. metode: Python cikls ---
start_time = time.time()
c_loop = np.zeros_like(a)
for i in range(a.shape[0]):
for j in range(a.shape[1]):
c_loop[i, j] = a[i, j] + b[i, j]
loop_duration = time.time() - start_time
# --- 2. metode: NumPy vektorizÄcija ---
start_time = time.time()
c_numpy = a + b
numpy_duration = time.time() - start_time
print(f"Python cikla ilgums: {loop_duration:.6f} sekundes")
print(f"NumPy vektorizÄcijas ilgums: {numpy_duration:.6f} sekundes")
print(f"NumPy ir aptuveni {loop_duration / numpy_duration:.1f} reizes ÄtrÄks.")
Izpildot Å”o kodu uz parasta datora, redzÄsiet, ka NumPy versija ir 100 lÄ«dz 1000 reizes ÄtrÄka. AtŔķirÄ«ba kļūst vÄl dramatiskÄka, palielinoties masÄ«vu izmÄriem. TÄ nav neliela optimizÄcija; tÄ ir fundamentÄla veiktspÄjas atŔķirÄ«ba.
"Zem PÄrsega" PriekÅ”rocÄ«ba
KÄpÄc NumPy ir tik daudz ÄtrÄks? Iemesls slÄpjas tÄ arhitektÅ«rÄ:
- KompilÄts Kods: NumPy operÄcijas neizpilda Python interpretators. TÄs ir iepriekÅ” kompilÄtas, augsti optimizÄtas C vai Fortran funkcijas. VienkÄrÅ”ais `a + b` izsauc vienu, Ätru C funkciju.
- AtmiÅas IzkÄrtojums: NumPy masÄ«vi ir blÄ«vi datu bloki atmiÅÄ ar konsekventu datu tipu. Tas ļauj pamatÄ esoÅ”ajam C kodam iterÄt pÄr tiem bez tipu pÄrbaudes un citÄm virsizmakÄm, kas saistÄ«tas ar Python sarakstiem.
- SIMD (Viena Instrukcija, VairÄki Dati): MÅ«sdienu procesori var veikt vienu un to paÅ”u operÄciju ar vairÄkiem datu gabaliem vienlaicÄ«gi. NumPy kompilÄtais kods ir izstrÄdÄts, lai izmantotu Ŕīs vektoru apstrÄdes iespÄjas, kas nav iespÄjams standarta Python ciklÄ.
PÄrraidīŔana pÄrmanto visas Ŕīs priekÅ”rocÄ«bas. Tas ir gudrs slÄnis, kas ļauj jums piekļūt vektorizÄtu C operÄciju jaudai pat tad, ja jÅ«su masÄ«vu formas pilnÄ«bÄ nesakrÄ«t.
BiežÄkÄs Kļūdas un LabÄkÄs Prakses
Lai gan pÄrraidīŔana ir spÄcÄ«ga, tÄ prasa rÅ«pÄ«bu. Å eit ir dažas biežÄkÄs problÄmas un labÄkÄs prakses, kas jÄpatur prÄtÄ.
NetieÅ”a PÄrraidīŔana Var SlÄpt Kļūdas
TÄ kÄ pÄrraidīŔana dažreiz var "vienkÄrÅ”i nostrÄdÄt", tÄ var radÄ«t rezultÄtu, kuru jÅ«s nebijÄt paredzÄjis, ja neesat uzmanÄ«gs ar masÄ«vu formÄm. PiemÄram, `(3,)` masÄ«va pievienoÅ”ana `(3, 3)` matricai darbojas, bet `(4,)` masÄ«va pievienoÅ”ana tai neizdodas. Ja nejauÅ”i izveidojat nepareiza izmÄra vektoru, pÄrraidīŔana jÅ«s neglÄbs; tÄ pareizi izraisÄ«s kļūdu. SmalkÄkas kļūdas rodas no rindas un kolonnas vektoru sajaukÅ”anas.
Esiet PrecÄ«zi ar FormÄm
Lai izvairÄ«tos no kļūdÄm un uzlabotu koda skaidrÄ«bu, bieži vien ir labÄk bÅ«t precÄ«ziem. Ja plÄnojat pievienot kolonnas vektoru, izmantojiet `reshape` vai `np.newaxis`, lai tÄ forma bÅ«tu `(N, 1)`. Tas padara jÅ«su kodu lasÄmÄku citiem (un jÅ«su nÄkotnes es) un nodroÅ”ina, ka jÅ«su nodomi ir skaidri NumPy.
AtmiÅas ApsvÄrumi
Atcerieties, ka, lai gan pati pÄrraidīŔana ir atmiÅas efektÄ«va (netiek veidotas starpkopijas), operÄcijas rezultÄts ir jauns masÄ«vs ar lielÄko pÄrraidÄ«to formu. Ja jÅ«s pÄrraidÄt `(10000, 1)` masÄ«vu ar `(1, 10000)` masÄ«vu, rezultÄts bÅ«s `(10000, 10000)` masÄ«vs, kas var patÄrÄt ievÄrojamu daudzumu atmiÅas. VienmÄr apzinieties izvades masÄ«va formu.
LabÄko PrakÅ”u Kopsavilkums
- Ziniet Noteikumus: IegaumÄjiet divus pÄrraidīŔanas noteikumus. Å aubu gadÄ«jumÄ pierakstiet formas un pÄrbaudiet tÄs manuÄli.
- Bieži PÄrbaudiet Formas: IzstrÄdes un atkļūdoÅ”anas laikÄ brÄ«vi izmantojiet `array.shape`, lai pÄrliecinÄtos, ka jÅ«su masÄ«viem ir gaidÄ«tÄs dimensijas.
- Esiet PrecÄ«zi: Izmantojiet `np.newaxis` un `reshape`, lai precizÄtu savu nodomu, Ä«paÅ”i strÄdÄjot ar 1D vektoriem, kurus varÄtu interpretÄt kÄ rindas vai kolonnas.
- Uzticieties `ValueError`: Ja NumPy saka, ka operandus nevarÄja pÄrraidÄ«t, tas ir tÄpÄc, ka noteikumi tika pÄrkÄpti. NecÄ«nieties ar to; analizÄjiet formas un pÄrveidojiet savus masÄ«vus atbilstoÅ”i savam nolÅ«kam.
NoslÄgums
NumPy pÄrraidīŔana ir vairÄk nekÄ tikai ÄrtÄ«ba; tas ir efektÄ«vas skaitliskÄs programmÄÅ”anas stÅ«rakmens Python valodÄ. Tas ir dzinÄjs, kas nodroÅ”ina tÄ«ru, lasÄmu un zibensÄtru vektorizÄtu kodu, kas definÄ NumPy stilu.
MÄs esam ceļojuÅ”i no pamatkoncepcijas par darbÄ«bÄm ar nesaderÄ«giem masÄ«viem lÄ«dz stingriem noteikumiem, kas regulÄ saderÄ«bu, un caur praktiskiem piemÄriem par formas manipulÄciju ar `np.newaxis` un `reshape`. MÄs esam redzÄjuÅ”i, kÄ Å”ie principi attiecas uz reÄliem datu zinÄtnes uzdevumiem, piemÄram, normalizÄciju un attÄlumu aprÄÄ·inÄÅ”anu, un mÄs esam pierÄdÄ«juÅ”i milzÄ«gÄs veiktspÄjas priekÅ”rocÄ«bas salÄ«dzinÄjumÄ ar tradicionÄlajiem cikliem.
PÄrejot no domÄÅ”anas par katru elementu atseviŔķi uz veselu masÄ«vu operÄcijÄm, jÅ«s atklÄjat patieso NumPy spÄku. PieÅemiet pÄrraidīŔanu, domÄjiet formu terminos, un jÅ«s rakstÄ«siet efektÄ«vÄkas, profesionÄlÄkas un jaudÄ«gÄkas zinÄtniskas un uz datiem balstÄ«tas lietojumprogrammas Python valodÄ.