بینش و تجربه از استفاده از شبیهسازها برای تست عملکرد آموزشدیده (Insight and Experience from Using Simulators to Test Trained Functionality)
نکات کلیدی
-
تست برنامههای یادگیری ماشین (ML) شبیه تست با ذهنیت «جعبهسیاه» است. توضیح و فهمیدن یک تصمیم گرفتهشده توسط عملکردِ آموزشدیده سخت است، حتی وقتی به ساختار داخلی مدل نگاه میکنید.
-
توزیع مجموعهدادههای آموزش و تست، خودِ عملکرد را تعریف میکند؛ میتوانید دادهها را طوری افراز (Partition) کنید که همه سناریوهای معتبرِ تستِ تعریفشده، همراه با سناریوهای تعریفشده براساس عملکرد را پوشش دهد.
-
با مفهوم Operational Design Domain (ODD) میتوانید برای تابع ML خود، نیازمندی تعریف کنید. وقتی رفتاری پیدا میکنید که با انتظارات شما مطابقت ندارد، باید تشخیص دهید که درون ODD هستید یا بیرون از آن.
-
شبیهسازها از Annotation پشتیبانی میکنند، مثلاً با شناسایی و جدا کردن اشیا در یک تصویرِ داده آموزشی. شبیهسازها ابزاری مبتنی بر ابزار (Tool-driven) برای کمک به تست سناریوهایی هستند که نمیتوانیم برای آنها داده «دنیای واقعی» تولید کنیم و میتوانند با فراهم کردن امکان کنترل محیط (ترافیک، آبوهوا، زیرساخت، و غیره)، اجرای تست را تسریع کنند.
-
دانش و تجربه تست کد سنتی وقتی با برنامههای ML کار میکنیم ارزشمند است. درک تکنیکهای تست جعبهسیاه و دانش دامنهای (Domain Knowledge) هنگام تست این نوع برنامهها مفید است.
وقتی فناوری جدید معرفی میشود، باید کشف کنیم چطور آن را تست کنیم. با انجام پژوهش در حوزه تأیید (Verification) و اعتبارسنجی (Validation) عملکرد آموزشدیده و توابع یادگرفتهشده توسط ماشین و بهکارگیری نتایج این پژوهش در تست، من به بینشها و تجربههایی در تست برنامههای یادگیری ماشین رسیدم که در این مقاله با شما به اشتراک میگذارم.
برای برنامههای یادگیری ماشین، خودِ کد چیز جذابی نیست. برخلاف سیستمهایی که در آنها عملکرد یا توابع توسط کدهای پیچیده و عظیم ساخته میشوند، برنامههای یادگیری ماشین معمولاً از چند خط کد تشکیل شدهاند که روی شبکههای پیچیدهای از نقاط داده وزندار (شبکههای عصبی و مشابه) سوار هستند که پیادهسازی واقعی را شکل میدهند. دادهای که در آموزش استفاده شده، جایی است که عملکرد در نهایت در آن تعریف میشود، و همانجا است که مشکلات و باگها را پیدا میکنید. داده، کلید هر عملکرد آموزشدیده است.
وقتی سیستمهای یادگیری ماشین را تست میکنیم، باید فرایندها و روشهای تست موجود را به شکل متفاوتی بهکار ببریم. تست باید مستقل باشد و با نگاهی تازه به هر کد یا عملکرد نزدیک شود. همچنین باید مجموعهدادههای تست مستقل ایجاد کنیم و به مکانیسمهای تأیید (Verification) در بخش آموزش تکیه نکنیم.
و باید به مشکلات مربوط به نسخهدهی (Version Handling) رسیدگی کنیم. مفهوم و اصل CACE (Change Anything, Change Everything) در یادگیری ماشین وجود دارد. عملکرد ML باید «تیره و غیرشفاف» در نظر گرفته شود، بهگونهای که در عمل، یک جعبهسیاه است.
حداقل میتوان گفت فهم دقیق اینکه یک خروجی دقیقاً چگونه تعیین شده، بسیار زمانبر و دشوار است. این موضوع برمیگردد به توزیع دادههای آموزشی و وزنهایی که هنگام آموزش استفاده شدهاند، و نوع شبکه. از دید یک تستر، بهتر است این تابع را یک ابر جعبهسیاه (Super Black Box) در نظر بگیریم. این همچنین به این معناست که اگر به هر دلیلی تصمیم بگیریم دوباره آموزش (Retrain) انجام دهیم، راحتتر است که مدل جدید را نسخه ۲٫۰ در نظر بگیریم تا ۱٫۲.
تست عملکرد یادگیری ماشین
در تست یادگیری ماشین (ML)، خودِ عملکرد به آن شکلِ سنتیاش خیلی موضوع اصلی نیست. کد تا حدی بیربط میشود. برای یک تستر قدیمی، کد و تابع، «مسیر اصلی» بودند. اما با ML، عملکردی که شما آن را تأیید یا تست میکنید، تا حد زیادی بر اساس داده آموزشی تعریف میشود. وقتی تمرکز را از کد به داده آموزشی جابهجا میکنیم، تست واحد (Unit Test) یا تستهای «نزدیک به کد» در عمل تبدیل میشوند به تست دادهای که برای آموزش عملکرد استفاده شده، بهجای تست تکتک دستورات یا توابع.
وقتی در سلسلهمراتب سنتی سطوح تست بالاتر میرویم، شبیهسازها و ابزارهای دیگر برای تست یا اعتبارسنجی عملکرد مفید خواهند بود. اما هر مشکلی که اینجا (در شبیهساز) یا در محیط عملیاتی/تولید (سیستم لانچشده شما یا خودروی خودران شما) پیدا میکنیم، باید با تغییر داده آموزشی به شکل ساختاریافتهای اصلاح شود، نه فقط با تغییر کد.
وقتی عملکرد آموزشدیده را تست میکنیم، شناخت داده آموزشی همیشه مهم خواهد بود. بررسی توزیع و ترکیب داده آموزشی میتواند جایگزین تست واحد شود. انجام بازبینیها (تست ایستا / Static Testing) روی این توزیع را میتوان به عنوان تست زودهنگام در نظر گرفت، همانطور که بازبینی کد یا بازبینی نیازمندیها را تست زودهنگام میدانیم. مجموعهداده خود را زود بررسی کنید تا توزیع ناخواسته یا Bias را شناسایی کنید. به این شکل میتوانید از عملکرد ضعیف عملکرد خود در مراحل بعدی جلوگیری کنید.
وقتی روی عملکرد آموزشدیده کار و آن را تست میکنیم، جنبه دیگری که این نوع کار را از کد و فعالیتهای تست «سنتی» متمایز میکند این است که هر تغییر یا رفع باگ، یک تابع جدید به شما میدهد. برخلاف تست سنتی که در آن میتوانید یک Fix را ایزوله کنید و یک Retest بههمراه مقدار محدودی Regression در نواحی نزدیک عملکردی انجام دهید، در ML باید آن را یک نسخه کاملاً جدید از تابع در نظر بگیرید و احتمالاً بخواهید کل مجموعه تست خود را دوباره اجرا کنید. البته میتوانید با مدیریت هوشمند ریسک و غیره این فرایند را تسریع کنید و با کمک ابزارها و شبیهسازها، فرایند را کاراتر کنید.
تعریف یا طراحی سیستمهای ML
یکی از اولین چیزهایی که هنگام تعریف سیستمهای ML به ذهن میرسد، نیازمندیها (Requirements) است. روشهای سنتی برای توصیف و مشخص کردن نیازمندیها، برای عملکرد آموزشدیده چندان خوب جواب نمیدهند. در پروژههایی که من روی آنها کار کردهام، از Operational Design Domain (ODD) برای تعریف زمینهای استفاده کردهایم که مدل باید در آن کار کند.
میتوانید ODD را بهعنوان راهی برای تعریف نیازمندیهای تابع ML خود در نظر بگیرید.
برای مثال، برای رانندگی خودکار، ODD را به دستههایی تقسیم میکنیم، مانند:
Scenery (صحنه / محیط فیزیکی)
-
تقاطعها (Junctions)
-
روستایی یا شهری (Rural or city)
-
جاده / خارج از جاده (Road / off-road)
Dynamic (پویایی)
-
آبوهوا (باران، مه، …)
-
نور (روز، شب، …)
Environment (محیط اطراف)
-
ترافیک (عابران پیاده، خودروها، دوچرخهها، …)
-
خودروی شما یا تابع شما در این زمینه
وقتی رفتاری پیدا میکنید که با انتظارات شما مطابقت ندارد، باید تشخیص دهید که داخل ODD هستید یا خارج آن. اگر متوجه شوید که این رفتار «بیرون» از ODD است، ممکن است بخواهید آن را به عنوان یک باگ یا ناهنجاری در نظر بگیرید که باید بیشتر بررسی شود.
توزیع داده آموزشی بخش زیادی از عملکردِ تابع آموزشدیده را تعیین میکند. با در نظر گرفتن این موضوع، یک «رفع باگ» در واقع تغییری در توزیع داده آموزشی است، نه تغییر چند خط کد.
داده، کلید است
توزیع مجموعهدادههای آموزشی و تست حیاتی است. اینجا جایی است که عملکرد تا حدی تعریف میشود. پس چطور میتوانیم تست کنیم و مطمئن شویم تمام عناصر دادهای مهم برای آموزش یک مدل ML با عملکرد درست را در اختیار داریم؟
باید به توزیع نگاه کنیم، قطعاً. بخش مشکل کار، کانتکست (مثلاً تفاوتهای فرهنگی یا ملی) و Bias است. اینجا است که تیم QA میتواند بهعنوان بازیگر مستقل وارد شود و نگرانیهایش را درباره داده آموزشی یا سایر مجموعهدادهها مطرح کند. یک نگاه بیرونی چیز خوبی است. افراز کردن (Partitioning) دادهها بهگونهای که همه سناریوهای معتبر نمایانده شوند، میتواند نقطه شروع خوبی باشد. اگر قرار است یک Classifier آموزش دهیم، همه کلاسهای معتبر (و احتمالاً چند کلاس نامعتبر) باید نمایانده شوند. من دوست دارم اینطور به موضوع نگاه کنم که باید مطمئن شویم همه افرازهای همارز (Equivalent Partitions) نمایانده شدهاند، چه معتبر و چه نامعتبر.
برای یک Fruit Classifier (طبقهبند میوه)، باید سیب، گلابی، موز و غیره را پوشش دهیم. همچنین باید درجات مختلف رسیده بودن و شکلهای مختلف را در نظر بگیریم. وقتی از مدل از پیش آموزشدیده (Pre-trained Model) استفاده میکنیم، اهمیت داشتن یک مجموعه آموزشی مستقل حتی بیشتر میشود. این فرصتی است برای اعمال یک لایه بیطرف برای اعتبارسنجی مدل. نگه داشتن هر ODD تعریفشده در حلقه هنگام انجام این تست حیاتی است. ODD مرزهایی خواهد بود که در حال تست آنها هستیم و کمکمان میکند برای درستی عملکرد یا رفتار ناخواسته استدلال کنیم.
چالش دیگر Annotation است؛ اگر بهصورت ذهنی و سلیقهای انجام شود، ممکن است به یک مشکل بزرگ تبدیل شود. این موضوع بستگی دارد به اینکه مدل شما برای چه استفادهای خواهد شد و چقدر نیاز به دقت در دادههای آموزشی و اعتبارسنجی دارید؛ اما دقیق بودن مهم است، برای مثال تعیین دقیق اینکه جاده در تصویر کجا تمام میشود و پیادهرو از کجا شروع میشود.
فرض کنید میخواهید مدلی برای Computer Vision استفاده کنید تا اسناد را اسکن یا دستهبندی کند. در این حالت، تمایز بین مثلاً Å و Ä در الفبای سوئدی مهم خواهد بود. هنگام آموزش مدل، باید Annotation کنیم که آیا یک نقطه یا دو نقطه بالای A وجود دارد.
سناریوی دیگری در ترافیک را برای عملکردی متصل به رانندگی خودکار در نظر بگیریم. تصویر باید Annotate شود تا بتوانیم بین عابران پیاده، جادهها، خودروهای دیگر و غیره تمایز قائل شویم.
شبیهسازها
شبیهسازها در زمینه Annotation کمک میکنند، هم در ایجاد داده آموزشی و هم در تست. آنها یک کمک ابزارمحور (Tool-driven Aid) برای ایجاد سناریوهایی هستند که برای آنها نمیتوانیم داده «دنیای واقعی» تولید کنیم و همچنین برای Auto Annotation.
برای مثال، ممکن است لازم باشد برای تست رانندگی خودکار، باران، مه، برف و غیره ایجاد کنیم. شبیهسازها میتوانند در این زمینه کمک کنند.
شبیهسازها همچنین در صورت نیاز، به ما Ground Truth در Annotation میدهند تا به تسریع تست کمک کنند. Ground Truth Annotate-شده به ما یک Oracle میدهد که مشخص میکند کدام بخش تصویر آسمان است، کدام بخش چمن است، دقیقاً کدام قسمت تصویر یک عابر پیاده است و غیره.
بیشتر شبیهسازها برای تست Computer Vision یا رانندگی خودکار، فیلترها یا Modeهایی دارند. آنها سناریوهای شما را بهطور خودکار Annotate میکنند و برای اجزای مختلف یک Ground Truth یا Oracle در اختیار شما میگذارند. با استفاده از حسگرهایی غیر از دوربین، مانند Radar یا LiDAR، شبیهساز میتواند برای شما Point Cloudها یا اطلاعات Semantic تولید کند تا به عنوان مبنایی برای تست استفاده کنید.
استفاده از شبیهسازها همچنین میتواند هنگام جستجوی Corner Caseها به شکل کاراتری کمک کند. برای مثال، ما سناریوهای خود را Vectorize کردیم و سپس جستجوی سناریوهایی که در آنها مدل شکست میخورد را خودکار کردیم. با کمی اتوماسیون ساده، میتوانیم یک سناریوی پایه برای شبیهساز برداریم و سپس در هر اجرا، کمی میزان باران یا نور روز را تغییر دهیم تا بهتدریج به دنبال ترکیبهایی از برف، ترافیک و غیره بگردیم که باعث میشوند مدل پیشبینی اشتباهی انجام دهد. در یک شبیهساز، این کار بهراحتی قابل اتوماسیون است؛ اما در دنیای واقعی، انجام آن بسیار سختتر خواهد بود.
پروژههای تحقیقاتی در تست یادگیری ماشین
بینشها و تجربههایی که در این مقاله مطرح شد، از پروژههای تحقیقاتی بهدست آمده است. این پروژهها روی این موضوع متمرکز بودند که چگونه عملکرد یادگیری ماشین را تست کنیم. کمیسیون اروپا و دولت سوئد این پروژهها را تأمین مالی کردهاند.
تیمی که من با آن کار میکردم، در سه مطالعه اصلی شرکت داشت. هر سه به Verification و Validation عملکرد آموزشدیده مرتبط بودند:
-
FramTest روی شناسایی چالشها در صنعت امروز تمرکز داشت.
-
SMILE روی فرایندها و روشهایی برای تعریف و دفاع از یک Safety Case تمرکز داشت.
-
Valu3s روی استفاده از شبیهسازها برای تست عملکرد آموزشدیده تمرکز داشت.
#۱ FramTest – «متدولوژیهای تست آینده: نیازها و الزامات»
پروژه FramTest (به زبان سوئدی) بررسی کرد که «شرکتها امروز چگونه با مسئله ML برخورد میکنند». ما یک مطالعه ادبیات انجام دادیم تا وضعیت هنر (State of the Art) در این حوزه را بررسی کنیم. یافته این بود که با وجود مقالات بسیار درباره توسعه عملکرد یادگیری ماشین، تعداد بسیار کمی به Verification و Validation میپردازند. برای پیگیری این مقالات علمی، ۱۲ مصاحبه عمیق با تسترها و رهبران در سوئد درباره این موضوع انجام دادیم.
نتایج مصاحبهها را میتوان به این موارد تقسیم کرد:
-
کمبود داده تست
-
نبود Annotation
-
مسائل فرهنگی
#۲ SMILE – «تحلیل ایمنی و Verification/Validation سیستمهای مبتنی بر یادگیری ماشین»
در مطالعه SMILE، ما به سناریوها، معماری و مهمتر از همه به جمعآوری داده (Data Collection) نگاه کردیم. ما به نیازمندیها و مدیریت ODD (Operational Design Domain) پرداختیم. همچنین استانداردهایی مانند ISO 26262 را با استاندارد جدید آن زمان، ISO 21448 (SOTIF) مقایسه کردیم. علاوه بر این، فهرست اتحادیه اروپا برای هوش مصنوعی قابل اعتماد (Trustworthy AI) را ارزیابی کردیم و دیدیم چگونه با استانداردهای ذکرشده مقایسه میشود.
آموختیم که نحوه جمعآوری داده و نحوه تنظیم نیازمندیها اهمیت بسیار زیادی دارد. همانطور که پیشتر بحث شد، جمعآوری داده باید با ODD مرتبط و سازگار باشد.
در این پروژه، بررسی کردیم که چگونه توزیع و ترکیب داده آموزشی باید وقتی یک Corner Case یا رفتار ناخواسته پیدا شد، تکامل یابد / تغییر کند. بسته به مدل و عملکرد شما، ممکن است Retrain کردن لایههای بیرونی مدل کافی باشد. اما در بیشتر موارد، برای اطمینان از اینکه رفتار ناخواسته مدیریت میشود، باید مدل را مجدداً آموزش دهید، و این کار فعالیتهای تست بیشتری را برخواهد انگیخت.
#۳ Valu3s – «Verification و Validation ایمنی و امنیت سیستمهای خودکار»
ما یک پروژه ۳٫۵ ساله تأمین مالیشده توسط اتحادیه اروپا به نام Valu3s انجام دادیم که در آن از شبیهسازها برای تسریع بلوغ عملکرد ML استفاده کردیم. برداشت من این است که اگر میخواهید هر نوع اتوماسیون، جستجوی Corner Case یا تست مبتنی بر سناریو انجام دهید، استفاده از محیط تست شبیهسازیشده حیاتی است.
تصاویر مطرحشده در مقاله نمونههایی از سناریویی هستند که هنگام خودکارسازی تستها از آن استفاده کردیم. تصویر سمت چپ مسیر یک عابر پیاده را که از خیابان عبور میکند نشان میدهد، و تصویر سمت راست خودرویی را نشان میدهد که یک مدل رانندگی خودکار به آن متصل است. با Vectorize کردن سناریو در قالب یک فایل ساختاریافته، شرایط بیرونی را طوری تغییر دادیم که ترکیبهایی پیدا کنیم که باعث میشد خودرو با عابر پیاده برخورد کند. بنابراین، با اتوماسیونی که روی پارامترهای مختلف مانند نور، باران، زمان روز و غیره تکرار میکرد، میتوانیم رفتارهای ناخواسته را پیدا کنیم.
یکی از Use Caseها در Valu3s به نظارت ترافیکی مرتبط بود؛ علاوه بر این، ما روی تشخیص پلاک خودرو (Number Plate Identification) هم کار کردیم. برای تست این مورد، ابزاری مبتنی بر ML توسعه دادیم که پلاک تولید میکند و آنها را در شبیهساز روی خودروها قرار میدهد.
این ابزار، رشتههای متنی معمولی را از یک فایل میگیرد و آنها را به تصاویری تبدیل میکند که در یک سناریوی تعریفشده روی خودروی مشخصی قرار داده میشوند. شبیهساز به ما اجازه میدهد پارامترهای محیطی مورد علاقه را کنترل و تغییر دهیم، و ابزار پلاکساز به ما امکان میدهد هر ترکیب پلاکی که برایمان اهمیت دارد امتحان کنیم. این ابزار همچنین در تست پلاکهای کشورهای دیگر هم کمک میکند.
جمعبندی
ما بهعنوان تستر، مهارت و دیدگاهی نسبت به «خوب» و «بد» داریم که همچنان کاملاً معتبر است. روشهای ما ممکن است تغییر کنند، اما یک نگاه مستقل در ادامه مسیر بسیار ارزشمند خواهد بود. اگر داده، و نه کد، عملکرد را تعریف میکند، تمرکز ما بهعنوان تستر نرمافزار باید به شکلی تازه و جدید به «سمت چپ» (Earlier in the lifecycle) جابهجا شود و طرز فکرمان کمی تغییر کند.
رفع یک باگ یا رفتار ناخواسته، نتیجهاش نسخه جدیدی از تابع شما خواهد بود؛ نه نسخه ۱٫۲، بلکه در عمل یک تابع جدید. من به این نتیجه رسیدم که برای رفع یک باگ، باید مجموعهدادهای را که مدل با آن آموزش میبیند تغییر دهید، نه چند خط کد را.
ما میتوانیم تست توابع ML را با کمی انطباق دادن روشهای سنتی تست نرمافزار، خودکارسازی کنیم. این کار، فاصلهی ورود به تست عملکرد یادگیری ماشین را کوچکتر میکند.
