基于朴素贝叶斯的文本分类器

来源:互联网 发布:jc js jk 编辑:程序博客网 时间:2024/05/01 20:33

        如果别人给你推荐一篇文章,只给你说了文章名字,那么你现在最好奇的应该是:这文章是什么类型的??类型直接决定了你会不会去看,还有就是如果别人给你说这文章是情感类的,听完你也许比较感兴趣但读完后发现这文章是军事类的,那么你会很不爽,多影响情绪,所以文章的所属类型还是必须要很准确的。像我之前实习的一家公司就是给人推送广告的,公司强调精准,意思很明了就是要把广告推送给可能会需要广告中所推产品的人们,我们技术人员拿到的只是简单的广告文案,而不清楚这个文案所属的类别,由于广告文案特别过,不可能每个都要人工来进行分类,所以我们的工作就是训练模型让机器来分。

        首先我们需要有足够的训练集,而且要比较准确,假设我们把训练集的文章放在了路径train_data_folder下,要预测的文章放在了路径test_data_folder下,处理得到

all_words_list,train_data_list,train_class_list,test_data_list。代码如下:

def TextProcessing(train_data_folder,test_data_folder):
    train_data_list=[]
    train_class_list=[]
    train_data_folder_list=os.listdir(train_data_folder)
    for folder in train_data_folder_list:
        new_path_folder=os.path.join(train_data_folder,folder)
        files=os.listdir(new_path_folder)
        for file in files:
            new_path_file=os.path.join(new_path_folder,file)
            with open(new_path_file,'r') as fp:
                raw=fp.read()
                words=list(jieba.cut(raw,cut_all=False))
                train_data_list.append(words)
                train_class_list.append(folder.decode('utf-8'))

    test_data_list=[]
    test_data_files=os.listdir(test_data_folder)
    for file in test_data_files:
        new_path_file=os.path.join(test_data_folder,file)
        with open(new_path_file,'r') as fp:
            raw=fp.read()
            words=list(jieba.cut(raw,cut_all=False))
            test_data_list.append(words)


    all_words_list={}
    for word_list in train_data_list:
        for word in word_list:
            if all_words_list.has_key(word):
                all_words_list[word]+=1
            else:
                all_words_list[word]=1
    all_words_tuple_list=sorted(all_words_list.items(),key=lambda f:f[1],reverse=True)
    all_words_list=list(zip(*all_words_tuple_list)[0])
    return all_words_list,train_data_list,train_class_list,test_data_list

all_words_list是训练集中的所有文章的词语按照出现次数多少从大到小排列后的词语集,train_data_list是是按照训练集中的每篇文章为单位,把每篇文章中的词语按照list的格式append到train_data_list中,train_class_list是训练集中每篇文章的类别,最后还有test_data_list无需赘述,在这个过程中用到了一个分词器jieba,关于它的介绍请自行google.


  下面这步就是得到整个训练集种的特征词:

def word_dic(all_words_list,deleteN,stopwords):
    feature_words=[]
    n=1
    for t in range(deleteN,len(all_words_list),1):
        if n>100:
            break
        if not all_words_list[t].isdigit() and all_words_list[t] not in stopwords and 0<len(all_words_list[t])<5:
            feature_words.append(all_words_list[t])
            n+=1
    return feature_words

因为中文中有些连接词对文章的属性是没有意义的,所以我这里总结了写stopwords,比如“的”、“”也“”、“当然”、“仅仅”这种词对文章的类别没有影响,所以不在特征词的范围内。

执行feature_words=word_dic(all_words_list,deleteN,stopwords)即可得到整个训练集中的特征词。


接下来要获取训练集和测试集中每篇文章的特征词:

def TextFeatures(train_data_list,test_data_list,feature_words):
    def text_features(text,feature_words):
        text_words=set(text)
        features=[1 if word in text_words else 0 for word in feature_words]
        return features
    train_features=[text_features(text,feature_words) for text in train_data_list]
    test_features=[text_features(text,feature_words) for text in test_data_list]
    return train_features,test_features


到这儿训练集的特征词和类别已经拿到手,接下来就可以构造模型了,我这里使用的是朴素贝叶斯算法:

classifier=MultinomialNB().fit(train_features,train_class_list)


模型构造完成接下来只需要把测试集的特征词塞进去即得到测试集的类别:

test_class_list=classifier.predict(test_data_list)



ending

详细代码已push到github请参考:https://github.com/TrustMe5/Naive-Bayes-TextClassifier

0 0