بایگانی برچسب برای: کنترل تردد

برنامه نویسی Parallel در سی شارپ و آشنایی با کلاس Task در سی شارپ

در قسمت قبل گفتیم که بوسیله کلاس Parallel و متدهای For و ForEach عملیات پردازش بر روی مجموعه ها را به صورت Parallel انجام دهیم. اما بحث Parallel Programming به همین جا ختم نمی شود و راه های دیگری نیز برای برنامه نویسی Parallel وجود دارد. یکی از این روش ها استفاده از کلاس Task است که این کلاس نیز در فضای نام System.Threading.Tasks قرار دارد. حالت های مختلفی برای استفاده از این کلاس وجود دارد که ساده ترین آن استفاده از خصوصیت Factory و متد StartNew است که در زیر نمونه ای از نحوه ایجاد یک Task را مشاهده می کنید:

 
Task.Factory.StartNew(()  = >
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i  < =  100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});

بوسیله کد بالا، یک Task جدید ایجاد شده که اعداد 1 تا 100 را در یک thread جداگانه در خروجی چاپ می شود. دقت کنید که بعد از اجرای برنامه شناسه Thread ای که Task در آن اجرا می شود با شناسه Thread اصلی برنامه متفاوت است. راهکار بعدی ایجاد یک شئ از روی کلاس Task و ارجرای آن است، در کد زیر Task بالا را به صورت ایجاد شئ ایجاد می کنیم:

 
Task task = new Task(()  = >
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i  < = 100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});
 
task.Start();
Console.ReadKey();

زمانی که Task جدیدی ایجاد می کنید بوسیله متد Start که برای کلاس Task تعریف شده است می توانید عملیات اجرای Task را شروع کنید. یکی از خصوصیت های تعریف شده در کلاس Task، خصوصیت IsCompleted است که بوسیله آن می توان تشخیص داد که Task در حال اجراست یا خیر:

 
Task task = new Task(()  = >
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i < =  100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});
 
task.Start();
while (!task.IsCompleted)
{
                 
}

دریافت خروجی از کلاس Task

می توان برای کلاس Task یک خروجی مشخص کرد، فرض کنید می خواهیم Task ای بنویسیم که میانگین حاصل جمع اعداد 1 تا 100 را حساب کرده و به عنوان خروجی بازگرداند. برای اینکار باید از کلاس Task که یک پارامتر جنریک دارد استفاده کنیم. ابتدا یک متد به صورت زیر تعریف می کنیم:

 
public static int CalcAverage()
{
    int sum = 0;
 
    for (int i = 1; i < = 100; i++)
    {
        sum += i;
    }
 
    return sum/100;
}

در قدم بعدی می بایست یک Task جنریک از نوع int تعریف کنیم و به عنوان سازنده نام متد تعریف شده را به آن ارسال کنیم:

 
Task < int >  task = new Task < int > (CalcAverage);
task.Start();
 
Console.WriteLine("Average: {0}", task.Result);

در کلاس بالا بعد از Start کردن Task، بوسیله خصوصیت Result می توانیم نتیجه خروجی از Task را بگیریم، دقت کنید که زمانی که می خواهیم مقدار خروجی را از Task بگیریم، برنامه منتظر می شود تا عملیات Task به پایان برسد و سپس نتیجه در خروجی چاپ می شود.

به این موضوع توجه کنید که بوسیله متد StartNew نیز می توان Task هایی که پارامتر خروجی دارند تعریف کرد:

 
var task = Task.Factory.StartNew < int > (CalcAverage);

کد بالا دقیقاً کار نمونه قبلی را انجام می دهد، فقط به جای ایجاد شئ Task و فراخوانی آن، از متد StartNew استفاده کردیم.

ارسال پارامتر به Task ها

یکی از قابلیت های Task ها امکان ارسال State به متدی است که قرار است به عنوان Task اجرا شود. برای مثال، فرض کنید در مثال قبلی که Task ایجاد شده حاصل میانگین را حساب کرده و به عنوان خروجی بر میگرداند می خواهیم عدد شروع و پایان را مشخص کنیم، برای اینکار ابتدا یک کلاس به صورت زیر تعریف می کنیم:

 
public class TaskParameters
{
    public int Start { get; set; }
    public int Finish { get; set; }
}

در ادامه کد متد CalcAverage را به صورت زیر تغییر می دهیم:

 
public static int CalcAverage(object state)
{
    var parameters = (TaskParameters) state;
    int sum = 0;
 
    for (int i = parameters.Start; i < = parameters.Finish; i++)
    {
        sum += i;
    }
 
    return sum/100;
}

در قدم بعدی باید روند ساخت شئ Task را به گونه ای تغییر دهیم که پارامترهای مورد نظر به عنوان state به متد CalcAverage ارسال شوند، برای اینکار به عنوان پارامتر دوم سازنده کلاس Task شئ ای از نوع TaskParameters به صورت زیر ارسال می کنیم:

 
Task < int > task = new Task < int > (CalcAverage, new TaskParameters()
{
    Start = 100,
    Finish = 1000
});

با انجام تغییرات بالا، توانستیم شئ ای را به عنوان State به Task ارسال کنیم، همچنین توجه کنید که امکان ارسال State بوسیله متد StartNew در خصوصیت Factory نیز وجود دارد. در این بخش با کلاس Task آشنا شدیم، در قسمت بعدی با نحوه متوقف کردن Task ها در زمان اجرا و کلاس CancellationToken آشنا می شویم.

منبع


قسمت اول آموزش-برنامه نویسی Asynchronous – آشنایی با Process ها، Thread ها و AppDomain ها

قسمت دوم آموزش- آشنایی با ماهیت Asynchronous در Delegate ها

قسمت سوم آموزش-آشنایی با فضای نام System.Threading و کلاس Thread

قسمت چهارم آموزش- آشنایی با Thread های Foreground و Background در دات نت

قسمت پنجم آموزش- آشنایی با مشکل Concurrency در برنامه های Multi-Threaded و راهکار های رفع این مشکل

قسمت ششم آموزش- آشنایی با کلاس Timer در زبان سی شارپ

قسمت هفتم آموزش-آشنایی با CLR ThreadPool در دات نت

قسمت هشتم آموزش- مقدمه ای بر Task Parallel Library و کلاس Parallel در دات نت

قسمت نهم آموزش- برنامه نویسی Parallel:آشنایی با کلاس Task در سی شارپ

قسمت دهم آموزش-برنامه نویسی Parallel در سی شارپ :: متوقف کردن Task ها در سی شارپ – کلاس CancellationToken

قسمت یازدهم آموزش- برنامه نویسی Parallel در سی شارپ :: کوئری های Parallel در LINQ

قسمت دوازدهم آموزش- آشنایی با کلمات کلیدی async و await در زبان سی شارپ

قسمت سیزدهم آموزش- استفاده از متد WhenAll برای اجرای چندین Task به صورت همزمان در سی شارپ

معرفی سیستم ایمنی مصنوعی(Artificial Immune System)

ایمنی از مولکول ها،سلول ها و قوانینی تشکیل شده که از آسیب رساندن عواملی مانند پاتوژن ها(Pathogens) به بدن جلوگیری می کند، قسمتی از پاتوژن به نام آنتی ژن(Antigen) که توسط این سیستم قابل شناسایی و موجب فعال شدن پاسخ سیستم ایمنی می شود. یک نمونه ای از پاسخ سیستم ایمنی ترشح آنتی بادی توسط سلول های B ،که آنتی بادی ها مولکول های شناساگری به شکل Y هستند که به سطح سلول های B متصل است و با یکسری قوانین از پیش تعریف شده آنتی ژن را شناسایی می کنند. مولکول های آنتی بادی قسمتی از آنتی ژن را به نام اپیتوپ شناسایی می کنند،ناحیه ای از آنتی بادی که وظیفه شناسایی و اتصال به آنتی ژن را دارد پاراتوپ گویند که با نام V شناخته می شود، که به منظور ایجاد بیشترین میزان تطابق با آنتی ژن ها می توانند شکل خود را تغییر دهند و به همین دلیل ناحیه متغیر نامیده می شود.

سیستم ایمنی مصنوعی

 

سطوح سیستم ایمنی

     1. اولين سطح – پوست

     2. دومین سطح – ايمني فيزيولوژيکي

  • اشک چشم ، بزاق دهان ، عرق و …

     3. سومین سطح – ایمنی ذاتی

  • پاسخ عمومی به آنتی ژن ها
  • بسیار کند

4. چهارمین سطح – ایمنی اکتسابی

  • پاسخ اختصاصی به آنتی ژن ها
  • بسیار سریع

سیستم ایمنی مصنوعی

ایمنی ذاتی(Innate Immunity)

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

 

واکنش دستگاه ایمنی ذاتی نسبت به عفونت

واکنش دستگاه ایمنی ذاتی نسبت به عفونت

 

ایمنی اکتسابی (Adaptive Immunity)

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

لنفسیت ها (Lymphocytes)

شناسایی آنتی ژن ها برعهده گلبول های سفید خون که لنفسیت نام دارد و دو نوع لنفسیت B و لنفسیت T داریم و در ادامه در مورد هر کدام توضیح خواهیم داد.

 لنفسیت های نوع B

 سلول های بنیادی که در مغز استخوان تولید می شوند و هر سلول B تعداد گیرنده سلولی (B-Cell Receptor) یا آنتی بادی(Antibody) در سطح خود دارد و هرکدام از این آنتی بادی ها دارای اشکال متفاوتی هستند که هر شکلی شبیه به سلول B را دارند و در نتیجه آنتی بادی هایی که توسط سلول B ساخته شده اند به مجموعه مشابهی از الگوهایی مولکولی متصل می شوند. آنتی بادی های سلول B دو ارزشی و دو عملکردی هستند، دو ارزشی به این دلیل که از طریق دو بازوی Fab به دو آنتی ژن متصل می شوند و از طریق قسمت FC به پذیرنده خاص روی سطح سلول های ایمنی دیگر وصل می شوند. اتصال به آنتی ژن دو نقش را بازی می کند که نقش اصلی آن برچسب زدن به آنتی ژن به عنوان یک مخرب تا مابقی سلول های سیستم ایمنی آن را تخریب کنند به این عملیات آماده مرگ می گویند، این کار با اتصال نواحی Fab آنتی بادی به آنتی ژن صورت می گیرد و ناحیه FC دستنخورده باقی می ماند تا اتصال با سلول های ایمنی دیگر مانند ماکروفاژها(Macrophages) صورت می پذیرد، یک آنتی بادی از دو زنجیره سبک مشابه (L) و دو زنجیره سنگین مشابه (H) تشکیل شده است که در شکل زیر نشان داده شده است.

 

سیستم ایمنی مصنوعی

 

لنفسیت های نوع T

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

سلول های T به چند دسته تقسیم می شوند: دسته اول سلول های T کشنده، زمانی که سلولی را شناسایی می کنند آن را از بین می برند. دسته دیگر سلول های T کمکی، آنتی بادی ها به سلول های B متصل هستند اما سلول های B آنتی ژن های خودی را از آنتی ژن های غیرخودی تشخیص نمی دهند به سلول T احتیاج دارند و پاسخ ایمنی سلول های B زمانی تولید می شود که سلول B و یک سلول T کمکی به طور همزمان یک آنتی ژن را شناسایی می کنند.

لنفسیت های نوع T

ویژگی های سیستم ایمنی بدن

سیستم ایمنی بدن شامل خصوصیاتی که بالطبع سیستم ایمنی مصنوعی از آن پیروی می کند که به صورت خلاصه در مورد هر کدام توضیح داده شده است:

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

2- تطبیقی بودن سیستم ایمنی با رخدادها و محیط: بدن انسان با محیط طبیعی خود در ارتباط است و همچنین مواد مفید یا مضر (عوامل بیماری زا) که وارد بدن انسان می شوند متغیر هستند به همین دلیل سیستم ایمنی به صورت پویا با تغییرات برخورد می کند و با وجود تغییر عوامل بیماری زا را تشخیص داده و با آنها مبارزه می کند.

3- قابلیت یادگیری: سیستم ایمنی بدن قادر است که ویروس های جدیدی را که مشاهده می کند به خاطر می سپارد.

4- همکاری گروهی: در سیستم ایمنی سلول ها به صورت گروهی، موازی و توزیع شده برای تشخیص و انهدام همکاری دارند.

5- چند لایه ای بودن: هیچ موجودیتی در سیستم ایمنی بدن انسان یک مکانیزم کامل امنیتی و دفاعی را فراهم نمی کند بلکه هر لایه سیستم ایمنی به صورت مستقل عمل کرده و با بقیه لایه ها در ارتباط است.

6- تنوع و گوناگونی: سیستم ایمنی بدن در برابر انواع مختلفی از نفوذها مقاومت کرده و تسلیم نمی شود.

7- بهینه بودن منابع: در سیستم ایمنی با ایجاد مرگ سلولی و تکثیر سلولی، یک نمونه فضای کوچکی از فضای جستجوی آنتی ژن ها در هر زمان نگه داری می کنند.

8- پاسخ انتخابی: در سیستم ایمنی بدن پس از شناسایی یک آنتی ژن پاسخ های متفاوتی داده می شود که به یک شکل عمل نمی کنند.

9- تنظیم تعداد سلول های ایمنی توسط سیستم ایمنی

 سیستم ایمنی مصنوعی

یک الگویی برای یادگیری ماشین است و یادگیری ماشین یعنی توانایی کامپیوتر برای انجام یک کار با یادگیری داده ها از روی تجربه است.

کاربردهای سیستم ایمنی مصنوعی

AIS یکی از الگوریتم های الهام گرفته از سیستم ایمنی بدن انسان است و راه حل هایی را برای مسائل پیچیده ارائه داده اند و از جمله کاربردهای آن عبارتند از:

خوشه بندی (Clustering)

زمانبندی (Scheduling)

تشخیص عیب (Fault Detection)

تشخیص ناهنجاری (َAnomaly Detection)

امنیت اطلاعات (Security Infrmation)

مسائل بهینه سازی (Optimization problems)

دسته بندی الگوها (Patterns Classification)

سیستم های یادگیرنده (Learning system)

تشخیص نفوذ (Intrusion Detection)

مراحل سیستم ایمنی مصنوعی

 برای حل مساله با استفاده از  AIS باید 3 مرحله زیر انجام پذیرد:

1- نحوه نمایش داده های مساله (تعریف فضای شکل)

2- معیار اندازه گیری میل ترکیبی

3-انتخاب یک الگوریتم ایمنی مصنوعی برای حل مساله

فضای شکل (Shape Space)

سیستم ایمنی بر مبنای شناسایی الگو یا شناسایی شکل آنتی ژن است و می توان این سیسستم را فضایی مملوء از اشکال مختلف تشبیه کرد و هدف پیدا کردن مکمل اشکال و در نتیجه شناسایی آنها است، یعنی پیدا کردن تعدادی شکل بهینه یا آنتی بادی در فضای شکل که مکمل تمامی شکل های موجود در داده های مسئله آنتی ژن است. آنتی ژن ها به صورت آرایه ای از اعداد نمایش داده می شود و هر شیوه های که برای نمایش آنتی ژن استفاده می شود برای نمایش آنتی بادی هم نیز استفاده می شود (نحوه نمایش آنتی بادی و آنتی ژن یکسان است).

نحوه محاسبه و میل ترکیبی آنتی بادی با آنتی ژن

هر چه آنتی بادی میل ترکیبی بیشتری با آنتی ژن داشته باشد یعنی هر چه فاصله آنتی بادی و آنتی ژن کمتر شود مکمل بهتری برای آنتی ژن است و میل ترکیبی را می توان به صورت شباهت آرایه ها در نظر گرفت. که بر همین اساس در الگوریتم AIS از فاصله به عنوان معیار ارزیابی خوب یا بد بودن یک آنتی بادی استفاده می شود.

الگوریتم های AIS

الگوریتم های AIS به 3 دسته تقسیم می شوند:

1- دسته اول الگوریتم هایی که بر مبنای انتخاب کلونی سلول های B ایجاد شده اند.

2- دسته دوم الگوریتم هایی که بر مبنای انتخاب معکوس سلول های T ایجاد شده اند.

3- دسته سوم بر مبنای تئوری شبکه ایمنی ایجاد شده اند.

انتخاب کلونی (Clonal Selection)

زمانی که سلول B آنتی ژن را شناسایی می کند و سلول های B شروع به تکثیر شدن می کنند و تعداد زیادی سلول B یکسان و مشابه تولید می شود، 12 ساعت طول می کشد که یک سلول B رشد کرده و به دو سلول تبدیل شود و بعد از تحریک شدن دوره تکثیر حدودا یک هفته طول می کشد و از یک سلول 2 به توان 14 (16000) سلول مشابه تولید می شود و هر چه میل پیوندی بین سلول B و آنتی ژن بیشتر شود نرخ تکثیر بیشتر خواهد شد، در نتیجه سلول های B با میل پیوندی بالاتر، کلونی بیشتری تولید می کنند که اصل انتخاب کلونی نام دارد.

اصل انتخاب کلونی در AIS الگوریتم خاص خودش را دارد که بعد از تکثیر شدن سلول های B شروع به بالغ شدن می کنند که این فرایند در 3 مرحله صورت می پذیرد:

1- دگرگونی ایزوتایپ

2- بلوغ میل پیوندی

3- تصمیم گیری بین حافظه یا پلاسما شدن سلول B

AIS با دگرگونی ایزوتوپ در گیر نیست ولی دو مرحله بعدی در AIS مهم می باشند. ابرجهش سومانیک قسمتی از بلوغ میل پیوندی که قسمت مهمی در AIS بشمار می آید و جهش میل پیوندی آنتی بادی را می تواند کاهش یا افزایش می دهد.

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

انتخاب کلونی (Clonal Selection)

انتخاب معکوس (Negative Selection)

میل ترکیبی سلول های T نابالغ با سلول های موجود در تیموس بررسی می شود و هرکدام از سلول های T نابالغ میل ترکیبی زیادی با یکی از سلول ها داشته باشند حذف می شوند و سایر سلول های T وارد جریان خون می شوند که  به این گونه انتخاب در آن برای حدف شدن انتخاب می شود انتخاب معکوس گویند.

 

انتخاب معکوس (Negative Selection)

 

تئوری شبکه ایمنی (Immune Network Theory)

آنتی بادی های موجود بر روی B-Cell ها می توانندعلاوه بر تشخیص آنتی ژن، آنتی بادی را هم می توانند تشخیص بدهند و باعث می شود سیستم ایمنی رفتاری پویا داشته که از آن در AIS استفاده می شود، و بر اساس این تئوری هر آنتی بادی قسمتی به نام ایدوتوپ دارد که توسط آنتی بادی دیگر قابل شناسایی است که در نتیجه آنتی بادی ها با شناسایی کردن یکدیگر سیگنال هایی را ارسال می کنند که می توانند یکدیگر را تحریک کنند و بدین ترتیب این شناسائی و تاثیر گذاری بر روی یکدیگر باعث پویایی شبکه ایمنی مصنوعی می شود. به مجموعه آنتی بادی ها که یکدیگر را شناسایی می کنند شبکه ایمنی یا ایدوتوپی گفنه می شود.

 

تئوری شبکه ایمنی (Immune Network Theory)

 

در هر الگوریتم AIS باید به 3 نکته توجه داشت:

1- در هر الگوریتم AIS باید حداقل یک جزء ایمنی مانند لنفسیت باشد.

2- در هر الگوریتم AIS باید ایده ای برگرفته از بیولوژی نظری یا تجربی باشد.

3- الگوریتم AIS که طراحی می شود باید به حل مسئله کمک کند.

مقایسه سیستم ایمنی طبیعی و الگوریتم های ایمنی مصنوعی

 

مقایسه سیستم ایمنی طبیعی و الگوریتم های ایمنی مصنوعی

 

برگرفته از پایان نامه بنت الهدی حلمی – دانشگاه علم و صنعت – تحت عنوان استخراج قوانین انجمنی با استفاده از سیستم ایمنی مصنوعی

استخراج قوانین انجمنی با استفاده از سیستم ایمنی مصنوعی

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

کاهش معناگری داده با استفاده از سیستم های ایمنی مصنوعی

 

منبع

فانکش استفاده از میوتیشن برای نسل فعلی:

ابتدا یک کروموزوم رندوم انتخاب می شود (کروموزومی به غیر از بهترین کروموزومی که در صدر لیست قرار دارد). سپس دو ژن رندوم از این کروموزوم انتخاب می شود و با هم جابجا می شود. افزایش تعداد میوتیشن ها آزادی الگوریتم را در جستجو خارج از فضای حالات کروموزوم ها بیشتر می کند.

همان طور که گفته شد ژن عددی از ۰ تا ۷ است که به معنی شماره سطری است که وزیر در آن قرار گرفته است. موقعیت ژن در یک کروموزوم به معنی شماره ستون قرار گیری وزیر است. مشخص کردن مکان قرار گیری هر وزیر را باید حتما در هر سطر و ستون مشخص کرد.

کروموزوم نیز مجموعه ای از ۸ ژن است. و این طور فرض می شود که هیچ ژنی در یک کروموزوم دوبار تکرار نشود. برای مثال اگر کروموزوم ما ۰|۱|۴|۲|۳|۶|۷|۵ باشد یعنی ۸ وزیر در خانه های زیر از ماتریس قرار گرفته اند.

(۰,۰), (۱,۱), (۲,۴), (۳,۲), (۴,۳), (۵,۶), (۶,۷), (۷,۵)

در اینجا میوتیشن با swap کردن ژنی که باید mutate شود با یک ژن تصادفی (به جز ژنی که می خواهیم میوتیشن را روی آن انجام دهیم) از همان کروموزوم انجام می شود.

در crossover ژن ها از کروموزوم های دو والدین با احتمال ۰٫۵ گرفته می شود. یک ژن از یکی از والدین گرفت می شود و به کروموزوم فرزند اضافه می شود. ژنی که تولید می شود در پرنت دیگر پاک می شود. این مرحله انقدر ادامه می یابد تا کروموزوم های پدر و مادر هر دو، خالی شود و فرزند آنها همه ژن ها را داشته باشد.

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

در کد c# مورد استفاده :

class GeneticAlgo: کلاسی است که مسئولیت همه عملیات الگوریتم ژنتیک را بر عهده دارد.

class FitnessComparator: یک کلاس مقایسه کننده است که کروموزوم ها را با fitness value مرتب می کند تا جمعیت نهایی را در جدول نشان دهد. بیشترین فیتنس در بالای جدول قرار می گیرد و کمترین آنها در پایین جدول.

struct Chromosome: ساختاری است که کروموزومی که حاوی ژنهااست، فیتنس و مجموع میانگین فیتنس ها را نشان می دهد.

class MainFrame: این کلاس موظف به کنترل اینترفیس کاربر و ایجاد جمعیت اولیه به منظور انتقال آن به الگوریتم ژنتیک است.

class Board: این کلاس گرافیک و عملیات صفحه شطرنج را بر عهده دارد.

متغیر private const int MAX_FIT = ۲۸ بیشترین مقدار فیتنس را دارد.

توابع:


private List<chromosome> GetInitialPopulation(int population)

{

List<chromosome> initPop = new List<chromosome>();

GeneticAlgo RandomGen = new GeneticAlgo();

for (int i = 0; i < population; i++)

{

List<int> genes = new List<int>(new int[] {0, 1, 2, 3, 4, 5, 6, 7});

Chromosome chromosome = new Chromosome();

chromosome.genes = new int[8];

for (int j = 0; j < 8; j++)

{

int geneIndex = (int)(RandomGen.GetRandomVal

(۰,genes.Count-1)+0.5);//randomly select a gene

chromosome.genes[j] = genes[geneIndex];

genes.RemoveAt(geneIndex);//remove selected gene

}

initPop.Add(chromosome);

}

return initPop;

}

 

تابع فوق اندازه جمعیت را به صورت پارامتر می گیرد و لیستی از کروموزوم هایی که دربردارنده ژن های تولید شده تصادفی هستند را بر می گرداند. مقدار ژن ها بصورت تصادفی از لیستی که شامل اعداد ۰ تا ۷ است انتخاب می شود. در حین اینکه مقادیر از لیست انتخاب می شوند، مقادیر انتخاب شده پاک می شوند تا از تکراری شدن ژن ها در کروموزوم جلوگیری شود. اندازه لیست مساوی با اندازه جمعیت است. پس از ایجاد جمعیت اولیه با استفاده از این تابع، لیست کروموزوم هایی که برمیگرداند به تابع DoMating داده می شود.


public void DoMating(ref List<Chromosome> initPopulation,

int generations, double probCrossver, double probMutation)

{

int totalFitness = 0;

CalcFitness(ref initPopulation, ref totalFitness);

for (int generation = 0; generation < generations; generation++)

{

PrepareRuletteWheel(ref initPopulation,totalFitness);

Crossover(ref initPopulation, probCrossver);

Mutate(ref initPopulation, probMutation);

CalcFitness(ref initPopulation, ref totalFitness);

if (initPopulation[initPopulation.Count – 1].fitness == 28)

break;

if (progress != null)

{

progress(generation + 1);

}

}

initPopulation.Sort(new FitnessComparator());

}
 

این تابع لیست کروموزوم ها را به عنوان جمعیت اولیه ، تعداد نسل هایی که می خواهیم در الگوریتم پخش شوند، احتمال crossover و احتمال mutation را به عنوان پارامتر می گیرد. مسئولیت این تابع هندل کردن پخش جمعیت به نسل مورد نیاز با فراخوانی توابع CalcFitness،PrepareRuletteWheel،CrossoverوMutate است.

 

public void CalcFitness(ref List<Chromosome> chromosome, ref int totalFitness)

{

int collisions = 0;

totalFitness = 0;

for (int k = 0; k < chromosome.Count; k++)

{

for (int i = 0; i < chromosome[k].genes.Length – 1; i++)

{

int x = i;

int y = chromosome[k].genes[i];

for (int j = i + 1; j < chromosome[k].genes.Length; j++)

{

if (Math.Abs(j – x) == Math.Abs

(chromosome[k].genes[j] – y))

collisions++;

}

}

Chromosome temp = chromosome[k];

temp.fitness = MAX_FIT – collisions;

chromosome[k] = temp;

totalFitness += chromosome[k].fitness;

collisions = 0;

}

}

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


private void PrepareRuletteWheel(ref List<Chromosome> parents,int total)

{

int currentTotalFitness=0;

for (int i = 0; i < parents.Count; i++)

{

currentTotalFitness += parents[i].fitness;

Chromosome temp = parents[i];

temp.cumAvgFitness = currentTotalFitness / (double)total;

parents[i] = temp;

}

}

rulette wheel که بر مبنای فیتنس کروموزوم است برای انتخاب والدین برای جفت گیری برای ایجاد نسل جدید استفاده می شود. این تابع مسئول آماده سازی rulette wheel بوده و لیستی از کروموزوم ها را به عنوان جمعیت فعلی و فیتنس کلی جمعیت می گیرد. این تابع نرخ فیتنس هر کروموزوم تا فیتنس کلی را محاسبه می کند سپس مجموع آن را برای اختصاص به مشخصه cumAvgFitness  کروموزوم محاسبه می کند.

با تابع RuletteWheel می توان احتمال انتخاب را بر اساس نرخ فیتنس تعیین کرد. با این روش کروموزم هایی با fitness value بالاتر احتمال بیشتری برای انتخاب در ساخت نسل بعدی دارند در حالی که کروموزم هایی با fitness value پایین تر با احتمال کمتری شرکت داده می شوند


public void Crossover(ref List<Chromosome> parents, double probability)

{

List<Chromosome> offspring = new List<Chromosome>();

for (int i = 0; i < parents.Count; i++)

{

if (Assay(probability)) //if the chance is to crossover

{

Chromosome parentX = AssayRuletteWheel(parents);

Chromosome parentY = AssayRuletteWheel(parents);

List<int> child = new List<int>();

for (int j = 0; j < 8; j++)

{

if (Assay(0.5)) //select from parentX

{

for (int k = 0; k < parentX.genes.Length; k++)

{

if (!child.Contains

(parentX.genes[k]))//instead of

//deleting the similar genes

//from parents select the

//next non-contained number

{

child.Add(parentX.genes[k]);

break;

}

}

}

else //select from parentY

{

for (int k = 0; k < parentY.genes.Length; k++)

{

if (!child.Contains

(parentY.genes[k]))//instead of

//deleting the similar genes from

//parents select the next

//non-contained number

{

child.Add(parentY.genes[k]);

break;

}

}

}

}

Chromosome offSpr = new Chromosome();

offSpr.genes = child.ToArray();

offspring.Add(offSpr);

}

else //else the chance is to clone

{

Chromosome parentX = AssayRuletteWheel(parents);

offspring.Add(parentX);

}

}

while (offspring.Count > parents.Count)

{

offspring.RemoveAt((int)GetRandomVal(0, offspring.Count – 1));

}

parents = offspring;

}

 

تابع فوق مسئول انجام عمل cross over است. تابع لیستی از کروموزم ها را به عنوان جمعیت فعلی و احتمال crossover را به عنوان پارامتر می گیرد. تابع Assay(int probability) با احتمال داده شده true بر می گرداند بنابراین با احتمال crossover برای تعیین اینکه عملیات crossover است یا cloning استفاده می شود.

if (Assay(probability)) //if the chance is to crossover

{

Chromosome parentX = AssayRuletteWheel(parents);

Chromosome parentY = AssayRuletteWheel(parents);

List<int> child = new List<int>();

for (int j = 0; j < 8; j++)

{

if (Assay(0.5)) //select from parentX

{

for (int k = 0; k < parentX.genes.Length; k++)

{

if (!child.Contains(parentX.genes[k]))//instead of

//deleting the similar genes from parents

//select the next non-contained number

{

child.Add(parentX.genes[k]);

break;

}

}

}

else //select from parentY

{

for (int k = 0; k < parentY.genes.Length; k++)

{

if (!child.Contains(parentY.genes[k]))//instead of

//deleting the similar genes from parents

//select the next non-contained number

{

child.Add(parentY.genes[k]);

break;

}

}

}

}

Chromosome offSpr = new Chromosome();

offSpr.genes = child.ToArray();

offspring.Add(offSpr);

}

این بخش از کد مسئول crossover دو پرنت parentX  و parentY می باشد. به منظور ایجاد فرزند، ژنها از دو والدین با احتمال ۰٫۵ انتخاب می شوند در حالیکه از تکرار ژنها در کروموزوم ها اجتناب می شود. در عملیات cloning یکی از والدین مستقیما به نسل بعدی آورده می شود.


public void Mutate(ref List&amp;lt;Chromosome&amp;gt; parents, double probability)

{

List&amp;lt;Chromosome&amp;gt; offsprings = new List&amp;lt;Chromosome&amp;gt;();

for (int i = 0; i &amp;lt; parents.Count; i++)

{

Chromosome offspring = parents[i];

for (int mutatePosition = 0; mutatePosition &amp;lt; 8; mutatePosition++)

{

if (Assay(probability)) //if the chance is to mutate

{

int newGeneIndex = (int)(GetRandomVal(0,6)+0.5);

if (newGeneIndex&amp;gt;=mutatePosition)

{

newGeneIndex += 1;

}

int swapTemp = offspring.genes[mutatePosition];

offspring.genes[mutatePosition] =

offspring.genes[newGeneIndex];

offspring.genes[newGeneIndex] = swapTemp;

}

}

offsprings.Add(offspring);

}

parents = offsprings;

}
 

این تابع اپراتور mutation را با احتمال داده شده استفاده می کند. این تابع تغییر میوتیش را در حین انتقال ژن ها در جمعیت فعلی بررسی می کند. اگر باید برای ژنی از میوتیشن استفاده شود آنگاه مقدار آن با یک ژنی که بصورت تصادفی انتخاب شده در همین کروموزوم (ژنی به جز خود ژنی که می خواهیم روی آن میوتیشن انجام دهیم)  swap می شود.

زمانی که به یک راه حل می رسیم آرایه ژن های کروموزومی که شامل راه حل هستند را میتوان به پراپرتی به نام Genes  در کلاس Board اختصاص داد.

این برنامه این امکان را می دهد که اندازه جمعیت، تعداد نسل ها، احتمال crossover و احتمال mutation را مشخص کنید.

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

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

این سوال ها سالها مطرح بوده است که بین crossover و mutation کدامیک بهتر است؟ کدامیک لازم است؟ کدامیک اصلی است؟ پاسخی که تاکنون بیشتر از بقیه پاسخها مورد قبول بوده این است که هر کدام نقش مخصوص خود را دارد. در حالت کلی بهتر است از هر دو استفاده شود. میتوان الگوریتمی داشت که فقط از mutation استفاده کند ولی الگوریتمی که فقط ازcrossover   استفاده کند کار نخواهد کرد. Crossover خاصیت جستجوگرانه و یا explorative دارد. میتواند با انجام پرشهای بزرگ به محل هائی دربین والدین رفته و نواحی جدیدی را کشف نماید. Mutation خاصیت گسترشی و یا  exploitive  دارد. میتواند با انجام تغییرات کوچک تصادفی به نواحی کشف شده وسعت ببخشد.  Crossoverاطلاعات والدین را ترکیب میکند درحالیکه mutation  میتواند اطلاعات جدیدی اضافه نماید. رسیدن به یک پاسخ بهینه در mutation شانسی است.

نتایج اجرای این الگوریتم نشان می دهد که جمعیت عامل بسیاری مهمی بوده و تاثیر زیادی دارد و crossover probability و mutation rate تاثیر غیر قابل انکاری بر اجرای الگوریتم ژنتیک دارند زیرا با هر بار تغییر در هر یک از این پارامترها نتایج به شدت تغییر می کند. در حقیقت نحوه انتخاب اپراتورهای GA یک تریدآف بین همگرایی سریع تر و حفظ قابلیت اکتشافی بودن الگوریتم (برای جلوگیری از همگرایی اشتباه) است. Crossover پارامتری است که به تنظیم رفتار الگوریتم ژنتیک کمک می کند. کم کردن احتمال crossover باعث می شود در نسل بعدی افراد بیشتری بدون تغییر باقی بمانند. بسته به مسئله کاهش یا افزایش مقدار احتمال crossover می تواند تاثیر مثبت یا منفی داشته باشد.

پس از اجراهای متوالی الگوریتم می توان دید که هیچ جوابی وجود ندارد گه به طور قطع بتوان گفت از بقیه بهتر است و بتوان گفت که مقدار تنظیم شده برای پارامترهای الگوریتم ژنتیک در این حالت از همه بهتر است. این بهترین مقادیر به عوامل زیادی وابسته هستند. برای مثال اگر الگوریتم شما generational است میخواهید احتمالی را برای این در نظر بگیرید که برخی از والدین بدون تغییر باقی بمانند. در غیر اینصورت برخی راه حل های خوب را از دست خواهید داد. بنابراین بهتر است crossover rate را نزدیک به ۰٫۷ تنظیم کرد. برخی از الگوریتم ها نیز هستند که به طور کامل به mutation وابسته اند و برای آنها crossover rate مساوی با ۰ در نظر گرفته می شود. اگر crossover probability برابر با ۱۰۰درصد باشد همه فرزندان توسط crossover ایجاد می شوند. اگر ۰ درصد باشد همه نسل جدید کپی دقیقی از کروموزوم فعلی جمعیت قدیمی است ولی به این معنی نیست که نسل جدید دقیقا همان نسل قبلی است.

انتخاب اپراتورهای الگوریتم توازنی میان سرعت و دقت همگرایی است یعنی exploration در مقابل exploitation.

اینطور که گفته شده بهتر است mutation بین ۰٫۰۱۵ تا ۰٫۰۲ باشد. چرا؟

Exploration یعنی جستجوی فضای حالت در حد امکان در حالی که exploitation یعنی تمرکز بر یک نقطه که امیدواریم global optimum باشد.

در GA اپراتورهای mutation اغلب برای exploration و اپراتور های Crossover اغلب برای exploitation یعنی هدایت جمعیت به سوی همگرایی به یک راه حل خوب استفاده می شوند. در نتیجه وقتی Crossover سعی در همگرایی به یک نقطه مشخص دارد mutation سعی خود را می کند که همگرایی صورت نگیرد و فضای بیشتری کاوش شود.

در ابتدای فرایند جستجو ترجیح ما بر این است که جستجوی بیشتری به منظور اکتشاف فضا صورت گیرد. از طرف دیگر در انتهای فرایند جستجو exploitations بیشتری ترجیح داده می شود که همگرایی جمعیت به سمت global optimum تضمین شود. تنها یک استثناء وجود دارد؛ زمانی که جمعیت به سمت بهینه محلی همگرا می شود اگر بتوانیم باید پراکندگی حمیت را افزایش دهیم تا فضای بیشتری جستجو شود و در دام بهینه محلی نیفتد. با توجه به این نکته mutation rate بالا باعث افزایش احتمال جستجوی فضای بیشتری از فضای جستجو می شود با این حال از همگرایی جمعیت به یک جواب بهینه جلوگیری می کند. از طرف دیگر اگر mutation rate خیلی کوچک باشد باعث همگرایی زودهنگام و نارس می شود و به حای رسیدن به global optimum در دام بهینه محلی گرفتار می شود.مقداری که انتخاب می شود به ماهیت مسئله و نحوه پیاده سازی الگوریتم بستگی دارد. پس mutation rate های بسیار بالا از همگرایی الگوریتم جلوگیری کرده و رسیدن به راه حل بهینه را تضمین نمی کنند. بنابراین عاقلانه تر این است که از mutation rate های کوچک تر استفاده شود. مقدار کوچک برای mutation rate تضمین می کند که میوتیشن های زیادی در آن واحد اتفاق نیفتد ولی این نیز به تعداد ژن های موجود در هر کروموزوم از جمعیت بستگی دارد. بهتر این است که با مقادیر کم شروع کرده و به تدریج آنها را افزایش داد و کارایی هر یک را بررسی کرد مثلا به ترتیب: ۰٫۰۰۱، ۰٫۰۱، ۰٫۰۵، ۰٫۱، ۰٫۲ و … . در رابطه با جستجو در فضای حالت در مقایسه با mutation rate بالاتر، جمعیت بزرگتر ترجیح داده می شود.

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

Exploitation = (crossover +  انتخاب بر اساس فیتنس) ما را به جواب بهینه نهایی می رساند.

این طور گفته می شود که اندازه جمعیت کوچکتر سرعت همگرایی بیشتری به الگوریتم می دهد ولی الگوریتم راحتتر در بهینه محلی گرفتار می شود. احتیاط بر این است که از جمعیت های بیش از حد کوچک استفاده نشود. معمولا به احتمال crossover و mutation بسیار بزرگ نیاز نخواهید داشت و جمعیتی با اندازه متوسط مناسب است.

است.
مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

مسئله چند وزیر یک معمای شطرنجی و ریاضیاتی است که بر اساس آن باید n وزیر شطرنج در یک صفحه n×n شطرنج به‌گونه‌ای قرار داده شوند که هیچ‌یک زیر ضرب دیگری نباشند. با توجه به اینکه وزیر به‌صورت افقی، عمودی و اُریب حرکت می‌کند، باید هر وزیر را در طول، عرض و قطر متفاوتی قرار داد.

اولین و مشهورترین شکل این مسئله معمای هشت وزیر است که برای حل آن باید ۸ وزیر را در یک صفحهً معمولی (۸×۸) شطرنج قرار داد. این مسئله ۹۲ جواب دارد که ۱۲ جواب آن منحصر به‌فرد است یعنی بقیه جواب‌ها از تقارن جواب‌های اصلی به‌دست می‌آید.

مسئله n وزیر در صورتی جواب دارد که n مساوی ۱ یا بیشتر از ۳ باشد. یعنی مسئله دو وزیر و سه وزیر راه حلی ندارند.

تاریخچه

این مسئله در سال ۱۸۴۸ توسط شطرنج بازی به نام Max Bezzel عنوان شد و ریاضی دانان بسیاری ازجمله Gauss و Georg Cantor بر روی این مسئله کار کرده و در نهایت آن را به n وزیر تعمیم دادند. اولین راه حل توسط Franz Nauck در سال ۱۸۵۰ ارائه شد که به همان مسئله n وزیر تعمیم داده شد. پس از آن Gunther راه حلی با استفاده از دترمینان ارائه داد که J.W.L. Glaisher آن را کامل نمود. در سال ۱۹۷۹، Edsger Dijkstra Nauck این مسئله را با استفاده از الگوریتم عقب‌گرد حل کرد.

حل مسئله

هشت وزیر را می‌توان با الگوریتم‌های مختلفی مانند تپه نوردی و روش ارضای محدودیت(csp) حل کرد که در زیر روش ارضای محدودیت را بررسی می‌کنیم. هر وزیری در هر ستونی هدفی دارد که همان مکانش در هرستون می‌شود یک گره .در کد زیر تعریف مکان‌ها را داریم:

Variables: { Q1, Q2, Q3, Q4 }

Domain: { (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4) }

Constraints: Alldifferent( Q1, Q2, Q3, Q4 ) and 
for i = 0...n and j = (i+1)...n, k = j-i, Q[i] != Q[j] + k and Q[i] != Q[j] - k

و این الگوریتم که برای جواب هر خانه‌است به دست می‌آید که یک csp است

min-conflicts(csp, max):
initial := complete assignment ;jamiyate avaliye
for 1..max do: ;az 1 .. akharin khane
if initial is a solution: ;if jamiyate tolide javab bod 
return initial ;barmigardanad
var := nextVar() ;da ghire indorat yek motaghair be jelo
value := leastConflicts( var ) ;taeein meghdar
var := value in initial ;gharar dadan meghdar dar motaghair
return failure ;bargash be ebtedaye algoritm

صورت مسئله

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

شمردن تعداد جواب‌ها

جدول زیر تعداد راه حل‌ها برای قرار دادن n وزیر بر روی صفحه n × nنشان می‌دهد. هر دو منحصر به فرد و متمایز، برای تعداد ۱-۱۴،۲۴-۲۶ است.

مسئله ی چند وزیر

  • توجه:

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

روش‌های حل مسئله

الگوریتم عقبگرد

از تکنیک عقبگرد Backtracking برای حل مسائلی استفاده می‌شود که در آن‌ها دنباله‌ای از اشیاء از یک مجموعه مشخص انتخاب می‌شود، به‌طوری‌که این دنباله، ملاکی را در بر می‌گیرد. عقبگرد حالت اصلاح شدهٔ جستجوی عمقی یک درخت است. این الگوریتم همانند جستجوی عمقی است، با این تفاوت که فرزندان یک گره فقط هنگامی ملاقات می‌شوند که گره امید بخش باشد و در آن گره حلی وجود نداشته باشد. با توجه به اینکه هیچ ۲ وزیری نباید همدیگر را گارد کنند و در یک سطر نمی‌توانند باشند، تعداد کل حالت‌ها برای n=۴ برابر ۴*۴*۴*۴=۲۵۶ است. در شطرنج یک وزیر می‌تواند به مهره‌هایی که در خانه‌های عمود یا مورب به وی قرار دارند حمله کند. یا به عبارت ریاضی، اگر ردیفها و ستونهای شطرنج را از یک تا هشت شماره‌گذاری کنیم و وزیر در خانه (i، j) قرار داشته باشد، مهره‌هایی که در خانه‌های (i، m) یا (m، j) یا (i ± m، j ± m) قرار دارند توسط وزیر تهدید می‌شوند.

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

مراحل جستجو برای یافتن جواب را به این صورت دنبال می‌کنیم که: وزیر اول را در ردیف اول و ستون اول قرار می‌دهیم.

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

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

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

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

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

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

در ردیف چهارم اولین خانه‌ای را میابیم که مورد تهدید وزیران پیشین نباشد. این بار خانه را می‌یابیم و وزیر چهارم را در آن خانه قرار می‌دهیم.

به یک جواب می‌رسیم. حال اگر فرض کنیم که این خانه جواب نیست و به مسیر خود ادامه دهیم، احتمالاً” می‌توانیم جوابهای دیگری نیز بیابیم.

شبه کد پیاده‌سازی الگوریتم عقبگرد برای مسئله n وزیر

void queens (index i)
{
	index j;
	if (promising(i))
		if (i == n)
			cout &amp;amp;amp;amp;lt;&amp;amp;amp;amp;lt; col[1] through col[n];
		else
			for (j = 1; j &amp;amp;amp;amp;lt;= n; j++) {
				col[i + 1] = j;
				queens(i + 1);
			}
}
bool promising (index i)
{
	index k;
	bool Switch;
	k = 1;
	Switch = true ;
	while (k &amp;amp;amp;amp;lt; i &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; switch) {
		if (col[i] == col[k] || abs(col[i] – col[k] == i - k))
			switch = false;
		k++;
	}
	return Switch;
}

برنامه زبان C به صورت غیر بازگشتی

# include &amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;gt;

int b[8];

inline static int unsafe(int y) {
        int i, t, x;
        x = b[y];
        for (i = 1; i &amp;amp;amp;amp;lt;= y; i++) {
                t = b[y - i];
                if ((t == x) ||
                     (t == x - i) ||
                     (t == x + i)) {
                        return 1;
               }
       }

        return 0;
}

static void putboard(void) {
        static int s = ۰;
        int x, y;
        printf("\n\nSolution #٪i\n", ++s);
        for (y = 0; y &amp;amp;amp;amp;lt; 8; y++) {
                for (x = 0; x &amp;amp;amp;amp;lt; 8; x++) {
                        printf((b[y] == x) ? "|Q": "|_");
               }
                printf("|\n");
       }
}

int main(void) {
        int y = ۰;
        b[۰] = -۱;
        while (y &amp;amp;amp;amp;gt;= ۰) {
                do {
                        b[y]++;
               } while ((b[y] &amp;amp;amp;amp;lt; 8) &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; unsafe(y));
                if (b[y] &amp;amp;amp;amp;lt; 8) {
                        if (y &amp;amp;amp;amp;lt; 7) {
                                b[++y] = -۱;
                       } else {
                                putboard();
                       }
               } else {
                        y--;
               }
       }

        return 0;
}

برنامه زبان ++C به صورت بازگشتی

  • برنامه زیر برای هشت وزیر نوشته شده‌است با انتخاب اعداد دیگر به جای هشت در define MAXSIZE 8 # می‌توان برای تعداد دیگری وزیر نیز استفاده کرد.
# include &amp;amp;amp;amp;lt;assert.h&amp;amp;amp;amp;gt;
# include &amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;gt;

# define MAXSIZE 8
class EightQueens
{
    int m_size;				
    int m_solution_count;		
    int m_attempt_count;		
    int m_queen[MAXSIZE];		
    bool m_row_inuse[MAXSIZE]; 		
    bool m_diag_rise[MAXSIZE*2];	
    bool m_diag_fall[MAXSIZE*2];	

public:

    EightQueens(int size, bool is_alt) {

	assert(size &amp;amp;amp;amp;lt;= MAXSIZE);

	m_size = size;
	m_solution_count = 0;
	m_attempt_count = 0;

	for (int i = 0; i &amp;amp;amp;amp;lt; m_size; i++) {
	    m_queen[i] = i;
	    m_row_inuse[i] = 0;
	}

	for (int j = 0; j &amp;amp;amp;amp;lt; m_size*2; j++) {
	    m_diag_rise[j] = 0;
	    m_diag_fall[j] = 0;
	}

	if (is_alt) SearchAlt(0);
	else        Search(0);

   }

    int GetSolutionCount() {
	return m_solution_count;
   }

    int GetAttemptCount() {
	return m_attempt_count;
   }

private:

    void SearchAlt(int col){

	if (col == m_size) {
	    m_solution_count++;
	    return;
	}

	for (int row = 0; row &amp;amp;amp;amp;lt; m_size; row++) {
	    m_attempt_count++;
	    if (m_row_inuse[row] == 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; IsDiagValid(col, row)) {
		m_queen[col] = row;
		m_row_inuse[row] = 1;
		SetDiags(col, 1);
		SearchAlt(col+1);
		SetDiags(col, 0);
		m_row_inuse[row] = 0;
		m_queen[col] = -1;
	   }
	}

   }

    void Search(int col) {
	if (col == m_size) {
	    m_solution_count++;
	    return;
	}

	for (int i = col; i &amp;amp;amp;amp;lt; m_size; i++) {
	    if (SwapQueenIfDiagValid(col, i)) {
		Search(col+1);
		UnSwapQueen(col, i);
	   };
	}
   }

    void SwapQueenBasic(int i, int j) {
	    int hold = m_queen[i];
	    m_queen[i] = m_queen[j];
	    m_queen[j] = hold;
   }

    void SetDiags(int col, int val) {
	assert(m_diag_rise[m_queen[col] + col]!= val);
	       m_diag_rise[m_queen[col] + col] =  val;
	assert(m_diag_fall[m_queen[col] - col + m_size]!= val);
	       m_diag_fall[m_queen[col] - col + m_size] =  val;
   }

    bool IsDiagValid(int col, int row) {
	return (m_diag_rise[row + col] == 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;
		m_diag_fall[row - col + m_size] == 0);
   }

    bool SwapQueenIfDiagValid(int i, int j) {
	m_attempt_count++;
	if (IsDiagValid(i, m_queen[j])) {
	    SwapQueenBasic(i, j);
	    SetDiags(i, 1);
            return true;
	}
        return false;
   }

    void UnSwapQueen(int i, int j) {
	SetDiags(i, 0);
	SwapQueenBasic(i, j);
   }

};

void
do_work(bool is_alt)
{
    int size = 8;

    EightQueens puzzle(size, is_alt);
    int soln = puzzle.GetSolutionCount();
    int attempt = puzzle.GetAttemptCount();
    assert(size!= 8 || soln == 92);
    const char* style = is_alt ? "cartesian": "permutation";
    printf("EightQueens[%d] has %d solutions found in %5d attempts using %s search. \n", size, soln, attempt, style);
}

int main()
{
    printf("We should have 92 solutions for 8x8. \n");
    do_work(0);
    do_work(1);
}

انیمیشن روش بازگشتی

 

مسئله چند وزیر

 

الگوریتم مونت کارلو

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

شبه کد پیاده‌سازی الگوریتم مونت کارلو برای الگوریتم عقبگرد مسئله n وزیر

  int ostimate _ n_ queens (int n)
   {
          index i , j , col [1..n];
          int m , mprod , numnodes ;
          set _of_ index  prom _children;
          i = ۰;
          numnodes =۱ ;
          m = ۱;

        mprod  = ۱ ;
        while  (m!= 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; i!= n) {
        mprod = mprod * m ;
        numnodes  = numnodes + mprod * n;
        i ++;
        m = ۰ ;
        prom_childern  = Ø;
        for (j = 1 ; j ≤ n ; j++;) {
                col [i]  = j ;
                if (promising(i)) {

         m++;
         prom_children = prom _ children U {i};
                }
            }
             if (m!= ۰)  {
                 j = random selection from prom _childeren;
                 col [i];
             }
        }
         return numnodes;
     }

روش مکاشفه‌ای

برای حل این مسئله که دارای ۹۲ جواب است، باید تکنیکهایی جهت کاهش حالات، روش Brute Force یا امتحان تک تک جواب‌ها انجام شود. تعداد همه حالاتی که می‌تواند در روش Brute Force چک شود برابر ۱۶٬۷۷۷٬۲۱۶ یا هشت به توان هشت است! یکی از روش‌های حل این مسئله برای n>=4 یا n=1 استفاده از روش مکاشفه‌ای ( heuristic)است:

1- عدد n را بر عدد ۱۲ تقسیم کن و باقی‌مانده را یادداشت کن

۲- به ترتیب اعداد زوج ۲ تا n را در لیستی بنویس

۳- اگر باقی‌مانده ۳ یا ۹ بود، عدد ۲ را به انتهای لیست انتقال بده.

۴- به لیست اعداد فرد ۱ تا n را به ترتیب اضافه کن، اما اگر باقی‌مانده ۸ بود اعداد را دو به دو باهم عوض کند (مثلاً ۱و۳و۵و۷و۹ تبدیل به ۳و۱و۷و۵و۹ میشه)

۵- اگر باقی‌مانده ۲ بود جای ۱ و۳ را با هم عوض کن و ۵ را به انتهای لیست ببر.

۶- اگر باقی‌مانده ۳ یا ۹ بود، اعداد ۱ و ۳ را به انتهای لیست ببر.

۷- حال با استفاده از لیست بدست آمده وزیرها در صفحه شطرنج چیده می‌شوند، به‌طوری‌که جای وزیر ستون اول، اولین عدد لیست، جای وزیر ستون دوم، دومین عدد لیست و…

این الگوریتم یک راه حل برای حل این مسئله‌است، برای بدست آوردن همه حالات از روش‌های دیگری می‌توان استفاده کرد. روش حل مسئله ۱۲ راه حل یکتا دارد که با در نظرگیری تقارن و چرخش به ۹۲ حالت قابل تبدیل است.

روش‌های جستجوی محلی

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

به عنوان مثال فرض کنید در صفحه شطرنج معمولی، ۸ وزیر را به دو روش زیر قرار دهیم:

مسئله ی چند وزیرمسئله ی چند وزیر

در روش چینش سمت چپ ۳ وزیر و در روش چینش سمت راست ۴ وزیر همدیگر را گارد می‌دهند. بنابراین روش چینش قبلی بهینه تر از روش چینش فعلی است. در واقع می‌توان مسئله بهینه‌سازی را به صورت زیر تعریف کرد. فرض کنید S مجموعه همه جواب‌های ممکن برای مسئله باشد. در صورتی S* می‌تواند جواب مسئله باشد که به ازای همه جواب‌های موجود در S، S* بهینه تر از دیگر جواب‌ها باشد. در مسئله ۸ وزیر دیدیم که جوابی بهینه‌است که تعداد گاردهای جفت وزیر آن کمتر باشد.

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

نحوه پیاده‌سازی و طراحی الگوریتم برای انتخاب حالت هسایه در این روش‌های جستجو از اهمیت ویژه‌ای برخوردار است. به عنوان مثال برای مسئله ۸ وزیر می‌توان به شکل‌های زیر حالت‌های همسایگی را تولید کرد:

۱) دو وزیر به تصادف انتخاب شده و جای آن دو باهم عوض گردد.

۲) یکی از وزیرها به تصادف انتخاب شده و شماره سطر آن به تصادف تغییر کند.

۳) ویزیری به تصادف انتخاب شده و یک خانه به سمت بالا یا پایین حرکت کند

مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

9.آشکار سازی صورت با استفاده فیلترهای گابور و شبکه های عصبی

ﭼﻜﻴﺪه: در این مقاله، روشی قدرتمند برای آشکارسازی صورت از زوایای مختلف با استفاده از ترکیب فیلترهای گابور و شبکه ی عصبی بیان می شود. در ابتدا رابطه ی ریاضی تولید فیلتر گابور ورد بررسی قرار می گیرد و در مرحله بعد با برسسی 75 بانک فیلتر مختلف، محدوده مقادیر پارامترهای مؤثر در تولید فیلتر گابور مشخص شده و سپس بهترین مقدار برای آنها به دست می آید. شبکه ی عصبی مورد استفاده در این نوع مقاله از نوع پیش خور با روش بازگشتی است و بردار ورودی این شبکه عصبی از کانوالو تصویر با تنها یک فیلتر گابور با زاویه  و فرکانس  در خوزه فرکانس به دست می آید. الگوریتم پیشنهادی در این مقاله روی 550 تصویر از 2 پایگاه تصویر فرت با پس زمینه ساده و مارکوس وبر با پس زمینه پیچیده آزمایش شده و دقت آشکارسازی آن به ترتیب 98/4% و 95% است. همچنین به کمک الگوریتم ویولا جونز ناحیه صورت را در 550 نمونه تصویر به دست آورده و مقایسه ای بین نتایج به دست آمده از الگوریتم ویولاجونز و آلگوریتم پیشنهادی آورده می شود.
کلمات کلیدی: آشکار سازی صورت، شبکه عصبی، فیلتر گابور، ویژگی های گابور

فایل PDF – در 13 صفحه- نویسنده : ﻣﺤﻤﻮد ﻣﺤﻠﻮﺟﻲ و رضا محمدیان

آشکار سازی صورت با استفاده فیلترهای گابور و شبکه های عصبی

پسورد فایل : behsanandish.com


10.بهبود روش های ناحیه بندی تصاویر MRI مغز انسان با استفاده از عملگر گابور

 

فایل PDF – در 15 صفحه- نویسنده : فرزاد فلاحی

بهبود روش های ناحیه بندی تصاویر MRI مغز انسان با استفاده از عملگر گابور

پسورد فایل : behsanandish.com


11. بهبود سیستم های ایمنی برای تشخیص اجسام در تصویرهای پرتونگاری بار

 

چکیده: بازرسی چشمی بار در فرودگاهها و مراکز حساس مستلزم صرف زمان زيادی است و اجسام در بسياری از موارد خصوصاً زمانی که در موقعيت و زاويههای خاصی قرار گرفته باشند قابل شناسايی با بازرسیهای سريع چشمی نيستند. امروزه از دستگاههای تصويربرداری پرتو ايکس برای تشخيص اجسام در بار استفاده میشود. تصاوير پرتونگاری حاصل به علت پراکندگی فوتونی دارای ميزانی از مهآلودگی هستند و گاهی تشخيص دقيق اجسام با مشکل مواجه میشود. روشهای پردازش تصوير میتوانند به بهبود کنتراست و در نتيجه بهتر شدن قابليت تشخيص اجسام کمک کنند. در پرتونگاری بار سطح نويز و پراکندگی در تصويرهای مختلف با هم تفاوت زيادی دارند که اين موضوع ضرورت استفاده از روشهای پردازش تصوير خودکار را ايجاب میکند. در اين پژوهش از دو روش موجک و صافی گابور با سطح آستانهی خودکار استفاده شده است. نتايج حاصل نشان میدهد تصويرهای بازسازی شده اگرچه در جزييات دارای اختلافاتی هستنند ولی در ميزان تشخيص اجسام توسط افراد تفاوت زيادی ندارند. در هر دو روش کنتراست و قابليت تشخيص اجسام نسبت به تصويرهای اوليه بهبود قابل ملاحظهای يافته است. زمان اجرای الگوريتم موجک گسسته حدود يک هشتم زمان اجرای صافی گابور است که با توجه به اهميت سرعت پردازش تصوير در بازرسی بار برتری قابل ملاحظهای است.

کلید واژهها: پرتونگاری بار،سیستم بازرسی بار،پرتو ایکس، روش موجک گسسته، فیلتر گابور

 

فایل PDF – در 13 صفحه- نویسندگان : سمانه شیخ ربیعی، بهروز رکرک، عفت یاحقی، بهنام آرضابک

بهبود سیستم های ایمنی برای تشخیص اجسام در تصویرهای پرتونگاری بار

پسورد فایل : behsanandish.com


12. ﺑﻬﺒﻮد کیفیت تصویر اﺛﺮاﻧﮕﺸﺖ ﺑﺎ اﺳﺘﻔﺎده از فیلتر بانک ﮐﻤﺎﻧﯽ گابور

ﭼﮑﯿﺪه: ﺗﺄﯾﯿﺪ و ﺷﻨﺎﺳﺎﯾﯽ ﻫﻮﯾﺖ از روی ﺗﺼﻮﯾﺮ اﺛﺮاﻧﮕﺸﺖ ارﺗﺒﺎط ﻣﺴﺘﻘﯿﻤﯽ ﺑﺎ ﮐﯿﻔﯿﺖ اﯾﻦ ﺗﺼـﻮﯾﺮ دارد. در اﯾـﻦ ﻣﻘﺎﻟـﻪ روش ﺟﺪﯾـﺪی ﺑﺮای ﺑﻬﺒﻮد ﮐﯿﻔﯿﺖ ﺗﺼﻮﯾر اﺛﺮ اﻧﮕﺸﺖ ﺑﺎ اﺳﺘﻔﺎده از ﻓﯿﻠﺘﺮ ﺑﺎﻧﮏ اﺳـﺖ ﮐﻤﺎﻧﯽ ﮔـﺎﺑﻮر اراﺋـﻪ ﺷـﺪه است. ﻓﯿﻠﺘـﺮ ﺑﺎﻧـﮏ ﮐﻤـﺎﻧﯽ ﮔـﺎﺑﻮر در ﺣﻘﯿﻘﺖ ﻧﻮﻋﯽ ﻓﯿﻠﺘﺮ ﺑﺎﻧﮏ ﮔﺎﺑﻮر اﺳﺘﺎﻧﺪارد ﻣﺘﺒﺤﺮ ﺷﺪه ﺑﺮای اﺳﺘﻔﺎده روی ﺗﺼﺎوﯾﺮ اﺛﺮ اﻧﮕﺸﺖ می ﺑﺎﺷﺪ. ارزﯾﺎﺑﯽ ﻣﯿـﺰان ﺗﻮﻓﯿـﻖ روش در بهبود ﮐﯿﻔﯿﺖ ﺗﺼﺎوﯾﺮ اﺛﺮ اﻧﮕﺸﺖ ﺑﻪ دو روش اﻧﺠﺎم ﺷﺪه است. در روش اول، ﻣﻘﺎﯾﺴﻪ ﺑﯿﻦ ﺗﺼﺎوﯾﺮ اﺻـﻠﯽ و ﺗﺼـﺎوﯾﺮ ﺑﻬﺒﻮد ﯾﺎﻓﺘﻪ ﺑﺮاﺳﺎس ﻧﺘﺎﯾﺞ ﺑﺪﺳﺖ آﻣﺪه از ارزﯾﺎﺑﯽ ﺗﺄﯾﯿﺪ و ﺷﻨﺎﺳﺎﯾﯽ ﻫﻮﯾﺖ ﺻﻮرت ﭘﺬﯾﺮﻓﺘﻪ اﺳﺖ که ﺳﯿﺴﺘﻢ ﺗﺸﺨﯿﺺ ﻫﻮﯾـﺖ ﭘﯿﺸﻨﻬﺎدی ﻣﺒﺘﻨﯽ ﺑﺮ معیار ﻫﻤﺒﺴﺘﮕﯽ ﻫﯿﺴﺘﻮﮔﺮام ﻧﺮﻣﺎﻟﯿﺰه ﺷﺪه ویژگی های تصویر آماری باینری شده (BSIF) است. در روش دوم، از ﻣﻌﯿﺎر ﻧﺴﺒﺖ ﺳﯿﮕﻨﺎل ﺑﻪ ﻧﻮﯾﺰ ﺑﯿﺸﯿﻨﻪ (PSNR) به منظور ارزﯾﺎﺑﯽ میزان بهبود ﮐﯿﻔﯿﺖ، اﺳﺘﻔﺎده ﺷـﺪه است. دو ﭘﺎﯾﮕـﺎه DBI و DBII برای اجرای روش و ارزیابی نتایج مورد استفاده ﻗﺮار گرفته اﻧﺪ .ﻧﺮخ ﺗﺴﺎوی ﺧﻄﺎی (EER) ﺗﺄﯾﯿﺪ ﻫﻮﯾـﺖ ﺑﺮای ﺗﺼﺎوﯾﺮ اﺻﻠﯽ از (ﺑﻪ ترتیب % ۱۵/۸۹ و  ۱۱/۷۰%) به ( % ۱۱/۳۵ و  ۸/۰۰%) ﺑـﺮای ﺗﺼـﺎوﯾﺮ ﺑﻬﺒـﻮد ﯾﺎﻓﺘـﻪ کاهش ﯾﺎﻓﺘﻪ اﺳﺖ .ﺑﺮای ﺗﺸﺨﯿﺺ ﻫﻮﯾﺖ ﻧﯿﺰ ﻧﺮخ ﻣﺮﺗﺒﻪ اول ﻣﯿﺰان ﺑﺎزﺷﻨﺎﺳـﯽ ﺻـﺤﯿﺢ ﺑـﺮای ﺗﺼـﺎوﯾﺮ اصلی از مقادیر( ۶۹/۲۸% و ۷۱/۱۶ %) به (۷۸/۸۰% و ۸۱/۷۰ %) ﺑﺮای ﺗﺼﺎوﯾﺮ ﺑﻬﺒﻮد ﯾﺎﻓﺘﻪ اﻓﺰاﯾﺶ ﯾﺎﻓﺘﻪ است.  ﻣﯿﺰان متوسط PSNR ﻣﺮﺑﻮط ﺑﻪ ﺗﺼﺎوﯾﺮ ﺑﻬﺒﻮد ﯾﺎﻓﺘﻪ ﻧﯿﺰ از ﻣﻮرد ﻣﺸﺎﺑﻪ ﺑﺮای ﺗﺼﺎوﯾﺮ اﺻﻠﯽ ﺑﯿﺸﺘﺮ اﺳﺖ.

ﮐﻠﯿﺪ واژهﻫﺎ: ﮐﯿﻔﯿﺖ ﺗﺼﻮﯾﺮ، ﻓﯿﻠﺘﺮﺑﺎﻧﮏ اﺛﺮاﻧﮕﺸﺖ، ﺑﻬﺒﻮد ﮐﻤﺎﻧﯽ ﮔﺎﺑﻮر

 

فایل PDF – در 17 صفحه- نویسندگان : مهران تقی پور گرجی کلایی، سید محمد رضوی و ناصر مهرشاد

ﺑﻬﺒﻮد کیفیت تصویر اﺛﺮاﻧﮕﺸﺖ ﺑﺎ اﺳﺘﻔﺎده از فیلتر بانک ﮐﻤﺎﻧﯽ گابور

پسورد فایل : behsanandish.com


13. تشخیص چهره با استفاده از PCA و فیلتر گابور

 

فایل PDF – در 8 صفحه- نویسندگان : حمیدرضا قجر، محسن سریانی و عباس کوچاری

تشخیص چهره با استفاده از PCA و فیلتر گابور

پسورد فایل : behsanandish.com


14. تعیین توزیع دانه بندی سنگ دانه های بتن و آسفالت با استفاده از استخراج ویژگی های گابور و شبکه های عصبی

چکیده: توزیع ابعادی سنگدانه های تشکیل دهنده بتن و آسفالت، از مهمترین پارامترها در کنترل طرحهای اختلاط بتن و آسفالت است که میتواند بر کیفیت نهایی، مقاومت و دوام بتن و آسفالت تاثیر گذار باشد. بهمنظور ارزیابی درصد اختلاط سنگدانه ها، روش پردازش تصویری دیجیتال یک روش غیر مستقیم، سریع و قابل اعتماد است. در این تحقیق بر پایه یکی از روشهای استخراج ویژگیهای دیداری تصویر (فیلترهای گابور) و استفاده از شبکه های عصبی، الگوریتمی جهت تعیین توزیع دانه بندی تصاویر سنگدانه های تشکیل دهنده بتن و آسفالت ارائه شده است. تعداد 100 تصویر از سنگدانه های تشکیل دهنده بتن و آسفالت برای آموزش شبکه عصبی به کار برده شد. سپس نتایج حاصله با نتایج تخمین خودکار دانه بندی سنگدانه ها در نرم افزار Split-Desktop و همچنین تجزیه سرندی مقایسه شد.نتایج به دست آمده بیانگر یک بهبود کلی در ارزیابی توزیع اندازه سنگدانه های تشکیل دهنده بتن و آسفالت و کاهش خطای 67% با استفاده از روش پیشنهادی نسبت به تخمین خودکار نرم افزار Split-Desktop است. همچنین در ارزیابی اندازه های F10 تا F100، روش پیشنهادی بهبود 62% را نشان داد.

واژه های کلیدی: توزیع دانه بندی، سنگدانه های بتن و آسفالت، استخراج ویژگی تصویر، فیلترهای گابور، شبکه های عصبی.

 

فایل PDF – در 14 صفحه- نویسندگان : هادی یعقوبی، حمید منصوری، محمد علی ابراهیمی فرسنگی و حسین نظام آبادی پور

تعیین توزیع دانه بندی سنگ دانه های بتن و آسفالت با استفاده از استخراج ویژگی های گابور و شبکه های عصبی

پسورد فایل : behsanandish.com


15. خوشه بندی سبک نگارش دست نوشته برون خط فارسی

 

چکیده– ﻫﺪﻑ ﺍﻳﻦ ﭘﺎﻳﺎﻥ ﻧﺎﻣﻪ، ﻳﺎﻓﺘﻦ ﻭ ﺍﺳﺘﺨﺮﺍﺝ ﻭﻳﮋﮔﻲ ﻫﺎﻳﻲ ﺍﺳﺖ ﮐﻪ ﺑﺮ ﻣﺒﻨﺎﻱ ﺁﻥ ﺑﺘﻮﺍﻥ ﺩﺳﺖ ﺧﻂ ﻓﺎﺭﺳﻲ ﺭﺍ ﺧﻮﺷﻪ ﺑﻨﺪﻱ ﮐﺮﺩ .ﺩﺭ ﺍﻳﻦ ﮐﺎﺭ، ﺩﺭ ﺍﺑﺘﺪﺍ ﺑﺮ ﺭﻭﻱ ﻭﻳﮋﮔﻲ ﻫﺎﻱ ﻣﺒﺘﻨﻲ ﺑﺮ ﺑﺎﻓﺖ، ﺗﻤﺮﮐﺰ ﺷﺪﻩ ﺍﺳﺖ .ﺍﻳﻦ ﻭﻳﮋﮔﻲ ﻫﺎ ﺷﺎﻣﻞ ﺩﻭ ﺩﺳﺘﻪ ﻭﻳﮋﮔﻲ ﺁﻣﺎﺭﻱ ﻣﺎﺗﺮﻳﺲ ﺑﺎﻫﻢ ﺁﻳﻲ ﻭ ﻭﻳﮋﮔﻲ ﻣﺒﺘﻨﻲ ﺑﺮ ﺗﺒﺪﻳﻞ ﮔﺎﺑﻮﺭ ﺍﺳﺖ .ﺑﺮﺍﻱ ﺍﺳﺘﺨﺮﺍﺝ ﺍﻳﻦ ﻭﻳﮋﮔﻲﻫﺎ، ﻳﮏ ﺑﺎﻓﺖ ﻣﻨﺎﺳﺐ ﺩﺭ ﺍﺑﻌﺎﺩ ۱۰۲۴×۱۰۲۴ ﻣﺴﺘﻘﻞ ﺍﺯ ﻣﺤﺘﻮﺍﻱ ﺳﻨﺪ، ﺍﺯ ﺗﺼﻮﻳﺮ ﺩﺳﺘﻨﻮﺷﺘﻪ ﺍﻳﺠﺎﺩ ﻣﻲ ﺷﻮﺩ .ﺍﺯ ﻭﻳﮋﮔﻲ ﻫﺎﻱ ﺩﻳﮕﺮﻱ ﮐﻪ ﺩﺭ ﺍﻳﻦ ﮐﺎﺭ ﺍﺯ ﺁﻥ ﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ، ﺗﻌﺪﺍﺩﻱ ﻭﻳﮋﮔﻲ ﺳﺎﺧﺘﺎﺭﻱ ﻣﺒﺘﻨﻲ ﺑﺮ ﻣﻨﺤﻨﻲ ﭘﻴﺮﺍﻣﻮﻧﻲ ﺍﺳﺖ .ﺍﻳﻦ ﻭﻳﮋﮔﻲ ﻫﺎ ﺭﺍ ﺍﺯ ﻫﺮ ﻳﮏ ﺍﺯ ﺗﺼﺎﻭﻳﺮ ﻣﻮﺟﻮﺩ ﺩﺭ ﻳﮏ ﻣﺠﻤﻮﻋﻪ ﺩﺍﺩﻩ ﺍﺯ 97 ﺩﺳﺘﻨﻮﺷﺘﻪ ﻓﺎﺭﺳﻲ ﮐﻪ ﺩﺍﺭﺍﻱ ﻣﺘﻮﻥ ﻣﺘﻔﺎﻭﺗﻲ ﺑﻮﺩﻧﺪ، ﺍﺳﺘﺨﺮﺍﺝ ﮐﺮﺩﻳﻢ ﻭ ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻢ k ﻣﻴﺎﻧﮕﻴﻦ ﻭ ﺷﺒﮑﻪ ﻋﺼﺒﻲ ﻧﮕﺎﺷﺖ ﻭﻳﮋﮔﻲ ﺧﻮﺩ ﺳﺎﻣﺎﻥ، ﺑﺮﺍﻱ ﺧﻮﺷﻪ ﺑﻨﺪﻱ ﺍﻳﻦ ﻭﻳﮋﮔﻲ ﻫﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺷﺪﻩ ﺍﺳﺖ.

ﺑﺮﺍﻱ ﺍﺭﺯﻳﺎﺑﻲ ﺍﻳﻦ ﻭﻳﮋﮔﻲ ﻫﺎ، ﻳﮏ ﺭﻭﺵ ﺍﺭﺯﻳﺎﺑﻲ ﺑﺮ ﻣﺒﻨﺎﻱ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺧﻮﺷﻪ ﺑﻨﺪﻱ k ﻣﻴﺎﻧﮕﻴﻦ، ﻃﺮﺍﺣﻲ ﮐﺮﺩﻩ ﺍﻳﻢ .ﺩﺭ ﺍﻳﻦ ﺍﻟﮕﻮﺭﻳﺘﻢ ﺍﺯ ﻣﻌﻴﺎﺭ ﻣﻘﺎﻳﺴﻪ ﺑﺎﻳﻨﺮﻱ ﮊﺍﮐﺎﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﮐﺮﺩﻩ ﺍﻳﻢ، ﻫﻢ ﭼﻨﻴﻦ ﺑﺮﺍﻱ ﻣﺤﺎﺳﺒﻪ ﻣﺮﺍﮐﺰ ﺧﻮﺷﻪ ﺩﺭ ﻫﺮ ﺩﻭﺭﻩ ﺗﮑﺮﺍﺭ ﺍﺯ ﺍﻟﮕﻮﺭﻳﺘﻢ k ﻣﻴﺎﻧﮕﻴﻦ، ﺍﺯ ﺭﻭﺵ ﺍﻧﺘﺨﺎﺏ ﺩﺍﺩﻩ ﭼﺮﺥ ﺭﻭﻟﺖ، ﺑﻬﺮﻩ ﮔﺮﻓﺘﻪﺍﻳﻢ.

ﻧﺘﺎﻳﺞ ﺑﺪﺳﺖ ﺁﻣﺪﻩ، ﻧﺸﺎﻥ ﻣﻲ ﺩﻫﺪ ﺑﺎ ﺗﺮﮐﻴﺐ ﺩﻭ ﻧﻮﻉ ﺍﺯ ﻭﻳﮋﮔﻲ ﻫﺎﻱ ﻣﺒﺘﻨﻲ ﺑﺮ ﻣﻨﺤﻨﻲ ﭘﻴﺮﺍﻣﻮﻧﻲ، ﻧﺮﺥ ﺧﻮﺷﻪ بندی 75 ﺩﺭﺻﺪ ﺍﺳﺖ ﮐﻪ ﻧﺴﺒﺖ ﺑﻪ ﺳﺎﻳﺮ ﺭﻭﺵﻫﺎﻱ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﺩﺭ ﺍﻳﻦ ﮐﺎﺭ، ﻧﺮﺥ ﺑﻬﺘﺮﻱ ﺭﺍ ﺩﺭ ﺑﺮﺩﺍﺷﺘﻪ ﺍﺳﺖ .

ﮐﻠﻴﺪ ﻭﺍﮊﻩ: ﺳﺒﮏ ﻧﮕﺎﺭﺵ، ﺧﻮﺷﻪ ﺑﻨﺪﻱ، ﺑﺎﻓﺖ، ﻓﻴﻠﺘﺮ ﮔﺎﺑﻮﺭ، ﻣﺎﺗﺮﻳﺲ ﺑﺎ ﻫﻢ ، ﺁﻳﻲ، ﻣﻨﺤﻨﻲ ﭘﻴﺮﺍﻣﻮﻧﻲ، ﮊﺍﮐﺎﺭﺩ ﭼﺮﺥ ﺭﻭﻟﺖ

فایل PDF – در 20 صفحه- نویسنده : فاطمه ولایتی

خوشه بندی سبک نگارش دست نوشته برون خط فارسی

پسورد فایل : behsanandish.com


16. شاخص گذاری بر روی تصاویر با استفاده از موجک های گابور و ممان های لژاندر

 

چکیده- در این مقاله، یک سیستم جدید شاخص گذاری و بازیابی تصاویر (CBIR) با استفاده از موجک های گابور و ممان های لژاندار پیشنهاد گردیده است. از انجائیکه موجک های گایور قادر به استخراج مطلوب اطلاعات خطوط و لبه های تصاویر در مقیاس ها و درجات تفکیک مختلف می باشند و از طرف دیگر، این تبدیل تنها تابعی است که می تواند حد تئوری دقت تفکیک توأم اطلاعات در هر حوزه مکان و فرکانس را حاصل نماید، در اینجا از آن به منظور تشخیص محتوای بصری تصاویر به کار گرفته شده است. هم چنین ممانهای لژاندار جهت بهبود نتایج حاصل از عمل بازیابی الگوریتم استفاده شده اند. کوچکی نسبی طول بردار ویژگی (58)، از مزایای این روش می باشد که عمل بازیابی را تسریع می بخشد. همچنین به دلیل آنکه اطلاعات رنگ تصاویر مورد استفاده قرار نمی گیرند، الگوریتم قادر به تشخیص تصاویر مشابه با رنگ های متفاوت نیز خواهد بود. نتایج حاصل از اجرای این سیستم، راندمان بالای آن را در تشخیص تصاویر مشابه مورد تأییید قرار می دهد.

واژگان کلیدی: شاخص گذاری و بازیابی تصاویر، فیلترهای گابور، ممانهای لژاندار، سیستم های مستقل از رنگ، پردازش تصویر.

 

فایل PDF – در 8 صفحه- نویسندگان : اسماعیل فرامرزی، ابوالقاسم صیادیان، علیرضا احمدیان

شاخص گذاری بر روی تصاویر با استفاده از موجک های گابور و ممان های لژاندر

پسورد فایل : behsanandish.com


17. طراحی بخش دریافت و پردازش تصویر برای یک پروتز بینایی

 

ﭼﮑﯿﺪه ﺗﻼش ﻫﺎ ﺑﺮاي ﺗﺤﻘﻖ ﭘﺮوﺗﺰﻫﺎي ﺑﯿﻨﺎﯾﯽ از دﻫﻪ ﮔﺬﺷﺘﻪ آﻏﺎز ﺷﺪه اﺳﺖ. ﭘﺮوﺗﺰﻫﺎي ﺑﯿﻨﺎﯾﯽ ﺟﺎﻧﺸﯿﻨﯽ ﺑﺮاي ﺳﯿﺴﺘﻢ ﺑﯿﻨﺎﯾﯽ ﻣﻌﯿﻮب ﻫﺴﺘﻨﺪ ﺗﺎ ﺑﺘﻮاﻧﻨﺪ ﺑﯿﻨﺎﯾﯽ را ﺑﻪ اﻓﺮاد ﻧﺎﺑﯿﻨﺎ ﺑﺎزﮔﺮداﻧﻨﺪ. ﺑﺎ وﺟﻮد اﯾﻦ ﺗﻼش ﻫﺎ، داﻧﺸﻤﻨﺪان ﻣﻮﻓﻖ ﺑﻪ ﺳﺎﺧﺖ ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ ﮐﻪ ﺑﺘﻮاﻧﺪ ﺟﺎﻧﺸﯿﻦ ﻣﻨﺎﺳﺒﯽ ﺑﺮاي ﺳﯿﺴﺘﻢ ﺑﯿﻨﺎﯾﯽ ﺷﻮد، ﻧﺸﺪه اﻧﺪ.
ﭘﺮدازش ﺗﺼﻮﯾﺮ در ﭘﺮوﺗﺰﻫﺎي ﺑﯿﻨﺎﯾﯽ ﺑﺮاي اﻓﺰاﯾﺶ درك ﺗﺼﻮﯾﺮي ﻓﺮد ﻧﺎﺑﯿﻨﺎ از ﻣﺤﯿﻂ اﻃﺮاف ﻫﻨﮕﺎم اﺳﺘﻔﺎده از ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ ﮐﺎرﺑﺮد دارد. در اﯾﻦ رﺳﺎﻟﻪ ﯾﮏ روش ﺟﺪﯾﺪ ﺑﺮ ﻣﺒﻨﺎي ﻓﯿﻠﺘﺮ ﮔﺎﺑﻮر و ﺗﺒﺪﯾﻞ ﮐﺴﯿﻨﻮﺳﯽ ﮔﺴﺴﺘﻪ ﺑﺮاي اﺳﺘﻔﺎده درﯾﮏ ﺳﯿﺴﺘﻢ ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ ﻣﻌﺮﻓﯽ ﺷﺪه اﺳﺖ. در اداﻣﻪ اﻟﮕﻮرﯾﺘﻢ ﻫﺎي ﺟﺪﯾﺪ و ﭘﺮدازش ﺗﺼﻮﯾﺮ ﭘﯿﺸﻨﻬﺎد ﺷﺪه در اﯾﻦ رﺳﺎﻟﻪ ارزﯾﺎﺑﯽ و ﻣﻘﺎﯾﺴﻪ ﺷﺪه اﻧﺪ و اﻟﮕﻮرﯾﺘﻢ ﭘﯿﺸﻨﻬﺎد ﺷﺪه ﺑﺎ 78 % ﻧﺮخ ﺑﺎزﺷﻨﺎﺳﯽ، ﮐﺎراﯾﯽ ﺑﻬﺘﺮي ﻧﺴﺒﺖ ﺑﻪ دﯾﮕﺮ روش ﻫﺎ داﺷﺘﻪ اﺳﺖ. ﺑﻪ ﻣﻨﻈﻮر ارزﯾﺎﺑﯽ اﻟﮕﻮرﯾﺘﻢ ﻫﺎي ﭘﯿﺸﻨﻬﺎدي و ﻫﻤﭽﻨﯿﻦ ﺑﺮاي ﺑﻪ ﮐﺎر ﮔﯿﺮي در ﻧﻤﻮﻧﻪ اوﻟﯿﻪ ﺳﯿﺴﺘﻢ ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ، اﯾﻦ ﭘﺮدازش ﻫﺎ ﺑﻪ ﺻﻮرت ﺳﺨﺖ اﻓﺰاري ﭘﯿﺎده ﺳﺎزي و آزﻣﺎﯾﺶ ﺷﺪه اﻧﺪ. ﺑﺮاي ﭘﯿﺎده ﺳﺎزي ﺳﺨﺖ اﻓﺰاري اﻟﮕﻮرﯾﺘﻢ ﻫﺎي ﭘﺮدازﺷﯽ از ﺑﺮد MINI2440 اﺳﺘﻔﺎده ﺷﺪه اﺳﺖ. ﺑﺮاي آزﻣﺎﯾﺶ ﻫﺎي ﻣﺮﺑﻮﻃﻪ، ﻣﺠﻤﻮﻋﻪ اي از اﻧﻮاع ﻣﺨﺘﻠﻒ ﺗﺼﺎوﯾﺮ ﺛﺎﺑﺖ و ﻫﻤﭽﻨﯿﻦ ﺗﺼﺎوﯾﺮ متحرک درﯾﺎﻓﺖ ﺷﺪه ﺗﻮﺳﻂ ﯾﮏ دورﺑﯿﻦ ﻣﻮرد اﺳﺘﻔﺎده ﻗﺮار ﮔﺮﻓﺘﻪ اﺳﺖ. تصاویر ﺑﺎ ﻧﺮخ 15 ﻓﺮﯾﻢ در ثانیه درﯾﺎﻓﺖ، ﭘﺮدازش و ﺑﺎ ﭘﺮوﺗﮑﻞ ﻣﻌﺮﻓﯽ ﺷﺪه و ﮐﺪﯾﻨﮓ ﻣﻨﭽﺴﺘﺮ ﺑﻪ ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ ارﺳﺎل ﻣﯽ ﺷﻮﻧﺪ.

ﮐﻠﻤﺎت ﮐﻠﯿﺪي: ﭘﺮوﺗﺰ ﺑﯿﻨﺎﯾﯽ، ﭘﺮدازش ﺗﺼﻮﯾﺮ، ﻓﯿﻠﺘﺮ ﮔﺎﺑﻮر، ﺗﺒﺪﯾﻞ ﮐﺴﯿﻨﻮﺳﯽ ﮔﺴﺴﺘﻪ، MINI2440

 

فایل PDF – در 20 صفحه- نویسنده : علی شاکر

طراحی بخش دریافت و پردازش تصویر برای یک پروتز بینایی

پسورد فایل : behsanandish.com

مجموعه مقالات فیلتر گابور (Gabor Filter) قسمت 1
مجموعه مقالات فیلتر گابور (Gabor Filter) قسمت 2

تاريخچه

الگوريتم SVM اوليه در ۱۹۶۳ توسط Vladimir Vapnik ابداع شد و در سال ۱۹۹۵ توسطVapnik و Corinna Cortes براي حالت غيرخطي تعميم داده شد.

ماشين بردار پشتيباني (Support vector machines) يکي از روش‌هاي يادگيري بانظارت(Supervised learning) است که از آن براي طبقه‌بندي و رگرسيون استفاده مي‌کنند.

اين روش از جمله روش‌هاي نسبتاً جديدي است که در سال‌هاي اخير کارايي خوبي نسبت به روش‌هاي قديمي‌تر براي طبقه‌بندي از جمله شبکه‌هاي عصبي پرسپترون نشان داده است. مبناي کاري دسته‌بنديکنندة SVM دسته‌بندي خطي داده‌ها است و در تقسيم خطي داده‌ها سعي مي‌کنيم خطي را انتخاب کنيم که حاشيه اطمينان بيشتري داشته باشد. حل معادلة پيدا کردن خط بهينه براي داده‌ها به وسيله روش‌هايQP (Quadratic Programming) که روش‌هاي شناخته شده‌اي در حل مسائل محدوديت‌دار هستند صورت مي‌گيرد.

SVM از يک تکنيک که kernel trick ناميده مي شود، براي تبديل داده هاي شما استفاده مي کند و سپس بر اساس اين تبديل، مرز بهينه بين خروجي هاي ممکن را پيدا مي کند. به عبارت ساده تبديلات بسيار پيچيده را انجام مي دهد، سپس مشخص مي کند چگونه داده هايتان را بر اساس برچسب ها يا خروجي هايي که تعريف کرده ايد، جدا کنيد.

يکي از روش هايي که در حال حاضر به صورت گسترده براي مسئله دسته بندي (Classification) مورد استفاده قرار مي گيرد، روش ماشين بردار پشتيبان (SVM) است. شايد به گونه اي بتوان محبوبيت کنوني روش ماشين بردار پشتيبان را با محبوبيت شبکه هاي عصبي در دهه گذشته مقايسه کرد. علت اين قضيه نيز قابليت استفاده اين روش در حل مسائل گوناگون مي باشد، در حاليکه روش هايي مانند درخت تصميم گيري را نمي توان به راحتي در مسائل مختلف به کار برد.

کاربردهاي SVM

الگوريتم  SVM، جز الگوريتم هاي تشخيص الگو دسته بندي مي شود. از الگوريتم SVM، در هر جايي که نياز به تشخيص الگو يا دسته بندي اشيا در کلاس هاي خاص باشد مي توان استفاده کرد. در ادامه به کاربرد هاي اين الگوريتم به صورت موردي اشاره مي شود:

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

ايده اصلي SVM

l      با فرض اينکه دسته ها بصورت خطي جداپذير باشند، ابرصفحه هائي با حداکثر حاشيه(maximum margin)  را بدست مي آورد که دسته ها را جدا کنند.

l      در مسايلي که داده ها بصورت خطي جداپذير نباشند، داده ها به فضاي با ابعاد بيشتر نگاشت پيدا مي کنند تا بتوان آنها را در اين فضاي جديد بصورت خطي جدا نمود.

l      در يک فرايند يادگيري که شامل دو کلاس مي­باشد، هدف SVM پيدا کردن بهترين تابع براي طبقه­بندي مي­باشد به نحوي که بتوان اعضاي دو کلاس را در مجموعه داده­ها از هم تشخيص داد. معيار بهترين طبقه­بندي به­صورت هندسي مشخص مي­شود، براي مجموعه داده­هايي که به­صورت خطي قابل تجزيه هستند. به­طور حسي آن مرزي که به­صورت بخشي از فضا تعريف مي­شود يا همان تفکيک بين دو کلاس بوسيله hyperplane تعريف مي­شود. همين تعريف هندسي به ما اجازه مي­دهد تا کشف کنيم که چگونه مرزها را بيشينه کنيم ولو اينکه تعداد بيشماري hyperplane داشته باشيم و فقط تعداد کمي، شايستگي راه حل براي SVM دارند.

مسئله جداسازي خطي: Linear Discrimination

اگر دو دسته وجود داشته باشند که بصورت خطي از هم جداپذير باشند، بهترين جدا کننده اين دو دسته چيست؟

الگوريتم هاي مختلفي از جمله  پرسپترون ميتوانند اين جداسازي را انجام دهند.

آيا همه اين الگوريتمها بخوبي از عهده اين کار بر مي آيند؟

 

آشنايي با مفاهيم ابتدايي

خط يا ابر صفحه جدا کننده:

هدف: پيدا کردن بهترين خط ( ابر صفحه) که دو دسته را از هم جدا کند. در حالت دو بعدي معادله اين خط بصورت زير است:

در حالت n  بعدي خواهيم داشت:

حداکثر حاشيه (maximum margin)

بر طبق قضيه اي در تئوري يادگيري اگر مثالهاي آموزشي بدرستي دسته بندي شده باشند، از بين جداسازهاي خطي، آن جداسازي که حاشيه داده هاي آموزشي را حداکثر مي کند، خطاي تعميم را حداقل خواهد کرد.

چرا حداکثر حاشيه؟

¢     به نظر مي رسد که مطمئن ترين راه باشد.

¢     تئوري هائي برمبناي VC dimension وجود دارد که مفيد بودن آنرا اثبات مي کند.

¢     بطور تجربي اين روش خيلي خوب جواب داده است.

¢     دليل اينکه SVM روي بزرگ­ترين مرز براي hyperplane پافشاري مي­کند اين­ست که قضيه قابليت عموميت بخشيدن به الگوريتم را بهتر تامين مي­کند. اين نه تنها به کارايي طبقه­بندي و دقت  آن روي داده­هاي آزمايشي کمک مي­کند، فضا را نيز براي طبقه­بندي بهتر داده­هاي آتي مهيا مي­کند.

بردار پشتيبان

نزديکترين داده هاي آموزشي به ابر صفحه هاي جدا کننده بردار پشتيبان ناميده مي شوند.

ماشين بردار پشتيبان خطي

ماشين بردار پشتيبان يک روش يادگيري نسبتا جديد است که اغلب براي کلاسبندي باينري مورد استفاده واقع مي شود. فرض کنيد L مشاهده داريم که هر مشاهده مشتمل بر زوج هاي است که در آن . بردار ورودي و  يک مقدار دو وضعيتي (1- يا 1+) است. ايده ي ماشين بردار پشتيبان مي کوشد، ابرصفحاتي در فضا رسم کند که عمل تمايز نمونه هاي کلاس هاي مختلف داده ها را بطور بهينه انجام دهد. مي توان يک ابرصفحه را از طريق رابطه زير نشان داد:

براي يک بردار خطي b با وزن w ، حاشيه جداسازي عبارتست از فاصله ي بين ابرصفحه تعريف شده توسط رابطه ي فوق و نزديکترين ويژگي به آن. هدف ماشين بردار پشتيبان يافتن ابرصفحه اي ست که بيشترين حاشيه ي جداسازي را داشته باشد. مهمترين وظيفه SVM ، يافتن پارامترهاي w0 و b0 بر اساس بردارهاي آموزشي داده شده، براي اين ابرصفحه بهينه است. براي يک بردار ويژگي X، فاصله تا ابرصفحه بهينه به صورت زير است:

از رابطه بالا نتيجه مي شود که ماکزيموم کردن حاشيه جداسازي بين الگوها و ابرصفحه، معادلست با مينيموم کردن فرم اقليدسي بردار وزن w. بنابراين مساله بهينه سازي مقيد را مي توان به صورت زير تعريف کرد:

براي حل اين مساله، تابع لاگرانژ زير را تشکيل داده و حل مي کنيم:

لاگرانژين L بايد نسبت به متغيرهاي اوليه  bو w مينيموم و نسبت به متغيرهاي دوگان ماکزيموم شود. با مساوي صفر قراردادن مشتق L نسبت به b،w:

به معادلات زير خواهيم رسيد:

مجموعه جواب، بسطي از نمونه هاي آموزشي است که مقدار  متناظر با آن ها، يک مقدار غير صفر است. اين نمونه هاي آموزشي خاص به بردارهاي پشتيبان مشهورند. بردارهاي پشتيبان روي مرز حاشيه قرار دارند. مابقي نمونه هاي آموزشي در اين قسمت نقشي ندارند.

تمايز نمونه هاي دو کلاس با ابرصفحه ي بهينه

با قرار دادن 7 و 8 در  به مساله دوگان ولف زير خواهيم رسيد:

حل اين مساله دوگان ضرايب لاگرانژ را به ما مي دهد. تابع ابرصفحه متمايز کننده را مي توان به صورت زير نوشت:

ماشين بردار پشتيبان براي بردارهاي ورودي جدايي ناپذير:

اغلب در عمل، يافتن يک ابرصفحه متمايز کننده به راحتي امکان پذير نيست. زيرا مثلا يک نويز قوي مي تواند باعث ايجاد رويهم افتادگي کلاس ها شود. در اين حالت از متغير هايي به نام متغيرهاي کمبود(Slack Variables) استفاده مي کنيم. به گونه اي که شرايط زير برقرار باشند:

حال يک تعميم خوب براي ابرصفحه ي متمايز کننده، با کنترل ظرفيت کلاسبند (از طريق ) و همچنين تعداد خطاهاي مرحله آموزش بدست مي آيد. مساله بهينه سازي به صورت زير تعريف خواهد شد:

مساله دوگان به فرم زير خواهد بود:

ماشين بردار پشتيبان غيرخطي:

ابرصفحه جداکننده بهينه اولين بار توسط Vapnik در سال ۱۹۶۳ ارائه شد که يک دسته کننده خطي بود. در سال ۱۹۹۲ ،Bernhard Boser ،  Isabelle GuyonوVapnik راهي را براي ايجاد دسته بند غيرخطي، با استفاده قرار دادن هسته براي پيدا کردن ابرصفحه با بيشتر حاشيه، پيشنهاد دادند. الگوريتم نتيجه شده ظاهرا مشابه است، به جز آنکه تمام ضرب هاي نقطه اي با يک تابع هسته غيرخطي جايگزين شده اند. اين اجازه مي دهد، الگوريتم، براي ابرصفحه با بيشترين حاشيه در يک فضاي ويژگيِ تغييرشکل داده، مناسب باشد. ممکن است، تغييرشکل غيرخطي باشد و فضاي تغيير يافته، داراي ابعاد بالاتري باشد. به هر حال دسته کننده، يک ابرصفحه در فضاي ويژگي با ابعاد بالا است، که ممکن است در فضاي ورودي نيز غيرخطي باشد.

در حالت غيرخطي، مي توان با اعمال پيش پردازش داده ها، مساله را به فضايي برد که در آن جا با يک ابرصفحه ساده قابل حل باشد. براي اين منظور يک نگاشت  تعريف مي کنيم که بردار ورودي d بعدي x را به بردار d’ بعدي z تبديل مي کند.

بايد به گونه اي انتخاب شود که بردارهاي فضاي ويژگي جديد جدايي پذير باشند. در حالت کلي مي توان گفت که اگر  بردارهاي ورودي را به فضايي ببرد که تعداد ابعاد آن به اندازه کافي بزرگ باشد (

منبع


منابع

1.https://fa.wikipedia.org

2.http://www.bigdata.ir

3.www.barjoueian.com

4.http://fumblog.um.ac.ir

ماشین بردار پشتیبان (svm) قسمت 1
ماشین بردار پشتیبان (svm) قسمت 2
ماشین بردار پشتیبان (svm) قسمت 3

ماشین بردار پشتیبانی

ماشین بردار پشتیبان (Support vector machines – SVMs) یکی از روش‌های یادگیری بانظارت است که از آن برای طبقه‌بندی و رگرسیون استفاده می‌کنند.

این روش از جملهٔ روش‌های نسبتاً جدیدی است که در سال‌های اخیر کارایی خوبی نسبت به روش‌های قدیمی‌تر برای طبقه‌بندی از جمله شبکه‌های عصبی پرسپترون نشان داده است. مبنای کاریدسته‌بندی کنندۀ SVM دسته‌بندی خطی داده‌ها است و در تقسیم خطی داده‌ها سعی می‌کنیم خطی را انتخاب کنیم که حاشیه اطمینان بیشتری داشته باشد. حل معادله پیدا کردن خط بهینه برای داده‌ها به وسیله روش‌های QP که روش‌های شناخته شده‌ای در حل مسائل محدودیت‌دار هستند صورت می‌گیرد. قبل از تقسیمِ خطی برای اینکه ماشین بتواند داده‌های با پیچیدگی بالا را دسته‌بندی کند داده‌ها را به وسیلهٔ تابعِ phi به فضای با ابعاد خیلی بالاتر می‌بریم. برای اینکه بتوانیم مسئله ابعاد خیلی بالا را با استفاده از این روش‌ها حل کنیم از قضیه دوگانی لاگرانژ برای تبدیلِ مسئلهٔ مینیمم‌سازی مورد نظر به فرم دوگانی آن که در آن به جای تابع پیچیدهٔ phi که ما را به فضایی با ابعاد بالا می‌برد، تابعِ ساده‌تری به نامِ تابع هسته که ضرب برداری تابع phi است ظاهر می‌شود استفاده می‌کنیم. از توابع هسته مختلفی از جمله هسته‌های نمایی، چندجمله‌ای و سیگموید می‌توان استفاده نمود.

یکی از معروفترین خودآموزها مربوط به است.

کاربردهای SVM

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

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

تاریخچه

الگوریتم SVM اولیه در ۱۹۶۳ توسط Vladimir Vapnik ابداع شدو در سال ۱۹۹۵ توسط Vapnik و Corinna Cortes برای حالت غیرخطی تعمیم داده شد.

خلاصه استفاده عملی از SVM

ماتریس الگو را آماده می کنیم. تابع کرنلی را برای استفاده انتخاب می کنیم. پارامتر تابع کرنل و مقدار C را انتخاب می کنیم. برای محاسبه ی مقادیرα_i الگوریتم آموزشی را با استفاده از حل‌کننده‌های QP اجرا می کنیم. داده‌های جدید با استفاده از مقادیرα_i و بردارهای پشتیبان می‌توانند دسته بندی شوند.

مزایا و معایب SVM

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

ماشین بردار پشتیبان خطی

شکل 1

ما مجموعه داده‌های آزمایش {\displaystyle {\mathcal {D}}} شامل n عضو(نقطه)را در اختیار داریم که به صورت زیر تعریف می‌شود:

{\displaystyle {\mathcal {D}}=\left\{(\mathbf {x} _{i},y_{i})\mid \mathbf {x} _{i}\in \mathbb {R} ^{p},\,y_{i}\in \{-1,1\}\right\}_{i=1}^{n}}

جایی که مقدار y برابر ۱ یا -۱ و هر {\displaystyle \mathbf {x} _{i}} یک بردار حقیقی p-بعدی است. هدف پیدا کردن ابرصفحه جداکننده با بیشترین فاصله از نقاط حاشیه‌ای است که نقاط با {\displaystyle y_{i}=1} را از نقاط با {\displaystyle y_{i}=-1} جدا کند. هر ابر صفحه می‌تواند به صورت مجموعه‌ای از نقاط {\mathbf {x}} که شرط زیر را ارضا می‌کند نوشت:

{\displaystyle \mathbf {w} \cdot \mathbf {x} -b=0,\,} جایی که . علامت ضرب است. {\displaystyle {\mathbf {w} }} بردار نرمال است، که به ابرصفحه عمود است. ما می خواهیم {\displaystyle {\mathbf {w} }} و {\displaystyle {\mathbf {b} }} را طوری انتخاب کنیم که بیشترین فاصله بین ابر صفحه‌های موازی که داده‌ها را از هم جدا می‌کنند، ایجاد شود. این ابرصفحه‌ها با استفاده از رابطه زیر توصیف می‌شوند.
{\displaystyle \mathbf {w} \cdot \mathbf {x} -b=1\,}

و

شکل 2
{\displaystyle \mathbf {w} \cdot \mathbf {x} -b=-1.\,}
اگر داده‌های آموزشی جدایی پذیر خطی باشند، ما می‌توانیم دو ابر صفحه در حاشیه نقاط به‌طوری‌که هیچ نقطه مشترکی نداشته باشند، در نظر بگیریم و سپس سعی کنیم، فاصله آن‌ها را، ماکسیمم کنیم. با استفاده از هندسه، فاصله این دو صفحه {\displaystyle {\tfrac {2}{\|\mathbf {w} \|}}} است. بنابراین ما باید {\displaystyle \|\mathbf {w} \|} را مینیمم کنیم. برای اینکه از ورود نقاط به حاشیه جلوگیری کنیم، شرایط زیر را اضافه می کنیم: برای هر i
of the first class {\displaystyle \mathbf {w} \cdot \mathbf {x} _{i}-b\geq 1\qquad {\text{ for }}\mathbf {x} _{i}}

یا

of the second class {\displaystyle \mathbf {w} \cdot \mathbf {x} _{i}-b\leq -1\qquad {\text{ for }}\mathbf {x} _{i}}

این می‌تواند به صورت زیر نوشته شود:

{\displaystyle y_{i}(\mathbf {w} \cdot \mathbf {x} _{i}-b)\geq 1,\quad {\text{ for all }}1\leq i\leq n.\qquad \qquad (1)}

با کنار هم قرار دادن این دو یک مسئله بهینه‌سازی به دست می‌آید:

Minimize (in {\displaystyle {\mathbf {w} ,b}})

{\displaystyle \|\mathbf {w} \|}

subject to (for any {\displaystyle i=1,\dots ,n})

{\displaystyle y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)\geq 1.\,}

فرم اولیه

مسئله بهینه‌سازی مشاهده شده در قسمت قبل، مسئله سختی، برای حل کردن است، زیرا به||w|| وابسته است (نرم w ) . خوشبختانه می‌توانیم، بدون تغییر در مسئله||w|| را با{\displaystyle {\tfrac {1}{2}}\|\mathbf {w} \|^{2}}جانشین کنیم( عبارت ½ برای آسودگی در محاسبات ریاضی آورده شده). این یک مسئله بهینه سازی (OP)برنامه‌ریزی غیرخطی(QP) است. به‌طور واضح تر :

Minimize (in {\displaystyle {\mathbf {w} ,b}}) c

{\displaystyle {\frac {1}{2}}\|\mathbf {w} \|^{2}}

subject to (for any {\displaystyle i=1,\dots ,n})

{\displaystyle y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)\geq 1.}

می توان عبارت قبل را با استفاده از ضرایب نا منفی لاگرانژ به صورت زیر نوشت که در آن ضرایب لاگرانژ هستند {\displaystyle \alpha _{i}}:

{\displaystyle \min _{\mathbf {w} ,b,{\boldsymbol {\alpha }}}\{{\frac {1}{2}}\|\mathbf {w} \|^{2}-\sum _{i=1}^{n}{\alpha _{i}[y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)-1]}\}}

اما فرمول فوق اشتباه است . فرض کنید ما بتوانیم خانواده‌ای از ابرصفحات که نقاط را تقسیم می‌کنند پیدا کنیم . پس همه {\displaystyle y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)-1\geq 0} . بنا بر این ما می‌توانیم مینیمم را با فرستادن همه {\displaystyle \alpha _{i}} به{\displaystyle +\infty } پیدا کنیم. با این حال شرط پیش گفته می‌تواند به صورت پایین بیان شود:

{\displaystyle \min _{\mathbf {w} ,b}\max _{\boldsymbol {\alpha }}\{{\frac {1}{2}}\|\mathbf {w} \|^{2}-\sum _{i=1}^{n}{\alpha _{i}[y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)-1]}\}}

ما به دنبال نقاط saddle میگردیم.حالا می‌توان این مسئله را به کمک برنامه‌ریزی غیرخطی استاندارد حل کرد. جواب می‌تواند به صورت ترکیب خطی از بردارهای آموزشی بیان شود :

{\displaystyle \mathbf {w} =\sum _{i=1}^{n}{\alpha _{i}y_{i}\mathbf {x_{i}} }}

تنها چند{\displaystyle \alpha _{i}} بزرگتر از صفر خواهد بود.{\displaystyle \mathbf {x_{i}} } متناظر، دقیقاً همان بردار پشتیبان خواهد بود و به شرط را ارضا خواهد کرد. از این می‌توان نتیجه گرفت که بردارهای پشتیبان شرط زیر را نیز ارضا می‌کنند: {\displaystyle y_{i}(\mathbf {w} \cdot \mathbf {x_{i}} -b)=1} که اجازه می دهد مفدار b تعریف شود. در عمل الگوریتم مقاوم تر خواهد بود اگر از تمام {\displaystyle N_{SV}} بردار پشتیبان میانگین گرفته شود:

{\displaystyle b={\frac {1}{N_{SV}}}\sum _{i=1}^{N_{SV}}{(\mathbf {w} \cdot \mathbf {x_{i}} -y_{i})}}

فرم دوگان

استفاده از این واقعیت که {\displaystyle \|\mathbf {w} \|^{2}=w\cdot w} و جانشینی {\displaystyle \mathbf {w} =\sum _{i=1}^{n}{\alpha _{i}y_{i}\mathbf {x_{i}} }} می‌توان نشان داد که دوگان SVM به مسئله بهینه‌سازی زیر ساده می‌شود:

Maximize (in {\displaystyle \alpha _{i}} )

{\displaystyle {\tilde {L}}(\mathbf {\alpha } )=\sum _{i=1}^{n}\alpha _{i}-{\frac {1}{2}}\sum _{i,j}\alpha _{i}\alpha _{j}y_{i}y_{j}\mathbf {x} _{i}^{T}\mathbf {x} _{j}=\sum _{i=1}^{n}\alpha _{i}-{\frac {1}{2}}\sum _{i,j}\alpha _{i}\alpha _{j}y_{i}y_{j}k(\mathbf {x} _{i},\mathbf {x} _{j})}

subject to (for any}{\displaystyle i=1,\dots ,n})

{\displaystyle \alpha _{i}\geq 0,\,}

and to the constraint from the minimization in {\displaystyle b}

{\displaystyle \sum _{i=1}^{n}\alpha _{i}y_{i}=0.}

در اینجا هسته به صورت {\displaystyle k(\mathbf {x} _{i},\mathbf {x} _{j})=\mathbf {x} _{i}\cdot \mathbf {x} _{j}} تعریف می‌شود. عبارت \alpha  تشکیل یک دوگان برای بردار وزن‌ها مجموعه آموزشی می دهد:

{\displaystyle \mathbf {w} =\sum _{i}\alpha _{i}y_{i}\mathbf {x} _{i}.}

ماشین بردار پشتیبان چند کلاسی

SVM اساساً یک جداکننده دودویی است. در بخش قبلی پایه‌های تئوری ماشین‌های بردار پشتیبان برای دسته بندی دو کلاس تشریح شد. یک تشخیص الگوی چند کلاسی می‌تواند به وسیله ی ترکیب ماشین‌های بردار پشیبان دو کلاسی حاصل شود. به‌طور معمول دو دید برای این هدف وجود دارد. یکی از آن‌ها استراتژی “یک در مقابل همه ” برای دسته بندی هر جفت کلاس و کلاس‌های باقی‌مانده‌است. دیگر استراتژی “یک در مقابل یک” برای دسته بندی هر جفت است. در شرایطی که دسته بندی اول به دسته بندی مبهم منجر می‌شود.برای مسائل چند کلاسی٬رهیافت کلی کاهش مسئله ی چند کلاسی به چندین مسئله دودویی است. هریک از مسائل با یک جداکننده دودویی حل می‌شود. سپس خروجی جداکننده‌های دودویی SVM با هم ترکیب شده و به این ترتیب مسئله چند کلاس حل می‌شود.

ماشین‌های بردار پشتیبان غیرخطی

شکل 3

ابرصفحه جداکننده بهینه اولین بار توسط Vapnik در سال ۱۹۶۳ ارائه شد که یک دسته‌کننده خطی بود. در سال ۱۹۹۲ ،Bernhard Boser ، Isabelle GuyonوVapnik راهی را برای ایجاد دسته بند غیرخطی، با استفاده قرار دادن هسته برای پیدا کردن ابرصفحه با بیشتر حاشیه، پیشنهاد دادند. الگوریتم نتیجه شده ظاهراً مشابه است، به جز آنکه تمام ضرب‌های نقطه‌ای با یک تابع هسته غیرخطی جایگزین شداند. این اجازه می‌دهد، الگوریتم، برای ابرصفحه با بیشترین حاشیه در یک فضای ویژگی تغییرشکل داده، مناسب باشد. ممکن است، تغییرشکل غیرخطی باشد و فضای تغییر یافته، دارای ابعاد بالاتری باشد. به هر حال دسته‌کننده، یک ابرصفحه در فضای ویژگی با ابعاد بالا است، که ممکن است در فضای ورودی نیز غیرخطی باشد.

اگر از هسته با تابع گوسیین استفاده شود، فضای ویژگی متناظر، یک فضای هیلبرت نامتناهی است. دسته‌کننده ی بیشترین حاشیه، خوش ترتیب است، بنابراین ابعاد نامتناهی، نتیجه را خراب نمی‌کند. هسته‌های متداول به صورت زیر هستند:

  • چندجمله‌ای (همگن): {\displaystyle k(\mathbf {x_{i}} ,\mathbf {x_{j}} )=(\mathbf {x_{i}} \cdot \mathbf {x_{j}} )^{d}}
  • چندجمله‌ای (ناهمگن): {\displaystyle k(\mathbf {x_{i}} ,\mathbf {x_{j}} )=(\mathbf {x_{i}} \cdot \mathbf {x_{j}} +1)^{d}}
  • گوسیین Radial Basis Function:  {\displaystyle k(\mathbf {x_{i}} ,\mathbf {x_{j}} )=\exp(-\gamma \|\mathbf {x_{i}} -\mathbf {x_{j}} \|^{2})}، for {\displaystyle \gamma >0.} Sometimes parametrized using {\displaystyle \gamma =1/{2\sigma ^{2}}}
  • تانژانت هذلولی: {\displaystyle k(\mathbf {x_{i}} ,\mathbf {x_{j}} )=\tanh(\kappa \mathbf {x_{i}} \cdot \mathbf {x_{j}} +c)}، for some (not every) {\displaystyle \kappa >0} and {\displaystyle c<0}

هسته با انتقال {\displaystyle \varphi (\mathbf {x_{i}} )} با تساوی {\displaystyle k(\mathbf {x_{i}} ,\mathbf {x_{j}} )=\varphi (\mathbf {x_{i}} )\cdot \varphi (\mathbf {x_{j}} )} در ارتباط است. همچنین مقدار wدر فضای انتقال یافته برابر{\displaystyle \textstyle \mathbf {w} =\sum _{i}\alpha _{i}y_{i}\varphi (\mathbf {x} _{i}).} است. ضرب نقطه‌ای با w می‌تواند توسط هسته محاسبه شود یعنی {\displaystyle \textstyle \mathbf {w} \cdot \varphi (\mathbf {x} )=\sum _{i}\alpha _{i}y_{i}k(\mathbf {x} _{i},\mathbf {x} )}. به هر حال در حالت عادی w’ وجود ندارد، به‌طوری‌که {\displaystyle \mathbf {w} \cdot \varphi (\mathbf {x} )=k(\mathbf {w'} ,\mathbf {x} ).}

 

منبع

 

 

ماشین بردار پشتیبان (svm) قسمت 1
ماشین بردار پشتیبان (svm) قسمت 2
ماشین بردار پشتیبان (svm) قسمت 3

روابط پوشانندگی در مسئلهٔ کوله پشتی بیکران

در حل مسئلهٔ کوله پشتی بیکران، با کنار گذاشتن اشیایی که هیچوقت مورد استفاده قرار نمی‌گیرند، می‌توان مسئله را ساده‌تر کرد. برای مثال، فرض کنید برای شی ای مانند i، می‌توان زیر مجموعه از اشیا به نام J یافت طوری‌که ارزش مجموع آن‌ها بزرگتر از ارزش i و وزن مجموع آن‌ها کمتر از وزن i باشد؛ بنابراین، i نمی‌تواند در جواب بهینه بیاید. در این هنگام مجموعهٔ J را پوشاننده ی iمی‌گوییم. (توجه کنید این استدلال برای مسئلهٔ کوله پشتی کراندار نمی‌تواند مورد استفاده قرار گیرد. زیرا ممکن است قبلاً از اشیا سازندهٔ مجموعهٔ J استفاده کرده باشیم و تمام شده باشند)

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

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq \alpha \,w_{i}}, and {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq \alpha \,v_{i}\,} for some {\displaystyle x\in Z_{+}^{n}}

که: {\displaystyle \alpha \in Z_{+}\,,J\subseteq N} و {\displaystyle i\not \in J}. و x_{j} تعداد انتخاب‌های شی نوع j را نشان می‌دهد. (دقت کنید این j‌ها، اعضای مجموعهٔ J هستند)

پوشانندگی انتخابی

شی {\displaystyle i} ام، به‌طور انتخابی توسط {\displaystyle J} پوشانده شده، اگر جمع وزن تعدادی از اعضای مجموعهٔ {\displaystyle J}، کمتر از {\displaystyle w_{i}} باشد و جمع ارزش آن‌ها بیشتر از {\displaystyle v_{i}}. به بیان ریاضی:

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq w_{i}} و {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq v_{i}} درصورتی که {\displaystyle x\in Z_{+}^{n}} که {\displaystyle \alpha =1}.

بررسی این نوع پوشانندگی، از لحاظ پیچیدگی محاسباتی چندان ساده نیست، بنابراین از بهترین روش‌ها، راه حل پویاست. در واقع این مسئله، یک مسئله کوله پشتی، اما با پارامترهای کوچکتر، مطابق زیر است:

{\displaystyle V=v_{i}} ، {\displaystyle W=w_{i}} و اشیا محدود به مجموعهٔ {\displaystyle J} هستند.

نماد ریاضی پوشانندگی انتخابی به صورت {\displaystyle i\ll J} است.

پوشانندگی حدی

شی {\displaystyle i} ام، به‌طور حدی توسط {\displaystyle J} پوشانده شده، اگر تعدادی از اشیا نوع {\displaystyle i} توسط {\displaystyle J} پوشانده شوند. به بیان ریاضی:

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq \alpha \,w_{i}} و {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq \alpha \,v_{i}\,} در صورتی که {\displaystyle x\in Z_{+}^{n}} و {\displaystyle \alpha \geq 1}.

این نوع پوشانندگی، نمایش کلی تری از پوشانندگی انتخابی نیست که برای اولین بار در معرفی شد و در الگوریتم EDUK مورد استفاده قرار گرفت. کوچکترین \alpha  ممکن، حد i نامیده می‌شود. به بیان ریاضی: {\displaystyle t_{i}=(\alpha -1)w_{i}}. در این هنگام، پاسخ بهینه حد اکثر می‌تواند به تعداد {\displaystyle \alpha -1} شی، از نوع i را شامل شود.

پوشانندگی چندگانه

شی {\displaystyle i}، به‌طور چندگانه توسط شی {\displaystyle j} پوشانده شده، اگر {\displaystyle i} توسط تعدادی از شی نوع {\displaystyle j} پوشانده شود. (یعنی شی{\displaystyle i}، فقط توسط تعدادی شی از نوع {\displaystyle j} پوشانده شود و نیازی به استفاده از اشیا دیگر نباشد). به بیان ریاضی:

{\displaystyle \qquad w_{j}\,x_{j}\ \leq w_{i}} و {\displaystyle \qquad v_{j}\,x_{j}\ \geq v_{i}} برای {\displaystyle x_{j}\in Z_{+}}

که{\displaystyle J=\{j\},\alpha =1,x_{j}=\lfloor {\frac {w_{i}}{w_{j}}}\rfloor }.

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

نماد ریاضی پوشانندگی انتخابی به صورت {\displaystyle i\ll _{m}j} است.

پوشانندگی ماژولار

فرض کنیم {\displaystyle b} بهترین شی باشد، یعنی برای تمام {\displaystyle i} ها، {\displaystyle {\frac {v_{b}}{w_{b}}}\geq {\frac {v_{i}}{w_{i}}}\,}{\displaystyle b} شی ای با بیشترین چگالی است.

شی {\displaystyle i} ام، به‌طور ماژولار توسط شی {\displaystyle j} پوشانده شده، اگر توسط {\displaystyle j} و تعدادی شی از نوع {\displaystyle b} پوشانده شود. (یعنی شی {\displaystyle i}، فقط توسط {\displaystyle j} و تعدادی شی از نوع {\displaystyle b} پوشانده شود و نیازی به استفاده از اشیا دیگر نباشد) به بیان ریاضی:

{\displaystyle w_{j}+tw_{b}\leq w_{i}} و {\displaystyle v_{j}+tv_{b}\geq v_{i}}

که {\displaystyle J=\{b,j\},\alpha =1,x_{b}=t,x_{j}=1}.

نماد ریاضی پوشانندگی ماژولار به صورت {\displaystyle i\ll _{\equiv }j} است.

الگوریتم کوله پشتی با استفاده از روش حریصانه

void Greedy Knapsack(w,n)
{
//W is the knapsack and the n objects
sort (p,w)//Pi/Wi  &gt;  =  Pi+1/Wi+1
for(i=0;i  &lt;  n;i++)
    x[i]=۰
    U=W
    for(i=0;i  &lt; n;i++) if(W[i] &gt;  u);
break ;
[
x[i]=1;
u=u-[wi] 
}
if(i  &lt;  n)
    x[i]=u/w 
}

شبه کد عقبگرد برای مسئله کوله پشتی ۰و۱

از انجاییکه این مسئله بهینه‌سازی است، ما رد بهترین مجموعه کنونی کالاها و مجموع ارزش آن‌ها را نگه می‌داریم که اینکار توسط ارائه bestset و و یک متغیر maxprofit انجام می‌شود. این مسئله را برای یافتن اولین جواب بهینه مطرح می‌کنیم

مسئله:n کالا داریم که هر کدام از آن‌ها دارای ارزشی و وزنی دارند. ارزش‌ها و وزن ها، اعدادی صحیح و مثبت هستند. مجموعه‌ای از کالاها با حداکثر مجموع ارزش را طوری تعیین کنید که مجموع اوزان آن‌ها بیش از عدد صحیح مثبت w نشود

ورودی:اعداد صحیح مثبت nوw,ارایه‌های wوpکه از ۱ تاn شاخص دهی شده و هر یک شامل اعداد صحیح و مثبتی هستند که بترتیب غیر نزولی بر اساس مقادیر [p[i]/w[i مرتب شده‌اند

خروجی:مقدار صحیح maxprofit که ماکزیمم ارزش است، ارائه bestset که از ۱ تا n شاخص دهی شده و در مقادیر bestsetو “yes”است اگر کالای iام در مجموعه بهینه قرار داشته باشد در غیر اینصورت مقدار ان “no” می‌باشد

void knapsack (index I ,
             int profit , int weight)
 {
    if (weight  &lt; = W &amp;&amp; profit &gt;  maxprofit){
      maxprofit=profit;
      numbest=i;
      bestset=include;
    }
   if(promising(i)){
   include[i+1]=”yes”;
 knapsack(i+1,profit+p[i+1],weight+w[i+1]);
 include[i+1]=”no”
 knapsack(i+1,profit,weight);
 }
 }
 bool promising(index i)
 {
 index j,k;
 int totweight;
 float bound;
 if(weight  &gt; =  W)
 return false;
 else {
 j=i+1;
 bound=profit;
 totweight=weight;
 while(j  &lt; = n &amp;&amp; totweight + w[j]  &lt; = W){
 totweight=totweight+w[j];
 bound=bound+p[j];
 j++;
 }
 k=j;
 if(k  &lt; = n) bound=bound+(W-totweight)*p[k]/w[k]; return bound &gt;  maxprofit;
 }
 }

طبق قرار دادn,w,p,W ,numbest , bestset , include , maxprofit ورودیهای روتین نیستند. اگر این متغیرهای را به صورت سراسری تعریف می‌کردیم، شبه کد زیر ماکزیمم ارزش و مجموعه دارای این ارزش را تولید می‌کرد:

 numbest=0;
maxprofit = 0 ;
knapsack(0,0,0);
cout  &lt;&lt; maxprofit;      // نوشتن ماکزیمم ارزش
for (j=i ; j &lt; = numbest ; j++)     //نمایش مجموعه بهینه کالاها
cout &lt;&lt; bestset[i];

کاربردها

مسئلهٔ کوله پشتی می‌تواند در تصمیم‌گیری‌هایی که در دنیای واقعی با آن‌ها روبرو هستیم، مورد استفاده قرار گیرد. مانند بریدن کالا به‌طوری‌که کمترین مقدار به هدر رود، انتخاب سرمایه‌گذاری‌هاو سبد سهام، انتخاب دارایی‌ها برای مسئلهٔ امنیت دارایی‌های قبلی و ساختن کلیدها برای سیستم رمزنگاری کوله پشتیِ مرکل-هلمن.

== یکی از کاربردهای اولیهٔ مسئلهٔ کوله پشتی، طراحی و بارم بندی آزمون است به نحوی که آزمون دهنده در پاسخگویی به سؤالات حق انتخاب داشته باشد. چنانچه بارم بندی سؤالات همگن باشد، مسئله بسیار ساده خواهد شد. برای مثال، اگر آزمون دارای 12 سؤال، هر سؤال به ارزش 10 نمره باشد، آزمون دهنده باید فقط 10 سؤال را پاسخ دهد تا به بیشینه نمره ممکنِ 100 برسد. اما برای آزمون‌هایی با بارم بندی نایکسان، مسئله کمی سخت‌تر می‌شود. Feuerman و Weiss سیستمی ارائه دادند که در آن دانش آموزان با آزمونی با بارم بندی ناهمگن، با جمع بارم 125 روبرو هستند. از دانش آموزان خواسته می‌شود با توجه به توانایی‌های خود به سؤالات پاسخ دهند. در اینجا با مسئلهٔ کوله پشتی روبرو هستیم. چه زیر مجموعه‌هایی، جمع نمره‌ای برابر با 100 خواهند داشت؟ برای هر دانش آموز، پاسخ گویی به کدام زیر مجموعه از سؤالات، نمرهٔ بیشتری را به ارمغان می‌آورد؟

یک مثال از مسئله کوله پشتی

صورت مسئله: دزدی قصد سرقت از مغازه‌ای را دارد و حداکثر وزن w از اجناس را که می‌تواند بدزد در این مغازه n نوع جنس وجود دارد. اگر وزن جنس iام wi و قیمت آن vi باشد بیشینه سودی که بدست می‌آورد چقدر است؟

این مسئله به دو صورت تعریف می‌شود: 1- صفر و یک در حالت صفر و یک مسئله به این صورت تعریف می‌شود که دزد یا یک جنس را برمی‌دارد یا برنمی‌دارد و حق برداشتن تکه‌ای از یک جنس را ندارد. برای این مسئله راه حل حریصانه‌ای وجود ندارد و به ارائه یک راه حل پویا خواهیم پرداخت.

ایده حل این مسئله در حالت پویا یه ابن صورت هست که دزد یا جنس iام را برمی‌دارد یا برنمی‌دارد و براساس این دو حالت سود زیرمسئله ایجاد شده محاسبه می‌شود و از مسیری که جواب بیشینه را داده پیش خواهیم رفت. به عبارتی:

کد c[i,w] = c[i-1, w]

 if wi  ≥  0
 max [vi + c[i-1, w-wi], c[i-1, w]}
 if i &gt; 0 and w  ≥  wi

شبه کد Dynamic-0-1-knapsack (v, w, n, W)

 for w = 0 to W
 do c[0, w] = 0
 for i = 1 to n
 do c[i, 0] = 0
 for w = 1 to W
 do if wi  ≤  w
 then if vi + c[i-1, w-wi]
 then c[i, w] = vi + c[i-1, w-wi]
 else c[i, w] = c[i-1, w]
 else
 c[i, w] = c[i-1, w]

۲-کسری در این حالت از مسئه دزد می‌تواند قسمتی از یک جنس را بردارد و مثل حالت قبل ۰ و ۱ی نمی‌باشد. برای این مسئله راه حال حریصانه وجود داره و به این شکل هست که دزد تا می‌تواند جنس پرارزش تر را برداشته و درصورتی که نتوانست بیشترین کسر ممکن آن را برمی‌دارد.

تاریخچه

مسئلهٔ کوله پشتی بیش از یک قرن مورد مطالعه قرار گرفته و اولین بررسی در سال ۱۸۹۷ انجام گرفته‌است. هر چند اولین داده‌های ثبت شده در این مورد، به کارهای ریاضیدانی به نام (1884–1956) Tobias Dantzig برمی گردد، چیزی با عنوان مسئلهٔ کوله پشتی قبلاً در میان عامهٔ مردم وجود داشته‌است.

مسئلهٔ کوله پشتی درجه دوم، اولین بار توسط Hammer، Gallo و Simeone در سال ۱۹۶۰ مطرح شد.

در سال ۱۹۸۸، تحقیقی از دانشگاه استونی بروک بر روی مجموعه‌ای از الگوریتم‌ها، نشان داد که از میان ۷۵ مسئلهٔ الگوریتمی، مسئلهٔ کوله پشتی، ۱۸ امین مسئلهٔ معروف و ۴ امین مسئلهٔ پرکاربرد بعد از درخت کی دی، درخت پیشوندی و bin packing problem است.

منبع


تعریف سوال

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

الگوریتم

این مسئله یکی از پایه‌ای‌ترین مسائل برنامه‌ریزی پویا است و صورت‌های مختلفی دارد که در انتها به آن‌ها و ایده‌ی اثبات‌شان اشاره می‌شود.
برای حل مدل ساده‌ی سوال، یک آرایه دوبعدی به نام d به ابعاد(n+1)×(W+1) را در نظر بگیرید که در آن n تعداد وسایل مختلفی که می‌توانیم در کوله‌پشتی بگذاریم وW حجم کوله‌پشتی است.
مقدارdi,j برابر یک است اگر و تنها اگر بتوان فقط با استفاده از i وسیله‌ی اول، دقیقا حجم j از کوله‌پشتی را پر کرد. یعنی یک زیرمجموعه‌ از i عضو اول وجود دارد که مجموع وزن‌شان j است. در غیر اینصورت، مقدارش برابر صفر است.
جواب مسئله بزرگترین اندیس j است که dn,j برابر یک باشد.
مقداردهی اولیه: با استفاده از ۰ وسیله‌ی اول (استفاده نکردن از وسایل) فقط می‌توان حجم ۰ را تولید کرد (کوله‌پشتی خالی) پس تمام خانه‌های به صورت d0,j برابر صفر اند به جز d0,0 که برابر ۱ است.
به روز رسانی: برای به دست آوردن di,j دو حالت وجود دارد این که خود وسیله‌ی i ام در کوله‌پشتی نباشد که در این صورت باید برای این که مقدار یک شود، مقدار di1,j برابر ۱ باشد. حالت دیگر این است که خود وسیله در کوله پشتی باشد. پس در این حالت مقدار در صورتی یک می‌شود که (مقدار حجم وسیله‌ی i ام را ai بگیریم) di۱,jai با فرض jai برابر یک باشد.

شبه کد:

d = {0} 
d[0][0] = 1 

for i from 1 to n 
	for j from 0 to W 
		d[i][j] = d[i-1][j] 
		if j   &gt;  = a[i]  and  d[i-1][j-a[i]] == 1
			d[i][j] = 1

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

d = {0} 
d[0] = 1 

for i from 1 to n 
	for j from 0 to W 
		if j   &gt; =  a[i] and d[j-a[i]] == 1
			d[j] = 1

کد بالا یک مشکل دارد. به نظرتان مشکلش چیست؟
فرض کنید در فقط یک وسیله داریم مثلا با حجم ۲ واحد و حجم کوله‌پشتی برابر ۴ است. پس فقط می‌توان ۲ واحد از کوله‌پشتی را پر کرد. اما اگر شبه کد بالا را برای آن اجرا کنید، می‌بینید که مقدار d4d4 برابر یک است. چون با استفاده از وسیله‌ی اول که حجم دو واحد داشت، مقدار d2d2 را یک کردیم، اما بعد از این متوقف نشدیم بلکه چون مقدار d2d2 برابر یک بود، مقدار d4d4 را نیز برابر یک قرار دادیم. پس انگار بیش از یک وسیله با حجم دو داشتیم. در واقع این کد جواب مسئله‌ی دیگری به نام خرد کردن پولاست که در آن به تعداد نامتناهی از هر کدام از وسایل داریم.
حال بیایید سعی کنیم مشکل کد بالا را حل کنیم. مشکل این بود که اول با استفاده از وسیله‌ی اول (یا بقیه‌ی وسایل) مقدار خانه‌های پایین جدول را به روز رسانی کردیم و سپس دوباره با استفاده از همان وسیله، مقادیر خانه‌های بالاتر را نیز به روز رسانی کردیم. چطور می‌شود اگر خانه‌ها را به ترتیب دیگری پیمایش کنیم تا این مشکل پیش نیاید؟ حجم وسایل که نمی‌تواند منفی باشد. پس اگر بالا به پایین آرایه را به روز رسانی کنیم، این مشکل پیش نمی‌آید. خودتان هم کمی فکر کنید که چرا این روش درست است.
بر همین اساس کد را تغییر می‌دهیم. شبه کد با آرایه‌ی یک بعدی (درست):

d = {0} 
d[0] = 1 

for i from 1 to n 
	for j from W to 0 
		if j   &gt; =  a[i] and d[j-a[i]] 
			d[j] = 1

پیچیدگی‌ الگوریتم

پیچیدگی زمانی که در تمام حالت‌ها از O(n×W) است. مقدار حافظه‌ی مورد نیاز نیز O(W) است.

صورت‌های مختلف سوال

مثال: فرض کنید وسایلی که می‌خواهید در کوله‌پشتی بگذارید، علاوه‌بر حجم، ارزش نیز داشته باشند و هدف شما فقط بردن وسایلی باشد که در مجموع ارزش‌شان بیشترین مقدار ممکن باشد. الگوریتمی از O(n×W) برای حل این سوال بدهید.

پاسخ

تعریف آرایه‌ی dd را به این صورت تغییر دهید که di,jdi,j یعنی با استفاده از ii وسیله‌ی اول و حجم jj حداکثر مجموع ارزش وسایل در کوله‌پشتی چقدر است. شیوه‌ی به روز رسانی شبیه سوال اصلی است و به خواننده محول می‌شود.

پیاده‌سازی اولیه

#include   &lt; iostream &gt; 
using namespace std; 
 
const int MAXN = 10*1000; 
const int MAXW = 100*1000; 
 
bool d[MAXW+10]; 
int p[MAXW+10]; 
int a[MAXN+10]; 
 
int main() 
{ 
	ios::sync_with_stdio(false); 
	int n, w; 
	cin   &gt;&gt;   n   &gt;&gt;   w; 
	for(int i=0; i  &lt; n; i++) cin &gt;&gt;   a[i]; 
 
	d[0] = 1; 
	for(int i=0; i  &lt; n; i++) for(int j=w; j &gt;  =a[i]; j--) 
			if( d[j] == 0 &amp;&amp; d[j-a[i]] == 1 ) 
			{ 
				d[j] = 1; 
				p[j] = a[i]; 
			} 
 
	int out = w; 
	for(; out  &gt; =  0; out--) 
		if( d[out] ) 
			break; 
 
	cout   &lt;&lt;   out   &lt;&lt;   endl; 
	while( out != 0 ) 
	{ 
		cout   &lt;&lt;   p[out]   &lt;&lt;   " "; 
		out -= p[out]; 
	} 
	cout   &lt;&lt;   endl; 
	return 0; 
}

منبع 

مسئله کوله پشتی قسمت 1
مسئله کوله پشتی قسمت 2

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

معمولاً در تخصیص منابع با محدودیت‌های مالی، با این مسئله روبرو هستیم. همچنین مسائلی از این قبیل در ترکیبیات، نظریه پیچیدگی محاسباتی،رمزنگاری و ریاضیات کاربردی به چشم می‌خورد.

نسخهٔ مسئله تصمیم برای مسئلهٔ کوله پشتی، این سؤال است: “آیا ارزش V با انتخاب اشیایی با مجموع وزن کمتر یا مساوی W، قابل دستیابی است؟”

نمونه‌ای از مسئلهٔ کوله پشتی یک بعدی: چه جعبه‌هایی باید انتخاب شوند تا مقدار پول بیشینه شود اما وزن جعبه‌های مذکور بیشتر از ۱۵ کیلوگرم نشود؟ یک مسئله چند محدودیتی، می‌تواند هم وزن و هم حجم جعبه‌ها را در نظر بگیرد. مدل‌سازی اندازه و شکل جعبه‌ها، یک مسئله بسته‌بندی است.
(راه حل: اگر هر تعداد دلخواهی از جعبه‌ها در دسترس باشد، ۳ جعبهٔ زرد و ۳ جعبهٔ خاکستری پاسخ‌اند. اما اگر مطابق شکل باشد، یعنی از هر جعبه فقط یکی داشته باشیم، تمامی جعبه‌ها به جز جعبهٔ سبز را انتخاب می‌کنیم)

تعریف

مسئله کوله پشتی چیست؟ فرض کنید که جهانگردی می‌خواهدکوله پشتی خود را با انتخاب حالتهای ممکن از بین وسائل گوناگونی که بیشترین راحتی را برایش فراهم می‌سازند پر کند. این مسئله می‌تواند با شماره‌گذاری این وسائل از ۱ تا n و تعریف برداری از متغیرهای دودویی(Binary) (j = ۱٬۲,۳…n) به صورت ریاضی فرمول بندی شود. به این معنی که: اگر شیء j ام انتخاب شود در غیر اینصورت وقتی میزان راحتی باشد که وسیله j ا م فراهم می‌آورد و وزن آن و c اندازه کوله پشتی باشد. مسئله ما انتخاب برداری از بین بردارهای دودویی x است، که محدودیت را برآورده کند. بطوری‌که تابع هدف ماکزیمم مقدار خود را بگیرد به عنوان نمونه‌ای از مسائلی که می‌توانند به صورت مسئله کوله پشتی فرمول بندی شوند، مسئله زیر را در نظر بگیرید: فرض کنید که شما مایل به سرمایه‌گذاری همه یا قسمتی ازسرمایه‌تان باشید. اگر مبلغی که برای سرمایه‌گذاری در نظر گرفتید c دلار باشد و n مورد برای سرمایه‌گذاری ممکن باشد، اجازه دهیدکه سود حاصل از سرمایه‌گذاری j ام و مقدار دلارهایی باشد که آن سرمایه‌گذاری لازم دارد. بدین ترتیب جواب بهینه مسئله کوله پشتی که تعریف کردیم به ما این امکان را می دهدکه بهترین حالت ممکن را از بین حالتهای مختلف سرمایه‌گذاری انتخاب کنیم. در این رابطه باید روشی برای حل این مسئله پیدا کرد. یک روش ابتدایی که در نگاه اول توجه ما را به خود جلب می‌کند، عبارت از برنامه‌نویسی برای کامپیوتر به منظور امتحان کردن تمامی بردارهای دودویی ممکن x است، تا از بین بردارهایی که محدودیت مسئله را ارضاء می‌کنند بهترین را انتخاب کند. متأسفانه تعداد چنین بردارهایی است. بطوری‌که یک کامپیوتر فرضی که می‌تواند یک بیلیون بردار را در یک ثانیه امتحان کند؛ برای n = ۶۰ بیش از ۳۰ سال وقت لازم دارد و بیش از ۶۰ سال برای n = ۶۱ و ده‌ها قرن برای n = ۶۵ والی آخر. با این وجود، با استفاده از الگوریتمهایی خاص می‌توان در بسیاری موارد مسئله‌ای با n = ۱۰۰ ۰۰۰ را در عرض چند ثانیه روی یک کامپیوتر کوچک حل کرد __________________

فرض کنید n جسم داریم که از 1 تا n شماره‌گذاری شده‌اند. جسم {\displaystyle i} ام ارزشی معادل {\displaystyle v_{i}}و وزنی برابر با w_i دارد. معمولاً فرض می‌شود که وزن‌ها و ارزش‌ها نامنفی‌اند. برای ساده‌تر شدن نمایش، بدون کم شدن از کلیت مسئله می‌توان فرض کرد اشیا به ترتیب صعودی بر حسب وزنشان مرتب شده‌اند. بیشترین وزنی که می‌توان در کوله پشتی حمل کرد،W است.

معروف‌ترین نوع از این مسئله، مسئلهٔ کوله پشتی ۰ و ۱ است. یعنی تعداد از هر شی، یا ۰ است (آن شی را انتخاب نمی‌کنیم) یا ۱ (آن شی انتخاب می‌شود). مسئلهٔ کوله پشتی ۰ و ۱ را می‌توان به این صورت، به زبان ریاضی بیان کرد:

  • مقدار {\displaystyle \qquad \sum _{i=1}^{n}v_{i}x_{i}} را بیشینه کنید.
  • به‌طوری‌که {\displaystyle \qquad \sum _{i=1}^{n}w_{i}x_{i}\leqslant W,\quad x_{i}\in \{0,1\}}

مسئلهٔ کوله پشتی کران دار، نسخهٔ دیگری از این سؤال است که در آن تعداد اشیا (x_i) عددی صحیح و نامنفی و حد اکثر برابر با{\displaystyle c_{i}} است. به بیان ریاضی:

  • مقدار {\displaystyle \qquad \sum _{i=1}^{n}v_{i}x_{i}}را بیشینه کنید.
  • به‌طوری که{\displaystyle \qquad \sum _{i=1}^{n}w_{i}x_{i}\leqslant W,\quad x_{i}\in \{0,1,\ldots ,c_{i}\}}

مسئلهٔ کوله پشتی بیکران (UKP)، هیچ محدودیتی روی تعداد اشیا قائل نمی‌شود. یعنی از هر شی، به هر تعداد دلخواهی می‌توان انتخاب کرد. نسخه‌ای ازین سؤال که بیش از همه مورد توجه قرار می‌گیرد، دارای ویژگی‌های زیر است:

  • یک مسئله تصمیم است.
  • مسئله ۰ و ۱ است.
  • برای هر شی، وزن و ارزش آن برابرند. یعنی{\displaystyle w_{i}=v_{i}}.

دقت کنید که در این مورد خاص، این مسئله هم ارز است با: ” مجموعه‌ای از اعداد صحیح نا منفی داده شده‌است. آیا زیر مجموعه‌ای از آن وجود دارد که جمع اعضایش دقیقاً W شود؟” و چنانچه وزن‌های منفی هم قابل قبول باشند، و W برابر با {\displaystyle 0} در نظر گرفته شود، مسئله عبارت است از: ” مجموعه‌ای از اعداد صحیح داده شده‌است. آیا زیر مجموعه‌ای غیر تهی از آن هست که جمع اعضایش {\displaystyle 0} شود؟” این مسئله خاص، مسئله جمع زیرمجموعه‌ها نامیده می‌شود. در رمزنگاری، هر گاه از مسئله کوله پشتی نام برده می‌شود، منظور مسئله جمع زیرمجموعه‌ها است.

چنانچه چند کوله پشتی داشته باشیم، مسئله تبدیل به سؤال bin packing می‌شود.

پیچیدگی محاسباتی

از دید علوم کامپیوتر، مسئلهٔ کوله پشتی شایان توجه است زیرا:

  • الگوریتمی با زمان اجرای شبه چندجمله‌ای با استفاده از برنامه‌نویسی پویا دارد.
  • الگوریتمی تقریبی با زمان چندجمله‌ای دارد که از الگوریتم‌های با زمان شبه چندجمله‌ای به عنوان یک زیر-برنامه استفاده می‌کند.
  • حل دقیق این سؤال، مسئله‌ای از نوع NP-complete است؛ بنابراین پیش‌بینی شده که راه حلی که هم درست و هم سریع باشد (با زمان اجرای چندجمله‌ای) برای هر ورودی دلخواه، ندارد.

مسئله جمع زیر مجموعه‌ها که نسخه‌ای از مسئلهٔ کلی کوله پشتی است، به عنوان یکی از 21 مسئلهٔ NP-کاملِ Karp مطرح است.

تلاش‌هایی برای استفاده از مسئلهٔ جمع زیر مجموعه‌ها به عنوان اصل در سیستم‌های رمزنگاری کلید عمومی، مانند سیستم رمزنگاری کوله پشتی مرکل-هلمن انجام شد. در این روش‌ها، معمولاً ازگروه‌هایی به جز اعداد صحیح استفاده می‌شد. Merkle-Hellman و الگوریتم‌های مشابه دیگر بعداً با شکست روبرو شدند، زیرا مسائل خاصی که تولید می‌کردند در زمان چندجمله‌ای قابل حل بودند.

در خیلی از تحقیقات سعی می‌شود به این سؤال پاسخ داده شود که نمونه‌های سخت مسئلهٔ کوله پشتی چه هستند؟ یا از دید دیگر، چه ویژگی‌هایی از مثال‌های مسئلهٔ کوله پشتی، باعث می‌شود در زمانی معقولتر نسبت به آنچه در صورت کلی NP-completeِ سؤال مطرح است، حل شوند. . الگوریتم‌های زیادی بر پایه ی: برنامه‌نویسی پویا، روش تقسیم و حد، یا ترکیبی از هر دو روش برای این مسئله وجود دارند.

راه حل برنامه‌نویسی پویا

مسئلهٔ کوله پشتی بیکران

اگر تمام وزن‌ها ({\displaystyle w_{1},\ldots ,w_{n},W}) اعداد صحیح نامنفی باشند، مسئلهٔ کوله پشتی در زمانی شبه چندجمله‌ای با استفاده از برنامه‌نویسی پویا قابل حل است.

برای سادگی فرض کنید تمام وزن‌ها اکیداً مثبت اند ({\displaystyle w_{i}>0}). می‌خواهیم جمع ارزش کالاهای انتخاب شده را بیشینه کنیم با این فرض که مجموع وزن آن‌ها حداکثر{\displaystyle W} شود. حال برای هر {\displaystyle w<W}، مقدار {\displaystyle m[w]} را بیشترین ارزش قابل دستیابی تعریف کنید به‌طوری‌که جمع وزن اشیا انتخاب شده حد اکثر w شود. بدیهی است که {\displaystyle m[W]} پاسخ مورد نظر است.

دقت کنید که {\displaystyle m[w]} ویژگی‌های زیر را دارد:

  • {\displaystyle m[0]=0\,\!} (جمع اعضای مجموعهٔ تهی ۰ است)
  • {\displaystyle m[w]=\max _{w_{i}\leq w}(v_{i}+m[w-w_{i}])} که {\displaystyle v_{i}} ارزش شی i ام است.

بیشترین ارزش قابل دستیابی از مجموعهٔ تهی، ۰ است. برای محاسبهٔ هر کدام از {\displaystyle m[w]}‌ها، باید n شی را بررسی کرد. همچنین آرایهٔ W، m عنصر دارد. بنابراین زمان اجرای این الگوریتم {\displaystyle O(nW)}است. بدیهی است با تقسیم کردن {\displaystyle w_{1},\,w_{2},\,\ldots ,\,w_{n},\,W} بر بزرگترین مقسوم علیه مشترک شان، می‌توان زمان اجرای الگوریتم را بهینه کرد.

پیچیدگی زمانی {\displaystyle O(nW)} تناقضی با NP-complete بودن مسئلهٔ کوله پشتی ندارد. زیرا W برخلاف n، برحسب ورودی چندجمله‌ای نیست. طول W ِ ورودی، متناسب با تعداد بیت‌های لازم برای نمایش W، یعنی {\displaystyle \log W} است، نه خود {\displaystyle W}.

مسئلهٔ کوله پشتی ۰ و ۱

روش مشابهی با استفاده از برنامه‌سازی پویا برای حل مسئله کوله پشتی ۰ و ۱ با پیچیدگی زمانی شبه چندجمله‌ای وجود دارد. مانند بالا، فرض کنید {\displaystyle w_{1},\,w_{2},\,\ldots ,\,w_{n},\,W}‌ها اعداد صحیح اکیداً مثبتی هستند. {\displaystyle m[i,w]} را بیشترین ارزش قابل دستیابی، با استفاده از اشیای ۱ تا i با حد اکثر وزن w تعریف کنید.

{\displaystyle m[i,w]} را می‌توان به‌طور بازگشتی، مطابق زیر تعریف کرد:

  • {\displaystyle m[0,\,w]=0}
  • {\displaystyle m[i,\,0]=0}
  • {\displaystyle m[i,\,w]=m[i-1,\,w]} اگر {\displaystyle w_{i}>w\,\!}
  • {\displaystyle m[i,\,w]=\max(m[i-1,\,w],\,m[i-1,w-w_{i}]+v_{i})} اگر {\displaystyle w_{i}\leqslant w}.

پاسخ با محاسبهٔ {\displaystyle m[n,W]} بدست می‌آید. برای کارآمد شدن راه حل، می‌توان از جدولی برای نگهداری نتایج محاسبات قبلی استفاده کرد؛ بنابراین پیچیدگی زمانی آن {\displaystyle O(nW)} و حافظه {\displaystyle O(nW)}خواهد شد. همچنین می‌توان حجم حافظه را به {\displaystyle O(W)} کاهش داد. به این ترتیب که آرایهٔ یک بعدی{\displaystyle m[w]}، ارزش بهینه تا کنون را نشان می‌دهد. از {\displaystyle i=1} شروع کرده، آرایه را پر می‌کنیم. سپس با حرکت بر روی i، مقدار {\displaystyle m[w]} را با افزدون یک شی جدید به انتخاب‌ها، به روز آوری می‌کنیم.

الگوریتم دیگری برای مسئله کوله پشتی ۰ و ۱، در سال ۱۹۷۴ ارائه شد که گاهی «رویارویی در میانه» نیز نامیده می‌شود. این الگوریتم نسبت به تعداد اشیا نمایی است. (این اسم، از الگوریتمی مشابه در رمزنگاری نشات گرفته‌است). هنگامی که W نسبت به n بسیار بزرگتر باشد (یعنیW از 2^n هم بزرگتر باشد)، این الگوریتم نسبت به روش پویا از نظر زمانی بهینه تر است. برای مثال فرض کنیدw_i‌ها نامنفی باشند، اما صحیح نباشند. در اینجا نیز می‌توان از روش پویا استفاده کرد: اگر عددها d رقم بعد از اعشار داشته باشند، کافی است آن‌ها را در {\displaystyle 10^{d}} ضرب و سپس رند کرد (با استفاده از محاسبات ممیز ثابت). روش پویا با این تغییرات، از مرتبهٔ زمانی {\displaystyle O(nW*10^{d})} و حافظهٔ {\displaystyle O(W*10^{d})} خواهد بود.

الگوریتم «رویارویی در میانه» به صورت زیر است:

  1. مجموعهٔ {\displaystyle {1,2,\ldots ,n}} را به دو مجموعهٔ A و B با اندازهٔ نسبتاً برابر تقسیم کنید.
  2. ارزش‌ها و وزن‌های هر زیر مجموعه از هریک ازA و B را بدست آورید.
  3. برای هر زیرمجموعه از A، بهترین مکملB را از زیر مجموعه‌هایش انتخاب کنید: به عبارتی زیر مجموعه‌ای از B با بیشترین جمع ارزش کالاها، به نحوی که جمع وزن‌های دو زیر مجموعه، از {\displaystyle W} بیشتر نشود. بیشترین ارزش بدست آمده را ذخیره کنید.

این الگوریتم از مرتبهٔ حافظهٔ {\displaystyle O(2^{n/2})} است و با پیاده‌سازی بهینه گام ۳، از مرتبهٔ زمانی{\displaystyle O(n*2^{n/2})} می‌شود. (برای مثال با مرتب کردن زیرمجموعه‌های B بر حسب وزن، چشم پوشی از زیر مجموعه‌هایی از B که وزنی بیشتر از سایر زیر مجموعه‌ها با ارزش بزرگتر/مساوی دارند و استفاده از جستجوی دودویی برای یافتن بهترین تطابق). مانند روش رویارویی در میانه در رمز نگاری، استفاده از این الگوریتم با هزینه کردن حافظه (مرتبهٔ نمایی به جای مقدار ثابت) باعث بهینه شدن زمان اجرا می‌شود. می‌دانیم چنانچه بخواهیم تمام زیر مجموعه‌های {1…n} را به روش brute force بررسی کنیم، مرتبهٔ زمانی {\displaystyle O(n*2^{n})} خواهد شد اما با این الگوریتم آن را بهینه کردیم.

الگوریتم تقریبی حریصانه

George Dantzig الگوریتمی تقریبی از نوع حریصانه برای حل مسئله کوله پشتی بیکران ارائه داد.

به این ترتیب که اشیا را به ترتیب نزولی بر حسب ارزش به واحد وزن مرتب می‌کند ({\displaystyle v_{i}/w_{i}}) سپس از شی شماره ۱ شروع می‌کند. بیشترین تعداد ممکن از آن را در کوله پشتی قرار می‌دهد، تا زمانی که دیگر جای خالی ای برای آن نوع باقی نماند. آنگاه سراغ شی بعدی می‌رود. (دقت کنید که در این نسخه از سؤال، محدودیتی برای تعداد اشیا نداریم) اگر m بیشینه ارزش اشیایی باشد که در کوله پشتی جا می‌شوند، این الگوریتم حداقل به مقدار {\displaystyle m/2} دست می‌یابد. اما اگر تعداد مجاز از هر شی محدود باشد، ممکن است خروجی این الگوریتم از پاسخ بهینه بسیار دور باشد.

مسئله کوله پشتی قسمت 1
مسئله کوله پشتی قسمت 2

هدف از خوشه بندی چیست؟

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

خوشه بندی چیست؟

خوشه بندی

کلاسترینگ(Clustering) یا خوشه‌ بندی از جمله الگوریتم‌های قطعه بندی به حساب می‌آید. الگوریتم خوشه‌بندی اطلاعاتی را که ویژگی‌های نزدیک به هم و مشابه دارند را در دسته‌های جداگانه که به آن خوشه گفته می‌شود قرار می‌دهد. به بیان دیگر خوشه‌بندی همان دسته‌بندی‌های ساده‌ای است که در کارهای روزانه انجام می‌دهیم. وقتی با یک مجموعه کوچک از صفات روبرو باشیم دسته بندی به سادگی قابل اجرا است، برای مثال در یک مجموعه ‌از خودکارهای آبی، مشکی، قرمز و سبز به راحتی می‌توانیم آن‌ها را در ۴ دسته قرار دهیم اما اگر در همین مجموعه ویژگی‌های دیگری مثل سایز، شرکت سازنده، وزن، قیمت و… مطرح باشد کار کمی پیچیده می‌شود. حال فرض کنید در یک مجموعه متشکل از هزاران رکورد و صدها ویژگی قصد دسته بندی دارید، چگونه باید این کار را انجام دهید؟!

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

هدف خوشه بندی (Clustering) یافتن خوشه های مشابه از اشیاء در بین نمونه های ورودی می باشد اما چگونه می توان گفت که یک خوشه بندی مناسب است و دیگری مناسب نیست؟ در حقیقت سوال اصلی این است که کدام روش خوشه بندی برای هر مجموعه داده ای مناسب خواهد بود؟ می توان نشان داد که هیچ معیار مطلقی برای بهترین خوشه بندی وجود ندارد بلکه این بستگی به مساله و نظر کاربر دارد که باید تصمیم بگیرد که آیا نمونه ها بدرستی خوشه بندی شده اند یا خیر؟ با این حال معیار های مختلفی برای خوب بودن یک خوشه بندی ارائه شده است که می تواند کاربر را برای رسیدن به یک خوشه بندی مناسب راهنمایی کند که در بخشهای بعدی چند نمونه از این معیارها آورده شده است. یکی از مسایل مهم در خوشه بندی انتخاب تعداد خوشه ها می باشد. در بعضی از الگوریتم ها تعداد خوشه ها از قبل مشخص شده است و در بعضی دیگر خود الگوریتم تصمیم می گیرد که داده ها به چند خوشه تقسیم شوند.

خوشه بندی داده ها

خوشه بندی یا Clustering یکی از شاخه های یادگیری بدون نظارت (Unsupervised) می باشد و فرآیند خود کاری است که در طی آن، نمونه ها به دسته هایی که اعضای آن مشابه یکدیگر می با­شند تقسیم می شوند که به این دسته ها خوشه (Cluster) گفته می­ شود. بنابراین خوشه مجموعه ای از اشیاء می باشد که در آن اشیاء با یکدیگر مشابه بوده و با اشیاء موجود در خوشه های دیگر غیر مشابه می باشند. برای مشابه بودن می توان معیارهای مختلفی را در نظر گرفت مثلا می توان معیار فاصله را برای خوشه بندی مورد استفاده قرار داد و اشیائی را که به یکدیگر نزدیکتر هستند را بعنوان یک خوشه در نظر گرفت که به این نوع خوشه بندی، خوشه بندی مبتنی بر فاصله نیز گفته می شود. بعنوان مثال در شکل ۱ نمونه های ورودی در سمت چپ به چهار خوشه مشابه شکل سمت راست تقسیم می شوند. در این مثال هر یک از نمونه های ورودی به یکی از خوشه ها تعلق دارد و نمونه ای وجود ندارد که متعلق به بیش از یک خوشه باشد.

خوشه بندی

بعنوان یک مثال دیگر شکل ۲ را در نظر بگیرید در این شکل هر یک از دایره های کوچک یک وسیله نقلیه (شیء) را نشان می دهد که با ویژگی های وزن و حداکثر سرعت مشخص شده اند. هر یک از بیضی ها یک خوشه می باشد و عبارت کنار هر بیضی برچسب آن خوشه را نشان می دهد. کل دستگاه مختصات که نمونه ها در آن نشان داده شده اند را فضای ویژگی می گویند.

 

خوشه بندی

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

خوشه بندی با طبقه بندی (Classification) متفاوت است. در طبقه بندی نمونه های ورودی برچسب گذاری شده اند ولی در خوشه بندی نمونه های ورودی دارای بر چسب اولیه نمی باشند و در واقع با استفاده از روشهای خوشه بندی است که داده های مشابه مشخص و بطور ضمنی برچسب گذاری می شوند. در واقع می توان قبل از عملیات طبقه بندی داده ها یک خوشه بندی روی نمونه ها انجام داد و سپس مراکز خوشه های حاصل را محاسبه کرد و یک بر چسب به مراکز خوشه ها نسبت داد و سپس عملیات طبقه بندی را برای نمونه های ورودی جدید انجام داد.

منبع


آشنایی با خوشه‌بندی (Clustering) و شیوه‌های مختلف آن

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

«تحلیل خوشه‌بندی» (Cluster Analysis) نیز مانند «تحلیل طبقه‌بندی» (Classification Analysis) در «یادگیری ماشین» (Machine Learning) به کار می‌رود. هر چند که تحلیل طبقه‌بندی یک روش «با ناظر» (Supervised) محسوب شده ولی خوشه‌بندی روشی «بدون ناظر» (Unsupervised) است.

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

خوشه‌بندی (Clustering)

«تحلیل خوشه‌بندی» (Cluster Analysis) یا بطور خلاصه خوشه‌بندی، فرآیندی است که به کمک آن می‌توان مجموعه‌ای از اشیاء را به گروه‌های مجزا افراز کرد. هر افراز یک خوشه نامیده می‌شود. اعضاء هر خوشه با توجه به ویژگی‌هایی که دارند به یکدیگر بسیار شبیه هستند و در عوض میزان شباهت بین خوشه‌ها کمترین مقدار است. در چنین حالتی هدف از خوشه‌بندی، نسبت دادن برچسب‌هایی به اشیاء است که نشان دهنده عضویت هر شیء به خوشه است.

به این ترتیب تفاوت اصلی که بین تحلیل خوشه‌بندی و «تحلیل طبقه‌بندی» (Classification Analysis) وجود دارد، نداشتن برچسب‌های اولیه برای مشاهدات است. در نتیجه براساس ویژگی‌های مشترک و روش‌های اندازه‌گیری فاصله یا شباهت بین اشیاء، باید برچسب‌هایی بطور خودکار نسبت داده شوند. در حالیکه در طبقه‌بندی برچسب‌های اولیه موجود است و باید با استفاده از الگوی‌های پیش‌بینی قادر به برچسب گذاری برای مشاهدات جدید باشیم.

خوشه بندی

با توجه به روش‌های مختلف اندازه‌گیری شباهت یا الگوریتم‌های تشکیل خوشه‌،‌ ممکن است نتایج خوشه‌بندی برای مجموعه داده ثابت متفاوت باشند. شایان ذکر است که تکنیک‌های خوشه‌بندی در علوم مختلف مانند، گیاه‌شناسی، هوش مصنوعی، تشخیص الگوهای مالی و … کاربرد دارند.

روش‌های خوشه‌بندی

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

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

خوشه‌بندی تفکیکی (Partitioning Clustering)

در این روش، براساس n‌ مشاهده و k گروه، عملیات خوشه‌بندی انجام می‌شود. به این ترتیب تعداد خوشه‌ها یا گروه‌ها از قبل در این الگوریتم مشخص است. با طی مراحل خوشه‌بندی تفکیکی، هر شیء فقط و فقط به یک خوشه تعلق خواهد داشت و هیچ خوشه‌ای بدون عضو باقی نمی‌ماند. اگر lij نشانگر وضعیت تعلق xi به خوشه cj باشد تنها مقدارهای ۰ یا ۱ را می‌پذیرد. در این حالت می‌نویسند:

lij=,  xicj   or   lij= xicj

هر چند این قانون‌ها زمانی که از روش «خوشه‌بندی فازی» (Fuzzy Clustering) استفاده می‌شود، تغییر کرده و برای نشان دادن تعلق هر شئی به هر خوشه از درجه عضویت استفاده می‌شود. به این ترتیب میزان عضویت xi به خوشه cj مقداری بین ۰ و ۱ است. در این حالت می‌نویسند:

lij[0,1]

معمولا الگوریتم‌های تفکیکی بر مبنای بهینه‌سازی یک تابع هدف عمل می‌کنند. این کار براساس تکرار مراحلی از الگوریتم‌های بهینه‌سازی انجام می‌شود. در نتیجه الگوریتم‌های مختلفی بر این مبنا ایجاد شده‌اند. برای مثال الگوریتم «k-میانگین» (K-means) با تعیین تابع هدف براساس میانگین فاصله اعضای هر خوشه نسبت به میانگینشان، عمل می‌کند و به شکلی اشیاء را در خوشه‌ها قرار می‌دهد تا میانگین مجموع مربعات فاصله‌ها در خوشه‌ها، کمترین مقدار را داشته باشد. اگر مشاهدات را با x نشان دهیم، تابع هدف الگوریتم «k-میانگین» را می‌توان به صورت زیر نوشت:

E=kj=1xcjdist(x,μcj)

که در آن μcj میانگین خوشه‌ cj و dist نیز مربع فاصله اقلیدسی است.

به این ترتیب با استفاده از روش‌های مختلف بهینه‌سازی می‌توان به جواب مناسب برای خوشه‌بندی تفکیکی رسید. ولی از آنجایی که تعداد خوشه‌ها یا مراکز اولیه باید به الگوریتم داده شود، ممکن است با تغییر نقاط اولیه نتایج متفاوتی در خوشه‌بندی بدست آید. در میان الگوریتم‌های خوشه‌بندی تفکیکی، الگوریتم k-میانگین که توسط «مک‌کوئین» (McQueen) جامعه شناس و ریاضیدان در سال ۱۹۶۵ ابداع شد از محبوبیت خاصی برخوردار است.

خوشه بندی

نکته: در شیوه خوشه‌بندی تفکیکی با طی مراحل خوشه‌بندی، برچسب عضویت اشیاء به هر خوشه براساس خوشه‌های جدیدی که ایجاد می‌شوند قابل تغییر است. به این ترتیب می‌توان گفت که الگوریتم‌های خوشه‌بندی تفکیکی جزء الگوریتم‌های «یادگیری ماشین بدون ناظر» (Unsupervised Machine Learning) محسوب می‌شوند.

در تصویر ۱ نتایج ایجاد ۴ خوشه‌ روی داده‌های دو بعدی به کمک الگوریتم k-میانگین نمایش داده شده است. داشتن حالت کروی برای داده‌ها به ایجاد خوشه‌های مناسب در الگوریتم k-میانگین کمک می‌کند.

خوشه‌بندی k-میانگین برای داده‌های دو بعدی

تصویر ۱- خوشه‌بندی k-میانگین برای داده‌های دو بعدی