[关闭]
@elibinary 2017-08-12T09:06:59.000000Z 字数 3108 阅读 1080

基于朴素贝叶斯的广告识别分类尝试

MachineLearning


贝叶斯定理

贝叶斯定理是关于随机事件 A 和 B 的条件概率的一则定理,用公式来描述就是:

可以看出,通过贝叶斯公式我们可以在已知三个概率函数时推出第四个。重要应用之一就是根据

独立变量的联合分布:

应用

假设:
A: features


B: category

求值:

假设各特征之间相互独立,也就是 之间都相互独立,那么就有

那么最终问题就转化为了对 求值,或者叫估值
就是 B 在训练集中的相对频率
在处理 时,有几种不同的处理方式

高斯模型
高斯模型假设特征在各类别下的观测值符合高斯分布
也就是说对于 ~

其中参数 可通过极大似然法来估计

多项式模型
多项式模型假设数据服从多项式分布

是对于特征 x 在一个样本中被类 B 拥有的概率
是在训练集中,特征 x 在属于类 B 的样本中出现的次数
是类 B 中的所有特征数量和

广告分类

朴素贝叶斯尽管看起来其假设非常简单,但是在很多场景下朴素贝叶斯分类器却工作的相当优秀。
而广告识别说白了其实就是一个二分类,给定一个文本,它要么是广告,要么是正常文本,也就是说

下面我尝试使用多项式模型构建模型并估计参数

首先还是使用上一篇中讲的 文本特征提起 来对训练集进行特征提取,然后就是估计模型以及判别方法

  1. import jieba
  2. from sklearn import feature_extraction
  3. from sklearn.feature_extraction.text import TfidfTransformer
  4. from sklearn.feature_extraction.text import CountVectorizer
  5. from collections import defaultdict
  6. import math
  7. # global var for probability
  8. probability_module = {}
  9. # { y_i: len_of_i_docs }
  10. t_n = {}
  11. # { feature_i: {num_of_y_1, num_of_y_2 ... ,num_of_y_n} }
  12. # features_num = defaultdict(dict)
  13. features_num = {}
  14. total_doc_num = 0
  15. samples = []
  16. def tf_idf(file_path):
  17. file = open(file_path, 'r')
  18. corpus = []
  19. temp_str = ''
  20. temp_samples = []
  21. for line in file:
  22. cut_res = jieba.lcut_for_search(line)
  23. temp_samples.append(cut_res)
  24. # corpus.append(' '.join(cut_res))
  25. temp_str += ' '.join(cut_res)
  26. temp_str += ' '
  27. file.close
  28. samples.append(temp_samples)
  29. corpus.append(temp_str)
  30. vectorizer = CountVectorizer()
  31. transformer = TfidfTransformer()
  32. word_freq = vectorizer.fit_transform(corpus)
  33. tf_idf = transformer.fit_transform(word_freq)
  34. words = vectorizer.get_feature_names()
  35. scores = tf_idf.toarray()[0]
  36. return zip(words, scores)
  37. # for i in range(len(scores)):
  38. # print(words[i], scores[i])
  39. # sort_res = sorted(list(arr), key=lambda item: item[1], reverse=True)
  40. def predict_module(samples, y, features):
  41. global total_doc_num
  42. for i in range(len(y)):
  43. if y[i] not in t_n:
  44. t_n[y[i]] = {}
  45. t_n[y[i]]['docs'] = len(samples[i])
  46. t_n[y[i]]['features'] = len(features[i])
  47. t_n[y[i]]['total'] = 0
  48. for features_i in features:
  49. for item in features_i:
  50. features_num[item] = {}
  51. for i in range(len(samples)):
  52. for sample in samples[i]:
  53. total_doc_num += 1
  54. for word in sample:
  55. if word in features_num:
  56. t_n[y[i]]['total'] += 1
  57. if y[i] in features_num[word]:
  58. features_num[word][y[i]] += 1
  59. else:
  60. features_num[word][y[i]] = 1
  61. def bayes_multinomial(doc, y):
  62. v = len(features_num)
  63. cut_res = jieba.lcut_for_search(doc)
  64. scores = {}
  65. for y_i in y:
  66. p_y = t_n[y_i]['docs'] / total_doc_num
  67. scores[y_i] = math.log(p_y)
  68. for word in cut_res:
  69. if word in features_num:
  70. if y_i in features_num[word]:
  71. p_y_w = (features_num[word][y_i] + 1) / (t_n[y_i]['total'] + v)
  72. else:
  73. p_y_w = 1 / (t_n[y_i]['total'] + v)
  74. scores[y_i] += math.log(p_y_w)
  75. return scores

接下来就是测试其分类效果了
本来是要把训练数据分成两份,一份用于参数估计,另一份用于测试模型准确率的。但是因为我本身的训练数据量比较少,一共也就几百条。。。所以只在其中随机挑了几十条作为测试集,准确度在 80% 左右,在输入正常样本是产生误判的几率较大,另外由于训练集和测试集过小,我暂时并不能确定模型完善度。
接下来我打算先使用 NumPy 对实现中参数向量结构部分进行重写,然后去找一个现有的语料库找个大点的数据集跑测一下。顺便有时间再试一下高斯模型以及伯努利模型的效果。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注