یونیت تست برای برنامه‌های یادگیری عمیق با پایتون

شکل ۱: آزمون واحد در یادگیری عمیق
شکل ۱: آزمون واحد در یادگیری عمیق


منتشر‌شده در: towardsdatascience به تاریخ 15 فوریه ۲۰۲۱
لینک منبع: Unit Testing in Deep Learning

جریان‌های کاری یادگیری عمیق / یادگیری ماشینی معمولا با آنچه که از یک فرآیند توسعه نرم‌افزار معمولی انتظار می‌رود، متفاوت هستند. اما این بدان معنا نیست که فرد نباید از آنها الهام بگیرد و بهترین روش‌ها را از توسعه نرم‌افزار که در طول سال‌ها تکامل‌یافته است، به کار گیرد. در این مقاله، من در مورد آزمون‌های واحد و دلیل و همچنین نحوه ترکیب این آزمون‌ها در کد شما صحبت خواهم کرد. ما با معرفی مختصری از آزمون‌های واحد شروع می‌کنیم، و به دنبال آن مثالی از آزمون‌های واحد در یادگیری عمیق و چگونگی اجرای آن‌ها از طریق خط فرمان و جستجوگر آزمون کد VS را خواهیم داشت.

مقدمه

آزمون واحد (unit testing) مفهومی است که برای افراد فعال در زمینه توسعه نرم‌افزار آشنا است. این یک تکنیک بسیار مفید است که می‌تواند به شما کمک کند تا از اشتباهات و اشکالات آشکار در کدهای خود جلوگیری کنید. این کار شامل تست واحدهای کد منبع، مانند توابع، روش‌ها و کلاس برای اطمینان از اینکه آن‌ها الزامات را برآورده می‌کنند و رفتار مورد انتظار را دارند، می‌باشد. تست‌های واحد معمولا کوچک هستند و زمان زیادی برای اجرا صرف نمی‌کنند. آزمایش‌ها دارای محدوده وسیعی از ورودی‌ها هستند که اغلب شامل موارد مرزی و لبه‌ای می‌باشند. خروجی‌های این ورودی‌ها معمولا توسط توسعه دهنده به صورت دستی برای تست خروجی واحد مورد آزمایش محاسبه می‌شوند. برای مثال برای یک تابع جمع‌، ما مواردی مانند موارد زیر را امتحان می‌کنیم. (بعدا شاهد یک مثال یادگیری عمیق خواهیم بود.)

شکل ۲: وروردی ها و خروجی ها
شکل ۲: وروردی ها و خروجی ها


شما مواردی را با ورودی‌های مثبت، ورودی‌های صفر، ورودی‌های منفی، ورودی‌های مثبت و منفی آزمایش می‌کنید. اگر خروجی تابع / روش ما که مورد آزمایش قرار می‌گیرد برابر با خروجی تعریف‌شده در آزمون واحد برای همه موارد ورودی باشد، واحد شما آزمون را قبول خواهد کرد در غیر این صورت با شکست مواجه خواهد شد. شما دقیقا می‌دانید که کدام مورد در آزمایش شکست خورد. که می‌تواند بیشتر بررسی شود تا مشکل را پیدا کنید. این یک چک سلامت عقل عالی است که باید در کدهایتان داشته باشید. به خصوص اگر توسعه دهندگان متعددی بر روی یک پروژه بزرگ کار کنند. تصور کنید کسی یک قطعه از کد را بر اساس فرضیات خاص و اندازه داده‌ها نوشته‌است و یک توسعه دهنده جدید چیزی را در پایگاه کد تغییر می‌دهد که دیگر آن فرضیات را برآورده نمی‌کند. سپس کد با شکست مواجه می‌شود. آزمون‌های واحد، اجتناب از چنین شرایطی را ممکن می‌سازند.

در زیر برخی از مزایای تست واحد آورده شده‌است.

  • شما را مجبور به نوشتن کد مدولار و قابل‌استفاده مجدد با ورودی‌ها و خروجی‌های به وضوح تعریف‌شده می‌کند. در نتیجه، ترکیب کد شما آسان‌تر خواهد بود.
  • افزایش اعتماد به نفس در تغییر / حفظ کد. این روش به شناسایی باگ‌های معرفی‌شده توسط تغییر کد کمک می‌کند.
  • بهبود اعتماد به نفس در خود واحد به این دلیل که اگر از آزمون واحد عبور کند ما مطمئن هستیم که هیچ مشکلی در منطقی بودن کد وجود ندارد و واحد همانطور که در نظر گرفته‌شده عمل می‌کند.
  • اشکال زدایی آسان‌تر می‌شود زیرا شما می‌دانید کدام واحد همانند موارد آزمون خاصی که شکست خورده‌اند، شکست خورده‌اند.

آزمون واحد در پایتون

هر زبان ابزارها و بسته‌های خود را برای انجام آزمون واحد در دسترس دارد. پایتون همچنین چند چارچوب تست واحد در دسترس دارد. بسته تست نشده به عنوان بخشی از کتابخانه استاندارد پایتون در دسترس است. من در مورد چگونگی استفاده از این چارچوب هم از طریق خط فرمان / برهم زنی و هم از طریق رابط کد VS بحث خواهم کرد. این چارچوب از Junit الهام‌گرفته شده و روش مشابهی به عنوان چارچوب اصلی آزمون واحد در زبان‌های دیگر دارد. این روش از اتوماسیون آزمون، به اشتراک گذاری کد راه‌اندازی و متوقف کردن برای تست‌ها، تجمع تست‌ها در مجموعه‌ها، و استقلال تست‌ها از چارچوب گزارش پشتیبانی می‌کند.

بلوک اصلی ساخت آزمون واحد در این چارچوب موارد آزمون هستند -سناریوهای واحد که باید تنظیم شوند و برای صحت بررسی شوند. در آزمون واحد، موارد آزمون با آزمون واحد نشان داده می‌شوند. برای انجام آزمایش خود باید زیرکلاس‌های آزمایش را بنویسید.

مورد آزمایش باید خود محدود باشد، به طوری که بتواند به صورت ایزوله یا در ترکیب دل‌خواه با هر تعداد از موارد آزمایش دیگر اجرا شود. روش‌های تست زیرکلاس مورد آزمایش باید دارای پیشوند تست در نام و اجرای کد تست خاص باشند.

برای انجام آزمایش، کلاس پایه مورد آزمایش دارای چندین روش تایید کننده است که به شما اجازه می‌دهد تا خروجی مورد آزمایش را در برابر خروجی واحد مورد آزمایش بررسی کنید. اگر آزمون با شکست مواجه شود، یک استثنا با یک پیام توضیحی مطرح خواهد شد، و عدم آزمون، مورد آزمون را به عنوان یک شکست شناسایی خواهد کرد. هر استثنا دیگری به عنوان خطا در نظر گرفته می‌شود.

دو نوع روش راه‌اندازی وجود دارد که می‌توان از آن‌ها برای راه‌اندازی کلاس خود برای آزمایش‌ها استفاده کرد.

  1. تنظیمات -این امر قبل از هر روش آزمایشی در کلاس شما نامیده می‌شود.
  2. تنظیمات کلاس -این فقط یک‌بار برای کل کلاس اجرا می‌شود. این روشی است که شما باید برای تست‌های یادگیری عمیق استفاده کنید. مدل را در این روش بارگذاری کنید تا از بارگذاری مجدد مدل قبل از اجرای هر روش آزمون جلوگیری شود. این کار باعث صرفه‌جویی در زمان بارگذاری مجدد مدل می‌شود.

توجه داشته باشید که ترتیبی که در آن تست‌های مختلف اجرا خواهند شد با مرتب‌سازی نام‌های روش تست با توجه به مرتب‌سازی برای رشته‌ها تعیین می‌شود.

حال اجازه دهید نگاهی به آزمون واحد ایجاد شده برای آزمایش یک بارکننده داده Pytorch برای یک پروژه قطعه‌بندی بیندازیم. کد مربوطه در زیر نشان ‌داده شده‌است.

مجموعه داده قطعه‌بندی مورد آزمایش قرار گرفته تا جفت تصاویر و ماسک مربوطه را در دسته‌هایی بارگذاری کند. بسیار مهم است که تصویر صحیح به ماسک صحیح نگاشته شود. برای این منظور، معمولا، هر دو تصویر و ماسک‌ها عدد یکسانی در نام خود دارند. اگر از طریق کمی پیش‌بینی در مقابل تصویر خود مقاومت می‌کنید، در این صورت اندازه نهایی شما باید همان طور که انتظار دارید باشد. برای PyTorch، تانسور بازگشتی توسط بارکننده داده باید به شکل BxCxHxW باشد، که در آن B اندازه دسته، C تعداد کانال‌ها، H ارتفاع و W عرض است.

حالا، توضیح می‌دهم که در کد چه اتفاقی دارد می‌افتد. من یک کلاس آزمایش تقسیم‌بندی داده‌ها را ایجاد کردم که از تست واحد نشات میگیرد. کلاس پایه مورد آزمون. همانطور که قبلا توضیح داده شد، من یک روش کلاس به کلاس ایجاد کردم که یک روش کلاس برای اطمینان از این است که مقداردهی اولیه تنها یک‌بار انجام می‌شود.

یک نکته که باید در اینجا به آن اشاره کنم این است که من از کار انداختن dataloader برای اهداف آزمایشی جلوگیری کرده‌ام. از آنجا که من انتظار دارم تصویر و ماسک با ۰۰۱ در نام آن‌ها در شاخص ۰ از اولین دسته ایجاد شده توسط dataloader حضور داشته باشند. بررسی یک شاخص نمونه متفاوت از یک دسته متفاوت یک تست حتی بهتر خواهد بود زیرا شما اطمینان حاصل خواهید کرد که سفارش در سراسر گروه‌ها سازگار است. من اولین دسته را در cls.samp les به عنوان یک ویژگی کلاس ذخیره می‌کنم.

اکنون که مقدار دهی اولیه انجام شده‌است، ما به آزمایش‌ها جداگانه نگاه می‌کنیم.

در آزمایش اول، من ابعاد تانسور تصویر بازگشتی توسط dataloader را بررسی می‌کنم. از آنجا که من در برابر تصاویر مقاومت نمی‌کنم، انتظار دارم اندازه آن ۳۲۰ * ۴۸۰ باشد و آن تصاویر به عنوان RGB خوانده شوند، بنابراین باید ۳ کانال وجود داشته باشد. در روش تعیین کلاس، اندازه دسته ۴ را مشخص کردم، بنابراین اولین بعد تانسور باید ۴ باشد.

اگر مشکلی در ابعاد وجود داشته باشد، این آزمون با شکست مواجه خواهد شد. در این مجموعه داده خاص، ماسک‌ها تنها یک کانال دارند. بنابراین انتظار دارم تعداد کانال‌ها ۱ باشد.

اندازه دسته باید ۴ باشد. و شکل ماسک باید ۳۲۰ * ۴۸۰ باشد. آخرین آزمایش دو چیز را بررسی می‌کند. اول اینکه آیا تانسور به‌دست‌آمده با اعمال تبدیل‌های مشخص‌شده در dataloader به صورت دستی همان نتیجه را به عنوان داتالدر می‌دهد یا خیر. و دومی این است که جفت تصاویر و ماسک درست هستند.

برای اعمال مستقیم یک تبدیل تصویر، شما باید این تبدیل را معرفی کرده و تصویر خود را به عنوان ورودی به آن نمونه منتقل کنید.

اگر تبدیل انتظار یک تصویر PIL یا عدد را داشته باشد، هر فرمت دیگری منجر به خطا می‌شود.

حال که آزمون یکپارچه خود را آماده کرده‌ایم، اجازه دهید اول نگاهی به چگونگی اجرای این آزمون از طریق خط فرمان بیندازیم.

شما می‌توانید از دستور زیر استفاده کنید:

-s or --start-directory directory: It specifies the start discovery directory. In our case, since the tests were in a Tests folder we specified that folder as a value for this flag.-p or --pattern pattern: It specifies the match pattern. I specified a custom pattern just to show you that this functionality is available. Since the default pattern is test*.py, it would work for our test script by default.-v or --verbose: If you specify this you’ll get output for every test method in your test class.

python -m unittest discover -s Tests -p "test_*"

اگر تمام روش های تست قبول شوند پیام OK را در انتها مشهاده خواهید کرد.

شکل ۳: تست واحد کوتاه زمانی که تمام تست ها قبول می شوند.
شکل ۳: تست واحد کوتاه زمانی که تمام تست ها قبول می شوند.


شکل ۴: خروجی وربوز تک تست هنگام عبور همه تست‌ها
شکل ۴: خروجی وربوز تک تست هنگام عبور همه تست‌ها

با این حال، اگر یکی از روش‌های تست با شکست مواجه شود، شما پیام شکست را با آزمایشی که مشخص نشده است دریافت خواهید کرد. شما می‌دانید که کدام اعلان خاص شکست خورد. همانطور که قبلا ذکر شد، این امر برای اشکال‌زدایی و یافتن چیزی که کد را شکسته‌ است، بسیار مفید است. در این مورد، من تصویر در حال خواندن را تغییر دادم اما تنسوری که مقایسه شد را تغییر ندادم که منجر به خطا شد.

شکل ۵: خروجی وربوز تک تست زمانی که همه تست‌ها رد نشدند
شکل ۵: خروجی وربوز تک تست زمانی که همه تست‌ها رد نشدند


شکل ۶: خروجی وربوز تک تست زمانی که همه تست‌ها رد نشدند
شکل ۶: خروجی وربوز تک تست زمانی که همه تست‌ها رد نشدند


شما می‌توانید این خط اجرای تست را در هر فایل دسته‌ای یا برهم زنی خودکار که ممکن است برای استقرار خودکار استفاده کنید، قرار دهید. به عنوان مثال، ما از آزمون‌های مشابه در Github Actions استفاده می‌کنیم تا به طور خودکار اعتبار سنجی کنیم که آیا کد قبل از اینکه نسخه به روز شده به صورت خودکار به مخزن بسته فرستاده شود، کار می‌کند یا خیر.

سپس، به شما نشان خواهم داد که چگونه از جستجوگر آزمون کد VS برای اجرای این آزمون‌ها از طریق رابط کاربری استفاده کنید.

اجرای آزمون‌های واحد پایتون در کد VS [ ۳ ]

آزمایش در پایتون به طور پیش‌فرض در کد VS غیرفعال شده‌است. برای فعال کردن آزمایش، از پایتون استفاده کنید: فرمان تست‌ها را در فرمان Pallete کانفیگور کنید. این فرمان شما را به انتخاب یک چارچوب آزمایش، پوشه حاوی تست‌ها، و الگوی مورد استفاده برای شناسایی فایل‌های آزمایشی ترغیب می‌کند. دو ورودی آخر دقیقا مشابه همان چیزی هستند که ما برای اجرای آزمون‌های واحد از طریق خط فرمان استفاده کردیم. چارچوب آزمون یکپارچه نیازی به نصب بیشتر ندارد. با این حال، اگر بسته چارچوبی که انتخاب کرده‌اید در محیط شما نصب نشده باشد، کد VS شما را به نصب آن ترغیب می‌کند.

شکل ۷: پایتون را انتخاب کنید: تست‌های فرمانPallete را کانفیگور کنید.
شکل ۷: پایتون را انتخاب کنید: تست‌های فرمانPallete را کانفیگور کنید.


شکل ۸: چارچوبی که می‌خواهید را انتخاب کنید. در این مورد، آزمون واحد.
شکل ۸: چارچوبی که می‌خواهید را انتخاب کنید. در این مورد، آزمون واحد.


شکل ۹: شاخه کشف آزمون را انتخاب کنید. تست‌ها در این مورد.
شکل ۹: شاخه کشف آزمون را انتخاب کنید. تست‌ها در این مورد.


شکل ۱۰: الگوی کشف آزمون را انتخاب کنید. در این مورد تست test_*.py
شکل ۱۰: الگوی کشف آزمون را انتخاب کنید. در این مورد تست test_*.py


شکل ۱۱: پیام مربوط به نصب
شکل ۱۱: پیام مربوط به نصب


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

شما می‌توانید تمام یا هر آزمون را از این دیدگاه اجرا کنید و همچنین به هر روش آزمون منحصر به فرد در کلاس‌های مختلف بروید.

شکل ۱۲: واسط تست واحد
شکل ۱۲: واسط تست واحد


اگر یک تست شکست بخورد، من با یک صلیب قرمز به جای یک تیک سبز ظاهر خواهم شد.

شکل ۱۳: مثال شکست تست واحدVS ()
شکل ۱۳: مثال شکست تست واحدVS ()

و اگر می‌خواهید در وقت صرفه‌جویی کنید، می‌توانید انتخاب کنید که تنها آزمونی را اجرا کنید که شکست خورد و نه همه تست‌ها.

جمع بندی

این مقاله در مورد آزمون واحد برای یادگیری عمیق نتیجه‌گیری می‌کند. ما به طور خلاصه دیدیم که آزمون‌های واحد چه هستند و چه مزایایی دارند. سپس، ما یک مثال عملی برای یک واحد داتالدر نوشته شده در PyTorch با استفاده از چارچوب بسته unittest را بررسی کردیم. ما یاد گرفتیم که چگونه این تست را هم از طریق خط فرمان و هم از طریق اینترنت اکسپلورر تست پایتون از کد VS اجرا کنیم. امیدوارم شروع به نوشتن تست‌های واحد برای کد خود کرده و از مزایای آن بهره‌مند شوید!

این متن با استفاده از ربات ترجمه مقاله علم داده ترجمه شده و به صورت محدود مورد بازبینی انسانی قرار گرفته است.در نتیجه می‌تواند دارای برخی اشکالات ترجمه باشد.
مقالات لینک‌شده در این متن می‌توانند به صورت رایگان با استفاده از مقاله‌خوان ترجمیار به فارسی مطالعه شوند.