نظرات مطالب
نگاهی به Latent Semantic Indexing
سلام
ممنون از مقاله جالبتون
آیا برنامه پیاده سازی شده ای هم وجود داره؟
نسخه ایرانی یا خارجی؟
نظرات مطالب
پر کردن مقادیر Enum در کلاینت
موضوع این مقاله درباره Enum است و نه ارسال داده‌های کلی به کلاینت. پس آیا فکر میکنید در اینجا چیزی برای اسکیپ شدن وجود داره؟
نظرات مطالب
KnockoutJs #5
با سلام و تشکر از مطالب مفیدی که تو سایت قرار میدید
من یه پروژه case study رو چند روزی هست که شروع کردم و بدون مشکل کارم رو ادامه میدادم تااینکه به ویو ویرایش مشخصات افراد رسیدم.
سه تا از فیلدهای مربوط به افراد شامل کشور، استان و شهر میشه که تو View مربوط به افراد جدید این سه تا DropDownList با استفاده از Knockout پر میشن. بطوری که DropDownList‌های مربوط به استان و شهر خالی هستند و با انتخاب کشور، استان پر میشه و با انتخاب استان، شهر پر میشه.
مشکل اینجاست که تو View ویرایش DropDownList‌های استان و شهر در بارگذاری اولیه فرم پر نمیشن ولی با تغییر مقادیر کشور، استانها در DropDownList خودش پر میشه و این کار برای شهر هم به خوبی انجام میشه.
حالا میخام ببینم که چطور میشه این مشکل رو حل کرد 
مطالب
آموزش فایرباگ - #4 - JavaScript Development
در قسمت قبل با توابع خط فرمان آشنا شدیم . در این قسمت با توابع کنسول آشنا خواهیم شد .

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

بعضی از این متدها عملکردی مشابه متدهای خط فرمان ( که در قسمت قبل شرح داده شدند ، ) دارند که از توضیح مجدد آن‌ها اجتناب می‌کنیم .

توابع کنسول - Console API :

توجه : همانند قسمت قبل ، در این قسمت هم برای همراه شدن با تست‌ها ، کد صفحه‌ی زیر را ذخیره کنید و برای اجرای کدها ، آن‌ها را در قسمت خط فرمان ( در تب کنسول ) قرار بدهید و دکمه‌ی Run ( یا Ctrl + Enter ) را بزنید .
<input type="button" onclick="startTrace('Some Text')" value="startTrace" />
<input type="button" onclick="startError()" value="test Error" />

<script type="text/javascript">
    function startTrace(str) {
        return method1(100, 200);
    }
    function method1(arg1, arg2) {
        return method2(arg1 + arg2 + 100);
    }
    function method2(arg1) {
        var var1 = arg1 / 100;
        return method3(var1);
    }
    function method3(arg1) {
        console.trace();
        var total = arg1 * 100;
        return total;
    }

    function testCount() {
        // do something
        console.count("testCount() Calls Count .");
    }

    function startError() {
        testError();
    }

    function testError() {
        var errorObj = new Error();
        errorObj.message = "this is a test error";
        console.exception(errorObj);
    }

    function testFunc() {
        var t = 0;
        for (var i = 0; i < 100; i++) {
            t += i;
        }
    }
</script>
  • console.log(object[,object,...])

    این دستور یک پیغام در کنسول چاپ می‌کند .
    console.log("This is a log message!");
    نتیجه :



    این دستور را می‌توانیم به شکل‌های مختلفی فراخوانی کنیم .
    مثلا :
    console.log(1 , "+" , 2 , "=", (1+2));
    نتیجه :


    در این دستور می‌توانیم از چند حرف جایگزین هم استفاده کنیم .


    مثال :

    console.log("Firebug 1.0 beta was %s in December %i.","released",2006);
    نتیجه :


    عملکرد 3 جایگزین نخست با توجه با مثال قبل مشخص شد . پس به سراغ جایگزین %o و %c می‌رویم .
    اگر در رشته‌ی مورد نظر ، یک شیء ( تابع ، آرایه ، ... ) برای جایگزین %o ارسال کنیم ، در خروجی آن شیء بصورت لینک نمایش داده می‌شود که با کلیک بروی آن ، فایرباگ آن شیء را در تب مناسبش Inspect می‌کند .
    مثال :
    console.log("this is a test functin : %o",testFunc);

    نتیجه :



    و زمانی که بروی لینک testFunc کلیک کنیم :



    یک ترفند : بوسیله جایگزین %o توانستیم به تابع مورد نظر لینک بدهیم . اگر بجای جایگزین %o از %s استفاده کنیم ، می‌توانیم بدنه‌ی تابع را ببینیم :
    console.log("this is a test functin : %s",testFunc);
    نتیجه :




    توسط جایگزین %c هم می‌توانید خروجی را فرمت کنید .

    console.log("%cThis is a Style Formatted Log","color:green;text-decoration:underline;");

    نتیجه :


  • console.debug(object[, object, ...])
  • console.info(object[, object, ...])
  • console.warn(object[, object, ...])
  • console.error(object[, object, ...])

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



  • console.assert(expression[, object, ...])

    چک می‌کند که عبارت ارسال شده true هست یا نه . اگر true نبود ، پیغام وارد شده را چاپ و یک استثناء ایجاد می‌کند .
    console.assert(1==1,"this is a test error");
    console.assert(1!=1,"this is a test error");

    نتیجه :



  • console.clear()
  • console.dir(object)
  • console.dirxml(node)
  • console.profile([title])
  • console.profileEnd()

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

  • console.trace()

    با این متد می‌توانید پی ببرید که از کجا و توسط چه متدهایی برنامه به قسمت trace رسیده . برای درک بهتر مجددا اسکریپت صفحه‌ی تست این مقاله را بررسی کنید ( جایی که متد trace قرار داده شده است ) .
    اکنون صفحه‌ی تست را باز کنید و بروی دکمه‌ی startTrace کلیک کنید . خروجی ظاهر شده در کنسول را از پایین به بالا بررسی کنید .


    حتما متوجه شدید که متد method3 چگونه در کدهایمان فراخوانی شده است !؟
    ابتدا با کلیک بروی دکمه‌ی startTrace ، متد startTrace اجرا شده و به همین ترتیب متد startTrace متد method1 ، متد method1 هم متد method2 و در نهایت method2 متد method3 را فراخوانی کرده است .
    دستور trace زمانی که در حال بررسی کدهای برنامه نویسان دیگر هستید ، بسیار می‌تواند به شما کمک کند .

  • console.group(object[, object, ...])

    با این دستور می‌توانید لاگ‌های کنسول را بصورت تو در تو گروه بندی کنید .
    console.group("Group1");
    console.log("Log in Group1");
    console.group("Group2");
    console.log("Log in Group2");
    console.group("Group3");
    console.log("Log in Group3");
    نتیجه :



  • console.groupCollapsed(object[, object, ...])

    این دستور معادل دستور قبلی است با این تفاوت که هنگام ایجاد ، گروه را جمع می‌کند .

  • console.groupEnd()

    به آخرین گروه بندی ایجاد شده خاتمه می‌دهد .

  • console.time(name)

    یک تایمر با نام داده شده ایجاد می‌کند . زمانی که نیاز دارید زمان طی شده بین 2 نقطه را اندازه گیری کنید ، این تابع مفید خواهد بود .

  • console.timeEnd(name)

    تایمر همنام را متوقف و زمان طی شده را چاپ می‌کند .
    console.time("TestTime");
    var t = 1;
    for (var i = 0; i < 100000; i++) { t *= (i + t) }
    console.timeEnd("TestTime");
    نتیجه :


  • console.timeStamp()

    توضیحات کامل را از اینجا دریافت کنید .

  • console.count([title])

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


  • console.exception(error-object[, object, ...])

    یک پیغام خطا را به همراه ردیابی کامل اجرای کدها تا زمان رویداد خطا ( مانند متد trace ) چاپ می‌کند .
    در صفحه‌ی تست این متد را اجرا کنید :
    startError();
    نتیجه :

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

  • console.table(data[, columns])

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


    برای اطلاعات بیشتر به اینجا مراجعه کنید .

منابع :
نظرات اشتراک‌ها
افزایش پرفورمنسAPI با استفاده از FastEndpoints
با توجه به پرفورمانس بسیار چشمگیری که داره ولی آیا حقیقتاً جایگزینی مناسب و عاقلانه و منطقی و مطمئنی بجای MVC در محیط پروداکشن پروژه‌های سازمانی (متوسط تا بزرگ) خواهد بود؟لطفاً اگه لینک نمونه سایت یا اپلیکیشنی هست که از پکیج FastEndpoints  استفاده کرده باشه را بذارید تا بررسی این موضوع ملموس‌تر باشه.
نظرات مطالب
بررسی مشکلات AngularJS 1.x
مسلما واکشی اطلاعات از صفحات وب انکارناپذیر است ولی وقتی که کل وب سایت با WebApi پیاده سازی می‌شود و از فریم ورک‌های تحت کلاینت استفاده شود، افراد دیگر به اطلاعات با ساختار دست پیدا می‌کنند و خیلی راحت‌تر از وب سایت‌های دیگر امکان واکشی اطلاعات وجود دارد.
راه حلی برای این موضوع وجود دارد؟
نظرات مطالب
آپلود فایل ها با استفاده از PlUpload در Asp.Net Mvc
با تشکر از دوستان .
یک مثال عملی؛ یه نرم افزار ارسال ایمیل تحت وب مثل جیمیل رو در نظر بگیرید. یه فرم ارسال ایمیل داره که می‌خواد اطلاعات رو بفرسته به سمت سرور. یه سری فایل هم قراره بصورت آجاکسی پیوست بشه. مراحل کار بدین صورته که ابتدا فایل‌ها آجاکسی به سرور فرستاده می‌شوند و یه جایی ذخیره می‌شوند. بعد فرم اطلاعات شامل گیرنده ، متن نامه و غیره بصورت آجاکس ارسال میشه. وقتی در سمت سرور می‌خوایم ایمیل رو بفرستیم، نیاز داریم که نام فایل‌های پیوست  شده در مرحله قبل رو هم داشته باشیم. 
همونطور که قبلا خدمت دوستان عرض کردم؛ راه حلی که من بذهنم می‌رسه اینه که بعد از اینکه فایل‌ها در مرحله اول آپلود شد، اسم فایل‌ها رو توی فرم در فیلد مخفی تزریق کنیم. بعد که فرم پست شد، طبیعتا دسترسی به نام فایل‌ها داریم. کد ذکر شده هم کار تزریق در هنگام تمام شدن ارسال فایل‌ها انجام میداد.
خواستم بدونم آیا این روش درست هست؟ و آیا روش تمیزتری وجود داره؟
باز هم تشکر
نظرات اشتراک‌ها
درس خوندن، ارزشش رو داره؟
گذشته از بحث مدرک محوری که متاسفانه کشور رو به جهت نامناسبی کشونده و باعث خیلی بی عدالتی‌ها و عقب ماندگی‌ها و ... در کشور شده (به خصوص در سیستم هایی که مستقیم یا غیر مستقیم دولتی هستند!)، ماهیت دانشگاه بسیار مهم است.
در دانشگاه چیزهایی مثل نحوه یادگیری، کارگروهی، بالا بردن انگیزه، حس رقابت، حس پیشرفت، اعتماد به نفس و خیلی چیزهای دیگه به طور عادی یا اجباری یاد داده می‌شود که کسی که دانشگاه نرفته قطعا این موارد رو هم تجربه نخواهد کرد بنابراین دیدگاه یک شخص تحصیل کرده از زمین تا آسمان با نمونه دانشگاه نرفته آن تفاوت دارد. (صد البته رتبه دانشگاه نیز در یادگیری و میزان این تجربیات تاثیر فراوان دارد یعنی نمیشه دو تا فارغ التحصیل دانشگاه رو که مثلا یکی در صنعتی اصفهان درس خونده رو با دانشگاه غیر انتفاعی فلان شهرستان(!) مقایسه کرد که از لحاظ وسعت اندازه یک مدرسه هم نیست و هر دو هم کارشناس تربیت می‌کنند.)
اما برای بچه‌های نرم‌افزار به نظرم قضیه حتی مهم‌تر از مابقی رشته‌ها هم هست. یعنی عقیده دارم دانشگاه رفتن برای کسایی که دوست دارند تو حوزه نرم‌افزار کارآفرین، کارشناس، یا هرچیزه دیگه ای بشن خیلی مهمه. چرا؟
(برای مثال) تو دانشگاه اسمبلی به شما یاد می‌دهند به همراه ریزپردازنده و معماری کامپیوتر که با ترکیب نظریه زبان‌ها و کامپایلر دانشجو می‌فهمه از زمانی که یک خط در کامپیوتر به عنوان برنامه در هر زبانی نوشته می‌شه این یک خط چطور توسط کامپایلر از لحاظ نحو، دستور بررسی می‌شه و چطور کد معادل سطح پایین ایجاد می‌شه و کد رو پردازنده چطوری با کمک چه ثبات‌هایی و چه دستوراتی در سطح ماشین اجرا می‌کنه.
یا درسی مثل طراحی الگوریتم‌هاست که انواع و اقسام الگوریتم‌های مختلف که تا الان ارائه شدند بررسی می‌کنه و از لحاظ سرعت و زمان (Order) مورد تحلیل قرار می‌ده که مثلا الگوریتم Quick Sort در چه زمانی یک لیست رو مرتب می‌کنه و Bubble Sort در چه زمانی و یا اینکه ضرب یک ماتریس n*n در حالت تک پردازنده و یا بصورت موازی چطور انجام می‌شه و چقدر زمان نیاز داره؟
یا شبیه سازی پنجره ویندوز در مد گرافیک در زبان C چه کتابخانه‌ها و سخت‌افزارهایی رو درگیر می‌کنه و یا منظور از نرمال سازی در سطح 3NF در مفاهیم پایگاه داده رابطه‌ای چی هست و چطور میشه به اون رو در واقعیت رسید. (که خیلی از مدعیان کار با MS SQL SERVER یا ... هستند که حتی اصول و مفاهیم ساده پایگاه داده رو هم نمی‌دونند.)
اینها چیزهایی هستند که کسانی که دانشگاه نرفتن و صرفا با یادگیری یک زبان برنامه نویسی وارد این حوزه شدند و حتی مدعی هم هستند(!)، نمی‌دانند.
ممکنه فکر کنید خوب دونستن اینها چه فایده‌ای داره؟
زمانی که سرباز بودم از مافوقم پرسیدم با وجود این‌همه سلاح اتوماتیک و سبک و کوچک و جدید چرا ما باید از کلاشینکف صد سال پیش روسی استفاده کنیم؟ جواب این بود که با یادگیری کامل این سلاح می‌تونید تقریبا با همه سلاح‌های موجود کار کنید و کلیات ماجرای همه این سلاح‌ها از همین کلاشینکف و ژ-۳ ارث بری‌می‌کند(!) و یادگیری بقیه با دونستن اطلاعات پایه تنها یادگیری بخش جدیدی که به این سلاح‌ها اضافه شده وگرنه پایه همان است.
شبیه همین جواب را زمانی شنیدم که از استادم پرسیدم یادگیری ساختار پردازنده 80X86 زمانی که الان پردازنده با ساختار چند هسته‌ای توسط اینتل تولید می‌شه چه فایده‌ای داره؟
بنابراین کسی که واقعا این مسائل پایه‌ای رو خوب یاد گرفته باشه توانایی فوق‌العاده‌ای در درک مسائل جدید در آینده خواهد داشت و قطعا محصول بسیار باکیفیت‌تر و بهینه‌تری تولید خواهد کرد و ذهن بسیار خلاق‌تری خواهد داشت و اگر شرایط اجتماعی برایش فراهم باشد موجب افتخار یک کشور نیز خواهد شد.
نکته آخر:
اگر فیلم  The Social Network  رو دیده باشید حتما اون بخشی رو که مارک زاکربرگ وارد کلاس دانشگاه هاروارد میشه و با بی‌حوصلگی تمام سرکلاس به مطالب استاد گوش می‌ده و می‌خواد کلاس رو ترک کنه که استاد ازش یک سوال درسی می‌پرسه (برای مسخره کردنش!) و مارک ایستاده و روی پله‌ها جواب استاد رو میده که هیج ، کمی جلوتر از فکر استاد پیش میره و جواب می‌ده که کلاس هنوز به اون بخش نرسیده و همه مات و مبهوت مونده‌اند...
بله، درسته خیلی از بزرگان این رشته دانشگاه نرفته‌اند و یا ترک تحصیل کرده‌اند ولی علت این بوده که درس‌های ارائه شده در دانشگاه اون‌ها رو سیراب نمی‌کرده و اونها نیاز به چیزی فرای درس‌های ساده دانشگاه داشتند که در دانشگاه هیچ وقت به اون نمی‌رسیدند.
این افراد رو نمیشه با کسانی که در دانشگاه برای پاس کردن فلان درس به هر دری می‌زنند تا به مدرک برسن یا ذهنشون توانایی حل یک معادله ساده درجه ۲ رو نداره که بخوان براش برنامه بنویسن، یکی کرد.
بنابراین امثال جابز و گیتس نوابغ بشری بودند و هستند که تونستند در جامعه‌ای که زمینه براشون مهیا بوده بدون نیاز به دانشگاه موفق بشن و شهرت جهانی پیدا کنند.
موفق باشید.
مطالب
Accord.NET #3
در مطلب قبل یک مثال مفهومی درباره کاربرد SVM بیان شد و دیدیم که این الگوریتم، یک روش دودویی است و عموما برای زمانی به کار می‌رود که مجموعه داده ما شامل دو کلاس باشد.
اگر بخواهیم نوع چهار میوه (سیب، گلابی، موز، پرتغال) را که از خط سورتینگ عبور می‌کنند، تشخیص دهیم و یا اینکه بخواهیم تشخیص اعداد دست نویس را داشته باشیم و یا اینکه حتی مطالب این وب سایت را که شامل چندین برچسب هستند، طبقه بندی کنیم، آیا در این تشخیص‌ها SVM به ما کمک می‌کند؟ پاسخ مثبت است.
در فضای نام یادگیری ماشین Accord.NET دو تابع خوب MulticlassSupportVectorLearning و MultilabelSupportVectorMachine برای این گونه از مسائل تعبیه شده است. زمانیکه مسئله‌ی ما شامل مجموعه داده‌هایی بود که در چندین کلاس دسته بندی می‌شوند (مانند دسته بندی میوه، اعداد و ...) روش Multiclass  و زمانیکه عناصر مجموعه داده ما به طور جداگانه شامل چندین برچسب باشند (مانند دسته بندی مطالب با داشتن چندین تگ، ...) روش Multilabel ابزار مفیدی خواهند بود. (+)

با توجه به دودویی بودن ماشین بردار پشتیبان، دو استراتژی برای به کارگیری این الگوریتم برای دسته بندی‌های چند کلاسه وجود دارد:
  • روش یک در مقابل همه - One-against-all : در این روش عملا همان روش دودویی SVM را برای هر یک از کلاس‌ها به صورت جداگانه بررسی می‌کنیم. مثلا برای تشخیص میوه، یک بار دو کلاس سیب و غیر سیب (مابقی) بررسی می‌شوند و به همین ترتیب برای سایر کلاس‌ها و در مجموع صفحات ابرصفحه جدا کننده بین هر کلاس در مقابل سایر کلاس‌ها ایجاد می‌شود.

  • روش یک در مقابل یک - One-against-one (*) : در این روش هر کلاس، با هر یک از کلاس‌های دیگر به صورت تک تک بررسی می‌شود و صفحات ابرصفحه جدا کننده مابین هر جفت کلاس متفاوت ایجاد می‌شود. (بیشتر در +)

*روش "یک در مقابل یک" یا One-against-one اساس کار دسته بندی MulticlassSupportVectorMachine در فضای نام Accord.MachineLearning است.

یک مثال کاربردی :  هدف در این مثال دسته بندی اعداد فارسی به کمک MulticlassSupportVectorMachine است.

به معرفی ابزار کار مورد نیاز می‌پردازیم.

1.مجموعه ارقام دستنویس هدی: مجموعه ارقام دستنویس هدی که اولین مجموعه‌ی بزرگ ارقام دستنویس فارسی است، مشتمل بر ۱۰۲۳۵۳ نمونه دستنوشته سیاه سفید است. این مجموعه طی انجام یک پروژه‏‌ی کارشناسی ارشد درباره بازشناسی فرم‌های دستنویس تهیه شده است. داده‌های این مجموعه از حدود ۱۲۰۰۰ فرم ثبت نام آزمون سراسری کارشناسی ارشد سال ۱۳۸۴ و آزمون کاردانی پیوسته‌‏ی دانشگاه جامع علمی کاربردی سال ۱۳۸۳ استخراج شده است. (اطلاعات بیشتر درباره مجموعه ارقام دستنویس هدی) .

تعداد 1000 نمونه (از هر عدد 100 نمونه) از این مجموعه داده، با فرمت bmp در این پروژه مورد استفاده قرار گرفته که به همراه پروژه در انتهای این مطلب قابل دریافت است.

2.استخراج ویژگی (Feature extraction ) : در بازشناسی الگو و مفاهیم کلاس بندی، یکی از مهمترین گام‌ها، استخراج ویژگی است. ما موظف هستیم تا اطلاعات مناسبی را به عنوان ورودی برای دسته بندی‌مان معرفی نماییم. روش‌های مختلفی برای استخراج ویژگی وجود دارند. ویژگی‌ها به دو دسته‌ی کلی ویژگی‌های ظاهری (Appearance) و ویژگی‌های توصیف کننده ( Descriptive) قابل تقسیم هستند. در تشخیص حروف و اعداد، ویژگی‌هایی مانند شدت نور نقاط (Intensity)، تعداد حلقه بسته، تعداد خطوط راست، تعداد دندانه، تعداد نقطه (برای حروف) و ... در دسته‌ی اول و ویژگی‌هایی مانند شیب خطوط، گرادیان، میزان افت یا شدت نور یک ناحیه، HOG و ... در دسته دوم قرار می‌گیرند. در این مطلب ما تنها از روش شدت نور نقاط برای استخراج ویژگی‌هایمان استفاده کرده‌ایم.
کد زیر با دریافت یک فایل Bitmap، ابتدا ابعاد را به اندازه 32*32 تغییر می‌دهد و سپس آن‌را به صورت یک بردار 1*1024 را بر می‌گرداند:

        //تابع استخراج ویژگی
        private static double[] FeatureExtractor(Bitmap bitmap)
        {
            bitmap = BitmapResizer(bitmap, 32, 32);

            double[] features = new double[32 * 32];
            for (int i = 0; i < 32; i++)
                for (int j = 0; j < 32; j++)
                    features[i * 32 + j] = (bitmap.GetPixel(j, i).R == 255) ? 0 : 1;

            return features;
        }

        //تابع تغییر دهنده ابعاد عکس
        private static Bitmap BitmapResizer(Bitmap bitmap, int width, int height)
        {
            var newbitmap = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage((Image)newbitmap))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(bitmap, 0, 0, width, height);
            }
            return newbitmap;
        }
3.ایجاد ورودی‌ها و برچسب : در این مرحله ما باید ورودی‌های دسته بندی SVM را که عملا آرایه‌ای براساس تعداد نمونه‌های مجموعه آموزش (train) است، ایجاد نماییم.

ورودی‌ها (inputs) = با توجه به اینکه تعداد نمونه‌ها 50 مورد از هر عدد (مجموعا 500 نمونه) تعیین شده است و تعداد ویژگی‌های هر نمونه یک بردار با طول 1024 است، ابعاد ماتریس ورودی مان [1024][500] می‌شود.
برچسب‌ها (labels) = تعداد برچسب مسلما به تعداد نمونه هایمان یعنی 500 مورد می‌باشد و مقادیر آن قاعدتا عدد متناظر آن تصویر است.


برای این کار از قطعه کد زیر استفاده می‌کنیم :
            var path = new DirectoryInfo(Directory.GetCurrentDirectory()).Parent.Parent.FullName + @"\dataset\";

            // ایجاد ورودی و برچسب
            int trainingCount = 50;
            double[][] inputs = new double[trainingCount * 10][];
            int[] labels = new int[trainingCount * 10];

            var index = 0;
            var filename = "";
            Bitmap bitmap;
            double[] feature;

            for (int number = 0; number < 10; number++)
            {
                for (int j = 0; j < trainingCount; j++)
                {
                    index = (number * trainingCount) + j;
                    filename = string.Format(@"{0}\{0} ({1}).bmp", number, j + 1);
                    bitmap = new Bitmap(path + filename);

                    feature = FeatureExtractor(bitmap);

                    inputs[index] = feature;
                    labels[index] = number;

                    Console.WriteLine(string.Format("{0}.Create input and label for number {1}", index, number));
                }
            }
4.در نهایت به دسته بندمان که همان MulticlassSupportVectorLearning است، خواهیم رسید. همانطور که در مطلب قبل مطرح شد، پس از تعریف پارامترهای Classifier مان، باید آن را به یک الگوریتم یادگیری که در اینجا هم همان روش SMO است، نسبت دهیم.
        private static double MachineLearning(IKernel kernel, double[][] inputs, int[] labels)
        {
            machine_svm = new MulticlassSupportVectorMachine(1024, kernel, 10);

            // معرفی دسته بندمان به الگوریتم یادگیری SMO
            MulticlassSupportVectorLearning ml = new MulticlassSupportVectorLearning(machine_svm, inputs, labels)
            {
                Algorithm = (svm, classInputs, classOutputs, i, j) => 
                    new SequentialMinimalOptimization(svm, classInputs, classOutputs)
            };

            var error = ml.Run();
            return error;
        }
می‌توانیم پس از اینکه ماشین دسته بندمان آماده شد، برای آزمایش تعدادی از نمونه‌های جدید و دیده نشده (UnSeen) را که در نمونه‌های آموزشی وجود نداشتند، مورد ارزیابی قرار دهیم. برای این کار اعداد 0 تا 9 از مجموعه داده مان را در نظر می‌گیریم و به وسیله کد زیر نتایج را مشاهده می‌کنیم :
            // بررسی یک دسته از ورودی‌ها 
            index = 51;
            for (int number = 0; number < 10; number++)
            {
                filename = string.Format(@"{0}\{0} ({1}).bmp", number, index);
                bitmap = new Bitmap(path + filename);

                feature = FeatureExtractor(bitmap);

                double[] responses;
                int recognizednumber = machine_svm.Compute(feature, out responses);

                Console.WriteLine
                (
                    String.Format
                    (
                        "Recognized number for file {0} is : '{1}' [{2}]",
                        filename,
                        recognizednumber,
                        (recognizednumber == number ? "OK" : "Error")
                    )
                );
                if (!machine_svm.IsProbabilistic)
                {
                    // Normalize responses
                    double max = responses.Max();
                    double min = responses.Min();

                    responses = Accord.Math.Tools.Scale(min, max, 0, 1, responses);
                    //int minIndex = Array.IndexOf(responses, 0);              
                }
            }


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

همانطور که دیدیم SVM گزینه‌ی بسیار مناسبی برای طبقه بندی خیلی از مسائل دو کلاسه و یا حتی چند کلاسه است. اما آکورد دات نت Classifier‌های خوب دیگری (مانند Naive Bayes و Decision Trees یا درخت تصمیم و ... ) را نیز در چارچوب خود جای داده که در مطالب آینده معرفی خواهند شد.

دریافت پروژه