برنامه نویسی پایتون (Python) با کتابخانه NumPy – به زبان ساده


کتابخانه «NumPy» یک ابزار قدرتمند برای زبان برنامهنویسی پایتون (Python) است که میتواند سرعت و کارایی را در پردازش دادههای عظیم به شدت افزایش دهد. چندین «چارچوب» (framework) «علم داده» (Data Science) و «یادگیری ماشین» (Machine Learning) با کتابخانه NumPy کار میکنند یا بر مبنای آن ساخته شدهاند. برای نشان دادن مزایای استفاده از NumPy، در ادامه برخی مثالهای مرتبط با وظایف علم داده و دادهکاوی ارائه و با بهرهگیری از لیستهای پایتون و عملگرهای موجود در NumPy پیادهسازی شدهاند.
لیستهای پایتون و آرایهها در کتابخانه NumPy
«لیستها» (Lists) در پایتون آرایههایی با اندیس صفر هستند که میتوانند شامل دادههایی از انواع گوناگون باشند.
دادههایی که در لیستهای پایتون قرار میگیرند به طور مجزا با اندیسگذاری یا تکرار در لیست قابل دسترسی هستند.
1my_list = ["one", "two", 3]
2
3#individual indexing - prints 'one'
4print(my_list[0])
5
6#iteration - prints 'one, two, 3'
7for el in enumerate(my_list):
8print(el, ', ')
لیستها در کتابخانه NumPy، با عنوان «ndarrays» نامیده میشوند (سرنامی برای n-dimensional arrays به معنای آرایهای n بُعدی است) و مشابه لیستهای پایتون در پایهایترین سطح هستند، اما کارکرد عملکردی برداری را فراهم میکنند که لیستها در پایتون ندارند. اکنون، فرض میشود که یک مجموعه از اعداد «صحیح» (Integers) به صورت [4,3,my_int_list = [1, 2 ساخته شده است و هدف تغییر دادن هر عنصر مجموعه با ضرب کردن هر عدد صحیح در مقدار ۲ است. کد زیر نحوه پیادهسازی این کار را با لیستها در پایتون نشان میدهد.
1for el in enumerate(my_int_list):
2el = el * 2
این کد به سرعت روی سه آیتم موجود در لیست اجرا میشود، اما حلقه به ترتیب هر آیتم موجود در لیست را میبینید و جایگزین میکند. این روش به لحاظ محاسباتی هنگام کار با مجموعه دادههای بزرگ بسیار پر هزینه خواهد بود. همچنین، هنگام کار با مجموعه دادههایی که در لیستهای چندبُعدی سازمان یافتهاند نیز به دلیل آنکه تکرار در این لیستها نیازمند حلقههای تو در تو است کارایی را به صورت نمایی کاهش میدهد و همچنان عملکرد این روش زیر سوال است. اکنون، عمل مشابهی با استفاده از آرایه NumPy انجام میشود.
1import numpy as np
2
3#create numpy array from original python list
4my_numpy_arr = np.array(my_int_list)
5
6#multiply each element by 2
7my_numpy_arr * 2
ضرب ماتریسها
علم داده و «یادگیری ماشین» (Machine Learning) به شدت بر «ریاضیات ماتریسها» (Matrix Arithmetic) تکیه دارند، اما دادهها همیشه به شیوهای که امکان محاسبات عنصر به عنصر روی آنها وجود داشته باشد سازمان نیافتهاند.
افرادی که با ضرب ماتریسها آشنا نیستند، به تصویر زیر توجه کنند که در آن نحوه انجام ضرب یک ماتریس 2×4 و 4×3 قابل مشاهده است.


هیچ مساله ریاضیاتی پیچیدهای پیرامون ضرب ماتریسها وجود ندارد، اما واضح است که نیاز به جابهجاییهای زیادی در هر ٰآرایه وجود دارد. اکنون، ضرب دو ماتریس با استفاده از پایتون انجام میشود. در این راستا، ابتدا باید اطمینان حاصل کرد که کار با ماتریسهای صحیحی آغاز میشود. برای ضرب دو ماتریس A و B با ابعاد به ترتیب m×n و k×e، عدد n باید برابر با k باشد. به عبارت دیگر، تعداد سطرها در A باید با تعداد ستونها در B برابر باشد. همچنین، نیاز به دانستن آن است که ماتریس نتایج باید از سایز m×e باشد و بنابراین باید یک آرایه خالی با ابعاد مذکور ساخته شود.
در ادامه، راهکار پایتون برای ضرب دو ماتریس که شامل ۶۰۰۰۰ و ۸۰۰۰۰ عدد صحیح هستند نمایش داده شده است.
1import time
2import random as r
3tick = time.time()
4#create a 300x200 matrix of 60,000 random integers
5my_list_1 = []
6for row_index in range(300):
7new_row = []
8for col_index in range(200):
9new_row.append(r.randint(0, 20))
10my_list_1.append(new_row)
11#create a 200x400 matrix of 80,000 random integers
12my_list_2 = []
13for row_index in range(200):
14new_row = []
15for col_index in range(400):
16new_row.append(r.randint(0, 20))
17my_list_2.append(new_row)
18#create 2X3 array to hold results
19my_result_arr = []
20for row_index in range(300):
21new_row = []
22for col_index in range(400):
23new_row.append(0)
24my_result_arr.append(new_row)
25# iterate through rows of my_list_1
26for i in range(len(my_list_1)):
27# iterate through columns of my_list_2
28for j in range(len(my_list_2[0])):
29# iterate through rows of my_list_2
30for k in range(len(my_list_2)):
31my_result_arr[i][j] += my_list_1[i][k] *
32my_list_2[k][j]
33time_to_completion = time.time() - tick
34print("execution time without NumPy: ", time_to_completion)
35>>> execution time without NumPy: 11.94363808631897
کد بالا اصطلاحا بسیار کثیف (Dirty Code) محسوب میشود. خواندن این کد دشوار است و راهکاری که بر اساس آن بنا شده نیازمند حلقههای تو در توی دوگانه و سهگانه است که هر یک دارای پیچیدگی زمانی بالا و برابر با (O(n² و (O(n³ هستند. اکنون عمل ضرب دو ماتریس با استفاده از کتابخانه NumPy انجام میشود.
1import numpy as np
2import time
3tick = time.time()
4np_arr_1 = np.arange(0, 60000).reshape(300, 200)
5np_arr_2 = np.arange(0, 80000).reshape(200, 400)
6my_result_arr = np.matmul(np_arr_1, np_arr_2)
7time_to_completion = time.time() - tick
8print("execution time with NumPy: ", time_to_completion)
9>>> execution time with NumPy: 0.01147603988647461
- (numpy.arange(start, stop یک آرایه NumPy با مقادیر ترتیبی بین مقادیر پاس داده شده به پارامترهای start و stop به جز خود مقدار stop میسازد.
- (reshape(x, y. یک راهکار آسان برای کاربر جهت بیان اینکه آرایه (matrix) به چه صورت باشد فراهم میکند.
- (np.matmul(array_1, array_2 کاری را انجام میدهد که پیش از این توسط سه حلقه تو در توی سنگین انجام میشد.
راهکار Numpy نشان میدهد که سه خط کد، کاری را انجام میدهد که با استفاده از خود پایتون (بدون استفاده از کتابخانهها) با ۲۲ خط کد امکانپذیر بود. زمان اجرا با استفاده از Numpy برابر با ۰.۰۹ درصد زمان اجرای کد پایتون و همچنین دارای قابلیت خوانایی بسیار بالایی است.
چرا NumPy سریعتر است؟
بسیاری از ویژگیهای NumPy به زبان C نوشته شدهاند. این موضوع به NumPy این امکان را میدهد تا آرایههایی از یک نوع را به شدت بستهبندی کند، در حالیکه لیستهای پایتون دارای اشارهگرهایی به اشیای منفرد هستند. این یعنی داده در یک آرایه NumPy باید دارای نوع مشابهی باشند، اما در عین حال دسترسی به دادهها سریعتر است زیرا دادههای مرتبط با هم در حافظه محلی شدهاند.
پایتون به عنوان یک زبان مفسری با نوع پویا، دارای سربار قابل توجهی حتی برای یک حلقه ساده است، در حالیکه کتابخانه NumPy با پیادهسازی C راهکاری برای این مشکل فراهم میکند.
نتیجهگیری
Numpy ابزاری برای پردازش مجموعه دادههای عظیم فراهم میکند که برای آموزش هر مدل پیشبینی حیاتی هستند. ابزارهایی برای یادگیری ماشین و «شبکههای عصبی» (Neural Networks) مانند کتابخانههای Scikit-learn ،TensorFlow و Pandas به شدت بر کتابخانه Numpy تکیه دارند. بنابراین، به کلیه افرادی که تمایل به فراگیری دادهکاوی، علم داده و یا یادگیری ماشین دارند، آموختن این کتابخانه اکیدا توصیه میشود.
اگر مطلب بالا برای شما مفید بوده، آموزشهای زیر نیز به شما پیشنهاد میشود:
- گنجینه آموزشهای برنامه نویسی پایتون (Python)
- مجموعه آموزشهای آمار، احتمالات و دادهکاوی
- مجموعه آموزشهای یادگیری ماشین و بازشناسی الگو
- مجموعه آموزشهای هوش محاسباتی
- مجموعه آموزشهای شبکههای عصبی مصنوعی
- آموزش برنامهنویسی R و نرمافزار R Studio
- مجموعه آموزشهای برنامه نویسی متلب (MATLAB)
- معرفی منابع آموزش ویدئویی هوش مصنوعی به زبان فارسی و انگلیسی
- آموزش پایتون (Python) — مجموعه مقالات جامع وبلاگ فرادرس
^^
متشکرم