学习笔记①:使用python进行文本分类

-- coding:utf-8 --

author = ‘zengyun’

import numpy as np

def 回调函数

词表到向量的转换函数

def load_data_set(): # 创建试验样本。
posting_list = [[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’],
[‘maybe’, ‘not’, ‘take’, ‘him’, ‘to’, ‘dog’, ‘park’, ‘stupid’],
[‘my’, ‘dalmation’, ‘is’, ‘so’, ‘cute’, ‘i’, ‘love’, ‘him’],
[‘stop’, ‘posting’, ‘stupid’, ‘worthless’, ‘garbage’],
[‘mr’, ‘licks’, ‘ate’, ‘my’, ‘steak’, ‘how’, ‘to’, ‘stop’, ‘him’],
[‘quit’, ‘buying’, ‘worthless’, ‘dog’, ‘food’, ‘stupid’]]
class_vec = [0, 1, 0, 1, 0, 1] # 1 代表侮辱性文字,0 代表正常言论。
# class_vec 返回第二个变量,是一个类别标签的集合。有两类 1 和 0 。
# 这些文本的类别由人工标注,这些标注信息用于训练程序以便自动检测侮辱性留言。
return posting_list, class_vec

将词条列表传递给 set 构造函数,set 就会返回一个不重复的列表。

def create_vocab_list(data_set): # 创建一个包含在所有文档中出现的不同重复词的列表,为此使用set集合。
vocab_set = set([]) # 创建一个空集合。
for document in data_set:
vocab_set = vocab_set | set(document) # 创建两个集合的并集。
return list(vocab_set)

函数的输入参数是词汇表 vocab_list 和某个文档 input_set,输出的是文档向量,向量的每个元素为 1 或者 0,

分别表示词汇表中的单词在输入文档中是否出现。

词集模型(set_of_word):将每个词的出现与否作为1个特征。

def set_of_words_2vec(vocab_list, input_set):
return_vec = [0] * len(vocab_list) # 创建一个其中所包含元素都为0的向量。
for word in input_set:
if word in vocab_list:
#  遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为 1 .
return_vec[vocab_list.index(word)] = 1
else:
print(“the word: %s is not in my vocabulary!” % word)
return return_vec

词袋模型(bag_of_word):如果每个词在文档中出现不止一次,意味着包含该词是否出现在文档中所不能表达的某种信息。

def bag_of_words_2vec(vocab_list, input_bag):
return_vec = [0] * len(vocab_list)
for word in input_bag:
if word in vocab_list:
return_vec[vocab_list.index(word)] += 1
#  遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值加 1 .
return return_vec

朴素贝叶斯分类器训练函数

def train_nb0(train_matrix, train_category):
# 输入参数为 文档矩阵 train_matrix, 以及由每篇文档类别标签所构成的向量 train_category。
num_train_docs = len(train_matrix) # 首先计算 侮文档矩阵 train_matrix 的总词数。
# 对多于两类的分类问题,则需要对代码进行修改。
num_words = len(train_matrix[0])
pa_busive = sum(train_category) / float(num_train_docs)
# 初始化概率(初始化程序中的分子变量和分母变量)。
# 1.如果其中一个概率值为 0,那么最后的乘积也为 0,为了降低这种影响,可以将所有词的出现次数初始化为 1,并将分母初始化为 2.
p0_num = np.ones(num_words)
p1_num = np.ones(num_words)
p0_denom = 2.0
p1_denom = 2.0
for i in range(num_train_docs):
# 分母变量是一个元素个数等于词汇表大小的 numpy 数组
if train_category[i] == 1:
p1_num += train_matrix[i]
p1_denom += sum(train_matrix[i])
else:
p0_num += train_matrix[i]
p0_denom += sum(train_matrix[i])
# 在 for 循环中 ,要遍历训练集 train_matrix 中的所有文档。一旦某个词语(侮辱性或正常词语)在某一文档中出现,
# 则该词对应的个数(p1_num)和(p0_num)就加 1 ,而且在所有的文档中,该文档的总词数也相应加 1 。对于两个类别都要进行同样的计算处理。
# 2.下溢出 由于太多很小的数相乘造成的。代数中,有 ln(a+b)=ln(a)+ln(b),通过求对数可以避免下溢出或者浮点数舍入导致的错误。
# 同时,采用自然对数进行处理不会有任何损失。
p1_vect = np.log(p1_num / p1_denom)
p0_vect = np.log(p0_num / p0_denom)
# 对每个元素除以该类别中的总词数。
return p0_vect, p1_vect, pa_busive

朴素贝叶斯分类函数

4个输入参数:要分类的向量 vec_2_classify, 使用函数 train_nb0() 计算得到的3个概率。

def classify_nb(vec_2_classify, p0_vec, p1_vec, p_class):
p1 = sum(vec_2_classify * p1_vec) + np.log(p_class)
p0 = sum(vec_2_classify * p0_vec) + np.log(1.0 - p_class)
if p1 > p0:
return 1
else:
return 0

def testing_nb(): # 便利函数
list_posts, list_classes = load_data_set()
my_vocab_list = create_vocab_list(list_posts)
train_mat = []
for post_in_doc in list_posts:
train_mat.append(set_of_words_2vec(my_vocab_list, post_in_doc))
p0_v, p1_v, p_ab = train_nb0(np.array(train_mat), np.array(list_classes))
test_entry = [‘love’, ‘my’, ‘dalmation’]
this_doc = np.array(set_of_words_2vec(my_vocab_list, test_entry))
print(test_entry, “classified as:”, classify_nb(this_doc, p0_v, p1_v, p_ab))
test_entry = [‘stupid’, ‘garbage’]
this_doc = np.array(set_of_words_2vec(my_vocab_list, test_entry))
print(test_entry, “classified as:”, classify_nb(this_doc, p0_v, p1_v, p_ab))

使用朴素贝叶斯进行交叉验证

接受一个大字符串并将其解析为字符串列表。该函数去掉少于两个字符的字符串,并将所有字符串转换为小写。

def text_parse(big_string):
import re
list_of_tokens = re.split(r’\W*’, big_string)
return [tok.lower() for tok in list_of_tokens if len(tok) > 2]

对贝叶斯垃圾邮件分类器进行自动化处理

def spam_test():
doc_list = []
class_list = []
full_text = []
for i in range(1, 26):
# 导入文件夹spam与ham下的文本文件,并将他们解析为词列表
file_name = ‘email/spam/’ + str(i) + ‘.txt’
with open(file_name, ‘rb’) as fd: # r 表示只读, b 表示二进制
word_list = text_parse(fd.read().decode(‘utf-8’, ‘ignore’))
# 使用 decode() 和 encode() 来进行解码和编码,现在用 utf-8 解码。
doc_list.append(word_list)
full_text.extend(word_list)
class_list.append(1)

    file_name = 'email/ham/' + str(i) + '.txt'
    with open(file_name, 'rb') as fd:
        word_list = text_parse(fd.read().decode('utf-8', 'ignore'))
    doc_list.append(word_list)
    full_text.extend(word_list)
    class_list.append(0)
vocab_list = create_vocab_list(doc_list)
# 接下来构建一个测试集与一个训练集,两个集合中的邮件都是随机选出来的。本例中共有50封电子邮件,其中10封电子邮件被选择为测试集。
# training_set 是一个整数列表,其中的值是 0 到 49。
training_set = list(range(50))
test_set = []
# 接下来随机选择其中的10个文件。
for i in range(10):
    rand_index = int(np.random.uniform(0, len(training_set)))
    test_set.append(training_set[rand_index])
    del (training_set[rand_index])
# 选择出的数字所对应的文档被添加到测试集,同时也将其从训练集中剔除。
# 这种随机选择数据的一部分作为训练集,而剩余部分作为测试集的过程称为留存交叉验证。
# 假定现在只完成了一次迭代,那么为了更精确地估计分类器的错误率,就应该进行多次迭代后求出平均错误率。
train_mat = []
train_classes = []
for doc_index in training_set:
    train_mat.append(set_of_words_2vec(vocab_list, doc_list[doc_index]))
    train_classes.append(class_list[doc_index])
p0_v, p1_v, ps_pam = train_nb0(np.array(train_mat), np.array(train_classes))
error_count = 0
# 接下来的for循环遍历训练集的所有文档,对每封邮件基于词汇表使用 set_of_words_2vec() 函数来构建词向量。
# 这些词在 train_nb0() 函数中用于计算分类所需的概率。然后遍历测试集,对其中每封电子邮件进行分类。
# 如果邮件分类错误,则错误数加 1,最后给出总的错误百分比。
for doc_index in test_set:
    word_vector = set_of_words_2vec(vocab_list, doc_list[doc_index])
    if classify_nb(np.array(word_vector), p0_v, p1_v, ps_pam) != class_list[doc_index]:
        error_count += 1
print("the error rate is:", float(error_count) / len(test_set))



###新建一个Python文件

import bayes

list_posts, list_classes = bayes.load_data_set()
my_vocab_list = bayes.create_vocab_list(list_postes)
print(my_vocab_list)

print(bayes.spam_test())
print(bayes.spam_test())

“`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值