جستجو
Generic filters
Filter by دسته‌ها
آموزش هوش مصنوعی و انواع آن
آموزش‌های پایه‌ای هوش مصنوعی
اصول هوش مصنوعی
پایتون و ابزارهای یادگیری عمیق
کتابخانه‌ های یادگیری عمیق
یادگیری با نظارت
یادگیری بدون نظارت
یادگیری تقویتی
یادگیری عمیق
یادگیری نیمه نظارتی
آموزش‌های پیشرفته هوش مصنوعی
بینایی ماشین
پردازش زبان طبیعی
پردازش گفتار
چالش‌های عملیاتی
داده کاوی و بیگ دیتا
رایانش ابری و HPC
سیستم‌‌های امبدد
علوم شناختی
دیتاست
اخبار
رسانه‌ها
آموزش پردازش زبان طبیعی
آموزش علوم داده
اینفوگرافیک
پادکست
ویدیو
رویدادها
کاربردهای هوش مصنوعی
کسب‌و‌کار
تحلیل بازارهای هوش مصنوعی
کارآفرینی
هوش مصنوعی در ایران
هوش مصنوعی در جهان
 چگونه سرعت حلقه‌ های pandas را ۷۱۸۰۳ برابر افزایش دهیم؟

چگونه سرعت حلقه‌ های pandas را ۷۱۸۰۳ برابر افزایش دهیم؟

اگر برای تحلیل داده‌های Data analysis خود از پایتون و کتاب‌خانه pandas استفاده می‌کنید، دیر یا زود مجبور می‌شوید با حلقه‌ های pandas هم کار کنید. اجرای حلقه‌های استاندارد برای یک دیتافریم کوچک بسیار زمان‌بر است بنابراین، اجرای آن برای دیتافریم‌های بزرگ‌تر قطعاً به زمان بیشتری نیاز دارد. وقتی برای اولین‌بار از یک حلقه استفاده می‌کنید و مجبور می‌شوید بیش از نیم ساعت منتظر اجرای آن کد بمانید، بهتر است راهی جایگزین برای این مسئله پیدا کنید.

حلقه‌های استاندارد

دیتافریم‌ها دارای سطر و ستون هستند و یکی از انواع اشیاء موجود در pandas به شمار می‌آیند. وقتی از یک حلقه استفاده می‌کنید، درواقع تمام این شیء را بارها و بارها تکرار می‌کنید. سرعت پایتون پایین است زیرا نمی‌تواند از مزایای توابع تعبیه‌شده built-in functions بهره ببرد. در مثالی که در ادامه به آن خواهیم پرداخت، یک دیتافریم با ۱۱۴۰ سطر و ۶۵ ستون را درنظر می‌گیریم که حاوی داده‌های مربوط به نتایح بازی‌های فصلی فوتبال در سال‌های ۲۰۱۶ تا ۲۰۱۹ است. ما قصد داریم یک ستون دیگر به این دیتافریم اضافه کنیم که حاوی اطلاعات مربوط به نتایج تساوی بازی‌های یک تیم به‌خصوص باشد. بدین منظور باید چنین نوشت:
def soc_loop(leaguedf,TEAM,):

    leaguedf['Draws'] = 99999

    for row in range(0, len(leaguedf)):

        if ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')) | \

            ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')):

            leaguedf['Draws'].iloc[row] = 'Draw'

        elif ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')) | \

            ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')):

            leaguedf['Draws'].iloc[row] = 'No_Draw'

        else:

            leaguedf['Draws'].iloc[row] = 'No_Game'

 

حلقه‌ های pandas
پس از آنکه نتیجه تمام بازی‌های لیگ برتر را وارد دیتافریم کردیم، باید بررسی کنیم که آیا تیم موردنظر (در این‌جا آرسنال) در کدام بازی‌ها شرکت داشته و اگر شرکت داشته، آن بازی را در خانه بازی کرده یا در شهری دیگر مهمان بوده است. همان‌طور که مشاهده می‌کنید، این کد بسیار کند است و اجرای آن ۲۰.۷ ثانیه زمان می‌برد. در ادامه، به شما می‌گوییم که چطور می‌توان سرعت اجرای چنین کدی را بهبود بخشید.

افزایش ۳۲۱ برابری سرعت کدها با استفاده از یک تابع تعبیه‌شده در pandas(): iterrows

در مثال اول ما حلقه را برای کل دیتافریم اجرا کردیم. تابع ()iterrows هر سطر از دیتافریم را به یک دنباله تبدیل می‌کند و دیتافریم را به صورت یک جفت شاخص-دنباله درنظر گرفته و تکرار می‌کند. بدین ترتیب، سرعت اجرای کدها از حالت حلقه‌های استاندارد بیشتر خواهد شد:
def soc_iter(TEAM,home,away,ftr):
    #team, row['HomeTeam'], row['AwayTeam'], row['FTR']
    if [((home == TEAM) & (ftr == 'D')) | ((away == TEAM) & (ftr == 'D'))]:
        result = 'Draw'https://hooshio.com/%da%86%da%af%d9%88%d9%86%d9%87-%d8%b3%d8%b1%d8%b9%d8%aa-%d8%a7%d8%ac%d8%b1%d8%a7%db%8c-%d8%ad%d9%84%d9%82%d9%87-%d9%87%d8%a7%db%8c-pandas-%d8%b1%d8%a7-71803-%d8%a8%d8%b1%d8%a7%d8%a8%d8%b1-%d8%a7%d9%81/
    elif [((home == TEAM) & (ftr != 'D')) | ((away == TEAM) & (ftr != 'D'))]:
        result = 'No_Draw'
    else:
        result = 'No_Game'
    return result

 

تابع تعبیه‌شده در pandas(): iterrows
اجرای این کد تنها ۶۸ میلی ثانیه زمان می‌برد که ۳۲۱ برابر سریع‌تر از حلقه‌های استاندارد است. اما بسیاری توصیه می‌کنند که از این روش استفاده نشود، زیرا هم روش‌های سریع‌تری وجود دارد و هم تابع ()iterrows  داده‌هایی از نوع dtype را ذخیره نمی‌کند. یعنی اگر برای داده‌های dtype موجود در دیتافریم از تابع ()iterrows استفاده کنید، ممکن است نوع این داده‌ها تغییر کند و مشکلات زیادی برای کد شما ایجاد شود. البته برای ذخیره داده‌های dtype می‌توانید از تابع ()itertuples  استفاده کنید، اما در این مقاله وارد جزئیات این مسئله نمی‌شویم، زیرا هدف ما افزایش سرعت اجرا و کارایی کدهاست. برای مطالعه بیشتر در این خصوص می‌توانید به این لینک مراجعه نمایید.
[irp posts=”۱۳۷۹۳″]

با تابع ()apply سرعت اجرای کد را تا ۸۱۱ برابر افزایش خواهد دهید

تابع apply به خودی‌خود سریع‌تر از روش‌های قبلی نیست، اما یک مزیت نسبت به آن‌ها دارد که به محتوای apply بستگی دارد. اگر تابع apply را در محیط Cython پیاده کنید، سرعت آن به مراتب بیشتر خواهد بود (که در این مثال همین کار را می‌کنیم).
با به‌کارگیری تابع Lambda می‌توانیم از روش apply استفاده کنیم. تنها کاری که لازم است انجام دهیم، تعیین یک مقدار برای axis است. در این مثال مقدار آن را برابر یک می‌گذاریم، زیرا می‌خواهیم عملیات در سطح ستون‌های دیتافریم انجام گیرد.
تابع ()apply سرعت
سرعت اجرای این کد حتی از روش قبلی نیز سریع‌تر است و تنها ۲۷ میلی ثانیه به طول می‌انجامد.

افزایش ۹۲۸۰ برابری سرعت اجرای کد با ایجاد بردار  در pandas

در این روش به کمک بردارها می‌توان کدی بسیار سریع و کارآمد نوشت. نکته این‌جاست که باید حلقه‌های مرحله‌ای پایتون را که در مثال قبلی استفاده کردیم، کنار بگذاریم و از کدهای بهینه‌سازی‌شده در زبان C استفاده کنیم که در استفاده از حافظه سیستم بسیار کارآمدتر هستند. تنها کافی است تابع خود را اندکی اصلاح کنیم:
def soc_iter(TEAM,home,away,ftr):
    df['Draws'] = 'No_Game'https://hooshio.com/%da%86%da%af%d9%88%d9%86%d9%87-%d8%b3%d8%b1%d8%b9%d8%aa-%d8%a7%d8%ac%d8%b1%d8%a7%db%8c-%d8%ad%d9%84%d9%82%d9%87-%d9%87%d8%a7%db%8c-pandas-%d8%b1%d8%a7-71803-%d8%a8%d8%b1%d8%a7%d8%a8%d8%b1-%d8%a7%d9%81/
    df.loc[((home == TEAM) & (ftr == 'D')) | ((away == TEAM) & (ftr == 'D')), 'Draws'] = 'Draw'
    df.loc[((home == TEAM) & (ftr != 'D')) | ((away == TEAM) & (ftr != 'D')), 'Draws'] = 'No_Draw'
در این روش حتی به تعریف حلقه نیز نیازی نداریم. تنها کافی است محتویات تابع را تنظیم کنیم. حال می‌توانیم دنباله‌های pandas را مستقیماً به تابع بدهیم. بدین ترتیب سرعت تا حد زیادی افزایش پیدا می‌کند.

افزایش ۷۱.۸۰۳ برابری سرعت اجرای کد با ایجاد بردارهای numpy

در مثال قبل، دنباله‌های pandas را به تابع دادیم با افزودن .values به کد، یک آرایه numpy خواهیم داشت.
دنباله‌های pandas
آرایه‌های numpy به دلیل استفاده از حافظه محلی، سرعت بالایی دارند. اجرایی شدن این کد تنها ۰.۳۰۵ میلی ثانیه زمان می‌برد و ۷۱۸۰۳ برابر سریع‌تر از حلقه استانداردی است که در مثال اول استفاده کردیم.

نتیجه‌گیری

اگر برای تحلیل داده‌ها از پایتون، pandas و numpy استفاده می‌کنید، همیشه راهی برای بهبود کدها پیش پای شما قرار دارد. ما عمل افزودن ستون جدید به دیتافریم را با هر ۵ روش بالا امتحان کردیم و سرعت اجرای کد موردنظر در هر روش تفاوت قابل‌توجهی با دیگری داشت:
حلقه‌ های pandas
چگونه سرعت اجرای حلقه‌ های pandas را تا ۷۱۸۰۳ برابر افزایش دهیم؟
اکنون که چگونگی افزایش سرعت اجرای حلقه‌ های pandas را فراگرفتید دو اصل زیر را هم به‌خاطر بسپارید:
۱. اگر مطمئن هستید که به استفاده از یک حلقه نیاز دارید، بهتر است از روش apply استفاده کنید.
۲. در غیر این صورت، ایجاد بردار vector همواره اولویت دارد، زیرا سرعت آن بسیار بالاست.

مقاله ما چطور بود؟

میانگین امتیاز / ۵. تعداد ارا :

مطالب پیشنهادی مرتبط

اشتراک در
اطلاع از
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
Please enable JavaScript in your browser to complete this form.