NBSVM 算法学习

NBSVM (Naive Bayes - Support Vector Machine)学习

[TOC]

相关资料

论文:Baselines and Bigrams: Simple, Good Sentiment and Topic Classification.

fastai课程: Naive Bayes video.

kaggle:NB-SVM strong linear baseline

Motivation

NB(Naive Bayes)在短文本上表现好,SVM在长文本上表现好。(论文里的观点,实际可能未必!)

NB(Naive Bayes)

贝叶斯公式(西瓜书里有比较有趣的介绍)。一些基本概念(ppt来自刘成林老师):

image-20200614214846240

举例说明,假如一个要判定一个comment是不是有毒(toxic), 如果看不到文本内容情况下,自然可以用抛硬币的模型则p(toxic=1)=0.5, 如果看到了内容里的一个单词,比如‘fxxk’,那么p(toxic=1|word=‘fxxk’)的概率可能要远远大于0.5,而目标就是求这个后验概率p(w|x),$P(w_i)$ 为类别为i的概率,贝叶斯公式:

$$p(w_i|x)= \frac{p(x|w_i)P(w_i)}{p(x)}$$

因为贝叶斯公式有理论指导,理论情况下是百分百准确的决策器,(主要看概率密度函数的估计,先验概率是否准确等。)但是一般情况下对条件概率的估计不会完全准确(本例中使用最大似然估计)

举例:

包含某单词x,的toxic=1的文本为200个,toxic=1的文本总共为1000,那么就能用最大似然估计出p(x|w=1),估计出p(x|w=-1),

本论文中的贝叶斯:

image-20200614210256663

image-20200614210401856

image-20200614210339659

image-20200614225506214

上式是该模型的主要公式,其中r将作为模型的权重,r为特征f在正性文本的比率比上f在负性文本的比率。

$r = \log \frac{\text{ratio of feature $f$ in positive comments}}{\text{ratio of feature $f$ in negative comments}}$

为了能够结合SVM,本文中的正负类用1, -1 表示。

数据介绍:

image-20200614211002446

(159571, 426005)表示共有159571个评论,字典大小为426005。也即x是由159571个426005维的count vector 构成的矩阵。

第一眼看论文部分,没太看懂哪里用了贝叶斯,假设train_i为159571个评论文本中的第i个, 对toxic这个label进行分类。特征维度为V(V=426005),特征矩阵即矩阵x,维度为(159571, 426005)的矩阵表示词典里的每个词在每个文本中出现的次数。最大似然估计条件概率:p(x|y=1), p(x|y=-1), 对应代码为 x[y==y_i].sum(0),y_i={0,1}, 这个维度为(1, 426005)表示每个特征出现在正/负文本中的文档数。求出包含某单词(特征)的正/负文本数,然后除以正/负文本的总个数,估计出 $p(x_j|w=0), p(x_j|w=1)$, j=1,…426005.其中$p(x_j|w=1)=p/||p||_1, p(x_j|w=-1)=q/||q||_1$ 然后论文用这两个设计了一个新的特征,r, 并且用来作为线性模型的权重。(详细见论文)

r的解释:

如果r>0,则表示该特征(该单词)更容易出现在正文本中,否则更容易出现在负文本中(结合线性模型比较符合经验判断。

线性模型的解释

image-20200614210256663

上图中的w=r,b为正负样本的数量比值,$x^{(k)}$为第k个case的特征向量。如果某个单词更容易出现在正样本中,则乘以一个正数的权重(这样的单词越多,文本越容易为正向),否则乘以负数的权重(这样的单词越多,越容易为负向)。b是现实正负样本的比值,总是偏向样本多的那个类别。

维度情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x.shape
(159571, 426005)

y = train['toxic'].values
x[y==1].shape
(15294, 426005)

x[y==1].sum(0).shape
(1, 426005)

(y==1).shape
(159571,)

(y==1).sum()
15294

SVM

将贝叶斯部分设计的特征作为输入。其他部分就是普通SVM模型。

image-20200614212008887

上面文章的最后一段也直接说明了:信任NB,除非SVM具有非常高的置信度。

实现r和NBSVM的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  def pr(y_i, y):
print(y)
p = x[y==y_i].sum(0)
return (p+1) / ((y==y_i).sum()+1)

x = trn_term_doc
test_x = test_term_doc

def get_mdl(y):
y = y.values
r = np.log(pr(1, y)/pr(0, y))
m = LogisticRegression(C=4, dual=True )
x_nb = x.multiply(r)
return m.fit(x_nb, y), r

preds = np.zeros((len(test), len(label_cols)))

for i, j in enumerate(label_cols):
print('fit', j)
m,r = get_mdl(train[j])
preds[:,i] = m.predict_proba(test_x.multiply(r))[:,1]

SVM用的是sklearn中的LogisticRegression。x是tf-idf生成的文本稀疏矩阵。

image-20200614211002446

(159571, 426005)表示共有159571个评论,字典大小为426005。也即x是由159571个426005维的count vector 构成的矩阵。

本任务中要预测多个label,16-21行代码是对多个label分别预测,模型是分开的。

总结

虽然论文里直说了