3 วิธีในการคูณเมทริกซ์ใน Python

เผยแพร่แล้ว: 2022-05-09

ในบทช่วยสอนนี้ คุณจะได้เรียนรู้วิธี คูณเมทริกซ์สองตัว ใน Python

คุณจะเริ่มต้นด้วยการเรียนรู้เงื่อนไขสำหรับการคูณเมทริกซ์ที่ถูกต้องและเขียนฟังก์ชัน Python ที่กำหนดเองเพื่อคูณเมทริกซ์ ถัดไป คุณจะเห็นว่าคุณสามารถบรรลุผลลัพธ์เดียวกันได้อย่างไรโดยใช้ความเข้าใจรายการที่ซ้อนกัน

สุดท้าย คุณจะต้องใช้ NumPy และฟังก์ชันในตัวเพื่อทำการคูณเมทริกซ์อย่างมีประสิทธิภาพมากขึ้น

วิธีตรวจสอบว่าการคูณเมทริกซ์ถูกต้องหรือไม่

ก่อนเขียนโค้ด Python สำหรับการคูณเมทริกซ์ เรามาทบทวนพื้นฐานของการคูณเมทริกซ์กันก่อน

การคูณเมทริกซ์ระหว่างเมทริกซ์สองตัว A และ B จะใช้ได้ก็ต่อเมื่อ จำนวนคอลัมน์ ในเมทริกซ์ A เท่ากับ จำนวนแถว ในเมทริกซ์ B

คุณน่าจะเคยเจอเงื่อนไขนี้สำหรับการคูณเมทริกซ์มาก่อน อย่างไรก็ตาม คุณเคยสงสัยหรือไม่ว่าเหตุใดจึงเป็นเช่นนี้

นั่นเป็นเพราะวิธีการทำงานของการคูณเมทริกซ์ ลองดูที่ภาพด้านล่าง

ในตัวอย่างทั่วไปของเรา เมทริกซ์ A มี m แถวและ n คอลัมน์ และเมทริกซ์ B มี n แถวและ p คอลัมน์

เมทริกซ์คูณ

รูปร่างของผลิตภัณฑ์เมทริกซ์คืออะไร?

องค์ประกอบที่ดัชนี (i, j) ในเมทริกซ์ผลลัพธ์ C คือผลคูณดอทของแถว i ของเมทริกซ์ A และคอลัมน์ j ของเมทริกซ์ B

ดังนั้นเพื่อให้ได้องค์ประกอบที่ดัชนีเฉพาะในเมทริกซ์ผลลัพธ์ C คุณจะต้องคำนวณผลคูณดอทของแถวและคอลัมน์ที่สอดคล้องกันในเมทริกซ์ A และ B ตามลำดับ

ทำซ้ำขั้นตอนข้างต้น คุณจะได้เมทริกซ์ผลิตภัณฑ์ C ของรูปร่าง mxp —พร้อม m แถวและ p คอลัมน์ดังที่แสดงด้านล่าง

ผลิตภัณฑ์-เมทริกซ์

และผลคูณดอทหรือผลคูณภายในระหว่างเวกเตอร์สองตัว a และ b ถูกกำหนดโดยสมการต่อไปนี้

dot-product

มาสรุปกันตอนนี้:

  • เห็นได้ชัดว่าดอทโปรดัคถูกกำหนดระหว่างเวกเตอร์ที่มีความยาวเท่ากันเท่านั้น
  • ดังนั้น เพื่อให้ผลคูณดอทระหว่างแถวกับคอลัมน์ถูกต้อง—เมื่อคูณเมทริกซ์สองตัว—คุณต้องการให้ทั้งคู่มีจำนวนองค์ประกอบเท่ากัน
  • ในตัวอย่างทั่วไปข้างต้น ทุกแถวในเมทริกซ์ A มีองค์ประกอบ n ตัว และทุกคอลัมน์ในเมทริกซ์ B มีองค์ประกอบ n ตัวเช่นกัน

หากคุณพิจารณาให้ละเอียดยิ่งขึ้น n คือจำนวนคอลัมน์ในเมทริกซ์ A และมันคือจำนวนแถวในเมทริกซ์ B ด้วย และนี่คือเหตุผลว่าทำไมคุณถึงต้องการ จำนวนคอลัมน์ ในเมทริกซ์ A เท่ากับ จำนวน ของแถว ในเมทริกซ์ B

ฉันหวังว่าคุณจะเข้าใจเงื่อนไขของการคูณเมทริกซ์ที่ถูกต้องและวิธีรับแต่ละองค์ประกอบในเมทริกซ์ผลิตภัณฑ์

มาเริ่มเขียนโค้ด Python เพื่อคูณเมทริกซ์สองตัวกัน

เขียนฟังก์ชัน Python แบบกำหนดเองเพื่อคูณเมทริกซ์

ในขั้นแรก ให้เราเขียนฟังก์ชันแบบกำหนดเองเพื่อคูณเมทริกซ์

ฟังก์ชันนี้ควรทำสิ่งต่อไปนี้:

  • ยอมรับเมทริกซ์สองตัวคือ A และ B เป็นอินพุต
  • ตรวจสอบว่าการคูณเมทริกซ์ระหว่าง A และ B ถูกต้องหรือไม่
  • ถ้าถูกต้อง ให้คูณเมทริกซ์ A และ B สองตัว แล้วส่งคืนเมทริกซ์ผลิตภัณฑ์ C
  • มิฉะนั้น ให้ส่งคืนข้อความแสดงข้อผิดพลาดที่เมทริกซ์ A และ B ไม่สามารถคูณได้

ขั้นตอนที่ 1 : สร้างเมทริกซ์จำนวนเต็มสองเมทริกซ์โดยใช้ฟังก์ชัน random.randint() ของ NumPy คุณยังสามารถประกาศเมทริกซ์เป็นรายการ Python ที่ซ้อนกันได้

 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]]

ขั้นตอนที่ 2: ไปข้างหน้าและกำหนดฟังก์ชัน multiply_matrix(A,B) ฟังก์ชันนี้ใช้เมทริกซ์ A และ B สองตัวเป็นอินพุต และส่งกลับเมทริกซ์ผลิตภัณฑ์ C หากการคูณเมทริกซ์ถูกต้อง

 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."

การแยกวิเคราะห์นิยามฟังก์ชัน

มาดำเนินการแยกวิเคราะห์นิยามฟังก์ชันกัน

ประกาศ C เป็นตัวแปรส่วนกลาง : โดยค่าเริ่มต้น ตัวแปรทั้งหมดภายในฟังก์ชัน Python มี ขอบเขต ภายใน และคุณไม่สามารถเข้าถึงได้จากภายนอกฟังก์ชัน เพื่อให้ผลิตภัณฑ์เมทริกซ์ C สามารถเข้าถึงได้จากภายนอก เราจะต้องประกาศเป็นตัวแปรส่วนกลาง เพียงเพิ่ม global qualifier ก่อนชื่อตัวแปร

ตรวจสอบว่าการคูณเมทริกซ์ถูกต้องหรือไม่: ใช้แอตทริบิวต์ shape เพื่อตรวจสอบว่าสามารถคูณ A และ B ได้หรือไม่ สำหรับอาร์เรย์ arr ใดๆ arr.shape[0] และ arr.shape[1] ให้จำนวน แถว และ คอลัมน์ ตามลำดับ ดังนั้น if A.shape[1] == B.shape[0] ตรวจสอบว่าการคูณเมทริกซ์นั้นถูกต้องหรือไม่ เฉพาะในกรณีที่เงื่อนไขนี้เป็น True เมทริกซ์ผลิตภัณฑ์จะถูกคำนวณ มิฉะนั้น ฟังก์ชันจะส่งคืนข้อความแสดงข้อผิดพลาด

ใช้การวนซ้ำแบบซ้อนเพื่อคำนวณค่า: ในการคำนวณองค์ประกอบของเมทริกซ์ผลลัพธ์ เราต้องวนซ้ำผ่านแถวของเมทริกซ์ A และวงรอบนอก for สิ่งนี้ inner for loop ช่วยให้เราวนซ้ำคอลัมน์ของเมทริกซ์ B และวงในสุด for ลูปช่วยเข้าถึงแต่ละองค์ประกอบในคอลัมน์ที่เลือก

️ ตอนนี้เราได้เรียนรู้วิธีการทำงานของฟังก์ชัน Python ในการคูณเมทริกซ์แล้ว มาเรียกใช้ฟังก์ชันด้วยเมทริกซ์ A และ B ที่เราสร้างขึ้นก่อนหน้านี้กัน

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

เนื่องจากการคูณเมทริกซ์ระหว่าง A และ B นั้นถูกต้อง ฟังก์ชัน multiply_matrix() จะส่งกลับเมทริกซ์ผลิตภัณฑ์ C

ใช้ Python Nested List Comprehension เพื่อคูณเมทริกซ์

ในส่วนที่แล้ว คุณเขียนฟังก์ชัน Python เพื่อคูณเมทริกซ์ ตอนนี้ คุณจะเห็นว่าคุณสามารถใช้ความเข้าใจรายการที่ซ้อนกันเพื่อทำเช่นเดียวกันได้อย่างไร

นี่คือความเข้าใจรายการที่ซ้อนกันเพื่อคูณเมทริกซ์

nested-list-comprehension-matrix-multiply

ในตอนแรกอาจดูซับซ้อน แต่เราจะแยกวิเคราะห์ความเข้าใจรายการที่ซ้อนกันทีละขั้นตอน

มาเน้นที่ความเข้าใจทีละรายการและระบุสิ่งที่ทำ

เราจะใช้เทมเพลตทั่วไปต่อไปนี้สำหรับการทำความเข้าใจรายการ:

 [<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

️ ดูคู่มือ List Comprehension ใน Python – พร้อมตัวอย่างเพื่อทำความเข้าใจในเชิงลึก

ก่อนดำเนินการต่อ โปรดทราบว่าเราต้องการสร้างเมทริกซ์ผลลัพธ์ C ทีละแถว

อธิบายความเข้าใจรายการที่ซ้อนกัน

ขั้นตอนที่ 1: คำนวณค่าเดียวในเมทริกซ์ C

กำหนดแถว i ของเมทริกซ์ A และคอลัมน์ j ของเมทริกซ์ B นิพจน์ด้านล่างให้รายการที่ดัชนี (i, j) ในเมทริกซ์ 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

ถ้า i = j = 1 นิพจน์จะส่งกลับรายการ c_11 ของเมทริกซ์ C ดังนั้นคุณสามารถรับหนึ่งองค์ประกอบในแถวเดียวด้วยวิธีนี้

ขั้นตอนที่ 2: สร้างหนึ่งแถวในเมทริกซ์ C

เป้าหมายต่อไปของเราคือการสร้างแถวทั้งหมด

สำหรับแถวที่ 1 ในเมทริกซ์ A คุณต้องวนซ้ำคอลัมน์ทั้งหมดในเมทริกซ์ B เพื่อให้ได้แถวที่สมบูรณ์หนึ่งแถวในเมทริกซ์ C

กลับไปที่เทมเพลตความเข้าใจรายการ

  • แทนที่ <do-this> ด้วยนิพจน์จากขั้นตอนที่ 1 เพราะนั่นคือสิ่งที่คุณต้องการทำ
  • ถัดไป แทนที่ <item> ด้วย B_col —แต่ละคอลัมน์ในเมทริกซ์ B
  • สุดท้าย แทนที่ <iterable> ด้วย zip(*B) — รายการที่มีคอลัมน์ทั้งหมดในเมทริกซ์ B

และนี่คือความเข้าใจรายการแรก

 [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

ขั้นตอนที่ 3: สร้างแถวทั้งหมดและรับเมทริกซ์ C

ถัดไป คุณจะต้องเติมเมทริกซ์ผลิตภัณฑ์ C โดยคำนวณส่วนที่เหลือของแถว

และสำหรับสิ่งนี้ คุณต้องวนซ้ำทุกแถวในเมทริกซ์ A

กลับไปที่รายการความเข้าใจอีกครั้ง และทำดังต่อไปนี้

  • แทนที่ <do-this> ด้วย list comprehension จากขั้นตอนที่ 2 จำได้ว่าเราคำนวณทั้งแถวในขั้นตอนก่อนหน้า
  • ตอนนี้ แทนที่ <item> ด้วย A_row —ทุกแถวในเมทริกซ์ A
  • และ <iterable> ของคุณคือเมทริกซ์ A ขณะที่คุณวนซ้ำแถวของมัน

และนี่คือความเข้าใจรายการซ้อนสุดท้ายของเรา

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

ได้เวลาตรวจสอบผลแล้ว!

 # cast into NumPy array 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]]

หากคุณพิจารณาให้ละเอียดยิ่งขึ้น สิ่งนี้จะเทียบเท่ากับลูปที่ซ้อนกันที่เรามีก่อนหน้านี้—เพียงว่ามันกระชับกว่า

คุณยังสามารถทำสิ่งนี้ทั้งหมดได้อย่างมีประสิทธิภาพมากขึ้นโดยใช้ฟังก์ชันในตัว มาเรียนรู้เกี่ยวกับพวกเขาในหัวข้อถัดไป

ใช้ NumPy matmul() เพื่อคูณเมทริกซ์ใน Python

np.matmul() รับเมทริกซ์สองตัวเป็นอินพุตและส่งคืนผลิตภัณฑ์หากการคูณเมทริกซ์ระหว่างเมทริกซ์อินพุต ถูกต้อง

 C = np.matmul(A,B) print(C) # Output: [[ 89 107] [ 47 49] [ 40 44]]

สังเกตว่าวิธีนี้ง่ายกว่าสองวิธีที่เราเรียนรู้ก่อนหน้านี้อย่างไร ที่จริงแล้ว แทนที่จะใช้ np.matmul() คุณสามารถใช้ตัวดำเนินการ @ ที่เทียบเท่า และเราจะเห็นสิ่งนั้นทันที

วิธีใช้ @ Operator ใน Python เพื่อคูณเมทริกซ์

ใน Python @ เป็นตัวดำเนินการไบนารีที่ใช้สำหรับการคูณเมทริกซ์

มันทำงานบนเมทริกซ์สองตัว และโดยทั่วไปแล้ว อาร์เรย์ NumPy แบบ N และส่งคืนเมทริกซ์ผลิตภัณฑ์

หมายเหตุ: คุณต้องมี Python 3.5 และใหม่กว่าเพื่อใช้ตัวดำเนินการ @

นี่คือวิธีที่คุณสามารถใช้

 C = [email protected] print(C) # Output array([[ 89, 107], [ 47, 49], [ 40, 44]])

โปรดสังเกตว่าเมทริกซ์ผลิตภัณฑ์ C เหมือนกับที่เราได้รับก่อนหน้านี้

คุณสามารถใช้ np.dot() เพื่อคูณเมทริกซ์ได้หรือไม่

หากคุณเคยเจอโค้ดที่ใช้ np.dot() เพื่อคูณเมทริกซ์สองตัว นี่คือวิธีการทำงาน

 C = np.dot(A,B) print(C) # Output: [[ 89 107] [ 47 49] [ 40 44]]

คุณจะเห็นว่า np.dot(A, B) ส่งคืนเมทริกซ์ผลิตภัณฑ์ที่คาดไว้ด้วย

อย่างไรก็ตาม ตามเอกสาร NumPy คุณควรใช้ np.dot() เพื่อคำนวณผลคูณดอทของเวกเตอร์หนึ่งมิติสองตัวเท่านั้น ไม่ใช่สำหรับการคูณเมทริกซ์

จากส่วนก่อนหน้านี้ องค์ประกอบที่ดัชนี (i, j) ของผลิตภัณฑ์เมทริกซ์ C คือผลคูณดอทของแถว i ของเมทริกซ์ A และคอลัมน์ j ของเมทริกซ์ B

เนื่องจาก NumPy ถ่ายทอดการทำงานของผลิตภัณฑ์ดอทนี้โดยปริยายไปยังทุกแถวและทุกคอลัมน์ คุณจะได้เมทริกซ์ผลิตภัณฑ์ที่เป็นผลลัพธ์ แต่เพื่อให้โค้ดของคุณอ่านได้และหลีกเลี่ยงความคลุมเครือ ให้ใช้ np.matmul() หรือตัวดำเนินการ @ แทน

บทสรุป

ในบทช่วยสอนนี้ คุณได้เรียนรู้สิ่งต่อไปนี้

  • เงื่อนไขสำหรับการคูณเมทริกซ์ให้ถูกต้อง: จำนวน คอลัมน์ ในเมทริกซ์ A = จำนวน แถว ในเมทริกซ์ B
  • วิธีเขียนฟังก์ชัน Python แบบกำหนดเองที่ตรวจสอบว่าการคูณเมทริกซ์นั้นถูกต้องและส่งคืนเมทริกซ์ผลิตภัณฑ์ได้อย่างไร เนื้อหาของฟังก์ชันใช้การซ้อนกันสำหรับลูป
  • ต่อไป คุณได้เรียนรู้วิธีใช้ความเข้าใจรายการที่ซ้อนกันเพื่อคูณเมทริกซ์ มีความกระชับมากกว่าการวนซ้ำ แต่มีแนวโน้มที่จะมีปัญหาในการอ่านได้
  • ในที่สุด คุณได้เรียนรู้การใช้ฟังก์ชันในตัวของ NumPy np.matmul() เพื่อคูณเมทริกซ์และวิธีนี้มีประสิทธิภาพมากที่สุดในแง่ของความเร็ว
  • คุณยังได้เรียนรู้เกี่ยวกับตัวดำเนินการ @ เพื่อคูณเมทริกซ์สองตัวใน Python

และนั่นเป็นการสรุปการสนทนาของเราเกี่ยวกับการคูณเมทริกซ์ใน Python ในขั้นตอนต่อไป เรียนรู้วิธีตรวจสอบว่าตัวเลขเป็นจำนวนเฉพาะใน Python หรือไม่ หรือแก้ปัญหาที่น่าสนใจเกี่ยวกับสตริง Python

มีความสุขในการเรียนรู้!