Building a Spam Classifier

اولویت‌بندی کارها

در این بخش می‌خواهیم با استفاده از یک مثال؛ ساختن یک طبقه‌بندی کننده اسپم، مسائلی که ممکن است در طراحی یک سیستم یادگیری ماشین برایتان پیش آید را با هم بررسی کنیم.

در شکل زیر دو ایمیل را مشاهده می‌کنید که ایمیل سمت چپ به وضوح یک هرزنامه یا ایمیل اسپم است و ایمیل سمت راست یک ایمیل واقعی است. چنانکه مشاهده می‌کنید در ایمیل‌ اسپم ممکن است که عمدا بعضی کلمات را با غلط املایی بنویسند. مانند کلمه w4tches یا M0rgages در ایمیل سمت چپ.

سوال این است چگونه با استفاده از یادگیری با نظارت یک طبقه‌بندی کننده (classifier) بسازیم که ایمیل‌های اسپم \((y=1)\) را از ایمیل‌های غیر اسپم \((y=0)\) تشخیص دهد.

اولین تصمصیمی که باید بگیریم آن است که \(x\) چه خصوصیاتی از ایمیل باشد. با داشتن خصوصیات \(x\) و برچسب \(y\) مثلا می‌توانیم از رگرسیون لجستیک جهت ساختن یک طبقه‌بندی کننده استفاده کنیم.

یکی از راه‌هایی که می‌توان مجموعه‌ای از خصوصیات را انتخاب کرد به این صورت است که مثلا 100 کلمه که نشانگر اسپم یا غیر اسپم بودن ایمیل هستند انتخاب کنیم. مانند: deal ،buy ،‌discount ،andrew ،now و ... سپس به قسمتی از ایمیلی که داریم نگاه می‌کنیم و بر اساس اینکه کلمات داخل آن وجود دارند یا نه ماتریس خصوصیات را به شکل زیر می‌سازیم:

  1. مرتب کردن کلمات برحسب الفبا
  2. andrew, buy, deal, discount, ..., now, ...
  3. تشکیل ماتریس خصوصیات بر اساس:
  4. $$ x_j = \begin{cases} 1 \text{ if word j appears in email} \\ 0 \text{ otherwise }\end{cases} $$

بنابراین اگر برای ایمیل زیر بخواهیم ماتریس خصوصیات را تشکیل دهیم خواهیم داشت:

$$ x = \begin{bmatrix} 0 \\ 1 \\ 1 \\ 0\\ \vdots \\ 1 \\ \vdots \end{bmatrix} $$
توجه داشته باشید که در عمل به جای انتخاب 100 کلمه به صورت دستی، \(n\) کلمه که بیشترین تکرار را دارند (معمولا در حدود 10 تا 50 هزار کلمه) انتخاب می‌شوند.

حال سوال اساسی این است که برای داشتن کمترین خطا، زمان خود را چگونه صرف کنیم؟

  • جمع‌آوری داده‌های زیاد: مثلا در مورد ایمیل‌های اسپم می‌توان با استفاده از پروژه‌هایی نظیر honeypot تعداد زیادی داده جمع‌آوری کرد. ولی چنانکه پیشتر هم بحث کردیم، داشتن داده زیاد هرچند اغلب کمک کننده است ولی نه همیشه.
  • ایجاد خصوصیت‌های حساب شده بر اساس اطلاعات مسیر ایمیل (از طریق هدر ایمیل): بیشتر اوقات موقعی که ایمیل اسپم فرستاده می‌شود، تلاش بر این است که منشا فرستادن ایمیل معلوم نباشد و از مسیرهای غیر معمول ایمیل را می‌فرستند. برخی از این اطلاعات در هدر ایمیل منعکس است. بنابراین با نگاه کردن به آن ممکن است بتوان خصوصیات بهتری برای الگوریتم ایجاد کرد.
  • ایجاد خصوصیت‌های حساب شده برای بنه پیام: برای مثال آیا کلمات discount یا discounts باید به عنوان کلمات مشابه در نظر گرفته شوند؟ در مورد کلمات deal و Dealer چطور؟ آیا لازم است برای نشانه گذاری (punctuation) خصوصیاتی ایجاد شود یا خیر؟
  • ایجاد الگوریتم‌های پیچیده‌تر جهت شناسایی غلط‌های املایی: اسپمرها اغلب به صورت عمدی غلط‌های املایی نظیر w4tches را داخل ایمیل ایجاد می‌کنند. با تکنیک‌های ساده‌ای که اینجا بحث شد، طبقه‌بندی کننده اسپم قادر نیست چنین کلماتی را تشخیص دهد. بنابراین این سوال پیش می‌اید که آیا لازم است الگوریتم‌های پیچیده‌تری طراحی کنیم؟

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

تحلیل خطا

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

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

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

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

دسته‌بندی کنید. در اینجا فرض کنید بعد از بررسی متوجه می‌شوید، 12 ایمیل مربوط به فروش محصولات داروسازی، 4 ایمیل مربوط به فروش محصولات بدل یا تقلبی، 53 ایمیل مربوط به ایمیل‌هایی است که قصد دزیدن رمز عبور را دارند و 31 ایمیل هم مربوط به سایر انواع ایمیل‌ها است. اگر با چنین چیزی مواجه شوید واضح است که الگوریتم شما در مورد ایمیل‌هایی که قصد دزدیدن رمز عبور را دارند ضعیف عمل کرده است و بهتر است روی این مورد کار کنید.

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

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

اهمیت ارزیابی عددی

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

به عنوان نمونه در مثال طبقه‌بندی ایمیل‌‌ها، آیا کلمات discount ،discounts ،discounted و discounting باید یکسان در نظر گرفته شوند؟

یکی از راه‌ها شاید آن باشد که به چند حرف اول کلمات نگاهی بیاندازیم (discount) و متوجه شویم تقریبا همه آن‌ها یک معنی را می‌رسانند. برای انجام این کار معمولا از نرم‌افزارهای "stemming" مانند "Porter stemmer" استفاده می‌شود.

استفاده از این نرم‌افزار هر چند می‌توان مفید و کمک کننده باشد، اما از طرفی دیگر می‌تواند مضر هم باشد. زیرا در تشخیص یکسان بودن کلماتی که چند کاراکتر اول آنها مشابه است ولی معانی متفاوتی دارند ممکن است اشتباه کند مانند کلمات university و universe.

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

مثلا فرض کنید که بدون stemming الگوریتم را اجرا و با خطای 5 درصد روبرو می‌شوید. بار دیگر الگوریتم را با استفاده از stemming اجرا کنید. اگر خطا کاهش پیدا کرده بود (مثلا ۳ درصد خطا داشتید)، خوب واضح است که استفاده از آن بهتر است.

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