3 způsoby, jak násobit matice v Pythonu

V tomto tutoriálu se naučíte, jak násobit dvě matice v Pythonu.

Začnete tím, že se naučíte podmínku pro platné násobení matic a napíšete si vlastní funkci Pythonu pro násobení matic. Dále uvidíte, jak můžete dosáhnout stejného výsledku pomocí vnořených seznamů.

Nakonec budete používat NumPy a jeho vestavěné funkce k efektivnějšímu provádění násobení matic.

Jak zkontrolovat, zda je násobení matice platné

Před psaním kódu Pythonu pro násobení matic se vraťme k základům násobení matic.

Maticové násobení mezi dvěma maticemi A a B je platné pouze tehdy, je-li počet sloupců v matici A roven počtu řádků v matici B.

Pravděpodobně jste se s touto podmínkou pro násobení matice setkali již dříve. Napadlo vás však někdy, proč tomu tak je?

No, je to kvůli tomu, jak funguje násobení matic. Podívejte se na obrázek níže.

V našem obecném příkladu má matice A m řádků a n sloupců. A matice B má n řádků a p sloupců.

Jaký je tvar matice produktu?

Prvek na indexu (i, j) ve výsledné matici C je bodový součin řádku i matice A a sloupce j matice B.

Chcete-li tedy získat prvek na konkrétním indexu ve výsledné matici C, budete muset vypočítat bodový součin odpovídajícího řádku a sloupce v maticích A a B.

Opakováním výše uvedeného postupu získáte matici produktu C tvaru mxp – s m řádky a p sloupci, jak je znázorněno níže.

A bodový součin neboli vnitřní součin mezi dvěma vektory a a b je dán následující rovnicí.

Pojďme si to nyní shrnout:

  • Je zřejmé, že bodový součin je definován pouze mezi vektory stejné délky.
  • Aby byl tedy tečkový součin mezi řádkem a sloupcem platný – při násobení dvou matic – potřebujete, aby obě měly stejný počet prvků.
  • Ve výše uvedeném obecném příkladu má každý řádek v matici A n prvků. A každý sloupec v matici B má také n prvků.

Když se podíváte blíže, n je počet sloupců v matici A a je to také počet řádků v matici B. A to je přesně důvod, proč potřebujete, aby se počet sloupců v matici A rovnal počtu řádků v matici B.

Doufám, že rozumíte podmínce platnosti násobení matic a tomu, jak získat každý prvek v matici produktu.

  Jak zablokovat číslo na iPhone

Pojďme napsat nějaký kód Pythonu pro vynásobení dvou matic.

Napište vlastní funkci Pythonu pro násobení matic

Jako první krok napíšeme vlastní funkci pro násobení matic.

Tato funkce by měla dělat následující:

  • Přijměte dvě matice, A a B, jako vstupy.
  • Zkontrolujte, zda platí násobení matic mezi A a B.
  • Pokud platí, vynásobte obě matice A a B a vraťte matici součinu C.
  • Jinak vraťte chybovou zprávu, že matice A a B nelze vynásobit.

Krok 1: Vygenerujte dvě matice celých čísel pomocí funkce random.randint() NumPy. Matice můžete také deklarovat jako vnořené seznamy Pythonu.

import numpy as np
np.random.seed(27)
A = np.random.randint(1,10,size = (3,3))
B = np.random.randint(1,10,size = (3,2))
print(f"Matrix A:n {A}n")
print(f"Matrix B:n {B}n")

# Output
Matrix A:
 [[4 9 9]
 [9 1 6]
 [9 2 3]]

Matrix B:
 [[2 2]
 [5 7]
 [4 4]]

Krok 2: Pokračujte a definujte funkci multiply_matrix(A,B). Tato funkce přijímá dvě matice A a B jako vstupy a vrací matici součinu C, pokud je násobení matice platné.

def multiply_matrix(A,B):
  global C
  if  A.shape[1] == B.shape[0]:
    C = np.zeros((A.shape[0],B.shape[1]),dtype = int)
    for row in range(rows): 
        for col in range(cols):
            for elt in range(len(B)):
              C[row, col] += A[row, elt] * B[elt, col]
    return C
  else:
    return "Sorry, cannot multiply A and B."

Analýza definice funkce

Pokračujme analýzou definice funkce.

Deklarujte C jako globální proměnnou: Ve výchozím nastavení mají všechny proměnné uvnitř funkce Pythonu lokální rozsah. A nemůžete k nim přistupovat zvenčí funkce. Aby byla produktová matice C přístupná zvenčí, budeme ji muset deklarovat jako globální proměnnou. Stačí přidat globální kvalifikátor před název proměnné.

Zkontrolujte, zda je násobení matice platné: Pomocí atributu tvar zkontrolujte, zda lze násobit A a B. Pro libovolné pole arr, arr.shape[0] a arr.tvar[1] uveďte počet řádků a sloupců. Pokud tedy A.tvar[1] == B.tvar[0] zkontroluje, zda je násobení matice platné. Pouze pokud je tato podmínka True, bude vypočtena matice produktu. V opačném případě funkce vrátí chybovou zprávu.

K výpočtu hodnot použijte vnořené cykly: Abychom vypočítali prvky výsledné matice, musíme procházet řádky matice A a to dělá vnější smyčka for. Vnitřní smyčka for nám pomáhá procházet sloupcem matice B. A nejvnitřnější smyčka for pomáhá přistupovat ke každému prvku ve vybraném sloupci.

▶️ Nyní, když jsme se naučili, jak funguje funkce Python pro násobení matic, zavolejme funkci s maticemi A a B, které jsme vygenerovali dříve.

multiply_matrix(A,B)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Protože násobení matic mezi A a B je platné, funkce multiply_matrix() vrací matici součinu C.

Použijte Python vnořený seznam Comprehension k násobení matic

V předchozí části jste napsali funkci Pythonu pro násobení matic. Nyní uvidíte, jak můžete použít vnořené seznamy, abyste udělali totéž.

  Jak opravit, když se Spotify nezobrazuje jako váš stav na Discordu

Zde je pochopení vnořeného seznamu pro násobení matic.

Zpočátku to může vypadat složitě. Ale budeme analyzovat pochopení vnořeného seznamu krok za krokem.

Zaměřme se na pochopení jednoho seznamu po druhém a identifikujme, co dělá.

Pro pochopení seznamu použijeme následující obecnou šablonu:

[<do-this> for <item> in <iterable>]

where,
<do-this>: what you'd like to do—expression or operation
<item>: each item you'd like to perform the operation on
<iterable>: the iterable (list, tuple, etc.) that you're looping through

▶️ Podívejte se na našeho průvodce Seznam porozumění v Pythonu – s příklady, abyste získali podrobné porozumění.

Než budeme pokračovat, uvědomte si, že bychom rádi sestavili výslednou matici C jeden řádek po druhém.

Vysvětlení pochopení vnořeného seznamu

Krok 1: Vypočítejte jednu hodnotu v matici C

Daný řádek i matice A a sloupec j matice B, níže uvedený výraz udává záznam na indexu (i, j) v matici C.

sum(a*b for a,b in zip(A_row, B_col)

# zip(A_row, B_col) returns an iterator of tuples
# If A_row = [a1, a2, a3] & B_col = [b1, b2, b3]
# zip(A_row, B_col) returns (a1, b1), (a2, b2), and so on

Pokud i = j = 1, výraz vrátí záznam c_11 matice C. Tímto způsobem tedy můžete získat jeden prvek v jednom řádku.

Krok 2: Vytvořte jeden řádek v matici C

Naším dalším cílem je postavit celou řadu.

Pro řádek 1 v matici A musíte projít všechny sloupce v matici B, abyste získali jeden úplný řádek v matici C.

Vraťte se k šabloně pro porozumění seznamu.

  • Nahraďte výrazem z kroku 1, protože to je to, co chcete udělat.
  • Dále nahraďte za B_col – každý sloupec v matici B.
  • Nakonec nahraďte za zip(*B) – seznam obsahující všechny sloupce v matici B.

A zde je první porozumění seznamu.

[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 

# zip(*B): * is the unzipping operator
# zip(*B) returns a list of columns in matrix B

Krok 3: Sestavte všechny řádky a získejte matici C

Dále budete muset naplnit matici produktu C výpočtem zbývajících řádků.

A k tomu musíte procházet všechny řádky v matici A.

Vraťte se znovu k porozumění seznamu a proveďte následující.

  • Nahraďte porozuměním seznamu z kroku 2. Připomeňme, že jsme v předchozím kroku vypočítali celý řádek.
  • Nyní nahraďte za A_row – každý řádek v matici A.
  • A vaše je samotná matice A, když procházíte jejími řádky.

A tady je naše konečné pochopení vnořeného seznamu.🎊

[[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A]

Je čas ověřit výsledek! ✔

# cast into <a href="https://etechblog.cz.com/numpy-reshape-arrays-in-python/">NumPy array</a> using np.array()
C = np.array([[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A])

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Pokud se podíváte blíže, je to ekvivalentní s vnořenými smyčkami for, které jsme měli dříve – jen je to stručnější.

Můžete to udělat ještě efektivněji pomocí některých vestavěných funkcí. Pojďme se o nich dozvědět v další části.

Použijte NumPy matmul() k násobení matic v Pythonu

Funkce np.matmul() přijímá dvě matice jako vstup a vrací součin, pokud je platné násobení matic mezi vstupními maticemi.

C = np.matmul(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Všimněte si, jak je tato metoda jednodušší než dvě metody, které jsme se naučili dříve. Ve skutečnosti můžete místo np.matmul() použít ekvivalentní operátor @ a to hned uvidíme.

Jak používat @ Operator v Pythonu k násobení matic

V Pythonu je @ binární operátor používaný pro násobení matic.

Pracuje se dvěma maticemi a obecně N-rozměrnými poli NumPy a vrací matici produktu.

Poznámka: Abyste mohli používat operátor @, musíte mít Python 3.5 a novější.

Zde je návod, jak jej můžete použít.

C = [email protected]
print(C)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Všimněte si, že matice produktu C je stejná jako ta, kterou jsme získali dříve.

Můžete použít np.dot() k násobení matic?

Pokud jste někdy narazili na kód, který používá np.dot() k násobení dvou matic, funguje to následovně.

C = np.dot(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Uvidíte, že np.dot(A, B) také vrátí očekávanou matici produktu.

Nicméně, jak na NumPy dokumentyměli byste použít np.dot() pouze k výpočtu bodového součinu dvou jednorozměrných vektorů a nikoli k násobení matic.

Připomeňme si z předchozí části, prvek na indexu (i, j) matice součinu C je bodový součin řádku i matice A a sloupce j matice B.

Protože NumPy implicitně vysílá tuto operaci tečkového součinu do všech řádků a všech sloupců, získáte výslednou matici součinu. Ale aby byl váš kód čitelný a předešlo se nejednoznačnosti, použijte místo něj np.matmul() nebo operátor @.

Závěr

🎯 V tomto tutoriálu jste se naučili následující.

  • Podmínka platnosti násobení matice: počet sloupců v matici A = počet řádků v matici B.
  • Jak napsat vlastní funkci Pythonu, která zkontroluje, zda je násobení matic platné, a vrátí matici produktu. Tělo funkce používá vnořené smyčky for.
  • Dále jste se naučili, jak používat porozumění vnořeným seznamům k násobení matic. Jsou stručnější než pro smyčky, ale jsou náchylné k problémům s čitelností.
  • Nakonec jste se naučili používat vestavěnou funkci NumPy np.matmul() k násobení matic a jak je to nejúčinnější z hlediska rychlosti.
  • Také jste se dozvěděli o operátoru @ pro násobení dvou matic v Pythonu.

A tím končí naše diskuse o násobení matic v Pythonu. Jako další krok se naučte, jak zkontrolovat, zda je číslo prvočíslo v Pythonu. Nebo řešit zajímavé problémy na řetězcích Pythonu.

Příjemné učení! 🎉