<jupyter_start><jupyter_text>marks lists<jupyter_code>punctuation_marks = [')','(','>','<',"؛","،",'{','}',"؟",':',"-", '»', '"', '«', '[', ']','"','+','=','?']
marks = ['/','//', '\\','|','!', '%', '&','*','$', '#','؟', '*','.','_' ]
alphabet_string_lower = string.ascii_lowercase
alphabet_string_upper = string.ascii_uppercase
english_char =  list(alphabet_string_lower) + list(alphabet_string_upper)


sep_list = [" ", '\xad', '\u200e','\u200f', '\u200d', '\u200d', '\u200d'] + marks

# stop_words1 =['به', 'و', 'در', 'با', 'این', 'شد', 'را', 'که', 'از', 'که', 'این', 'با', 'است', 'برای', 'آن', 'یک', 'خود', 'تا', 'کرد', 'بر', 'هم', 'نیز', 'هزار', 'ریال', 'بود']
stop_words = ["برای", "پس", "سپس", "تا", "از", "که", "و", "به", "را", "با", "بر", "در", "اینکه", "این", "ان", "چرا",
              "شاید", "انها", "چون", "انطور", "اینطور", "انچه", "آخ", "آخر", "آخرها", "اخه", "آره", "آری", "انان",
              "اگر", "درباره", "خیلی", "توی", "بلکه", "بعضی", "بعدا", "باید", "البته", "الان", "اصلا", "اساسا",
              "احتمالا", "اخیرا", "ایا", "اهان", "امرانه", "ان گاه", "انرا", "انقدر", "اساسا", "بنابراین", "هرحال",
              "بی‌انکه", "به‌قدری", "بیشتر", "کمتر", "تر", "ترین", "تو", "چند", "چندین", "چه", "خیلی", "دیگر", "دیگه",
              "طبیعتا", "عمدا", "گاهی", "نیز", "او", "تو", "من", "ما", "طور", "دو", "هر", "همه", "ایم", "اند", "اید",
              "است", "هست", "زدگی", "خصوصا", "ن", "ب", "کسی", "چیزی", "بالاخره", "وقتی", "زمانی", "می"]<jupyter_output><empty_output><jupyter_text>stop_words<jupyter_code># stop_word_data_20k = ['', 'پیام', 'خواه','دار', 'شده', '۵', 'گزار', 'ها', 'گیر', 'قرار', 'انت', '۴', 'حضور', 'وی', 'می',  'ان', 'بین', 'سال', '۷', 'گفت', 'کار', 'ی', 'کرده', 'اما', 'ادامه', 'شو', 'روز', 'کن', 'گذشته', 'داشت', 'های', 'باز', 'انجام', 'داد', '۳', 'باید', 'اینکه', 'پیش', 'بیش', 'دو', 'باش', 'توان', 'دیگر', '۲', 'عنو',  'امروز', '۹', '۸', 'پای', 'مورد', 'صورت', 'مردم', 'ب', 'هر', 'ما', 'ایر', 'رو', 'اظهار', '۱', 'افزود', '–', '۶', 'ا', 'ر', 'ث',  '۰', 'ش', 'د', 'ژ', 'ک', 'ع', 'ه', 'ج', 'ز', 'م', 'ت', '٢', '٣', '٧', 'ق', 'ل', 'ن', '@', ',', '\u2066', '٩', '٤', '٥', '٨', '١', '٦', 'س', 'ص', 'ء', 'ف', "'", 'ö', 'گ', '》', 'ط', 'پ', '…', 'خ', 'ê', 'ح', '\u2067', '\u2069', 'ۗ', '•', '٪', '\u200b', '×', 'ۚ', 'ۖ', 'چ', '"', '\u2063', 'ذ', '\uf0d8', '۔', 'ü', 'ﻭ', 'غ', '️', 'ﷲ', '\u202c', '\u202a', 'ﻫ', 'ۙ', 'ض', '·', '¬', ';', 'خبر گزاری','گزازش','خبرنگار',]
# # stop_word_data_17k = ['', 'درصد', 'وی', 'کن', 'توان', 'پیام', 'ما', 'گفت', 'دولت', 'خواه', 'باید', 'اینکه','ان', 'تولید', 'دار', 'اگر', 'هستند', , 'شو', 'پیش', 'وجود','ایر', 'شده', 'کار', 'برخی', 'رو', 'بین', 'توسط', 'گیر', 'نظر', 'باش', 'همچنین', 'سال', 'دو', 'داشت', 'انجام', 'افزای', 'اما', 'هر', 'حال', 'قرار', 'مورد', 'افزود', 'گرفته',  'انها', 'انت', 'دلیل', 'ب', 'ادامه', 'می', 'شرکت', 'اساس', 'پای', 'گزار', 'کرده', 'ساز', 'بخش', 'بیش', 'داد', 'موضوع', 'روز', 'یا', 'شرایط', 'بوده',  'همین', 'کاهش', 'گذشته', 'توجه', 'یکی', 'امروز', 'ماه', 'زار', 'اقدام', '۵', 'داشته', '۲', 'عنو', 'داده', 'های', 'دیگر', 'نسبت', 'بیان', 'همه', '۸', 'اعلام',  'نقل', 'پس', '۷', 'میلیون', '۹', 'ر', '۶', '۴', '۳', 'ه', '۰', 'گروه', 'اشاره', '۱۳۹۹', '۱', 'ج', 'مردم', 'استفاده', 'ی', 'ت', '٥', '٢', '١', '٣', '٦', 'د', '–', 'ژ', 'ص', 'ع', 'م', 'پ', 'ا', '٤', 'ش', '٧', '٩', 'ک', 'ز', 'ف', 'ح', '’', 'ن', ',', '٨', "'", 'چ', '٠', '•', '·', '\u200b', 'غ', '…', 'ل', 'خ', 'ذ', 'ث', '\uf0d8', 'س', '@', 'ق', 'ء', 'ط', 'گ', ';', '٬', 'ۗ', '\uf0fc', '—', 'ñ', 'á', 'ﻫ', '×', '−', '±', '"', '﴾', '°', 'ﻭ',  '🔹', 'ۚ', 'ۖ', '\u202b', 'ş', 'é', 'ة', 'ۙ']
# stop_word_data_11k = ['', 'پیام', 'اینکه', 'ایر', 'شده', 'کن', 'باش', 'کشور', 'های', 'کار', 'روز', 'اعلام', 'گزار', 'همچنین', 'سال', 'کرده', 'داد', 'انت', 'عنو', '۳', 'حضور', 'خواه', 'وی', 'افزود', 'گفت', 'بیان', 'توان', 'شو', 'بخش', 'باید', 'دار', 'داشت', 'ان', 'توجه', 'مورد', 'دو', 'انجام', '۲', 'رو', 'هر', 'یا', 'صورت', 'هستند', 'اما', 'ی', '٢', 'گذشته', '۴', 'قرار', 'بیش', 'دیگر', 'ادامه', 'امروز', '۰', '۶', '۵', '۹', '۷', '۸', '۱', 'ا', '٣', 'ب', 'س', '–', '٨', 'ج', '٧', 'پ', "'", 'ز', 'ر', 'ه', 'ع', 'ء', 'م', '\u202c', 'ش', '٦', 'ن', '٩', '@', 'ۚ', '٤', 'د', 'ص', 'ک', '\u202b', 'ث', 'چ', 'ل', 'ط', 'ح', 'ف', 'ت', '…', '٥', '\u2067', '١', 'ذ', 'ق', '—', '٠', ',', 'غ', '\ufeff', '٪', '"', '\u2069', '•', 'ۗ', '’', 'ژ', 'خ', 'и', 'О', 'с', 'б', 'Я', 'С', 'в', '۔', '·','بر','تا','در','به','از', 'گ', 'Ö', 'é', ';', '\u206b', '》', '⠀', '\u202a', 'ۖ', '❇', 'ﻫ'] + stop_words1
# stop_words = set(stop_word_data_20k + stop_word_data_11k)<jupyter_output><empty_output><jupyter_text>regex  patterns, prefixe list and postfix list<jupyter_code>raw_postfix = [
        ('[\u200c](تر(ین?)?|گری?|های?)' , ''),
        (r'(تر(ین?)?|گری?)(?=$)' , ''), #تر ، ترین، گر، گری در آخر کلمه
       # (r'(?<=[^ او])(م|ت|ش|مان|تان|شان|ی)$' , ''), # حذف شناسه های مالکیت و فعل در آخر کلمه
        (r'(?<=[^ او])(م|ت|ش|مان|تان|شان)$' , ''), # حذف شناسه های مالکیت و فعل در آخر کلمه
        (r'(ان|ات|گی|گری|های)$' , ''), #ان، ات، ها، های آخر کلمه  
]

raw_arabic_notation = [
    # remove FATHATAN, DAMMATAN, KASRATAN, FATHA, DAMMA, KASRA, SHADDA, SUKUN
    ('[\u064B\u064C\u064D\u064E\u064F\u0650\u0651\u0652]', ''),
    ]

raw_long_letters = [
    (r' +', ' '),  # remove extra spaces
    (r'\n\n+', '\n'),  # remove extra newlines
    (r'[ـ\r]', ''),  # remove keshide, carriage returns
    ]

raw_half_space = [
    ('[\u200c]', ''),
]<jupyter_output><empty_output><jupyter_text>verbs, mokassar,morakab list<jupyter_code>present_roots =['توان','باش','رو','بر','یاور', 'یانداز', 'یای','یاندیش','بخش','باز','خر','بین','شنو','دار','دان','رسان','شناس','گو','گذار','یاب','لرز','ساز','شو','نویس','خوان','کاه','گیر','خواه','کن' ]

past_roots = ['توانست','بود','کرد','اورد','انداخت','امد','خرید','باخت','برد','رفت','اندیشید','بخشید','دید','شنید','داشت','دانست','رساند','شناخت','گفت','گذشت','یافت','لرزید','ساخت','شد','نوشت','خواند','کاست','گرفت','خواست']
all_verbs_roots = present_roots + past_roots
empty_list = ['','','','','','','']
verb_prefix = ['نمی‌', 'می‌','ن','ب',"" ]
present_verb_postfix = ['م','ی','د','ید','ند','یم']
past_verb_postfix = ['ایم','اید','ای','ام','اند']
past_verb_postfix2 = ['م','ی','ید','ند','یم']
present_verbs = []
past_verbs = []
all_verbs = {}
for pref in verb_prefix:
    for present_root, past_root in zip(present_roots, past_roots):
        for post in past_verb_postfix2:
            all_verbs[pref + past_root+post] = past_root
        for post in past_verb_postfix:
            all_verbs[past_root+'ه‌'+post] = past_root
        for post in present_verb_postfix:
            all_verbs[pref+present_root+post] = present_root
            
words_list = ['ادب', 'آداب', 'طرف', 'اطراف', 'حقیقت', 'حقایق', 'موج', 'امواج', 'ادیب', 'ادبا', 'عمق', 'اعماق', 'خزینه', 'خزائن', 'مرکز', 'مراکز', 'اثر', 'آثار', 'عالم', 'علما', 'خبر', 'اخبار', 'موقع', 'مواقع', 'اسیر', 'اسرا', 'علم', 'علوم', 'دوره', 'ادوار', 'مصرف', 'مصارف', 'اسم', 'اسامی', 'علامت', 'علائم', 'دین', 'ادیان', 'معرفت', 'معارف', 'اسطوره', 'اساطیر', 'علت', 'علل', 'دفتر', 'دفاتر', 'مبحث', 'مباحث', 'امیر', 'امرا', 'عقیده', 'عقائد', 'ذخیره', 'ذخایر', 'ماده', 'مواد', 'امر', 'اوامر', 'عمل', 'اعمال', 'رفیق', 'رفقا', 'مذهب', 'مذاهب', 'امام', 'ائمه', 'عید', 'اعیاد', 'رای', 'آرا', 'مصیبت', 'مصائب', 'اصل', 'اصول', 'عنصر', 'عناصر', 'رسم', 'رسوم', 'معبد', 'معابد', 'افق', 'آفاق', 'عاطفه', 'عواطف', 'رابطه', 'روابط', 'مسجد', 'مساجد', 'بیت', 'ابیات', 'عضو', 'اعضا', 'رمز', 'رموز', 'معبر', 'معابر', 'تاجر', 'تجار', 'عبارت', 'عبارات', 'رجل', 'رجال', 'مظهر', 'مظاهر', 'تصویر', 'تصاویر', 'عجیب', 'عجایب', 'رقم', 'ارقام', 'منظره', 'مناظر', 'جد', 'اجداد', 'فقیه', 'فقها', 'زاویه', 'زوایا', 'مرض', 'امراض', 'جانب', 'جوانب', 'فن', 'فنون', 'زعیم', 'زعما', 'مورد', 'موارد', 'جزیره', 'جزایر', 'فکر', 'افکار', 'سانحه', 'سوانح', 'مرحله', 'مراحل', 'جبل', 'جبال', 'فریضه', 'فرایض', 'سلطان', 'سلاطین', 'مفهوم', 'مفاهیم', 'جریمه', 'جرایم', 'فعل', 'افعال', 'شعر', 'اشعار', 'منبع', 'منابع', 'حادثه', 'حوادث', 'فقیر', 'فقرا', 'شاعر', 'شعرا', 'مکان', 'اماکن', 'حشم', 'احشام', 'قاعده', 'قواعد']
mokassar_dict ={}
for i in range(0,len(words_list),2):
    mokassar_dict[words_list[i+1]] = words_list[i]<jupyter_output><empty_output><jupyter_text>tokenizer<jupyter_code>def split(txt, seps):
    default_sep = seps[0]    
    # we skip seps[0] because that's the default separator
    for sep in seps[1:]:
        txt = txt.replace(sep, default_sep)
    return [i.strip() for i in txt.split(default_sep)]

#get doc and return (word,doc id)
def tokenizer(text):
    for l in english_char:
        text = text.replace(l,"")
    word_list = split(text.strip().replace("\n"," "), sep_list)
    word_list = [x for x in word_list if not x.startswith("ir") and not x.startswith("NID")]
    return word_list<jupyter_output><empty_output><jupyter_text>normalizer<jupyter_code>def remove_punctuation_marks(word_list):
#     word_list = list(word_list)
    for i in range(len(word_list)):
        for mark in punctuation_marks:
            word_list[i] = word_list[i].replace(mark,"")

    return word_list


def edit_long_letters(word_list):
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_long_letters]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
    return word_list




def remove_arabic_notation(word_list):
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_arabic_notation]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
    return word_list


def create_translation_table(src_list, dst_list):
     return dict((ord(a), b) for a, b in zip(src_list, dst_list)) #map src unicode to dst char

    
def char_digit_Unification(word_list): 
    word_list = [x for x in word_list if not x.isnumeric() or (x.isnumeric() and float(x)<3000)]
    translation_src, translation_dst = ' ىكي“”', ' یکی""'
    translation_src += 'ئ0123456789أإآ%'
    translation_dst += 'ی۰۱۲۳۴۵۶۷۸۹ااا٪'
    translations_table = create_translation_table(translation_src, translation_dst)
    for i in range(len(word_list)):
        word_list[i] = word_list[i].translate(translations_table)
    return word_list

def remove_mokassar(word_list):
    for i in range(len(word_list)):
        word_list[i] = mokassar_dict.get(word_list[i],word_list[i])
        
    return word_list
    


def verb_Steaming(word_list):
    for i in range(len(word_list)):
        word_list[i] = all_verbs.get(word_list[i],word_list[i])
        
    return word_list
    

def remove_postfix(word_list):

    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_postfix]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            if len(word_list[i])>4 and  not (word_list[i] in all_verbs_roots):
                word_list[i] = pattern.sub(rep, word_list[i])
    return word_list


    
    
def remove_prefix(word_list):
    starts =['بی‌' , 'نا', 'با']
    for i in range(len(word_list)):
        for start in starts:
            if word_list[i].startswith(start) and len(word_list[i])>4:
                word_list[i] = word_list[i][len(start):]
                break

    return word_list

def morakab_Unification(word_list):
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_half_space]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
    return word_list

#all to gether 
def normalizer(word_list):
    #remove punc
    for i in range(len(word_list)):
        for mark in punctuation_marks:
            word_list[i] = word_list[i].replace(mark,"")
            
    #edit long letters
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_long_letters]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
            
    #remove mokassar
    for i in range(len(word_list)):
        word_list[i] = mokassar_dict.get(word_list[i],word_list[i])
    
    #remove_arabic_notation
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_arabic_notation]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
    
    #char_digit_Unification
    word_list = [x for x in word_list if not x.isnumeric() or (x.isnumeric() and float(x)<3000)]
    translation_src, translation_dst = ' ىكي“”', ' یکی""'
    translation_src += 'ئ0123456789أإآ%'
    translation_dst += 'ی۰۱۲۳۴۵۶۷۸۹ااا٪'
    translations_table = create_translation_table(translation_src, translation_dst)
    for i in range(len(word_list)):
        word_list[i] = word_list[i].translate(translations_table)
    
    #verb_Steaming
    for i in range(len(word_list)):
        word_list[i] = all_verbs.get(word_list[i],word_list[i])
        
    #remove_prefix
    starts =['بی‌' , 'نا', 'با']
    for i in range(len(word_list)):
        for start in starts:
            if word_list[i].startswith(start) and len(word_list[i])>4:
                word_list[i] = word_list[i][len(start):]
                break
    
    #remove_postfix
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_postfix]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            if len(word_list[i])>4 and  not (word_list[i] in all_verbs_roots):
                word_list[i] = pattern.sub(rep, word_list[i])
    #morakab_Unification
    patterns_compiled = [(re.compile(x[0]), x[1]) for x in raw_half_space]
    for pattern, rep in patterns_compiled:
        for i in range(len(word_list)):
            word_list[i] = pattern.sub(rep, word_list[i])
            
    for word in word_list:
        if word in stop_words:
            word_list.remove(word)
    
    return [x for x in word_list if len(x) >= 2]<jupyter_output><empty_output><jupyter_text>read data<jupyter_code>%%time
all_data = pd.DataFrame()
pd_list = []
pd_list .append(pd.read_excel('IR00_3_11k News.xlsx', engine = 'openpyxl'))
pd_list .append(pd.read_excel('IR00_3_17k News.xlsx', engine = 'openpyxl'))
pd_list .append(pd.read_excel('IR00_3_20k News.xlsx', engine = 'openpyxl'))
# pd_list .append(pd.read_excel('3.xlsx', engine = 'openpyxl'))
# pd_list .append(pd.read_excel('2.xlsx', engine = 'openpyxl'))
# pd_list .append(pd.read_excel('1.xlsx', engine = 'openpyxl'))
for df in pd_list:
    all_data = all_data.append(df,ignore_index=True)
all_data["topic"].replace({"political": "politics", "sport": "sports"}, inplace=True)
all_data = all_data[all_data.content != 'None\n\n']
all_data = all_data.reset_index(drop=True)
all_data.index +=1
all_data['id'] = all_data.index
contents = all_data['content'].to_list()
doc_ids = all_data['id'].to_list()
doc_url = all_data['url']
docs_topic = all_data['topic']
docs_num = len(doc_ids)<jupyter_output>Wall time: 8.44 s<jupyter_text>create inverted index and change docs content to bag of word<jupyter_code>def create_dictionary(contents, doc_ids):
    for content, id in zip(contents,doc_ids):
        doc_tokens = tokenizer(content)
        doc_normalized_tokens = normalizer(doc_tokens)
        term_freq_dict = dict(collections.Counter(doc_normalized_tokens))
        
        for term, freq in term_freq_dict.items():
            term_freq_dict[term] = (1 + math.log((freq), 10))
        contents[id-1] = term_freq_dict
        for term,freq in term_freq_dict.items():
            term_postings = inverted_index.get(term,{})
            term_postings[id] = (1 + math.log((freq), 10))
            inverted_index[term] = term_postings

def calculate_tf_idf_weight(contents):
    docs_len = []
    for doc in contents:
        length = 0
        for term in doc.keys():
            df = len(inverted_index[term])
            idf = math.log(docs_num/df,10)
            doc[term] *= idf
            length += doc[term]
        docs_len.append( math.sqrt(length))
    return docs_len

            
          

%%time
inverted_index ={}
create_dictionary(contents, doc_ids)
docs_len = calculate_tf_idf_weight(contents)<jupyter_output>Wall time: 5min 4s<jupyter_text>save inverted_index and docs_len<jupyter_code># %%time
# file_inverted_index = open('ph3_KNN_inverted_index.obj', 'wb') 
# pickle.dump(inverted_index, file_inverted_index)
# file_inverted_index.close()
# inverted_index = {}



# file_docs_len = open('ph3_KNN_docs_len.obj', 'wb') 
# pickle.dump(docs_len, file_docs_len)
# file_docs_len.close()
# docs_len = {}
# file_contents = open('ph3_KNN_contents.obj', 'wb') 
# pickle.dump(contents, file_contents)
# file_contents.close()
# contents =[]
# inverted_index['سلام']
# docs_len =[]<jupyter_output><empty_output><jupyter_text>read inverted_index and docs_len<jupyter_code>%%time
readed = open('ph3_KNN_inverted_index.obj', 'rb') 
inverted_index = pickle.load(readed)
readed = open('ph3_KNN_docs_len.obj', 'rb') 
docs_len = pickle.load(readed)
readed = open('ph3_KNN_contents.obj', 'rb') 
contents = pickle.load(readed)<jupyter_output>Wall time: 3.82 s<jupyter_text>read unlabeled data<jupyter_code>unlabeled_inverted_index = {}
unlabeled_df = pd.read_excel('IR_Spring2021_ph12_7k.xlsx', engine = 'openpyxl')
unlabeled_contents = unlabeled_df['content'].to_list()
unlabeled_doc_ids = unlabeled_df['id'].to_list()
unlabeled_doc_url = unlabeled_df['url']
unlabeled_docs_num = len(doc_ids)<jupyter_output><empty_output><jupyter_text>create unlabeled inverted_index and update unlabeled_contents<jupyter_code>def create_unlabaled_dictionary(unlabeled_contents, unlabeled_doc_ids):
    for content, id in zip(unlabeled_contents,unlabeled_doc_ids):
        doc_tokens = tokenizer(content)
        doc_normalized_tokens = normalizer(doc_tokens)
        term_freq_dict = dict(collections.Counter(doc_normalized_tokens))
        
        for term, freq in term_freq_dict.items():
            term_freq_dict[term] = (1 + math.log((freq), 10))
            
        unlabeled_contents[id-1] = term_freq_dict
        for term,freq in term_freq_dict.items():
            term_postings = unlabeled_inverted_index.get(term,{})
            term_postings[id] = freq
            unlabeled_inverted_index[term] = term_postings
            
def calculate_tf_idf_weight(unlabeled_contents):
    unlabeled_docs_len = []
    for doc in unlabeled_contents:
        length = 0
        for term in doc.keys():
            df = len(inverted_index[term])
            idf = math.log(docs_num/df,10)
            doc[term] *= idf
            length += doc[term]
        unlabeled_docs_len.append( math.sqrt(length))
    return unlabeled_docs_len
%%time
unlabeled_inverted_index = {}
create_unlabaled_dictionary(unlabeled_contents, unlabeled_doc_ids)
unlabeled_docs_len = calculate_tf_idf_weight(unlabeled_contents)<jupyter_output>Wall time: 26.1 s<jupyter_text>save unlabeled data<jupyter_code>%%time
file_unlabeled_inverted_index = open('ph3_KNN_unlabeled_inverted_index.obj', 'wb') 
pickle.dump(unlabeled_inverted_index, file_unlabeled_inverted_index)
file_unlabeled_inverted_index.close()
unlabeled_inverted_index = {}
file_unlabeled_docs_len = open('ph3_KNN_unlabeled_docs_len.obj', 'wb') 
pickle.dump(unlabeled_docs_len, file_unlabeled_docs_len)
file_unlabeled_docs_len.close()
unlabeled_docs_len = {}
file_unlabeled_contents = open('ph3_KNN_unlabeled_contents.obj', 'wb') 
pickle.dump(unlabeled_contents, file_unlabeled_contents)
file_unlabeled_contents.close()
unlabeled_contents =[]<jupyter_output><empty_output><jupyter_text>read unlabeled inverted_index and contents<jupyter_code>%%time
readed = open('ph3_KNN_unlabeled_inverted_index.obj', 'rb') 
unlabeled_inverted_index = pickle.load(readed)
readed = open('ph3_KNN_unlabeled_docs_len.obj', 'rb') 
unlabeled_docs_len = pickle.load(readed)
readed = open('ph3_KNN_unlabeled_contents.obj', 'rb') 
unlabeled_contents = pickle.load(readed)<jupyter_output>Wall time: 625 ms<jupyter_text>KNN<jupyter_code>def extract_top_k(doc_terms, k):
    similarity = {}
    docs_score = [0] * docs_num
    for term,Wt_q in doc_terms.items():  
        idf = math.log(docs_num/len(inverted_index[term]))
        for doc_id, freq in inverted_index[term].items():    
            docs_score[doc_id-1] += (Wt_q * freq)*idf
      
    docs_score = list((np.array(docs_score))/(np.array(docs_len)))
    for doc_id in doc_ids:
        if docs_score[doc_id-1] != 0:
            similarity[doc_id] = docs_score[doc_id-1]
    heap = [(-value, key) for key,value in similarity.items()]
    largest = heapq.nsmallest(k, heap)
    top_k = [(y, -x) for x,y in largest]
    return top_k

            
def KNN(unlabeled_doc_ids,unlabeled_contents, k ):
    categories = {"culture":[], "economy":[], "sports":[], "politics":[], "health":[]}
    for doc_id in tqdm(unlabeled_doc_ids):
        doc_terms = unlabeled_contents[doc_id-1]
        top_k = extract_top_k(doc_terms, k)
        labels = [docs_topic[x] for x,_ in top_k]
        categories[max(set(labels), key=labels.count)].append(doc_id)
    return categories

%%time
cat = KNN(unlabeled_doc_ids, unlabeled_contents, 5)
for categ in cat:
    print(categ,"  ", len(cat[categ]))<jupyter_output>culture    179
economy    2019
sports    1695
politics    1632
health    1475<jupyter_text>save labeled docs<jupyter_code># %%time
# file_labeled_7kdocs = open('ph3_labeled_7kdocs.obj', 'wb') 
# pickle.dump(cat, file_labeled_7kdocs)
# file_labeled_7kdocs.close()<jupyter_output>Wall time: 0 ns<jupyter_text>load labeled docs<jupyter_code>%%time
readed = open('ph3_labeled_7kdocs.obj', 'rb') 
categories = pickle.load(readed)<jupyter_output>Wall time: 1.01 ms<jupyter_text>query responding<jupyter_code>def vectorize_query(query_str):
    query_tokens = tokenizer(query_str)
    query_normalized_tokens = normalizer(query_tokens)
    term_freq_dict = dict(collections.Counter(query_normalized_tokens))
    query_terms = {}
    for  term,freq in term_freq_dict.items():
        if term in inverted_index.keys() and term not in stop_words:
            query_terms[term] = 1+math.log(freq,10)
    print(query_terms)
    return query_terms
    
def score_docs(query_terms, cat_docs):
    docs_score = {x:0 for x in cat_docs}
    for term,Wt_q in query_terms.items():
        for doc_id in cat_docs:
            docs_score[doc_id] += Wt_q * unlabeled_contents[doc_id-1].get(term, 0)
    
    for doc_id in cat_docs:
        docs_score[doc_id] /= unlabeled_docs_len[doc_id-1]
    return docs_score
def extract_top_k(docs_similarity, k):

    heap = [(-value, key) for key,value in docs_similarity.items()]
    largest = heapq.nsmallest(k, heap)
    top_k = [(y, -x) for x,y in largest]
    return top_k
def query_responding():
    query = input("chose one category between [culture, economy, sports, politics, health] \n enter query like this cat:text : ")
    category = query.split(':')[0]
    query = query.split(':')[1]

    query_terms = vectorize_query(query)
    
    cat_docs = categories[category]
    docs_similarity = score_docs(query_terms, cat_docs)
    a = datetime.datetime.now()
    top_docs = extract_top_k(docs_similarity, 50)
    b = datetime.datetime.now()

    print("{:<5} result in {} ms\nid \t(score)\t\t  -> link\n".format(len(top_docs),1000*(b-a).total_seconds()))
    for doc_id, score in top_docs:
        if score>0:
            print( "{:<5}({}) -> {} ".format(doc_id,"-", doc_url[doc_id]))
query_responding()<jupyter_output>chose one category between [culture, economy, sports, politics, health] 
 enter query like this cat:text : economy:انقلاب
{'انقلاب': 1.0}
50    result in 0.0 ms
id 	(score)		  -> link

4423 (-) -> https://www.isna.ir/news/98021306870/طول-خطوط-ریلی-ایران-امسال-چقدر-می-شود 
3302 (-) -> https://www.isna.ir/news/99020906760/اعتبار-۷۰-میلیاردی-توسعه-زیرساخت-های-گردشگری-روستاهای-استان-بوشهر 
1983 (-) -> https://www.isna.ir/news/99052317223/پرونده-فرودگاه-قدیم-غار-نمکدان-و-پلاژ-بانوان-قشم-روی-میز-دادستان 
5276 (-) -> https://www.isna.ir/news/98110604396/10-هزار-واحد-در-طرح-اقدام-ملی-مسکن-در-قم-پیش-بینی-شده-است 
4186 (-) -> https://www.isna.ir/news/99111511732/۲۶پروژه-با-۲۳۰۰میلیارد-تومان-در-کردستان-افتتاح-می-شود 
5277 (-) -> https://www.isna.ir/news/98110604329/کلنگ-4000-واحد-مسکونی-طرح-اقدام-ملی-در-قم-بر-زمین-زده-شد 
2560 (-) -> https://www.isna.ir/news/98020301754/مخبر-دشمن-با-روح-حکومت-کار-دارد 
5275 (-) -> https://www.isna.ir/news/98110604422/آیین-کلنگ-زنی-۴۰۰۰-واحد-مسکونی-طرح-اقدام-ملی-د[...]
{'fraction_non_alphanumeric': 0.20962650157845106, 'fraction_numerical': 0.021483334016645483, 'mean_word_length': 4.298001737619462, 'pattern_counts': {'":': 7, '<': 71, '<?xml version=': 0, '>': 82, 'https://': 8, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '510740', 'license': 'MIT', 'n_tokens_mistral': 11698, 'n_tokens_neox': 10989, 'n_words': 1936, 'path': 'Phase3- speed up query responding by K-means clustering and  KNN/IR_phase3(KNN).ipynb', 'repo_name': 'MohammadJavadArdestani/information-retrival-system', 'size': '24391'}