NLP实践五-----朴素贝叶斯,SVM,LDA主题模型

博客介绍了朴素贝叶斯、SVM和LDA主题模型。朴素贝叶斯基于贝叶斯定理,有多项式、不努力、高斯等常见模型,还提及处理数值型数据方法、除0问题、下溢出及移除停用词等;SVM和LDA主题模型给出了原理及代码实践的参考文章。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


朴素贝叶斯

1. 原理
朴素贝叶斯的原理是基于贝叶斯定理的,我们要求的就是后验概率P(Cj|x),这里x就是特征向量,Cj就是类别j,后验概率最大的P(Cj|x)对于的类j就是样本特征为x对于的类别,其中我认为它的假设是最影响它的分类效果的原因,这就是我们看到朴素贝叶斯在不同样本分类的效果会有很大区别,见下图:
在这里插入图片描述


2.常见模型
其实这两种常见模型的具体区别就在于P(c)和先验概率的计算不同,解释也不同:
2.1多项式模型
  在多项式模型中,设某文档d=(t1,t2,…,tk),tk是该文档中出现过的单词,允许重复,则先验概率P©= 类c下单词总数/整个训练样本的单词总数。类条件概率P(tk|c)=(类c下单词tk在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|)。
2.2不努力模型
  P©= 类c下文件总数/整个训练样本的文件总数
  P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下包含的文件+2)
2.2高斯模型
上文看出,计算各个划分的条件概率P(a|y)是朴素贝叶斯分类的关键性步骤,当特征属性为离散值时,只要很方便的统计训练样本中各个划分在每个类别中出现的频率即可用来估计P(xi|c),下面重点讨论特征属性是连续值的情况。
当特征属性为连续值时,通常假定其值服从高斯分布(也称正态分布)。即:
在这里插入图片描述
因此只要计算出训练样本中各个类别中此特征项划分的各均值和标准差,代入上述公式即可得到需要的估计值。


ps:
 1 朴素贝叶斯处理数值型数据的方法:
  (1) 区间离散化,设阈值,分段。
  (2) 高斯化:求出概率密度函数,假设变量服从正态分布,根据已有变量统计均值和方差,
    得出概率密度函数,这样就解决了计算连续值作为分类的条件概率值。
      参考:http://blog.mythsman.com/?p=2683

2 除0问题:
    Laplace校准 所有计算均加一,总类别数目加n;

3 下溢出:很小的值相乘,四舍五入误差
    采用log 乘法变相加;


4移除停用词:也可以提高文本分类的性能
2.代码实践

参考代码:https://www.cnblogs.com/rongyux/p/5602037.html
多项式模型:

1.创建数据集
import numpy as np
from numpy import  *
# 1.创建数据集
def loadDataSet():
    postingList=[['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']]
    classVec = [0,1,0,1,0,1]    #1 is abusive, 0 not
    return postingList,classVec
# 2.创造词汇表
def createVocabList(dataSet):
    vocabSet = set([])  #create empty set
    for document in dataSet:
        vocabSet = vocabSet | set(document) #union of the two sets
    return list(vocabSet)

#3.将词汇表转换成01的形式
def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
    return returnVec


# 4.训练模型
def trainNB0(trainMatrix,trainCategory,len_vocab):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = np.ones(numWords); p1Num = np.ones(numWords)      #change to ones()
    p0Denom = len_vocab; p1Denom = len_vocab                        #多项式模型

    #计算每一个样本
    for i in range(numTrainDocs):
        #标签为1
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = np.log(p1Num/p1Denom)          #change to log()
    p0Vect = np.log(p0Num/p0Denom)          #change to log()
    return p0Vect,p1Vect,pAbusive

# 5.分类
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)    #element-wise mult  这里点乘
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0


# 6.测试
def testingNB():
    listOPosts,listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat=[]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    #计算
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses),len(myVocabList))
    testEntry = ['love', 'my', 'dalmation']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print (testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
    testEntry = ['stupid', 'garbage']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print (testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))

testingNB()

使用sklearn中的库:

from sklearn.naive_bayes import MultinomialNB
listOPosts, listClasses = loadDataSet()
myVocabList = createVocabList(listOPosts)
trainMat = []
for postinDoc in listOPosts:
    trainMat.append(setOfWords2Vec(myVocabList, postinDoc))


clf=MultinomialNB()
clf.fit(np.array(trainMat),listClasses)
testEntry = ['love', 'my', 'dalmation']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print(clf.predict(thisDoc.reshape(1,-1)))

svm

1.原理:参考 https://zhuanlan.zhihu.com/p/49331510
2.代码实践:https://blog.youkuaiyun.com/m0_37870649/article/details/81747614

import  numpy as  np
import pandas as pd
from keras_preprocessing.sequence import pad_sequences
from keras_preprocessing.text import Tokenizer
from sklearn import decomposition, preprocessing
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import SVC

train_prepeared_path='../data/train_prepared.csv'
val_prepeared_path='../data/val_prepared.csv'
test_prepeared_path='../data/test_prepared.csv'



print('加载分词后的数据')
train=pd.read_csv(train_prepeared_path,sep=',',engine='python',encoding='utf-8').sample(frac=0.2,random_state=24)
val=pd.read_csv(val_prepeared_path,sep=',',engine='python',encoding='utf-8').sample(frac=0.1,random_state=24)
test=pd.read_csv(test_prepeared_path,sep=',',engine='python',encoding='utf-8').sample(frac=0.1,random_state=24)


print(train.shape)


all_content=pd.concat([train['content'],val['content']],axis=0,ignore_index=True)

vectorizer=TfidfVectorizer(min_df=2)
vectorizer.fit(all_content)
X_all=vectorizer.transform(all_content).toarray()

test_x=vectorizer.transform(test['content']).toarray()
train_x=X_all[:len(train),:]
val_x=X_all[len(train):,:]



from sklearn.naive_bayes import MultinomialNB
def multiclass_logloss(actual, predicted, eps=1e-15):
    """对数损失度量(Logarithmic Loss  Metric)的多分类版本。
    :param actual: 包含actual target classes的数组
    :param predicted: 分类预测结果矩阵, 每个类别都有一个概率
    """
    # Convert 'actual' to a binary array if it's not already:
    if len(actual.shape) == 1:
        actual2 = np.zeros((actual.shape[0], predicted.shape[1]))
        for i, val in enumerate(actual):
            actual2[i, val] = 1
        actual = actual2

    clip = np.clip(predicted, eps, 1 - eps)
    rows = actual.shape[0]
    vsota = np.sum(actual * np.log(clip))
    return -1.0 / rows * vsota

clf=MultinomialNB()
clf.fit(train_x,train['label'])
label=clf.predict_proba(val_x)
label2=clf.predict_proba(test_x)
print(multiclass_logloss(val['label'],label))
print(multiclass_logloss(test['label'],label2))


#先降维再用svm

svd = decomposition.TruncatedSVD(n_components=120)
svd.fit(train_x)
xtrain_svd = svd.transform(train_x)
xvalid_svd = svd.transform(val_x)
xtest_svd = svd.transform(test_x)


scl = preprocessing.StandardScaler()
scl.fit(xtrain_svd)
xtrain_svd_scl = scl.transform(xtrain_svd)
xvalid_svd_scl = scl.transform(xvalid_svd)
xtest_svd_scl = scl.transform(xtest_svd)

# 调用下SVM模型
clf = SVC(C=1.0, probability=True) # since we need probabilities
clf.fit(xtrain_svd_scl, train['label'].values)
predictions = clf.predict_proba(xvalid_svd_scl)
predictions2 = clf.predict_proba(xtest_svd_scl)

print ("logloss: %0.3f " % multiclass_logloss(val['label'].values, predictions))
print ("logloss: %0.3f " % multiclass_logloss(test['label'].values, predictions2))


LDA主题模型 :参考文章:https://blog.youkuaiyun.com/u013710265/article/details/73480332

from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import CountVectorizer

corpus=['沙瑞金 赞叹 易学习 的 胸怀 , 是 金山 的 百姓 有福 , 可是 这件 事对 李达康 的 触动 很大 。 易学习 又 回忆起 他们 三人 分开 的 前一晚 , 大家 一起 喝酒 话别 , 易学习 被 降职 到 道口 县当 县长 , 王大路 下海经商 , 李达康 连连 赔礼道歉 , 觉得 对不起 大家 , 他 最 对不起 的 是 王大路 , 就 和 易学习 一起 给 王大路 凑 了 5 万块 钱 , 王大路 自己 东挪西撮 了 5 万块 , 开始 下海经商 。 没想到 后来 王大路 竟然 做 得 风生水 起 。 沙瑞金 觉得 他们 三人 , 在 困难 时期 还 能 以沫 相助 , 很 不 容易 。'
        ,'沙瑞金 向 毛娅 打听 他们 家 在 京州 的 别墅 , 毛娅 笑 着 说 , 王大路 事业有成 之后 , 要 给 欧阳 菁 和 她 公司 的 股权 , 她们 没有 要 , 王大路 就 在 京州 帝豪园 买 了 三套 别墅 , 可是 李达康 和 易学习 都 不要 , 这些 房子 都 在 王大路 的 名下 , 欧阳 菁 好像 去 住 过 , 毛娅 不想 去 , 她 觉得 房子 太大 很 浪费 , 自己 家住 得 就 很 踏实 。',
        '347 年 ( 永和 三年 ) 三月 , 桓温 兵至 彭模 ( 今 四川 彭山 东南 ) , 留下 参军 周楚 、 孙盛 看守 辎重 , 自己 亲率 步兵 直攻 成都 。 同月 , 成汉 将领 李福 袭击 彭模 , 结果 被 孙盛 等 人 击退 ; 而 桓温 三 战三胜 , 一直 逼近 成都 。']
stpwrdpath = "../data/stop_words.txt"
stop_words=[line.strip() for line in open(stpwrdpath,encoding='utf-8').readlines()]
#将停用词表转换为list
cntVector = CountVectorizer(stop_words=stop_words)
cntTf = cntVector.fit_transform(corpus)
lda = LatentDirichletAllocation(n_topics=2,
                                learning_offset=50.,
                                random_state=0)
docres = lda.fit_transform(cntTf)

print(docres)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值