شعار زيفيرنت

تقنيات التضمين في البيانات النصية باستخدام KNN

التاريخ:

تم نشر هذه المقالة كجزء من مدونة علوم البيانات.

في هذه المقالة ، سنحاول تصنيف مراجعات الطعام باستخدام تقنيات مدمجة متعددة بمساعدة أحد أبسط نماذج التعلم الآلي المُصنفة والتي تسمى K-Nearest Neighbor.

هنا جدول الأعمال الذي سيتبع في هذه المقالة.

  1. هدف
  2. تحميل البيانات
  3. معالجة البيانات
  4. معالجة النص
  5. تقسيم الوقت
  6. تقنيات التضمين
  7. أنواع تقنيات التضمين
    1. BOW
    2. قوة العمل-جيش الدفاع الإسرائيلي
    3. Word2Old
    4. متوسط ​​Word2Vec
    5. TF-جيش الدفاع الإسرائيلي-Word2Vec
  8. بناء نموذج
  9. وفي الختام

هدف

الهدف من هذه المقالة هو تحديد ما إذا كانت المراجعة إيجابية (التقييم 3+) أو سلبية (التقييم 1 أو 2). نظرًا لأن البيانات التي سنعمل عليها هي بيانات نصية سنستكشف تقنيات تضمين مختلفة يمكننا استخدامها لتقليل البيانات عالية الأبعاد إلى بيانات منخفضة الأبعاد وبناء نماذج فوق ذلك.

تحميل البيانات

سنستخدم بيانات Amazon Fine Food Reviews. إنه متاح للجمهور على Kaggle.

مصدر البيانات: https://www.kaggle.com/snap/amazon-fine-food-reviews

مجموعة البيانات متاحة في شكلين وسنستخدمها سكليتي شكل للعمل عليه. نحن نستخدم هذا النموذج لأنه من الأسهل الاستعلام عن البيانات وتصور البيانات بكفاءة باستخدام SQL.

نظرًا لأن هدف هذه المقالة هو تحديد التقييمات الإيجابية (3+) أو المراجعات السلبية (3 تقييمات) ، فسوف نتجاهل التقييمات التي تساوي 3 (محايدة) أثناء تحميل البيانات.

#establishing connect to sqlite database con = sqlite3.connect ('../ input / database.sqlite') # قراءة مجموعة البيانات وتجاهل المراجعات المحايدة orignal_data = pd.read_sql_query ("" "حدد * من المراجعات أين النتيجة! = 3 "" ، يخدع)

فيما يلي تفاصيل مجموعة بيانات Amazon Fine Food Reviews.

عدد المراجعات: 568,454
عدد المستخدمين: 256,059
عدد المنتجات: 74,258
المدة: أكتوبر 1999 - أكتوبر 2012
عدد السمات / الأعمدة في البيانات: 10

معلومات السمة:

  1. Id
  2. ProductId - معرّف فريد للمنتج
  3. معرف المستخدم - معرف فريد للمستخدم
  4. اسم الشخصية
  5. البسط - عدد المستخدمين الذين وجدوا المراجعة مفيدة
  6. القاعد - عدد المستخدمين الذين أشاروا إلى ما إذا كانوا قد وجدوا المراجعة مفيدة أم لا
  7. النتيجة - تصنيف بين 1 و 5
  8. الوقت - الطابع الزمني للمراجعة
  9. ملخص - ملخص موجز للمراجعة
  10. نص - نص المراجعة

معالجة البيانات

إزالة التكرارات

نحن هنا نزيل الإدخالات التي لها نفس القيمة في "UserId" و "ProfileName" و "Time" و "Text".

 #first الفرز المستحق لمعرّف المنتج

sort_prodid = orignal_data.sort_values ​​('ProductId'، محور = 0، inplace = False، kind = 'quicksort'، na_position = 'last')
data_no_duplicate = sort_prodid.drop_duplicates (مجموعة فرعية = {“UserId”، ”ProfileName”، “Time”، ”Text”}، keep = 'first'، inplace = False)
data_no_duplicate.shape

المساعدة البسط <= فائدة السمة

  1. HelpfulnessNumerator = نعم (بحث مفيد)
  2. HelpfulnessDenominator = نعم + لا (بحث مفيد + غير مفيد)
  1. لذا فإن HelpfulnessNumerator سيكون دائمًا <= HelpfulnessDenominator. هنا نحتفظ فقط بهذه الإدخالات.

#keeping فقط الإدخالات حيث HelpfulnessNumerator <= HelpfulnessDenominator
data_no_duplicate = data_no_duplicate.loc [data_no_duplicate ['HelpfulnessNumerator'] <= data_no_duplicate ['HelpfulnessDenominator']]

فرز البيانات على "الوقت" والاحتفاظ فقط بـ 100 ألف نقطة

يحتوي نظامي على ذاكرة وصول عشوائي (RAM) بسعة 16 جيجابايت. لقد لاحظت أن العمل على أكثر من 100 ألف نقطة بيانات من مجموعة البيانات يؤدي إلى تجاوز الذاكرة في نظامي. لذا اختر عددًا من نقاط البيانات حسب ذاكرة الوصول العشوائي للنظام. لذلك ، بسبب قيود الذاكرة ، سنختار 100 ألف نقطة بيانات فقط.

#sorting البيانات على أساس الطابع الزمني Sorted_data_time = data_no_duplicate.sort_values ​​(["الوقت"] ، المحور = 0 ، تصاعدي = صحيح ، inplace = خطأ) # تحديد 100 ألف نقطة من بيانات البيانات التي تم فرزها_100k = Sorted_data_time.iloc [0: 100000، :]

تحويل "النقاط" إلى مراجعة إيجابية أو سلبية

تتراوح السمة #Score بين 1 و 5 ، لقد تجاهلنا بالفعل الدرجة 3 (محايدة). # لذا نقوم هنا بتحويل النتيجة إلى مراجعة إيجابية أو سلبية # الدرجة <3 ثم 0 (سلبي) وإلا 1 (إيجابي) قسم def (x): إذا كانت x <3: إرجاع 0 وإلا: إرجاع 1 الفعلي_score = data_100k ['النتيجة '] نقاط البيع

معالجة النص

سنقوم الآن بإجراء معالجة نصية مسبقة على عمود "النص" في البيانات. هذا هو العمود الذي يحتوي على المراجعة الأولية للطعام.

فيما يلي الخطوات التي سنقوم بتنفيذها في عمود "النص".

  1. إزالة علامات HTML
  2. إزالة الأحرف الخاصة
  3. حفظ الكلمات الإنجليزية فقط
  4. يحول كل الكلمات إلى أحرف صغيرة
  5. إزالة Stopwords
  6. تطبيق Stemming

سنقوم الآن بكتابة الوظائف التي ستطبق التغييرات المذكورة أعلاه على عمود "النص".

import re def cleanhtml (الجملة): cleanr = re.compile ('') cleansent = re.sub (cleanr، ""، الجملة) إرجاع cleansent def cleanpunc (الجملة): # لإزالة الأحرف الخاصة التي تم تنظيفها = re.sub (r تم تنظيف '[؟ |! |' | "| #] '، r' '، جملة) = re.sub (r' [. |، |) | (|| /] '، r' '، تم تنظيفه الخيار #below ليس ضروريًا في كل مرة. فقط إذا لم يتم العثور على مورد Stopword ، فقم بتشغيل الأمر أدناه # nltk.download ('stopwords') استيراد nltk من nltk.corpus import stopwords stop = set (stopwords.words ('english')) # تهيئة جذع كرة الثلج الذي سيحول الكلمات إلى جذر المعنى sno = nltk.stem.SnowballStemmer ('الإنجليزية')

في خطوات المعالجة المسبقة للنص المذكور أعلاه ، من الواضح أن الخطوات من 1 إلى 4 يجب فهمها. الخطوتان الأخيرتان تحتاجان إلى بعض التوضيح.

كلمات التوقف هي الكلمات التي يشيع استخدامها في اللغة لدرجة أنها تحمل القليل جدًا من المعلومات. على سبيل المثال: "a" ، "the" ، "is" ، "are" إلخ. أثناء التحدث بلغة ، تكون مفيدة لأنها تحمل معلومات حول "tense" كما أنها تجمع الجملتين المختلفتين معًا. ولكن أثناء إجراء معالجة البرمجة اللغوية العصبية أو المعالجة المسبقة للنص لنماذج التعلم الآلي ، لا تضيف هذه الكلمات الكثير من المعلومات. على سبيل المثال في هذه المقالة في نموذج مراجعة الطعام يحتاج فقط إلى معلومات حول كلمة تمثل إما مشاعر إيجابية / سلبية وإضافة أي كلمة توقف لن يغير معنى تلك المراجعة.

النابعة هي عملية تحويل الكلمة إلى معناها الجذري. هذا مهم لأنه في اللغة يمكن كتابة الكلمات بصيغة الزمن (الحاضر ، الماضي ، أو المستقبل) ولكن ما نحتاجه هو جوهر الكلمة بحيث يمكن استخدامها لتحديد المراجعات الإيجابية أو السلبية.

الآن ، سنقوم بتطبيق جميع الخطوات المذكورة أعلاه على عمودي "النص" و "الملخص".

#applying جميع خطوات المعالجة المسبقة على سمة النص من استيراد tqdm tqdm # لإظهار شريط التقدم i = 0 str1 = '' final_string = [] s = '' للإرسال في tqdm (قيم data_100k ['Text'].): filter_sent = [] sent = cleanhtml (sent) #cleaning علامات HTML لـ w in sent.split (): for cleaned_words in cleanpunc (w) .split (): if ((cleaned_words.isalpha ()) & (len (cleaned_words)> 2)): # حفظ الكلمات الإنجليزية فقط إذا كانت (cleaned_words.lower () ليست متوقفة): s = (sno.stem (cleaned_words.lower ())). encode ("utf-8") #stemming filtered_sent.append ( s) else: تابع else: تابع str1 = b "". الانضمام (filtered_sent) final_string.append (str1) i + = 1 data_100k ['CleanedText'] = final_string data_100k ['CleanedText'] = data_100k ['CleanedText']. str .decode ("utf-8") # تطبيق جميع خطوات المعالجة المسبقة السمة "الملخص" من tqdm import tqdm # for progress baar i = 0 str1 = '' final_string = [] s = 'للإرسال في tqdm (data_100k [ 'الملخص']. القيم): filtered_sent = [] sent = cleanhtml (sent) #cleaning علامات HTML لـ w in sent.split (): for cleaned_words in clea npunc (w) .split (): إذا ((cleaned_words.isalpha ()) & (len (cleaned_words)> 2)): if (cleaned_words.lower () not in stop): s = (sno.stem (cleaned_words. low ())). encode ("utf-8") filtered_sent.append (s) else: تابع آخر: تابع str1 = b "". الانضمام (filtered_sent) final_string.append (str1) i + = 1 data_100k ['CleanedSummary' ] = final_string data_100k ['CleanedSummary'] = data_100k ['CleanedSummary']. str.decode ("utf-8")

الآن سنقوم بإسقاط الأعمدة الأصلية والاحتفاظ بالنسخة النظيفة عليها.

cleantext_data_100k = data_100k.drop (["نص" ، "ملخص"] ، محور = 1 ، inplace = خطأ) cleantext_data_100k.head ()

تقسيم الوقت

نظرًا لأن المراجعات المقدمة في مجموعة البيانات تعتمد على الوقت ، فسنقوم بتقسيم البيانات باستخدام الوقت وليس بشكل عشوائي.

سنحتفظ بأول 60,000 مراجعة للتدريب على الـ 20,000 مراجعة التالية للتحقق المتبادل وآخر 20,000 مراجعة للاختبار.

#splitting the dataset
train_data=cleantext_data_100k.iloc[0:60000,:]
crossvalidation_data=cleantext_data_100k.iloc[60000:80000,:]
test_data=cleantext_data_100k.iloc[80000:100000,:]

تقنيات التضمين

تُستخدم تقنيات التضمين لتمثيل الكلمات المستخدمة في البيانات النصية إلى متجه. نظرًا لأنه لا يمكننا استخدام البيانات النصية مباشرة لتدريب النموذج ، ما نحتاجه هو التمثيل في شكل رقمي والذي بدوره يمكن استخدامه لتدريب النموذج. دعنا نستكشف تقنيات التضمين المختلفة.

أنواع تقنيات التضمين

BOW

BOW تعني حقيبة الكلمات. إنها أبسط تقنية مضمنة لتمثيل البيانات النصية في متجه رقمي. كما يوحي الاسم ، فإن هذه التقنية تخلق حقيبة من جميع الكلمات الموجودة في بيانات التدريب. انظر الصورة أدناه لفهم أفضل.

نص البيانات باستخدام KNN

المصدر شرح مبسط لنموذج حقيبة الكلمات | بواسطة فيكتور زو | نحو علم البيانات

عيب BOW هو أنه يحسب فقط حدوث كلمة في الجملة ولا يهتم بترتيبات الكلمات التي بدورها تفقد العلاقة بين كلمتين موجودتين في الجملة إن وجدت. عيب آخر هو أنه يخلق المتجه باستخدام مفردات التدريب الخاصة بالبيانات وإذا زادت المفردات عدة أضعاف ، فإن حجم المتجه سيزداد بشكل كبير مما قد يتسبب في تجاوز الذاكرة.

هناك شيء آخر يمكننا القيام به للاحتفاظ ببعض معلومات التسلسل وهو استخدام bi-grams ، و tri-grams ، إلخ.

عندما نقوم بإعداد BOW بسيط ، يتم أخذ كل كلمة على أنها بُعد ولكن عندما نطبق ثنائي جرام أو ثلاثي جرام ، يتم أخذ كلمتين / ثلاث كلمات متتالية كبعد واحد. هذا يساعدنا على الاحتفاظ ببعض المعلومات.

هناك مشكلة واحدة عند استخدام n-grams وهي أنها تزيد الأبعاد بشكل كبير.

الآن دعنا نطبق BOW.

من sklearn.feature_extraction.text import CountVectorizer count_vect = CountVectorizer (ngram_range = (1,2،XNUMX)) train_bow = count_vect.fit_transform (train_data ['CleanedText']. test_bow = count_vect.transform (test_data ['CleanedText']. قيم) # الحصول على أسماء الميزات ، سيعمل هذا كرأس لبيانات BOW وسيساعد على التعرف على الميزات المهمة feature_names_bow = count_vect.get_feature_names ()

قوة العمل-جيش الدفاع الإسرائيلي

TF-IDF هي تقنية تضمين أخرى لتمثيل الكلمات في شكل متجه. دعونا نرى كيف يعمل.

يتكون TF-IDF من كلمتين. TF تعني تردد المدى و IDF تعني تردد المستند المعكوس. دعونا نرى كيف يعمل كل من فريق العمل والجيش الإسرائيلي الواحد تلو الآخر.

TF (w، r) = عدد المرات التي تحدث فيها كلمة w في صف r / إجمالي عدد الكلمات في هذا الصف r

لذلك سيكون TF دائمًا بين 0 و 1.

بشكل أساسي ، يوفر TF المعلومات التي تشير إلى احتمال العثور على كلمة w في الصف r.

بينما يتم احتساب TF لصف / مستند ، يتم حساب IDF على المجموعة الكاملة لكلمة.

IDF (w) = تسجيل الدخول (N / n)

هنا ، N-> إجمالي عدد المراجعات / المستندات ، n-> عدد المراجعات التي تحتوي على كلمة w.

لاحظ ان تسجيل (N / ني) ستكون دائمًا أكبر من 0 لأن N / n ستكون أكبر من تساوي 1 لأن n <= N دائمًا. وأيضًا إذا زاد n ينخفض ​​جيش الدفاع الإسرائيلي وإذا كان n ينقص يزداد جيش الدفاع الإسرائيلي. بكلمات بسيطة ، إذا ظهرت كلمة في كثير من الأحيان ، فسيكون جيش الدفاع الإسرائيلي منخفضًا ، وبكلمات نادرة ، سيكون جيش الدفاع الإسرائيلي مرتفعًا.

الآن بعد أن فهمنا TF و IDF ، دعونا نفهم كيف يعملان معًا.

TF-IDF (ث ، ص) = TF (ث ، ص) * جيش الدفاع الإسرائيلي (ث)

لاحظ الآن أن TF-IDF تعطي وزناً أكبر لكل من الكلمات النادرة والمتكررة. إذا كانت الكلمة نادرة ، فسيكون جيش الدفاع الإسرائيلي مرتفعًا وإذا كانت الكلمة متكررة فسيكون TF مرتفعًا.

باختصار ، تظل مشكلة الأبعاد العالية كما هي في قوة قوة الدفاع- جيش الدفاع الإسرائيلي. كما أنها لا تهتم بالمعنى الدلالي للجملة.

Word2Old

دعونا نرى واحدة من أقوى التقنيات لتحويل النص إلى متجه. تأخذ هذه التقنية أيضًا في الاعتبار المعنى الدلالي للنص. إنها تقنية حديثة. يأخذ كلمة ويحولها إلى متجه.
سنرى هنا نظرة عامة على Word2Vec وليس بشكل متعمق لأن التعمق في الأمر يتطلب فهمًا عميقًا للنماذج التي يستخدمها word2vec في الخلفية وهو خارج نطاق هذه المقالة. في عام 2 من قبل فريق من الباحثين بقيادة توماس ميكولوف في Google على ورقتين.
لذلك في الخلفية ، يمكن لـ Word2Vec استخدام أي من الخوارزميتين المذكورتين أدناه لتحويل كلمة إلى متجه. هاتان التقنيتان هما

  1. حقيبة الكلمات المستمرة (CBOW)
  2. تخطي غرام

في بنية حقيبة الكلمات المستمرة ، يتنبأ النموذج بالكلمة الحالية من نافذة كلمات السياق المحيطة. لا يؤثر ترتيب كلمات السياق على التنبؤ (افتراض مجموعة الكلمات). في بنية التخطي المستمر ، يستخدم النموذج الكلمة الحالية للتنبؤ بالنافذة المحيطة بكلمات السياق. تزن بنية تخطي الجرام كلمات السياق القريبة بشكل أكبر من كلمات السياق البعيدة. وفقًا لملاحظة المؤلفين ، فإن CBOW يكون أسرع بينما يقوم skip-gram بعمل أفضل للكلمات النادرة.

المصدر Word2vec - ويكيبيديا

دعونا نرى التنفيذ في التعليمات البرمجية في مجموعة البيانات الخاصة بنا ... ..

استيراد نظام التشغيل من gensim.models استيراد Word2Vec من gensim.models import KeyedVectors # في هذا المشروع ، نستخدم نموذجًا تم اختباره مسبقًا بواسطة google # ملفه 3.3G ، بمجرد تحميل هذا في ذاكرتك # يشغل ~ 9 جيجا بايت ، لذا يرجى القيام بهذه الخطوة فقط إذا كان لديك> 12 جيجا بايت من ذاكرة الوصول العشوائي # لاستخدام مقتطف الشفرة هذا ، قم بتنزيل "GoogleNews-vectors-negative300.bin" # من https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit # حجمه 1.9 جيجابايت بحجم. # يمكنك التعليق على هذه الخلية بأكملها أو تغيير هذه المتغيرات وفقًا لحاجتك is_ram_gt_16 = صحيح إذا is_ram_gt_16 و os.path.isfile ('../ GoogleNews-vectors-negative300.bin'): w2v_model = KeyedVectors.load_word2vec_format ('.. /GoogleNews-vectors-negative300.bin '، binary = True) # ينتج نموذج word2vec من google 300 متجه أبعاد لكلمة train_list_of_sent = [] لإرسالها في train_data [' CleanedText ']. القيم: train_list_of_sent.append (sent.split (sent.split () )) test_list_of_sent = [] للإرسال في test_data ['CleanedText']. القيم: test_list_of_sent.append (sent.split ()) crossvalidation_list_of_sent = [] لإرسالها في بيانات_تقاطعية ['CleanedText']. Split ()) # فقط للتأكد من أننا حصلنا على جميع الجمل مطبوعة (len (train_list_of_sent)) print (len (test_list_of_sent)) print (len (crossvalidation_list_of_sent)) w2v_vector = w2v_model.wv.vectors w2v_vector.shape def find_word2vector.shape def find_word2v. : w300v = [] للإرسال في tqdm (list_of_sent): # لكل جملة sent_vector = np.zer os (300) #create 2 أبعاد من الأصفار للكلمة المرسلة: # لكل كلمة في الجملة إذا كانت الكلمة في w2v_model.wv.vocab: # إذا كانت الكلمة موجودة في نموذج word2vec vec = w2v_model.wv [word] # get the vector التمثيل من الكلمة sent_vector + = vec # أضف المتجه إلى sent_vector #a بعد إضافة جميع متجهات الكلمة في الجملة أضف المتجه الذي يمثل الآن # الجملة بأكملها إلى vectors_of_sentences w2v.append (sent_vector) إرجاع تمثيل w2v # word2vec لـ train_data train_w2v = find_word2vec (train_list_of_sent) crossvalidation_w2v = find_word2vec (crossvalidation_list_of_sent) test_w2v = find_wordXNUMXvec (test_list_of_sent)

متوسط ​​Word2Vec

كما يوحي الاسم هنا ، سنحسب متوسط ​​متجه الكلمات الذي توفره تقنية تضمين Word2Vec.
لكن لماذا نطلبها؟
نحن نعلم أنه في مثالنا لمجموعة بيانات المراجعات ، تكون المراجعات عبارة عن سلسلة من الكلمات أو الجمل. إذن كيف يمكننا تحويلها إلى متجهات باستخدام word2vec؟ هناك بعض التقنيات مثل Sent2Vec التي يمكنها تحويل جملة معينة إلى متجه ولكن أبسط طريقة لتحويل جملة معينة إلى متجه هي متوسط ​​متجهات Word2Vec لتلك الجملة.
في هذا ، نضيف كل تمثيل word2vec (الأبعاد d) ونقسم على العدد الإجمالي للكلمات في المراجعة. هذه التقنية ليست مثالية لأنها تعمل بشكل جيد بما يكفي لبناء ناقلات الجملة.

Average Word2Vec(R)=1/n[Word2Vec(w1)+Word2Vec(w2)+……+Word2Vec(wn)]

حيث ، R -> Review ، n–> عدد الكلمات قيد المراجعة و w1 ، w2 ،… .wn هي كلمات في المراجعة.
دعنا نرى الرمز الآن ... ..

def find_avgword2vec (list_of_sent): avgw2v = [] للإرسال في tqdm (list_of_sent): # لكل جملة sent_vector = np.zeros (300) # إنشاء 300 أبعاد من الأصفار count_word = 0 للكلمة المرسلة: # لكل كلمة في الجملة إذا كانت الكلمة في w2v_model.wv.vocab: # إذا كانت الكلمة موجودة في نموذج word2vec vec = w2v_model.wv [word] # احصل على التمثيل المتجه للكلمة sent_vector + = vec # أضف المتجه إلى sent_vector count_word + = 1 # بعد إضافة كل الكلمة المتجهات في الجملة تضيف المتجه الذي يمثل الآن # الجملة بأكملها إلى vectors_of_sentences إذا count_word! = 0: sent_vector / = count_word avgw2v.append (sent_vector) يُرجع avgw2v # تمثيل word2vec لـ train_data train_avgw2v = find_avgword2ofverage (train2veclist) of crossvalidation_data crossvalidation_avgw2v = find_avgword2vec (crossvalidation_list_of_sent) # تمثيل word2vec المتوسط ​​لـ test_data test_avgw2v = find_avgword2vec (test_list_of_sent)

قوة العمل-جيش الدفاع الإسرائيلي Word2Vec

هذه إستراتيجية أخرى لتحويل الجمل إلى متجهات. نحن هنا لا نحسب فقط متوسط ​​تمثيلات Word2Vec للكلمات ولكننا نأخذ أيضًا في الاعتبار تمثيلات TF-IDF لهذه الكلمات.
فيما يلي خطوات حساب تمثيل TF-IDF Word2Vec

  1. أولاً ، ابحث عن ناقل tf-idf (t)
  2. ثم لحساب tfidf-word2vec للمراجعة
    1. احسب word2vec (مراجعة الكلمة) (W2V (w))
    2. اضربها مع قيمة tf-idf المقابلة
  3. اجمع كل منهم واقسم على مجموع قيم tf-idf

TF-IDF Word2Vec(R)=[t1*W2V(w1)+t2*W2V(w2)+……+tn*W2V(wn)]/[t1+t2+……+tn]

حيث ، t1 ، t2 ... tn هي تمثيلات TF-IDF للكلمات المقابلة في المراجعة.
لذا فإن avgword2vec & tfidf-word2vec هي تقنيات بسيطة لتحويل الجمل إلى متجهات. هذه ليست استراتيجيات مثالية لكنها تعمل بشكل جيد مع معظم الأمثلة
دعنا نرى الرمز الآن ... ..

def find_tfidfw2v (list_of_sent): tfidf_w2v = [] للإرسال في tqdm (list_of_sent): # لكل جملة وزن = 0 # لتخزين مجموع قيم tfidf للكلمات في الجملة sent_vector = np.zeros (300) للكلمة المرسلة: إذا word في w2v_model.wv.vocab: # إذا كانت الكلمة موجودة في نموذج w2v إذا كانت الكلمة في tfidf_dictionary: # إذا كانت الكلمة موجودة في القاموس vec = w2v_model.wv [word] # ثم احصل على المتجه sent_vector + = (vec * tfidf_dictionary [word] ) # تلخيص كل tfidfw2v (vector * tfidf) في وزن الجملة = tfidf_dictionary [word] #store the sum if weight! find_tfidfw0v (crossvalidation_list_of_sent) test_tfidfw2v = find_tfidfw2v (test_list_of_sent) # y-train سيكون هو نفسه على التوالي لجميع الطرق. ytrain = train_data ['Score'] ycrossvalidation = crossvalidation_data ['Score'] ytest = test_data ['Score']

بناء نموذج

هنا سنطبق KNN على مجموعات بيانات البناء المذكورة أعلاه باستخدام تقنيات تضمين مختلفة. سوف نطبق كليهما غاشم و شجرة دينار كويتي الخوارزميات المتاحة في KNN من حزمة scikit-Learn من الثعبان.

سنجد أيضًا أفضل K لكل تقنية تضمين وخوارزمية لـ KNN ونرسم النتائج. أيضًا ، سنستخدم AUC كمقياس أداء لقياس أداء النموذج. في النهاية ، سنقدم جدولًا موجزًا ​​لجميع الأساليب المختلفة لمراقبة أداء كل منها.

KNN الغاشمة على القوس

من sklearn استيراد المقاييس استيراد matplotlib.pyplot مثل plt من sklearn.metrics استيراد roc_curve من sklearn.metrics استيراد roc_auc_score # تطبيق التحقق البسيط المتقاطع للعثور على أفضل K #GridSearchCV و K-Fold يستغرق وقتًا أطول ، لذا فإن استخدام التحقق المتقاطع البسيط def find_best_k (القطار ، التحقق المتقاطع) ، algo، k_range، njobs): k_plot = [] auc_cv_plot = [] auc_train_plot = [] لـ k في النطاق (1، k_range، 2): k_plot.append (k) #fitting the model model = KNeighboursClassifier (n_neighbours = k، algorithm = algo، n_jobs = njobs) model.fit (train، ytrain) # توقع الاحتمالات لبيانات التحقق المتقاطع pred_proba_cv = model.predict_proba (التحقق المتبادل) # احتفظ باحتمالات النتيجة الإيجابية فقط pred_proba_cv_pos = pred_proba_cv [:، 1] # توقع الاحتمالات data pred_proba_train = model.predict_proba (القطار) # احتفظ باحتمالات النتيجة الإيجابية فقط pred_proba_train_pos = pred_proba_train [:، 1] #calculating auc for crossvalidation data auc_cv = roc_auc_score (ycrossvalidation، pred_proba_cv_pos) #calculation r بيانات القطار auc_train = roc_auc_score (ytrain، pred_proba_train_pos) auc_cv_plot.append (auc_cv) auc_train_plot.append (auc_train) print ("CV AUC لـ K ="، k، "is"، auc_cv، "تدريب AUC لـ K ="، ، "is"، auc_train) إرجاع k_plot، auc_cv_plot، auc_train_plot
من sklearn.neighbours استيراد KNeighboursClassifier # تطبيق التحقق البسيط المتقاطع مثل GridSearchCV و K-Fold يستغرق وقتًا أطول algo = 'brute' krange = 30 njobs = 1 # njobs = -1 (عمل متوازي) لا يعمل مع مصفوفة متفرقة k_plot_bow، auc_cv_plot_bow ، auc_train_plot_bow = find_best_k (train_bow، crossvalidation_bow، algo، krange، njobs)

هنا يمكننا أن نرى أنه بعد k = 20 هناك تغيير ضئيل في AUC. لذلك سوف نستخدم K = 20 كأفضل معلمة تشعبية لنموذج BOW.

# تدريب النموذج باستخدام أفضل K حصلنا عليه k_bow = 20 knn_bow = KNeighboursClassifier (n_neighbours = k_bow، algorithm = 'brute') knn_bow.fit (train_bow، ytrain) bow_pred = knn_bow.predict_proba (test_bow) # فصل دراسي منفصل للتخطيط مصفوفة الارتباك bow_pred_cm = np.argmax (bow_pred، axis = 1) # احتمالات حفظ النتائج الإيجابية bow_pred = bow_pred [:، 1] # تنبؤات التدريب bow_pred_train = knn_bow.predict_proba (train_bow) bow_pred_cm_train = np.predmax (bow_pred_cm_train = np.predmax (bow_pred_cm_train = np.predmax (bow_pred ) # حفظ احتمالات النتائج الإيجابية bow_pred_train = bow_pred_train [:، 1] #calculating AUC على بيانات الاختبار auc_bow = roc_auc_score (ytest، bow_pred) #roc لبيانات القطار fpr_train، tpr_train، عتبات = roc_curve (ytrain، bow_pred_train) البيانات fpr_test ، tpr_test ، العتبات = roc_curve (ytest ، bow_pred) 

KNN الغاشمة على TF-IDF

algo = 'brute' krange = 30 njobs = 1 # njobs = -1 (عمل متوازي) لا يعمل مع مصفوفة متفرقة ، auc_cv_plot_tfidf) plt.plot (k_plot_tfidf، auc_train_plot_tfidf) plt.xlabel ("K") plt.ylabel ("AUC") plt.xticks (np.arange (min (k_plot_tfidf)، max (k_plot، 1_tf) plt.show ()

هنا K = 21 هو أفضل معلمة تشعبية كما نلاحظ في الرسم البياني أعلاه.

#training النموذج مع أفضل K حصلنا عليها k_tfidf = 21 knn_tfidf = KNeighboursClassifier (n_neighbours = k_tfidf، algorithm = 'brute') knn_tfidf.fit (train_tfidf، ytrain) tfidf_pred = knn_tfidf.predict_pred = knn_tfidf.predict_pred = knn_tfidf. مصفوفة الارتباك tfidf_pred_cm = np.argmax (tfidf_pred، محور = 1) tfidf_pred = tfidf_pred [:، 1] tfidf_pred_train = knn_tfidf.predict_proba (train_tfidf) tfidf_pred_cm_tfrain = auc_tfidf = roc_auc_score (ytest، tfidf_pred) fpr_train، tpr_train، العتبات = roc_curve (ytrain، tfidf_pred_train) fpr_test، tpr_test، thresholds = roc_curve (ytest، tfidf_curve)

KNN brute على متوسط ​​Word2Vec

algo='brute'
krange=30
njobs=-1 #use all available cpu core
k_plot_avgw2v,auc_cv_plot_avgw2v,auc_train_plot_avgw2v=find_best_k(train_avgw2v,crossvalidation_avgw2v,algo,krange,njobs)
plt.plot(k_plot_avgw2v,auc_cv_plot_avgw2v)
plt.plot(k_plot_avgw2v,auc_train_plot_avgw2v)
plt.xlabel("K")
plt.ylabel("AUC")
plt.xticks(np.arange(min(k_plot_avgw2v), max(k_plot_avgw2v)+1, 2.0))
plt.show()
نص البيانات باستخدام KNN
# تدريب النموذج باستخدام أفضل K حصلنا عليه k_avgw2v = 21 knn_avgw2v = KNeighboursClassifier (n_neighbours = k_avgw2v، algorithm = 'brute'، n_jobs = -1) knn_avgw2v.fit (train_avgw2v، ytvwed2) avg. اشتقاق فئة منفصلة لرسم مصفوفة الارتباك avgw2v_pred_cm = np.argmax (avgw2v_pred ، محور = 2) avgw2v_pred = avgw1v_pred [:، 2] # تنبؤات التدريب avgw2v_pred_train = knn_avgw1v.predict_pred avgw2v_pred_train = avgw2v_pred_train [:، 2] #calculating AUC on test data auc_avgw2v = roc_auc_score (ytest، avgw2v_pred) #roc لبيانات القطار fpr_train، tpr_train، thresholds = roc_tprcurve، avtoldw1 roc_curve (ytest ، avgw2v_pred)

KNN الغاشمة TF-IDF Word2Vec

algo='brute'
krange=30
njobs=-1 #use all available CPU core
k_plot_tfidfw2v,auc_cv_plot_tfidfw2v,auc_train_plot_tfidfw2v=find_best_k(train_tfidfw2v,crossvalidation_tfidfw2v,algo,krange,njobs)
plt.plot(k_plot_tfidfw2v,auc_cv_plot_tfidfw2v)
plt.plot(k_plot_tfidfw2v,auc_train_plot_tfidfw2v)
plt.xlabel("K")
plt.ylabel("AUC")
plt.xticks(np.arange(min(k_plot_tfidfw2v), max(k_plot_tfidfw2v)+1, 2.0))
plt.show()
كي إن إن بروت
k_tfidfw2v=23 knn_tfidfw2v=KNeighborsClassifier(n_neighbors=k_tfidfw2v,algorithm='brute',n_jobs=-1) knn_tfidfw2v.fit(train_tfidfw2v,ytrain) tfidfw2v_pred=knn_tfidfw2v.predict_proba(test_tfidfw2v) #deriving discrete class for plotting confusion matrix tfidfw2v_pred_cm = np. argmax(tfidfw2v_pred, axis=1) tfidfw2v_pred=tfidfw2v_pred[:,1] #training predictions tfidfw2v_pred_train=knn_tfidfw2v.predict_proba(train_tfidfw2v) tfidfw2v_pred_cm_train = np.argmax(tfidfw2v_pred_train, axis=1) tfidfw2v_pred_train=tfidfw2v_pred_train[:,1] auc_tfidfw2v=roc_auc_score (ytest، tfidfw2v_pred) fpr_train، tpr_train، عتبات = roc_curve (ytrain، tfidfw2v_pred_train) fpr_test، tpr_test، thresholds = roc_curve (ytest، tfidfw2v_pred)

KNN kd-tree على BOW

هنا في نهج شجرة kd ، سنستخدم طريقة تسمى "TruncatedSVD" لتقليل أبعاد مجموعة البيانات. نحن نقوم بذلك لأن طريقة الشجرة يمكن أن تستغرق وقتًا طويلاً للتدريب على البيانات عالية الأبعاد.

من sklearn.decomposition import TruncatedSVD no_of_components = 500 tsvd = TruncatedSVD (n_components = no_of_components) tsvd_train_bow = tsvd.fit_transform (train_bow) tsvd_test_bow = tsvd.transformation (test_bow)
algo='kd_tree' krange=30 njobs=-1 #use all available cpu cores kdtree_k_plot_bow,kdtree_auc_cv_plot_bow,kdtree_auc_train_plot_bow=find_best_k(tsvd_train_bow,tsvd_crossvalidation_bow,algo,krange,njobs) plt.plot(kdtree_k_plot_bow,kdtree_auc_cv_plot_bow) plt.plot(kdtree_k_plot_bow, kdtree_auc_train_plot_bow) plt.xlabel ("K") plt.ylabel ("AUC") plt.xticks (np.arange (min (kdtree_k_plot_bow)، max (kdtree_k_plot_bow) +1، 2.0)) plt.show ()

وبالمثل ، قمنا ببناء جميع الأساليب الأخرى ، وفيما يلي النتيجة التي لاحظناها.

وفي الختام

نص البيانات باستخدام KNN

نكتشف ذلك TFIDF مع Bruteforce يعطي كحد أقصى الجامعة الأمريكية بالقاهرة 0.799 مع hyperparameter K = 21 من أي نموذج آخر.

اقرأ المزيد من المقالات على موقعنا مدونة.

الوسائط الموضحة في هذه المقالة ليست مملوكة لشركة Analytics Vidhya ويتم استخدامها وفقًا لتقدير المؤلف. 

بقعة_صورة

أحدث المعلومات الاستخباراتية

بقعة_صورة