Наивная байесовская классификация 20 различных видов сообщений может предсказать только три различных класса сообщений - PullRequest
3 голосов
/ 20 октября 2019

Я пытался реализовать наивную байесовскую модель для классификации сообщений. Результат моих кодов имеет только три разных прогнозируемых класса, в то время как в учебных примерах 20 классов. Мне интересно, правильно ли я это сделал? Можете ли вы увидеть, что я сделал что-то не так с моими кодами?

Вот мои шаги:

1) Из обучающих сообщений я получаю словарь уникальных слов с их частотами, удаляя все знаки препинания. , остановите слова и замените все заглавные буквы на маленькие.

2) Затем я выбрал список из 1000 наиболее часто встречающихся слов в качестве моих избранных слов. (Я думаю, что этот шаг неправильный, я чувствую, что мне также нужно посмотреть, сколько разных сообщений появляется в каждом слове).

3) Затем для каждого сообщения я превратил их в вектор частот слов в соответствии со списком избранных слов.

4) Затем я вычисляю априоры, которые являются пропорцией количества сообщений каждого класса к общему количеству сообщений.

5) Затем я создаю таблицу условных вероятностей p (wi | cj) для вероятности того, что выбранное слово wj будет из класса cj. Я вычислил его по формуле

(1 + numberOfOccurenceOfWiinCj) / (totalNumberOfWordsInCj + numberOfFeatureWords).

Я читал, что мы можем использовать частоту обратных документов для термина t, который является log (nd / nd (t)), где nd - общее количество текстов, а nd (t) - количество текста, содержащего терминт. Мой вопрос здесь состоит в том, как мы используем частоту обратных документов в кодах?

6) Затем для каждого обучающего сообщения я вычисляю вероятность того, что оно находится в данном классе cj, сначала векторизовав сообщение и выполняя

log (prior_of_cj) + log (1 + number_of_times_w1_appears) log (p (wi | cj)) + ... + log (1 + number_of_times_w1000_appears) log (p (wi | cj)).

7) Затем я выбираю класс с максимальным вычисленным значением в качестве моего прогноза.

import numpy as np
import string
import re
import pickle
import csv
from collections import Counter
import nltk
nltk.download('punkt')
nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.text import Text
from nltk.stem import WordNetLemmatizer
import itertools
import operator
import pandas as pd
#imports end

# import os
# for dirname, _, filenames in os.walk('/kaggle/input'):
#     for filename in filenames:
#         print(os.path.join(dirname, filename))

#data load 
with open('/content/drive/My Drive/Colab Notebooks/data_train.pkl','rb') as f:
  train=pickle.load(f)
with open('/content/drive/My Drive/Colab Notebooks/data_test.pkl','rb') as f:
  test=pickle.load(f)

#data_list=train[0]
#y_train=train[1]
original_train= train[0][0:1000]
data_list= original_train
originaly_train=train[1][0:1000]
y_train=originaly_train
test_sample=test[0:100]



# # preprocess Start
def preProcess(content):
    content=content.lower() #to lower case 
    content=re.sub(r'\d+', '', content) #remove digits 
    content=content.translate(str.maketrans('', '', string.punctuation))#remove puctuations 
    content=content.strip()#remove extra space 
    return re.sub("\s\s+", " ", content)


# make a string of concatenation of all strings.
concatAllString= ""
for index,temp in enumerate(data_list):
    data_list[index]=preProcess(temp)
    concatAllString+=" "
    concatAllString+=data_list[index]

#get a sorted dictionary of frequencies of each unique words.
words = nltk.tokenize.word_tokenize(concatAllString)
fdist1 = nltk.FreqDist(words)
all_words_dict = dict((word, freq) for word, freq in fdist1.items() if not word.isdigit())
all_words_dict=dict(sorted(all_words_dict.items(), key=lambda x: x[1], reverse=True))



#Step4: Filter out all stop words from the dictionary and words of length greater than 6 and less than 2
stop_words = set(stopwords.words('english')) 
all_words_dict={k:v for k, v in all_words_dict.items() if k not in stop_words and len(k)<=6 and len(k)>1}


#Step5: get 1000 feature words with highest frequencies from the all_words_dictionary
feature_words =  dict(itertools.islice(all_words_dict.items(), 1000))

#Step6: create vectorized version of messages in the training set
def vectorizeData(str):
    c = Counter(preProcess(str).split())
    return [c[i] for i in feature_words]


vectorized_training=[[]]*len(original_train)
for index,temp in enumerate(original_train):
    vectorized_training[index]= vectorizeData(temp)


#Step 6: Compute prior table
uniquelabels = [] 
for i in y_train:
    if not i in uniquelabels:
        uniquelabels.append(i)

fdist2 = nltk.FreqDist(y_train)
priors = dict((word, freq) for word, freq in fdist2.items() if not word.isdigit())
for key, value in priors.items():
    priors[key] = float(value)/len(y_train)



#Step7 : compute conditional probabilities
smoothingParameter=1.0
tableOfConditionals=np.zeros((len(priors), len(feature_words)))

for i in range(len(priors)):
    tempDatas= np.array(vectorized_training)[np.array(y_train)==list(priors.keys())[i],:]
    tempDatas= np.sum(tempDatas,axis=0)
    for j in range(len(feature_words)):
        tableOfConditionals[i,j]=(tempDatas[j]+smoothingParameter)/(np.sum(tempDatas)+smoothingParameter*len(feature_words))


#Step8: Compute probability of being in each class for a given example


def computeLabel(ex):
    labelProbabilities= dict.fromkeys(priors, 0)
    vectorTemp=vectorizeData(ex)
    indexi=0
    for key, value in priors.items():
        result=0
        for index in vectorTemp:
            result=result+np.log(tableOfConditionals[indexi,index])*np.log(vectorTemp[index]+1)

        labelProbabilities[key]=result+np.log(value)
        indexi=indexi+1
    return max(labelProbabilities.items(), key=operator.itemgetter(1))[0]

predictions = ['H'] * len(test_sample)
for i in range(len(test_sample)):
    predictions[i]=computeLabel(test_sample[i])

print(predictions)

# with open('/content/drive/My Drive/Colab Notebooks/randompredict.csv','w') as filehandle:
#   filehandle.writelines("%s\n" % predict for predict in predictions)

#Final step: Compute probability of each example in the testing and store in submission file


print("Your submission was successfully saved!")

Пожалуйста, помогите, я работал над ним в течение 3 дней ... Я думаю, что это должно сделать, каким образомЯ выбираю характерные слова. Я выбираю только те из них, которые встречаются чаще всего, поэтому, вероятно, это не лучший способ уловить важность слова в документе

...