عملکرد ماشین بردار پشتیبان چگونه در مقایسه با بیز ساده چگونه است؟ آیا آموزش دادن آن کند تر است؟ بیایید در این تمرین برنامه نویسی ، پاسخ این سوالات را کشف کنیم. این دومین بخش از قسمت دوم یادگیری نظارت شده، یعنی ماشین بردار پشتیبان یا کلاسه بند بردار پشتیبان است. اگر نظریه را نخوانده اید (بخش اول) ، توصیه می کنیم اول آن را مطالعه کنید. بسیار مهم است که اصول اولیه کلاسه بند SVM را بدانید.
مقاله مرتبط :
- یادگیری نظارت شده و کلاسه بندی بیز ساده – بخش اول : نظریه
- یادگیری نظارت شده و کلاسه بندی بیز ساده – بخش دوم : کد نویسی
- ماشین بردار پشتیبان ( SVM ) – بخش اول : نظریه
- ماشین بردار پشتیبان ( SVM ) – بخش دوم : کد نویسی
در حالی که شما تنها با خواندن این آموزش، دانش کافی در مورد اجرای این الگوریتم را به دست خواهید آورد ، اکیداً توصیه می کنیم نرم افزار کد نویسی خود را باز کرده و همراه با آموزش، کد ها را تمرین کنید. بدین صورت شما دید بهتر و یادگیری ماندگار تری خواهید داشت.
۰٫ چه کاری باید انجام دهیم
این تمرین برنامه نویسی، تکمیل کننده ی برنامه قبلی کلاسه بند بیز ساده است که ایمیل را به هرزنامه و غیر هرزنامه طبقه بندی می کرد. نگران نباشید ، اگر آموزش کد نویسی بیز ساده (قسمت اول) را نگذرانده اید (اگرچه من به شما پیشنهاد می کنم اول آن را سپری کنید) در کدی که در اینجا ارائه شده نیز به صورت انتزاعی مورد بحث قرار خواهد گرفت.
ما سعی خواهیم کرد با کاهش ۱۰٪ اندازه اصلی مجموعه داده ها ، زمان آموزش را کاهش دهیم. سپس پارامتر های تنظیم را تغییر می دهیم تا دقت را افزایش دهیم. خواهیم دید که کرنل ، C و گاما دقت و زمانبندی را چگونه تغییر می دهند.
۱- بارگیری
من یک مخزن گیت هاب برای مجموعه داده ها و کد نمونه ایجاد کرده ام. می توانید آن را از اینجا بارگیری کنید (از پوشه فصل ۲ استفاده کنید). در صورت عدم موفقیت ، می توانید برای استفاده ودرک کار، از نسخه ی من (classifier.py در پوشه فصل ۲) استفاده کنید. فایل plot.py را نادیده بگیرید.
۲- کمی در مورد پالایش
اگر بخشی از کد نویسی بیز ساده را پشت سر گذاشته باشید ، می توانید از این قسمت عبور کنید. (این برای خوانندگانی است که به طور مستقیم از اینجا شروع کرده اند).
قبل از استفاده از کلاسه بند های sklearn ، باید داده ها را پالایش کنیم. پالایش کردن شامل حذف کلمات توقف ، استخراج رایج ترین کلمات از متن و غیره است. در مثال کد مربوطه، مراحل زیر را انجام می دهیم:
برای درک جزئیات ، یک بار دیگر به بخش کد نویسی فصل ۱ در اینجا مراجعه کنید.
- فرهنگ لغتی از کلمات را از اسناد ایمیل های مجموعه آموزش بسازید.
- ۳۰۰۰ کلمه ی رایج تر را در نظر بگیرید.
- برای هر سند در مجموعه آموزش ، ماتریس تکرار برای این کلمات در فرهنگ لغت و برچسب های مربوطه را ایجاد کنید. [نام پرونده های ایمیل هرزنامه با پیشوند “spmsg” شروع می شود.
The code snippet below does this: def make_Dictionary(root_dir): all_words = [] emails = [os.path.join(root_dir,f) for f in os.listdir(root_dir)] for mail in emails: with open(mail) as m: for line in m: words = line.split() all_words += words dictionary = Counter(all_words) # if you have python version 3.x use commented version. # list_to_remove = list(dictionary) list_to_remove = dictionary.keys() for item in list_to_remove: # remove if numerical. if item.isalpha() == False: del dictionary[item] elif len(item) == 1: del dictionary[item] # consider only most 3000 common words in dictionary. dictionary = dictionary.most_common(3000) return dictionary def extract_features(mail_dir): files = [os.path.join(mail_dir,fi) for fi in os.listdir(mail_dir)] features_matrix = np.zeros((len(files),3000)) train_labels = np.zeros(len(files)) count = 0; docID = 0; for fil in files: with open(fil) as fi: for i,line in enumerate(fi): if i == 2: words = line.split() for word in words: wordID = 0 for i,d in enumerate(dictionary): if d[0] == word: wordID = i features_matrix[docID,wordID] = words.count(word) train_labels[docID] = 0; filepathTokens = fil.split('/') lastToken = filepathTokens[len(filepathTokens) - 1] if lastToken.startswith("spmsg"): train_labels[docID] = 1; count = count + 1 docID = docID + 1 return features_matrix, train_labels
۳- ورود به دنیای کلاسه بند بردار پشتیبان ( SVC )
کد استفاده از svc مشابه کد بیز ساده است. ابتدا svc را از کتابخانه وارد می کنیم. در مرحله بعد ، ویژگی های آموزش و برچسب ها را استخراج می کنیم. در آخر ، ما از مدل می خواهیم تا برچسب های مجموعه آزمون را پیش بینی کند. بلوک کد ساده ی آن به شرح زیر است:
from sklearn import svm from sklearn.metrics import accuracy_score TRAIN_DIR = "../train-mails" TEST_DIR = "../test-mails" dictionary = make_Dictionary(TRAIN_DIR) print "reading and processing emails from file." features_matrix, labels = extract_features(TRAIN_DIR) test_feature_matrix, test_labels = extract_features(TEST_DIR) model = svm.SVC() print "Training model." #train model model.fit(features_matrix, labels) predicted_labels = model.predict(test_feature_matrix) print "FINISHED classifying. accuracy score : " print accuracy_score(test_labels, predicted_labels)
ترکیب همه با هم
import os import numpy as np from collections import Counter from sklearn import svm from sklearn.metrics import accuracy_score def make_Dictionary(root_dir): all_words = [] emails = [os.path.join(root_dir,f) for f in os.listdir(root_dir)] for mail in emails: with open(mail) as m: for line in m: words = line.split() all_words += words dictionary = Counter(all_words) list_to_remove = dictionary.keys() for item in list_to_remove: if item.isalpha() == False: del dictionary[item] elif len(item) == 1: del dictionary[item] dictionary = dictionary.most_common(3000) return dictionary def extract_features(mail_dir): files = [os.path.join(mail_dir,fi) for fi in os.listdir(mail_dir)] features_matrix = np.zeros((len(files),3000)) train_labels = np.zeros(len(files)) count = 0; docID = 0; for fil in files: with open(fil) as fi: for i,line in enumerate(fi): if i == 2: words = line.split() for word in words: wordID = 0 for i,d in enumerate(dictionary): if d[0] == word: wordID = i features_matrix[docID,wordID] = words.count(word) train_labels[docID] = 0; filepathTokens = fil.split('/') lastToken = filepathTokens[len(filepathTokens) - 1] if lastToken.startswith("spmsg"): train_labels[docID] = 1; count = count + 1 docID = docID + 1 return features_matrix, train_labels TRAIN_DIR = "../train-mails" TEST_DIR = "../test-mails" dictionary = make_Dictionary(TRAIN_DIR) print "reading and processing emails from file." features_matrix, labels = extract_features(TRAIN_DIR) test_feature_matrix, test_labels = extract_features(TEST_DIR) model = svm.SVC() print "Training model." #train model model.fit(features_matrix, labels) predicted_labels = model.predict(test_feature_matrix) print "FINISHED classifying. accuracy score : " print accuracy_score(test_labels, predicted_labels)
این اجرای بسیار ساده ی کلاسه بند بردار پشتیبان است. مقادیر پارامترهای تنظیم را مقادیر پیش فرض آن ها در نظر گرفته است. (کرنل = خطی ، C = 1 و گاما = ۱)
- بررسی کنید که در این مورد چه میزان دقتی را کسب می کنید؟
- زمان آموزش چقدر است؟ آیا این سرعت سریع تر یا کندتر از بیز ساده است؟
- میزان دقت در مقایسه با بیز ساده چگونه است؟
خب … چطور زمان آموزش را کاهش می دهیم؟
یک روش این است که اندازه مجموعه آموزش را کاهش دهید. فرض کنید ما آن را تا یک دهم اندازه ی اصلی کاهش می دهیم و سپس دقت آن را بررسی می کنیم. البته که دقت کاهش می یابد.
در اینجا ۷۰۲ ایمیل برای آموزش داریم. یک دهم آن به معنای ۷۰ ایمیل برای آموزش است که بسیار کم است. (با وجود مزایایی که می توانیم به آن ها برسیم).
این کد های زیر را قبل از آموزش مدل خود اضافه کنید. (این کد میزان feature_matrix و labels را تا یک دهم کاهش می دهد).
features_matrix = features_matrix[:len(features_matrix)/10] labels = labels[:len(labels)/10]
اکنون زمان و دقت آموزش چیست؟
تنظیم پارامتر
من حدس می زنم که شما دقتی در حدود ۵۶٪ دریافت کرده اید. خیلی کم است.
اکنون با نگه داشتن یک دهم مجموعه ی آموزش ، بیایید سه پارامتر کرنل ، C و گاما را تنظیم کنید.
۱٫ کرنل
کرنل را به rbf تغییر دهید. یعنی در model = SVC() پارامتر کرنل را اضافه کنید.
model = svm.SVC(kernel="rbf", C = 1)
۲٫ C
متغیر بعدی C (پارامتر تنظیم) را به ۱۰ ، ۱۰۰ ، ۱۰۰۰ ، ۱۰۰۰۰ تغییر دهید. تعیین کنید آیا دقت افزایش یا کاهش می یابد؟
شما متوجه خواهید شد که در C = 100 ، نمره دقت به ۸۵٫۳۸٪ افزایش می یابد و تقریباً فراتر از آن باقی می ماند.
۳٫ گاما
در آخر ، بیایید با گاما بازی کنیم. یک پارامتر دیگر gamma = 1.0 اضافه کنید.
model = svm.SVC(kernel="rbf", C=100, gamma=1)
اوه! نمره دقت کاهش یافت. درسته؟ مقدار بالاتر gamma = 10 را امتحان کنید. مقدار دقت بیشتر کاهش یافت. سعی کنید گاما را کاهش دهید. از مقادیر ۰٫۱ ، ۰٫۰۱ ، ۰٫۰۰۱ استفاده کنید. اکنون دقت چطور است؟ در حال افزایش است؟
متوجه خواهید شد که در این حالت از آموزش ، مقادیر پایین گاما به ما دقت بالایی می دهند. (شهود: این بدان معنی است که نقاط داده پراکنده هستند ، به اندازه کافی از مرز تصمیم گیری در نمودار فاصله دارند).
در این حالت ، متوجه می شویم که با کاهش اندازه مجموعه آموزش ، ۸۵٫۴ بهترین دقتی است که به آن دست پیدا می کنیم. (پی نوشت: نمره دقت در بیز ساده چه بود؟)
اجرای سریع اسکریپت [اختیاری]
شاید متوجه شده باشید که هر بار، اسکریپت وقت زیادی را برای پالایش کردن و خواندن داده ها (ویژگی ها و برچسب ها) از ایمیل ها، می گیرد. می توانید با ذخیره کردن داده هایی که از اولین بار استخراج شده اند ، این روند را سرعت بخشید.
انجام این کار، ، باعث صرفه جویی در وقت بیشتر برای تمرکز روی یادگیری پارامترهای تنظیم می شود.
برای ذخیره و بارگیری از قطعه زیر برای کد خود استفاده کنید.
import cPickle import gzip def load(file_name): # load the model stream = gzip.open(file_name, "rb") model = cPickle.load(stream) stream.close() return model def save(file_name, model): # save the model stream = gzip.open(file_name, "wb") cPickle.dump(model, stream) stream.close() #To save save("/tmp/features_matrix", features_matrix) save("/tmp/labels", labels) save("/tmp/test_feature_matrix", test_feature_matrix) save("/tmp/test_labels", test_labels) #To load features_matrix = load("/tmp/features_matrix") labels = load("/tmp/labels") test_feature_matrix = load("/tmp/test_feature_matrix") test_labels = load("/tmp/test_labels")
توجه: به عنوان مرجع می توانید به فایل های classifier.py و classifier-fast.py در اینجا رجوع کنید.
نتیجه گیری
به طور کلی ، کلاسه بند بردار پشتیبان زمان آموزش بیشتری نسبت به بیز ساده دارد اما پیش بینی آن سریع تر است. در تمرین کد نویسی بالاتر، بیز ساده از SVC بهتر است. با این حال ، این کاملاً به سناریو و مجموعه داده هایی بستگی دارد که کدام یک بهترین عملکرد را دارند.
حتی بعد از کاهش داده های آموزش به یک دهم، دقت بالایی می توان بدست آورد.
اما ، چرا باید مجموعه آموزش را کاهش دهیم؟
زمان آموزش بیشتر است ، به طور کلی برای SVC سه برابر بیشتر از بیز ساده است. کاربرد هایی وجود دارد که در مقایسه با دقت ، پیش بینی سریع تر را نیاز داریم.
- به معاملات با کارت اعتباری فکر کنید. پاسخ دادن سریع برای تشخیص کلاه برداری معامله از دقت ۹۹٪ بسیار مهم تر است. دقت ۹۰٪ در اینجا قابل تحمل است.
- از طرف دیگر ، تنها برچسب زدن ایمیل به هرز نامه یا غیر هرزنامه ممکن است تاخیر ها را تحمل کند و ما می توانیم برای دقت بیشتر تلاش کنیم.
آیا باید پارامترها را همیشه تنظیم کنیم ؟؟
نه واقعا. در جعبه ابزار sklearn توابع داخلی وجود دارد که این کار را برای ما انجام می دهد. ما آنه ا را در پست های آینده بررسی خواهیم کرد.
امیدوارم این آموزش برای شما ایده پایه ی در مورد کد نویسی SVC را به دنبال داشته باشد. چگونه می توانیم پارامترها را تنظیم کنیم و حتی در اندازه کوچکی از مجموعه داده ها ، به دقت عادلانه ای برسیم. (ما فقط ۷۰ ایمیل در مجموعه آموزش داشتیم و در تست در برابر ۳۵۰ ایمیل به ۸۵٪ دقت رسیدیم) 😊.