ضرب ماتریس یک عملیات اساسی در جبر خطی است.
ما معمولاً از آن در برنامه های متعددی مانند پردازش تصویر، یادگیری ماشینی و بسیاری موارد دیگر استفاده می کنیم. NumPy یک بسته پایتون قابل توجه برای محاسبات علمی است.
با این حال، در این پست، روشهای مختلف برای انجام ضرب ماتریس در پایتون بدون استفاده از NumPy را بررسی خواهیم کرد.
استفاده خواهیم کرد حلقه های تو در تو، تابع map() داخلی و درک لیست.
علاوه بر این، ما به مزایا و معایب هر استراتژی و همچنین زمان اعمال هر یک از آنها خواهیم پرداخت. اگر در جبر خطی تازه کار هستید و می خواهید در مورد ضرب ماتریس بیشتر بدانید؛ به خواندن ادامه دهید
کجا از ضرب ماتریس استفاده کنیم؟
ضرب ماتریس در استفاده می شود گرافیک کامپیوتری برای تغییر تصاویر دو بعدی و سه بعدی به عنوان مثال، می توانید اشیاء روی صفحه را بچرخانید، مقیاس دهید و ترجمه کنید. ماتریس ها در پردازش تصویر برای نمایش تصاویر به عنوان آرایه های پیکسل استفاده می شوند. علاوه بر این، ماتریس ها ممکن است برای انجام عملیاتی مانند فیلتر کردن تصویر استفاده شوند.
ما همچنین از ماتریس در استفاده می کنیم فراگیری ماشین. آنها می توانند به ما در نمایش داده ها و پارامترهای مدل کمک کنند. ما میتوانیم عملیاتهای متعددی را انجام دهیم، مانند محاسبات محصولات نقطهای و محصولات ماتریس-بردار.
مطمئناً این عملیات در عملیات علمی نیز بسیار سودمند است. ما می توانیم از آن در فیزیک و مهندسی برای توصیف کمیت های فیزیکی استفاده کنیم. از این رو، می توانیم با بردارها و تانسورها کار کنیم.
چرا ممکن است استفاده از NumPy را انتخاب نکنیم؟
در حالی که NumPy یک است کتابخانه پایتون، همیشه گزینه ایده آل برای ضرب ماتریس نیست. ممکن است به دلایلی مانند اندازه و وابستگی، یادگیری و سیستم های قدیمی استفاده از NumPy را انتخاب نکنیم.
استفاده از توابع داخلی پایتون یا توسعه کد سفارشی ممکن است در برخی موارد کارآمدتر باشد. توجه به این نکته ضروری است که NumPy یک کتابخانه قوی است. علاوه بر این، می توانید از آن برای ضرب ماتریس نیز استفاده کنید.
حال، بیایید نگاهی بیندازیم به اینکه چگونه میتوانیم بدون NumPy به ضرب ماتریس برسیم.
روش حلقه های تو در تو
تکنیک حلقههای تودرتو از حلقههای تودرتو برای اجرای ضرب ماتریس در پایتون استفاده میکند. تابع بر روی هر عنصر ماتریس تکرار می شود. و با استفاده از یک سری حلقه های تودرتو آنها را ضرب می کند. تابع نتیجه را برمی گرداند که در یک ماتریس جدید ذخیره می شود.
درک این رویکرد ساده است. با این حال، ممکن است به اندازه راه های دیگر کارآمد نباشد، به خصوص برای ماتریس های بزرگتر. با این حال، اگر در جبر خطی تازه کار هستید، این یک انتخاب عالی برای شماست.
def matrix_multiplication(A, B):
# Determine the matrices' dimensions.
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
# ماتریس نتیجه را روی صفر قرار دهید.
result = [[0 for row in range(cols_B)] for col in
range(rows_A)]
# Iterate through rows of A
for s in range(rows_A):
# Iterate through columns of B
for j in range(cols_B):
# Iterate through rows of B
for k in range(cols_A):
result[s][j] += A[s][k] * B[k][j]
return result
بیایید مثالی از نحوه انجام این کار داشته باشیم. شما فقط می توانید این خطوط کد را در زیر برای آزمایش این مثال اضافه کنید.
# Sample matrices
A = [[1, 4, 3], [4, 9, 6]]
B = [[7, 8], [9, 10], [11, 12]]
# Perform matrix multiplication
result = matrix_multiplication(A, B)
# Print the result
print(result)
# Output: [[76, 84], [175, 194]]
مزایا:
- آسان برای درک.
- برای تازه کارها یا کسانی که به دنبال درک عمیق تری از ضرب ماتریس هستند عالی است.
معایب:
- به اندازه تکنیک های جایگزین موثر نیست، به ویژه برای ماتریس های بزرگتر.
- به اندازه رویکردهای جایگزین قابل خواندن نیست.
متد تابع map().
متد تابع map یک رویکرد جایگزین برای انجام ضرب ماتریس در پایتون ارائه می دهد. در این روش از تابع داخلی map() استفاده می کنیم. از این رو، ما از یک ابزار برنامه نویسی تابعی استفاده می کنیم که یک تابع ارائه شده را برای هر عنصر تکرار شونده (لیست، تاپل و غیره) اعمال می کند. همچنین تابع map() دو پارامتر یک تابع و یک تکرارپذیر را می پذیرد. و یک تکرار کننده برمی گرداند که تابع را برای هر عنصر تکرارپذیر اعمال می کند.
در این روش، از هر یک از اعضای ماتریس عبور می کنیم و با استفاده از تابع map() تو در تو ضرب را انجام می دهیم.
تابع zip() برای تکرار هر یک از عناصر ماتریس به صورت موازی استفاده می شود.
در نهایت از تابع sum() برای جمع کردن نتایج استفاده می شود.
def matrix_multiplication(A, B):
# To get the dimensions of the matrices
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
# We use map() function for multiplication.
result = [[sum(a * b for a, b in zip(row_a, col_b)) for
col_b in zip(*B)] for row_a in A]
return result
حالا دوباره می توانیم کد خود را با یک مثال تست کنیم.
# Example matrices
A = [[3, 2, 3], [4, 5, 6]]
B = [[7, 8], [9, 10], [11, 12]]
# Use map() function to perform matrix multiplication
result = list(map(lambda x: list(map(lambda y: sum(i*j
for i,j in zip(x,y)), zip(*B))), A))
# Print the result
print(result)
# Output: [[72, 80], [139, 154]]
مزایای
- موثرتر از رویکرد حلقه های انباشته
- از برنامه نویسی کاربردی برای ساده تر کردن کد استفاده می کند.
معایب
- برخی از افرادی که با برنامه نویسی تابعی آشنایی ندارند ممکن است آن را کمتر خوانده شوند.
- این روش کمتر از تکنیک حلقه های تودرتو قابل درک است.
روش درک فهرست
درک لیست شما را قادر می سازد یک لیست جدید را در یک خط کد ایجاد کنید. از این رو، این با اعمال یک عبارت برای هر یک از اعضای یک لیست موجود است.
در این روش، ضرب با تکرار مکرر از طریق هر عضو ماتریس انجام می شود. ما از درک لیست لایه ای استفاده می کنیم.
# Sample matrices
A = [[1, 12, 3], [14, 5, 6]]
B = [[7, 8], [9, 10], [12, 12]]
# Matrix multiplication using list comprehension
result = [[sum(A[i][k] * B[k][j] for k in range(len(A[0])))
for j in range(len(B[0]))] for i in range(len(A))]
# Print the result
print(result)
[[151, 164], [215, 234]]
مزایا
- در مقایسه با تابع map() کوتاهتر و خواناتر است.
معایب
- ممکن است کمتر از استفاده از تابع map () موثر باشد، به ویژه برای ماتریس های بزرگ.
- از رویکرد حلقه های تو در تو دشوارتر است.
نتیجه
در این پست، جایگزینهای استفاده از NumPy هنگام ضرب ماتریس در پایتون را بررسی کردیم. ما ضرب ماتریس را در حلقههای تودرتو، تابع map() داخلی و درک لیست انجام دادیم.
بهترین استراتژی به نیازهای خاص پروژه شما بستگی دارد.
هر کدام از استراتژی ها مزایا و معایب خاص خود را دارند. برای اطمینان از عملکرد صحیح تابع، ایده خوبی است که چند مورد تست با ابعاد و مقادیر مختلف ماتریس اضافه کنید.
شما همچنین باید چند تست عملکرد را برای مقایسه میزان اجرای این روش ها در نظر بگیرید.
پاسخ دهید