طبقه بندی commit های رفع اشکال با ML.NET

Summarize this content to 400 words in Persian Lang
این مقاله یک مطالعه موردی در استفاده از ML.NET برای آموزش و انتخاب یک مدل طبقهبندی باینری بهینه برای استفاده در طبقهبندی تعهدات کد بهعنوان مربوط به رفع اشکال یا غیراشکال بر اساس فرادادههای commit آنها است.
این یک نسخه اصلاح شده از گزارش خلاصه نهایی پروژه کارشناسی ارشد من است و بنابراین لحن، سبک و رویکرد کمی متفاوت از نوشته های دیگر من خواهد بود. در صورت امکان، من به سایر مقالات خود در خصوص جزئیات بیشتر مفاهیم پیوند خواهم داد. با این وجود، من معتقدم که شما باید آن را یک مثال جالب از اینکه چرا به نظر من ML.NET یک کتابخانه یادگیری ماشینی موثر است و برخی از کاربردهای خلاقانه Phi-3 LLM برای کمک به پیشنویس مجموعه دادههای آموزشی پیشبازبینی است.
هدف و زمینه پروژه
مهندسان نرم افزار، دانشمندان داده، مهندسان داده و سایر متخصصان فناوری از سیستم های مدیریت کنترل منبع مانند git برای ردیابی تغییرات مخازن کد در طول زمان استفاده می کنند. این تغییرات commit نامیده می شود و مربوط به یک یا چند فایل است و شامل یک یا چند فایل و خط کد است که اصلاح می شود. اغلب اضافه ها و حذف های زیادی در چندین فایل وجود دارد. هر یک از این commit ها حاوی اطلاعاتی در مورد زمان وقوع، چه کسی آن را انجام داده و پیامی که برای توصیف مجموعه کلی تغییرات استفاده کرده اند، است.
برای کمک به تجزیه و تحلیل تاریخچه پایگاه های کد مبتنی بر git، ابزاری به نام GitStractor توسعه داده ام. این پروژه می تواند داده ها را بدون توجه به زبان های برنامه نویسی مورد استفاده از هر مخزن git استخراج کرده و آن داده ها را در مجموعه ای از فایل های CSV ذخیره کند. این فایلهای CSV سپس میتوانند توسط یک دفترچه تجزیه و تحلیل یا ابزار تجسم دادهها برای تجسم ساختار پروژه و نحوه تغییر آن در طول زمان جذب شوند.
GitStractor در توانایی خود در جمعآوری و انتقال بینش از کد مؤثر بوده است، اما قادر به انتقال اطلاعات مهم در مورد کیفیت نرمافزار بدون راهی برای تعیین اینکه آیا یک commit مربوط به رفع اشکال است یا غیرمرتبط با باگ، نبود.
این پروژه برای آموزش چنین مدل طبقهبندی باینری به گونهای وجود دارد که امتیاز F1 مدل حاصل را به حداکثر میرساند و در عین حال دقت بالایی را برای پیشبینیهای رفع اشکال حفظ میکند تا احتمالات مثبت کاذب را که به اشتباه مناطق خوب کد را مشکلدار علامتگذاری میکنند، به حداقل برساند. چنین اشتباهاتی می تواند اعتبار افراد یا تیم ها را به خطر بیندازد.
از آنجایی که GitStractor مبتنی بر دات نت است (بعد از اینکه اجرای اولیه پایتون بسیار کند بود)، مدل ایده آل باید تحت ML.NET یا به عنوان یک مدل بومی ML.NET یا به عنوان یک مدل قابل واردات به ML.NET با استفاده از Open Neural Network eXchange اجرا شود. فرمت ONNX).
آماده سازی داده ها
به منظور آموزش یک مدل نظارت شده برای طبقه بندی تعهدات به عنوان رفع اشکال یا بدون اشکال، من به یک مجموعه داده برچسب دار مناسب با اطلاعات مربوط به تک تک کامیت ها به همراه طبقه بندی آنها به عنوان رفع اشکال یا بدون اشکال نیاز داشتم. متأسفانه، هیچ مجموعه داده مناسبی وجود نداشت، بنابراین من نیاز به ایجاد آن داشتم.
مجموعه داده های پایه
مجموعه داده اولیه کوچکی از تعهدات از مخازن پروژه منبع باز و کوچکتر به عنوان منبع تعهد برای مجموعه آموزشی اولیه انتخاب شد. این تعهدات از مخازن زیر آمده است:
ML.NET – کتابخانه یادگیری ماشین مایکروسافت برای برنامه های دات نت
نوت بوک های Polyglot / .NET Interactive – مجموعه ای از هسته های ادغام شده در نوت بوک های Jupyter که امکان زبان های اضافی مانند C#، F#، PowerShell و SQL را فراهم می کند.
GitStractor – ابزاری که برای استخراج اطلاعات git به فایلهای CSV استفاده میشود (چون البته من ابزار را با خودش آنالیز کردم).
Emergence – یک پروژه ساخت بازی های سرکش علمی تخیلی که زمانی روی آن کار می کردم.
Wherewolf – یک مدل احتمالی از بازی کارتی One Night Ultimate Werewolf که در حال حاضر با توجه به زمان در حال توسعه آن هستم.
هر یک از این مخازن یک مخزن است که تحت مجوز MIT است و نمونه ای از کد عمومی است که من با آن آشنایی شخصی دارم. این آشنایی شخصی به دلیل نحوه ایجاد برچسب های آموزشی مهم بود همانطور که به زودی در مورد آن صحبت خواهیم کرد.
هر commit شامل جزئیات مربوط به هش منحصر به فرد خود (شا)، نویسنده و committer commit (گاهی اوقات ممکن است committer با نویسنده متفاوت باشد و نشان دهنده شخصی است که تغییراتی را توسط نویسنده دیگری انجام داده است)، پیام commit، تعدادی از موارد کاری ذکر شده است. تعداد فایلها و خطوط کد اضافهشده، حذفشده و اصلاحشده، و یک بولی که نشان میدهد آیا commit یک commit ادغام commit از یک شاخه به شاخه دیگر را نشان میدهد.
تولید برچسب های اولیه
یک ستون برچسب به مجموعه داده اضافه شد که نشان می دهد آیا commit یک commit رفع اشکال را نشان می دهد یا خیر. مقدار اولیه این ستون از استفاده از LLamaSharp برای تعامل با یک مدل زبان بزرگ Phi-3 Mini 4k Instruct (LLM) که روی دستگاه روی یک ماشین لینوکس با استفاده از کارت گرافیک RTX 4070 و CUDA 12 اجرا میشود، به دست آمد.
درخواستی که به LLM داده شد به آن دستور داد که یک خروجی JSON شامل پیشبینی و دلیلی برای آن پیشبینی تولید کند. سپس این پاسخ به یک شی تبدیل شد و ستونهای PredictedLabel و Reason به مجموعه داده اضافه شدند.
با تنظیمات بهینه، این تعامل 0.7 ثانیه در هر commit طول کشید، که هنوز برای استفاده در تولید که ممکن است هزاران commit وجود داشته باشد به طور غیرقابل قبولی طولانی بود.
EDA و نمونه گیری داده ها
پس از استخراج دادههای هر 5 مخزن و ایجاد برچسبهای اولیه، از یک نوت بوک برای بارگیری 5 فایل داده جداگانه، ادغام هر یک با برچسبهای پیشبینیشده (ذخیره شده در یک CSV جداگانه برای جلوگیری از بازنویسی فایل منبع) و سپس ادغام استفاده شد. همه 5 حاصل DataFrame اشیاء با هم به صورت یکپارچه واحد DataFrame.
از آنجا، ردیف های حاوی NA مقادیر حذف شدند و از تجزیه و تحلیل داده های اکتشافی برای شناسایی نقاط پرت و همبستگی استفاده شد.
از نظر فایلها و خطوط اضافه/حذف، نقاط پرت شدیدی وجود داشت. با این حال، من ترجیح دادم در مرحله آمادهسازی دادهها به این موارد توجه نکنم، زیرا مقادیر شدید در مخازن دنیای واقعی وجود دارد و مشکل با استفاده از یک تبدیل عادیسازی مانند min/max یا اسکالر استاندارد به عنوان بخشی از خط لوله آموزش مدل بهتر حل میشود. .
برخی از مهندسیهای ویژگی در طول این فرآیند با اضافه شدن ستونهای جدید برای زمان روز، روز هفته و ماه سال صورت گرفت. با این حال، EDA نشان داد که فعالیتها در مخازن در چندین منطقه زمانی رخ میدهند و ما نمیتوانیم زمانهای commit را بدون دانستن منطقه زمانی محلی برای committer به طور دقیق عادی کنیم. در نتیجه، تمام مقادیر مربوط به زمان و تاریخ حذف شدند تا اطمینان حاصل شود که مدل با اختلاف منطقه زمانی مغایرت ندارد.
تمام اطلاعات مربوط به نویسنده و مرتکب نیز حذف شد، زیرا این فیلدها ممکن است برای مدلهایی که برای یک مخزن خاص آموزش داده شدهاند مرتبط باشند، برای یک مدل پیشبینی تعمیمیافته مرتبط نیستند و ممکن است تعصبات ناعادلانهای را علیه افراد نشان دهند.
تجزیه و تحلیل همبستگی برخی از همبستگی ها را نشان داد IsBugFix ستون (ستون برچسب ما)، اما هیچ همبستگی واقعا قوی وجود نداشت که به نظر می رسید احتمالاً یک مدل مناسب را ایجاد کند. استخراج یونیگرام ها و بیگرام ها از پیام به این امر کمک کرد و نشان داد که پردازش زبان طبیعی برای یک مدل با عملکرد خوب بسیار مهم است.
از آنجایی که برچسبهای آموزشی اولیه توسط یک LLM تولید شدهاند، برای استفاده در آموزش مدل بدون بررسی و اصلاح انسانی مناسب نیستند. مجموعه داده کلی شامل 6576 تعهد بود که با توجه به دامنه این پروژه برای بررسی دستی بسیار ممانعت کننده است.
برای پرداختن به این موضوع، با استفاده از یک استراتژی نمونهبرداری طبقهبندی شده نماینده، به 500 تعهد نمونهبرداری کردم که در آن هر مخزن موجود در آزمایش دارای بخش نسبی از تعهدات خود برای انتخاب دادههای آموزشی نهایی بود. این انتخاب بیشتر طبقه بندی شد تا اطمینان حاصل شود که هر مخزن دارای تعداد مساوی از تعهدات رفع اشکال و غیر رفع اشکال از پیش بینی های اولیه است که در اینجا نشان داده شده است:
سپس 500 ردیف در مجموعه داده نهایی به صورت دستی توسط خودم بررسی شد (توجه داشته باشید که من با تمام 5 مخزن آشنا هستم و 20 سال تجربه به عنوان یک مهندس نرم افزار برای واجد شرایط بودن برای انجام این کار دارم) و مقادیر تصحیح شده در ستون Label ذخیره شدند. داشتن حرف اول PredictedLabel ستون و یک اصلاح شد Label ستون برای ارزیابی معیارهای دقت طبقهبندیکننده اولیه برای مقاصد مقایسه مجاز است.
با نصب برچسب های نهایی، تجزیه و تحلیل داده های اکتشافی اضافی بر روی نمونه نهایی انجام شد. نمونه به دست آمده دارای عدم تعادل کلاسی بود که 71 درصد از ردیفها نشاندهنده ارتکاب بدون رفع اشکال بود در حالی که 29 درصد شامل رفع اشکال بود. این عدم تعادل کلاس به این دلیل رخ داد که دقت مثبت Phi-3 LLM پایین بود، که منجر به تعداد بالای مثبت کاذب در نمونه طبقهبندی شد. با این حال، نتایج در حد تحمل بود، با این احتیاط که ممکن است به داده های آموزشی اضافی برای ایجاد بهترین نتایج نیاز باشد.
از همه جنبههای دیگر، توزیعهای مدل نهایی قبل از نمونهبرداری شبیه به مجموعه داده اصلی بود، بنابراین تمام ستونهای غیر ضروری حذف شدند و یک فایل آموزشی نهایی برای آموزش مدل ایجاد شد.
آموزش و ارزیابی مدل
فرآیند آموزش مدل اساساً در یک نوت بوک Polyglot منفرد (هستههای NET اضافه شده به نوتبوکهای Jupyter) با استفاده از ML.NET انجام شد.
این فناوریها کیفیت بالایی دارند، اما فاقد اجزای حیاتی مانند ماتریس سردرگمی گرافیکی و سایر قابلیتهای نمودار هستند. برای پرداختن به این موضوع، من 4 کتابخانه کوچک یادگیری ماشینی را برای این پروژه تحت عنوان عامل ایجاد کردم MattEland.ML، MattEland.ML.Interactive، MattEland.ML.Charting، و MattEland.ML.DataFrame. این کتابخانه ها هنوز برای استفاده عمومی آماده نیستند، اما ممکن است اصلاح شوند و یا به یک پروژه متن باز کامل تبدیل شوند یا ممکن است به دنبال یافتن راهی برای گنجاندن آنها در پروژه اصلی ML.NET باشم.
بله، من واقعاً به اندازه کافی عصبی هستم که برای پشتیبانی از این پروژه از کتابخانه های منبع باز نمونه سازی کردم.
مدل های اولیه ML.NET AutoML
یکی از مزایای ML.NET یک کتابخانه قدرتمند AutoML است که بسیاری از مربیان مدل های مختلف، خطوط لوله مدل و فراپارامترهای مدل را ارزیابی می کند، بنابراین تصمیم گرفتم فرآیند مدل سازی خود را با آن شروع کنم.
مدل های اولیه امتیازات F1 0.65 یا بالاتر را با دقت مثبت بیش از 70 درصد نشان دادند.
توجه: تمام معیارهای این بخش معرف معیارهای تأیید هستند. مدلها با استفاده از اعتبارسنجی متقابل 5 برابری روی 80 درصد دادهها آموزش داده شدند و 20 درصد باقیمانده دادهها به عنوان دادههای تأیید نهایی در مدل انتخاب شده توسط AutoML با استفاده از اعتبارسنجی متقاطع در برابر 80 درصد دادههای آموزشی استفاده شدند.
همانطور که انتظار می رفت، مدل های اولیه در درجه اول درختان سریع و جنگل های سریع، پیاده سازی ML.NET از درختان تصمیم و جنگل های تصادفی بودند.
این مدلهای اولیه AutoML همچنین خطوط لوله آموزشی شامل ورودیهای مقادیر گمشده، تبدیل مقادیر بولی به مقادیر ممیز شناور برای سازگاری ML.NET، تبدیل متن / استخراج n-گرم، و الحاق تمام ستونهای ویژگی به یکدیگر برای پردازش ML.NET ایجاد کردند.
با این حال، این خطوط لوله پردازش متن، مقادیر حساس را از ستون پیام پاک نکردند یا کلمات توقف را حذف نکردند. برای رفع این مشکل، پروژه از AutoML ساده به AutoML با کنترل دستی روی خط لوله منتقل شد. سپس خط لوله پردازش خودم را پیادهسازی کردم که در یک مرحله TextNormalizingTransformer سفارشی اضافه شد.
این خط لوله همه اعداد و آدرسهای اینترنتی در ستون پیام را با مقادیر نگهبان جایگزین کرد. این معیارها را اندکی کاهش داد، اما از تطبیق بیش از حد مدلها بر روی کلمه یا کاراکتر n-gram موجود در URLها یا شمارههای شماره جلوگیری کرد.
از آنجا، خط لوله چندین بار تکرار شد و بر روی هر یک از مدلهای طبقهبندی دودویی رایج ML.NET که توسط AutoML پشتیبانی میشوند، متمرکز شد: جنگل سریع (جنگل تصادفی)، درخت سریع (درخت تصمیم)، افزایش گرادیان LGBM، رگرسیون لجستیک L-BFGS و رگرسیون لجستیک SDCA. به هر مربی مدل 10 تکرار نمونه برای تنظیم هایپرپارامتر داده شد تا بعداً با یکدیگر و مدل های دیگر از پلتفرم های دیگر مقایسه شوند.
سایر مدل های در نظر گرفته شده
علاوه بر مدلهای پایه ML.NET، مدلهای دیگری نیز برای مقایسه مورد ارزیابی قرار گرفتند.
از ML.NET 2.0، ML.NET از طبقه بندی متن با تنظیم دقیق مدل های BERT پشتیبانی می کند. یک مدل روبرتا روی داده های آموزشی به خوبی تنظیم شد، اما این مدل به دلیل فراخوان مثبت تنها 0.25 امتیاز F1 پایین 0.37 داشت.
شش مربی مدل با استفاده از Python و SciKit-Learn نیز با استفاده از جنگل تصادفی، طبقهبندی کننده بردار پشتیبان، NB چندجملهای رگرسیون لجستیک، KNN و الگوریتمهای شبکه عصبی MLP مورد ارزیابی قرار گرفتند. این مدلها به اندازه گزینههای ML.NET من، تنظیم فراپارامتر یا توسعه خط لوله گسترده نداشتند، اما آزمایش در پایتون برای پرچمگذاری مدلهای بالقوهای که با استفاده از ML.NET در نظر گرفته نشدهاند مورد استفاده قرار گرفت (مدلهای ML.NET و SciKit-Learn عموماً قابل مقایسه هستند. در کیفیت مدل خروجی آنها، زیرا ریاضیات اساسی یکسان است). اگر مدلی با دقت بالا کشف شد که از صادرات ONNX پشتیبانی می کرد، ممکن است برای مدل نهایی در نظر گرفته شود. متاسفانه هیچ کدام کشف نشد.
Phi-3 LLM اولیه نیز باید برای بررسی در اینجا ذکر شود. در حالی که این مدل امتیاز F1 0.71 داشت، دقت مثبت آن تنها 56 درصد بود.
در نهایت، Azure Machine Learning API AutomatedML برای آموزش یک جفت مدل مورد استفاده قرار گرفت – یکی با استفاده از طبقهبندی استاندارد باینری و دیگری با فعال کردن یادگیری عمیق. هر دو مدل از روشهای مجموعه شامل جنگلهای تصادفی و مدلهای XGBoost استفاده میکردند، اما امتیاز F1 در حدود 0.58 داشتند که باعث میشد نسبت به مدلهای ML.NET کمتر قابل دوام باشند.
تنظیم فراپارامتر مدل نهایی
با توجه به مشاهدات آزمایشهای اولیه مختلف، مجموعهای از مدلهای نهایی با استفاده از ML.NET برای تنظیم فراپارامتر هدفمند حول محدودهای از مقادیر هدفمند با استفاده از الگوریتم تیونر هزینه مقرون به صرفه ECI که برای اکتشاف تنظیم ابرپارامتر سلسله مراتبی با هدف به حداقل رساندن محاسبات ساخته شده است، آموزش داده شد. الزامات این تلاشهای آموزشی همچنین زمان محاسباتی بیشتری را به آزمایش تنظیم برای بهینهسازی مدل انتخابی اختصاص داد.
این آزمایش با استفاده از یک جنگل سریع، یک مدل تقویتشده با گرادیان نور، رگرسیون لجستیک ساده، یک ماشین فاکتورسازی آگاه از میدان، SVM یادگیری عمیق محلی مایکروسافت، یک پرسپترون متوسط و یک SVM خطی انجام شد. معیارهای مدل نهایی در اینجا ذکر شده است:
انتخاب مدل نهایی بین مدلهای جنگل سریع، GBM سبک و رگرسیون لجستیک نزدیک بود. در این تصمیم مدلها با امتیاز F1، دقت مثبت، و ارزیابی اهمیت ویژگیهای جایگشت و تنظیمات فراپارامتر آنها مورد ارزیابی قرار گرفتند.
جنگل تصادفی از 3 درخت با حداکثر 10 برگ استفاده کرد و آموزش خود را به استفاده از 72 درصد از ویژگی ها برای تشکیل درخت محدود کرد. به نظر می رسد مرتبط ترین فاکتورهای PFI آن، همگی بیگرام های کاراکتر یا سه گانه های مرتبط با رشته های فرعی هستند که در کلماتی مانند “رفع” یا “مسئله”. به نظر نمیرسد مدل برای ویژگیهای ستونهای غیر پیام ارزشی قائل باشد.
مدل سبک GBM دارای تنظیمات مشابه با جنگل تصادفی با استفاده از نرخ یادگیری 0.5 بود. مانند جنگل تصادفی، در درجه اول به دنبال رشته های کاراکتر بود، اما رشته ها معنای کمتری داشتند. علاوه بر این، آموزش این مدل به طور قابل توجهی بیشتر طول کشید و احتمالاً در طول تمرین با داده های اضافی به خوبی مقیاس نمی شود.
مدل رگرسیون لجستیک دارای مقدار تنظیم L1 0.08 و تنظیم L2 0.0003 بود. این مدل تعداد کلمات را ارزشمند میدانست، به دنبال کلماتی مانند fix، bad و update میگشت و بررسی میکرد که آیا این تغییر شامل فایلهای جدیدی میشود یا خیر. در حالی که عملکرد آن کمی بدتر از جنگل تصادفی بود، این مدل ممکن است به احتمال زیاد به خوبی بر روی داده های مخازن خارج از 5 مورد استفاده شده برای آموزش تعمیم دهد. با این حال، دقت مثبت آن 8٪ بدتر است و امتیاز F1 نیز 0.7 پایین تر است.
خوشبختانه، رگرسیون لجستیک در ML.NET یک مدل کالیبره شده است در حالی که جنگل های تصادفی غیر کالیبره شده هستند. این به این معنی است که رگرسیون لجستیک هم یک برچسب پیشبینیشده و هم احتمالی را ارائه میکند که 1 به طور قطع رفع اشکال است و 0 مطمئناً بدون اشکال است.
نه تنها این احتمال یک نقطه داده اضافی برای گنجاندن بالقوه در تصاویر GitStractor است، بلکه به من این امکان را میدهد تا آستانهای برای پیشبینیها برای بهبود بیشتر دقت مدل تعیین کنم. اگرچه من هنوز نمودار منحنی فراخوانی دقیق را برای ML.NET پیادهسازی نکردهام، شما با افزایش آستانه طبقهبندی مثبت، همان منحنی فراخوانی دقیق را دنبال میکنید. سپس دقت مثبت مدل را بهبود می بخشد در حالی که یادآوری مثبت مدل را کاهش می دهد.
استقرار مدل
سه بهترین مدل شناسایی شده در طول آموزش در فایلهای zip. ذخیره شدند (فرمت فایل انتخابی ML.NET) و سپس مدل رگرسیون لجستیک در GitStractor جاسازی شد.
سپس من یک ناظر جدید git commit را پیادهسازی کردم که اطلاعات commit خام را به قالب ورودی مورد انتظار مدل تبدیل کرد و هدف خروجی من را متشکل از برچسب و احتمال پیشبینیشده تعریف کرد.
این به GitStractor اجازه میدهد تا commitهای دریافتی را در زمان واقعی طبقهبندی کند و برچسب پیشبینیشده و احتمال آن را در فایل CSV تولید شده برای تجزیه و تحلیل بعدی سریال کند.
از آنجایی که رگرسیون لجستیک نسبتاً سریع و ساده است، اطمینان دارم که دادههای آموزشی خود را بیش از حد برازش نکردهام. علاوه بر این، عملکرد آن به من اجازه میدهد تا کل مخازن commitهای git را در زمانی که دستورالعمل Phi-3 mini 4k LLM برای طبقهبندی چندین commit قبلاً صرف کرده بود، طبقهبندی کنم. علاوه بر این، دلیلی دارم که باور کنم در صورت نیاز میتوانم این فرآیند استخراج را موازیسازی کنم، زیرا ML.NET به من اجازه میدهد از یک Thread-Safe عملکردی استفاده کنم. PredictionEnginePool کلاس
در حالی که من هنوز در ابتدای تجزیه و تحلیل داده های خروجی و کالیبراسیون بهترین برش پیش بینی برای استفاده برای این مدل هستم، در حال حاضر شروع به دیدن ارزش مدل در شناسایی مناطقی از کد که نیاز به اصلاح یا آزمایش اضافی دارند، کرده ام.
نتیجه گیری
من این پروژه را در رابطه با کاوش در اعماق یادگیری ماشین، توسعه گردشهای کاری حول آموزش مدلهای ML.NET در نوتبوکهای Polyglot، و آموزش یک طبقهبندی کننده باینری موثر برای پیشبینیهای رفع اشکال، موفقیتآمیز میدانم.
امیدوارم در آینده این ابزار GitStractor را گسترش دهم، اما اگر جنبه خاصی از این پروژه برای شما جالب است، لطفاً به من اطلاع دهید و جزئیات بیشتری را ارائه خواهم کرد.
در نهایت، در یک یادداشت شخصی، من کاملاً مفتخرم که فناوریهای داتنت مورد علاقهام بخشی از تلاشهای تحقیقاتی من و مدرک کارشناسی ارشد در تجزیه و تحلیل دادهها بوده است.
این مقاله یک مطالعه موردی در استفاده از ML.NET برای آموزش و انتخاب یک مدل طبقهبندی باینری بهینه برای استفاده در طبقهبندی تعهدات کد بهعنوان مربوط به رفع اشکال یا غیراشکال بر اساس فرادادههای commit آنها است.
این یک نسخه اصلاح شده از گزارش خلاصه نهایی پروژه کارشناسی ارشد من است و بنابراین لحن، سبک و رویکرد کمی متفاوت از نوشته های دیگر من خواهد بود. در صورت امکان، من به سایر مقالات خود در خصوص جزئیات بیشتر مفاهیم پیوند خواهم داد. با این وجود، من معتقدم که شما باید آن را یک مثال جالب از اینکه چرا به نظر من ML.NET یک کتابخانه یادگیری ماشینی موثر است و برخی از کاربردهای خلاقانه Phi-3 LLM برای کمک به پیشنویس مجموعه دادههای آموزشی پیشبازبینی است.
https://www.youtube.com/watch?v=rcVSkUgipc0
هدف و زمینه پروژه
مهندسان نرم افزار، دانشمندان داده، مهندسان داده و سایر متخصصان فناوری از سیستم های مدیریت کنترل منبع مانند git برای ردیابی تغییرات مخازن کد در طول زمان استفاده می کنند. این تغییرات commit نامیده می شود و مربوط به یک یا چند فایل است و شامل یک یا چند فایل و خط کد است که اصلاح می شود. اغلب اضافه ها و حذف های زیادی در چندین فایل وجود دارد. هر یک از این commit ها حاوی اطلاعاتی در مورد زمان وقوع، چه کسی آن را انجام داده و پیامی که برای توصیف مجموعه کلی تغییرات استفاده کرده اند، است.
برای کمک به تجزیه و تحلیل تاریخچه پایگاه های کد مبتنی بر git، ابزاری به نام GitStractor توسعه داده ام. این پروژه می تواند داده ها را بدون توجه به زبان های برنامه نویسی مورد استفاده از هر مخزن git استخراج کرده و آن داده ها را در مجموعه ای از فایل های CSV ذخیره کند. این فایلهای CSV سپس میتوانند توسط یک دفترچه تجزیه و تحلیل یا ابزار تجسم دادهها برای تجسم ساختار پروژه و نحوه تغییر آن در طول زمان جذب شوند.
GitStractor در توانایی خود در جمعآوری و انتقال بینش از کد مؤثر بوده است، اما قادر به انتقال اطلاعات مهم در مورد کیفیت نرمافزار بدون راهی برای تعیین اینکه آیا یک commit مربوط به رفع اشکال است یا غیرمرتبط با باگ، نبود.
این پروژه برای آموزش چنین مدل طبقهبندی باینری به گونهای وجود دارد که امتیاز F1 مدل حاصل را به حداکثر میرساند و در عین حال دقت بالایی را برای پیشبینیهای رفع اشکال حفظ میکند تا احتمالات مثبت کاذب را که به اشتباه مناطق خوب کد را مشکلدار علامتگذاری میکنند، به حداقل برساند. چنین اشتباهاتی می تواند اعتبار افراد یا تیم ها را به خطر بیندازد.
از آنجایی که GitStractor مبتنی بر دات نت است (بعد از اینکه اجرای اولیه پایتون بسیار کند بود)، مدل ایده آل باید تحت ML.NET یا به عنوان یک مدل بومی ML.NET یا به عنوان یک مدل قابل واردات به ML.NET با استفاده از Open Neural Network eXchange اجرا شود. فرمت ONNX).
آماده سازی داده ها
به منظور آموزش یک مدل نظارت شده برای طبقه بندی تعهدات به عنوان رفع اشکال یا بدون اشکال، من به یک مجموعه داده برچسب دار مناسب با اطلاعات مربوط به تک تک کامیت ها به همراه طبقه بندی آنها به عنوان رفع اشکال یا بدون اشکال نیاز داشتم. متأسفانه، هیچ مجموعه داده مناسبی وجود نداشت، بنابراین من نیاز به ایجاد آن داشتم.
مجموعه داده های پایه
مجموعه داده اولیه کوچکی از تعهدات از مخازن پروژه منبع باز و کوچکتر به عنوان منبع تعهد برای مجموعه آموزشی اولیه انتخاب شد. این تعهدات از مخازن زیر آمده است:
-
ML.NET – کتابخانه یادگیری ماشین مایکروسافت برای برنامه های دات نت
-
نوت بوک های Polyglot / .NET Interactive – مجموعه ای از هسته های ادغام شده در نوت بوک های Jupyter که امکان زبان های اضافی مانند C#، F#، PowerShell و SQL را فراهم می کند.
-
GitStractor – ابزاری که برای استخراج اطلاعات git به فایلهای CSV استفاده میشود (چون البته من ابزار را با خودش آنالیز کردم).
-
Emergence – یک پروژه ساخت بازی های سرکش علمی تخیلی که زمانی روی آن کار می کردم.
-
Wherewolf – یک مدل احتمالی از بازی کارتی One Night Ultimate Werewolf که در حال حاضر با توجه به زمان در حال توسعه آن هستم.
هر یک از این مخازن یک مخزن است که تحت مجوز MIT است و نمونه ای از کد عمومی است که من با آن آشنایی شخصی دارم. این آشنایی شخصی به دلیل نحوه ایجاد برچسب های آموزشی مهم بود همانطور که به زودی در مورد آن صحبت خواهیم کرد.
هر commit شامل جزئیات مربوط به هش منحصر به فرد خود (شا)، نویسنده و committer commit (گاهی اوقات ممکن است committer با نویسنده متفاوت باشد و نشان دهنده شخصی است که تغییراتی را توسط نویسنده دیگری انجام داده است)، پیام commit، تعدادی از موارد کاری ذکر شده است. تعداد فایلها و خطوط کد اضافهشده، حذفشده و اصلاحشده، و یک بولی که نشان میدهد آیا commit یک commit ادغام commit از یک شاخه به شاخه دیگر را نشان میدهد.
تولید برچسب های اولیه
یک ستون برچسب به مجموعه داده اضافه شد که نشان می دهد آیا commit یک commit رفع اشکال را نشان می دهد یا خیر. مقدار اولیه این ستون از استفاده از LLamaSharp برای تعامل با یک مدل زبان بزرگ Phi-3 Mini 4k Instruct (LLM) که روی دستگاه روی یک ماشین لینوکس با استفاده از کارت گرافیک RTX 4070 و CUDA 12 اجرا میشود، به دست آمد.
درخواستی که به LLM داده شد به آن دستور داد که یک خروجی JSON شامل پیشبینی و دلیلی برای آن پیشبینی تولید کند. سپس این پاسخ به یک شی تبدیل شد و ستونهای PredictedLabel و Reason به مجموعه داده اضافه شدند.
با تنظیمات بهینه، این تعامل 0.7 ثانیه در هر commit طول کشید، که هنوز برای استفاده در تولید که ممکن است هزاران commit وجود داشته باشد به طور غیرقابل قبولی طولانی بود.
EDA و نمونه گیری داده ها
پس از استخراج دادههای هر 5 مخزن و ایجاد برچسبهای اولیه، از یک نوت بوک برای بارگیری 5 فایل داده جداگانه، ادغام هر یک با برچسبهای پیشبینیشده (ذخیره شده در یک CSV جداگانه برای جلوگیری از بازنویسی فایل منبع) و سپس ادغام استفاده شد. همه 5 حاصل DataFrame
اشیاء با هم به صورت یکپارچه واحد DataFrame
.
از آنجا، ردیف های حاوی NA
مقادیر حذف شدند و از تجزیه و تحلیل داده های اکتشافی برای شناسایی نقاط پرت و همبستگی استفاده شد.
از نظر فایلها و خطوط اضافه/حذف، نقاط پرت شدیدی وجود داشت. با این حال، من ترجیح دادم در مرحله آمادهسازی دادهها به این موارد توجه نکنم، زیرا مقادیر شدید در مخازن دنیای واقعی وجود دارد و مشکل با استفاده از یک تبدیل عادیسازی مانند min/max یا اسکالر استاندارد به عنوان بخشی از خط لوله آموزش مدل بهتر حل میشود. .
برخی از مهندسیهای ویژگی در طول این فرآیند با اضافه شدن ستونهای جدید برای زمان روز، روز هفته و ماه سال صورت گرفت. با این حال، EDA نشان داد که فعالیتها در مخازن در چندین منطقه زمانی رخ میدهند و ما نمیتوانیم زمانهای commit را بدون دانستن منطقه زمانی محلی برای committer به طور دقیق عادی کنیم. در نتیجه، تمام مقادیر مربوط به زمان و تاریخ حذف شدند تا اطمینان حاصل شود که مدل با اختلاف منطقه زمانی مغایرت ندارد.
تمام اطلاعات مربوط به نویسنده و مرتکب نیز حذف شد، زیرا این فیلدها ممکن است برای مدلهایی که برای یک مخزن خاص آموزش داده شدهاند مرتبط باشند، برای یک مدل پیشبینی تعمیمیافته مرتبط نیستند و ممکن است تعصبات ناعادلانهای را علیه افراد نشان دهند.
تجزیه و تحلیل همبستگی برخی از همبستگی ها را نشان داد IsBugFix
ستون (ستون برچسب ما)، اما هیچ همبستگی واقعا قوی وجود نداشت که به نظر می رسید احتمالاً یک مدل مناسب را ایجاد کند. استخراج یونیگرام ها و بیگرام ها از پیام به این امر کمک کرد و نشان داد که پردازش زبان طبیعی برای یک مدل با عملکرد خوب بسیار مهم است.
از آنجایی که برچسبهای آموزشی اولیه توسط یک LLM تولید شدهاند، برای استفاده در آموزش مدل بدون بررسی و اصلاح انسانی مناسب نیستند. مجموعه داده کلی شامل 6576 تعهد بود که با توجه به دامنه این پروژه برای بررسی دستی بسیار ممانعت کننده است.
برای پرداختن به این موضوع، با استفاده از یک استراتژی نمونهبرداری طبقهبندی شده نماینده، به 500 تعهد نمونهبرداری کردم که در آن هر مخزن موجود در آزمایش دارای بخش نسبی از تعهدات خود برای انتخاب دادههای آموزشی نهایی بود. این انتخاب بیشتر طبقه بندی شد تا اطمینان حاصل شود که هر مخزن دارای تعداد مساوی از تعهدات رفع اشکال و غیر رفع اشکال از پیش بینی های اولیه است که در اینجا نشان داده شده است:
سپس 500 ردیف در مجموعه داده نهایی به صورت دستی توسط خودم بررسی شد (توجه داشته باشید که من با تمام 5 مخزن آشنا هستم و 20 سال تجربه به عنوان یک مهندس نرم افزار برای واجد شرایط بودن برای انجام این کار دارم) و مقادیر تصحیح شده در ستون Label ذخیره شدند. داشتن حرف اول PredictedLabel
ستون و یک اصلاح شد Label
ستون برای ارزیابی معیارهای دقت طبقهبندیکننده اولیه برای مقاصد مقایسه مجاز است.
با نصب برچسب های نهایی، تجزیه و تحلیل داده های اکتشافی اضافی بر روی نمونه نهایی انجام شد. نمونه به دست آمده دارای عدم تعادل کلاسی بود که 71 درصد از ردیفها نشاندهنده ارتکاب بدون رفع اشکال بود در حالی که 29 درصد شامل رفع اشکال بود. این عدم تعادل کلاس به این دلیل رخ داد که دقت مثبت Phi-3 LLM پایین بود، که منجر به تعداد بالای مثبت کاذب در نمونه طبقهبندی شد. با این حال، نتایج در حد تحمل بود، با این احتیاط که ممکن است به داده های آموزشی اضافی برای ایجاد بهترین نتایج نیاز باشد.
از همه جنبههای دیگر، توزیعهای مدل نهایی قبل از نمونهبرداری شبیه به مجموعه داده اصلی بود، بنابراین تمام ستونهای غیر ضروری حذف شدند و یک فایل آموزشی نهایی برای آموزش مدل ایجاد شد.
آموزش و ارزیابی مدل
فرآیند آموزش مدل اساساً در یک نوت بوک Polyglot منفرد (هستههای NET اضافه شده به نوتبوکهای Jupyter) با استفاده از ML.NET انجام شد.
این فناوریها کیفیت بالایی دارند، اما فاقد اجزای حیاتی مانند ماتریس سردرگمی گرافیکی و سایر قابلیتهای نمودار هستند. برای پرداختن به این موضوع، من 4 کتابخانه کوچک یادگیری ماشینی را برای این پروژه تحت عنوان عامل ایجاد کردم MattEland.ML
، MattEland.ML.Interactive
، MattEland.ML.Charting
، و MattEland.ML.DataFrame
. این کتابخانه ها هنوز برای استفاده عمومی آماده نیستند، اما ممکن است اصلاح شوند و یا به یک پروژه متن باز کامل تبدیل شوند یا ممکن است به دنبال یافتن راهی برای گنجاندن آنها در پروژه اصلی ML.NET باشم.
بله، من واقعاً به اندازه کافی عصبی هستم که برای پشتیبانی از این پروژه از کتابخانه های منبع باز نمونه سازی کردم.
مدل های اولیه ML.NET AutoML
یکی از مزایای ML.NET یک کتابخانه قدرتمند AutoML است که بسیاری از مربیان مدل های مختلف، خطوط لوله مدل و فراپارامترهای مدل را ارزیابی می کند، بنابراین تصمیم گرفتم فرآیند مدل سازی خود را با آن شروع کنم.
مدل های اولیه امتیازات F1 0.65 یا بالاتر را با دقت مثبت بیش از 70 درصد نشان دادند.
توجه: تمام معیارهای این بخش معرف معیارهای تأیید هستند. مدلها با استفاده از اعتبارسنجی متقابل 5 برابری روی 80 درصد دادهها آموزش داده شدند و 20 درصد باقیمانده دادهها به عنوان دادههای تأیید نهایی در مدل انتخاب شده توسط AutoML با استفاده از اعتبارسنجی متقاطع در برابر 80 درصد دادههای آموزشی استفاده شدند.
همانطور که انتظار می رفت، مدل های اولیه در درجه اول درختان سریع و جنگل های سریع، پیاده سازی ML.NET از درختان تصمیم و جنگل های تصادفی بودند.
این مدلهای اولیه AutoML همچنین خطوط لوله آموزشی شامل ورودیهای مقادیر گمشده، تبدیل مقادیر بولی به مقادیر ممیز شناور برای سازگاری ML.NET، تبدیل متن / استخراج n-گرم، و الحاق تمام ستونهای ویژگی به یکدیگر برای پردازش ML.NET ایجاد کردند.
با این حال، این خطوط لوله پردازش متن، مقادیر حساس را از ستون پیام پاک نکردند یا کلمات توقف را حذف نکردند. برای رفع این مشکل، پروژه از AutoML ساده به AutoML با کنترل دستی روی خط لوله منتقل شد. سپس خط لوله پردازش خودم را پیادهسازی کردم که در یک مرحله TextNormalizingTransformer سفارشی اضافه شد.
این خط لوله همه اعداد و آدرسهای اینترنتی در ستون پیام را با مقادیر نگهبان جایگزین کرد. این معیارها را اندکی کاهش داد، اما از تطبیق بیش از حد مدلها بر روی کلمه یا کاراکتر n-gram موجود در URLها یا شمارههای شماره جلوگیری کرد.
از آنجا، خط لوله چندین بار تکرار شد و بر روی هر یک از مدلهای طبقهبندی دودویی رایج ML.NET که توسط AutoML پشتیبانی میشوند، متمرکز شد: جنگل سریع (جنگل تصادفی)، درخت سریع (درخت تصمیم)، افزایش گرادیان LGBM، رگرسیون لجستیک L-BFGS و رگرسیون لجستیک SDCA. به هر مربی مدل 10 تکرار نمونه برای تنظیم هایپرپارامتر داده شد تا بعداً با یکدیگر و مدل های دیگر از پلتفرم های دیگر مقایسه شوند.
سایر مدل های در نظر گرفته شده
علاوه بر مدلهای پایه ML.NET، مدلهای دیگری نیز برای مقایسه مورد ارزیابی قرار گرفتند.
از ML.NET 2.0، ML.NET از طبقه بندی متن با تنظیم دقیق مدل های BERT پشتیبانی می کند. یک مدل روبرتا روی داده های آموزشی به خوبی تنظیم شد، اما این مدل به دلیل فراخوان مثبت تنها 0.25 امتیاز F1 پایین 0.37 داشت.
شش مربی مدل با استفاده از Python و SciKit-Learn نیز با استفاده از جنگل تصادفی، طبقهبندی کننده بردار پشتیبان، NB چندجملهای رگرسیون لجستیک، KNN و الگوریتمهای شبکه عصبی MLP مورد ارزیابی قرار گرفتند. این مدلها به اندازه گزینههای ML.NET من، تنظیم فراپارامتر یا توسعه خط لوله گسترده نداشتند، اما آزمایش در پایتون برای پرچمگذاری مدلهای بالقوهای که با استفاده از ML.NET در نظر گرفته نشدهاند مورد استفاده قرار گرفت (مدلهای ML.NET و SciKit-Learn عموماً قابل مقایسه هستند. در کیفیت مدل خروجی آنها، زیرا ریاضیات اساسی یکسان است). اگر مدلی با دقت بالا کشف شد که از صادرات ONNX پشتیبانی می کرد، ممکن است برای مدل نهایی در نظر گرفته شود. متاسفانه هیچ کدام کشف نشد.
Phi-3 LLM اولیه نیز باید برای بررسی در اینجا ذکر شود. در حالی که این مدل امتیاز F1 0.71 داشت، دقت مثبت آن تنها 56 درصد بود.
در نهایت، Azure Machine Learning API AutomatedML برای آموزش یک جفت مدل مورد استفاده قرار گرفت – یکی با استفاده از طبقهبندی استاندارد باینری و دیگری با فعال کردن یادگیری عمیق. هر دو مدل از روشهای مجموعه شامل جنگلهای تصادفی و مدلهای XGBoost استفاده میکردند، اما امتیاز F1 در حدود 0.58 داشتند که باعث میشد نسبت به مدلهای ML.NET کمتر قابل دوام باشند.
تنظیم فراپارامتر مدل نهایی
با توجه به مشاهدات آزمایشهای اولیه مختلف، مجموعهای از مدلهای نهایی با استفاده از ML.NET برای تنظیم فراپارامتر هدفمند حول محدودهای از مقادیر هدفمند با استفاده از الگوریتم تیونر هزینه مقرون به صرفه ECI که برای اکتشاف تنظیم ابرپارامتر سلسله مراتبی با هدف به حداقل رساندن محاسبات ساخته شده است، آموزش داده شد. الزامات این تلاشهای آموزشی همچنین زمان محاسباتی بیشتری را به آزمایش تنظیم برای بهینهسازی مدل انتخابی اختصاص داد.
این آزمایش با استفاده از یک جنگل سریع، یک مدل تقویتشده با گرادیان نور، رگرسیون لجستیک ساده، یک ماشین فاکتورسازی آگاه از میدان، SVM یادگیری عمیق محلی مایکروسافت، یک پرسپترون متوسط و یک SVM خطی انجام شد. معیارهای مدل نهایی در اینجا ذکر شده است:
انتخاب مدل نهایی بین مدلهای جنگل سریع، GBM سبک و رگرسیون لجستیک نزدیک بود. در این تصمیم مدلها با امتیاز F1، دقت مثبت، و ارزیابی اهمیت ویژگیهای جایگشت و تنظیمات فراپارامتر آنها مورد ارزیابی قرار گرفتند.
جنگل تصادفی از 3 درخت با حداکثر 10 برگ استفاده کرد و آموزش خود را به استفاده از 72 درصد از ویژگی ها برای تشکیل درخت محدود کرد. به نظر می رسد مرتبط ترین فاکتورهای PFI آن، همگی بیگرام های کاراکتر یا سه گانه های مرتبط با رشته های فرعی هستند که در کلماتی مانند “رفع” یا “مسئله”. به نظر نمیرسد مدل برای ویژگیهای ستونهای غیر پیام ارزشی قائل باشد.
مدل سبک GBM دارای تنظیمات مشابه با جنگل تصادفی با استفاده از نرخ یادگیری 0.5 بود. مانند جنگل تصادفی، در درجه اول به دنبال رشته های کاراکتر بود، اما رشته ها معنای کمتری داشتند. علاوه بر این، آموزش این مدل به طور قابل توجهی بیشتر طول کشید و احتمالاً در طول تمرین با داده های اضافی به خوبی مقیاس نمی شود.
مدل رگرسیون لجستیک دارای مقدار تنظیم L1 0.08 و تنظیم L2 0.0003 بود. این مدل تعداد کلمات را ارزشمند میدانست، به دنبال کلماتی مانند fix، bad و update میگشت و بررسی میکرد که آیا این تغییر شامل فایلهای جدیدی میشود یا خیر. در حالی که عملکرد آن کمی بدتر از جنگل تصادفی بود، این مدل ممکن است به احتمال زیاد به خوبی بر روی داده های مخازن خارج از 5 مورد استفاده شده برای آموزش تعمیم دهد. با این حال، دقت مثبت آن 8٪ بدتر است و امتیاز F1 نیز 0.7 پایین تر است.
خوشبختانه، رگرسیون لجستیک در ML.NET یک مدل کالیبره شده است در حالی که جنگل های تصادفی غیر کالیبره شده هستند. این به این معنی است که رگرسیون لجستیک هم یک برچسب پیشبینیشده و هم احتمالی را ارائه میکند که 1 به طور قطع رفع اشکال است و 0 مطمئناً بدون اشکال است.
نه تنها این احتمال یک نقطه داده اضافی برای گنجاندن بالقوه در تصاویر GitStractor است، بلکه به من این امکان را میدهد تا آستانهای برای پیشبینیها برای بهبود بیشتر دقت مدل تعیین کنم. اگرچه من هنوز نمودار منحنی فراخوانی دقیق را برای ML.NET پیادهسازی نکردهام، شما با افزایش آستانه طبقهبندی مثبت، همان منحنی فراخوانی دقیق را دنبال میکنید. سپس دقت مثبت مدل را بهبود می بخشد در حالی که یادآوری مثبت مدل را کاهش می دهد.
استقرار مدل
سه بهترین مدل شناسایی شده در طول آموزش در فایلهای zip. ذخیره شدند (فرمت فایل انتخابی ML.NET) و سپس مدل رگرسیون لجستیک در GitStractor جاسازی شد.
سپس من یک ناظر جدید git commit را پیادهسازی کردم که اطلاعات commit خام را به قالب ورودی مورد انتظار مدل تبدیل کرد و هدف خروجی من را متشکل از برچسب و احتمال پیشبینیشده تعریف کرد.
این به GitStractor اجازه میدهد تا commitهای دریافتی را در زمان واقعی طبقهبندی کند و برچسب پیشبینیشده و احتمال آن را در فایل CSV تولید شده برای تجزیه و تحلیل بعدی سریال کند.
از آنجایی که رگرسیون لجستیک نسبتاً سریع و ساده است، اطمینان دارم که دادههای آموزشی خود را بیش از حد برازش نکردهام. علاوه بر این، عملکرد آن به من اجازه میدهد تا کل مخازن commitهای git را در زمانی که دستورالعمل Phi-3 mini 4k LLM برای طبقهبندی چندین commit قبلاً صرف کرده بود، طبقهبندی کنم. علاوه بر این، دلیلی دارم که باور کنم در صورت نیاز میتوانم این فرآیند استخراج را موازیسازی کنم، زیرا ML.NET به من اجازه میدهد از یک Thread-Safe عملکردی استفاده کنم. PredictionEnginePool
کلاس
در حالی که من هنوز در ابتدای تجزیه و تحلیل داده های خروجی و کالیبراسیون بهترین برش پیش بینی برای استفاده برای این مدل هستم، در حال حاضر شروع به دیدن ارزش مدل در شناسایی مناطقی از کد که نیاز به اصلاح یا آزمایش اضافی دارند، کرده ام.
نتیجه گیری
من این پروژه را در رابطه با کاوش در اعماق یادگیری ماشین، توسعه گردشهای کاری حول آموزش مدلهای ML.NET در نوتبوکهای Polyglot، و آموزش یک طبقهبندی کننده باینری موثر برای پیشبینیهای رفع اشکال، موفقیتآمیز میدانم.
امیدوارم در آینده این ابزار GitStractor را گسترش دهم، اما اگر جنبه خاصی از این پروژه برای شما جالب است، لطفاً به من اطلاع دهید و جزئیات بیشتری را ارائه خواهم کرد.
در نهایت، در یک یادداشت شخصی، من کاملاً مفتخرم که فناوریهای داتنت مورد علاقهام بخشی از تلاشهای تحقیقاتی من و مدرک کارشناسی ارشد در تجزیه و تحلیل دادهها بوده است.