请教!朴素贝叶斯报错一大堆?

img

#数据准备,数据已下载
import nltk
#nltk.download('movie_reviews')
#nltk.download('stopwords')
#数据查看
#movie_reviews.categories()#数据集中对数据分类情况查看,提取数据集中的类别名
#每个分类的实际存储内容:
#movie_reviews.fileids(cat)#查看每个类别的内容
from nltk.corpus import movie_reviews
from sklearn.model_selection import StratifiedShuffleSplit
from nltk.corpus import stopwords
from nltk.collocations import BigramCollocationFinder
#Bigram是由相邻的且有意义的两个单词组成的序列,用于捕获单词之间的关系。
#BigramCollocationFinder是一个可以帮助我们找到在文本中出现频率较高的Bigram的工具。
#StratifiedShuffleSplit是一种基于分层抽样的交叉验证方法。
from nltk.metrics import BigramAssocMeasures
#BigramAssocMeasures是NLTK中的一个类,用于计算和评估不同的基于bigram的关联性度量
#载入数据集及所需模块
def GetData():
    #存储数据
    DataSet=[]
    #存储类别
    YLabels=[]
    for cat in movie_reviews.categories():
        for fileid in movie_reviews.fileids(cat):

            words=list(movie_reviews.words(fileid))
            DataSet.append((words,cat))
            #二元组,它由两个或多个元素组成,每个元素可以是任意数据类型
            #二元组,在设立是([标签],'特征')
            YLabels.append(cat)
    return DataSet,YLabels
    #cat 当前文件的分类 fileid:当前文件ID
    #定义了一个函数,载入数据集并划分数据集
def GetTrainTest(InData,YLabels):
    TrainSize=0.7
    TestSize=0.3
    RanData=StratifiedShuffleSplit(train_size=TrainSize,test_size=TestSize,random_state=77)
    #StratifiedShuffleSplit:一个交叉验证的方法,用于训练集和测试集的划分。
    #random_state=77一种随机种子类型
    for TrainInx,TestInx in RanData.split(InData,YLabels):
        #InData:所有数据的特征集合 YLabels:对应的标签集合。RanData:随机数生成器,用于划分数据集
        #装载数据集
        TrainData=[InData[i] for i in TrainInx]
        #TrainInx是StratifiedShuffleSplit方法生成的索引值
        TrainY=[YLabels[i] for i in TrainInx]
        #装载测试集
        TestData=[InData[i] for i in TestInx]
        TestY=[YLabels[i] for i in TestInx]
    return TrainData,TestData,TrainY,TestY
#三种构造特征集的方式
def BuildWordFeatures(InData):
    #用字典保存特征
    FeatureSet={}
    #词列表的实例元组里的第一个子项
    words=InData[0]
    #把特征保存到字典中,即每个词
    for word in words:        
        FeatureSet[word]=1
    #实例元组中第二个子项是类别标签    
    return (FeatureSet,InData[1])
#ps:第一种,直接用每个分词
def BuildNegFeatures(InData):#???
    words=InData[0]
    final=[]
    #标识,为true则上个词是负面词,当前词要修饰
    NegTag=False
    #负面词列表
    NegWords=['no','not']
    #在负面词的本体前加"Not_"前缀,负面词本身不进入特征字典,修饰后的加入
    for word in words:
        if NegTag:
            word='Not_'+word
            NegTag=False
        if word not in NegWords:
            final.append(word)
        else:
            NegTag=True  
    #用字典保存特征
    FeatureSet={}
    for word in final:
        FeatureSet[word]=1
    #实例元组中第二个子项是类别标签
    return (FeatureSet,InData[1])
#ps:第二种,单词进阶式,将负面词修饰一下
#一个处理停用词的函数
def StopWords(InData):
    StopWord=stopwords.words('english')
    NegWords=['no','not']
    #创建新的停用词列表来排除负面词
    NewStopWord=[word for word in StopWord if word not in NegWords]
    label=InData[1]#权重???
    #删除停用词
    words=[word for word in InData[0] if word not in NewStopWord]
    return (words,label)
def BuildKeyPhraseFeatrues(InData):
    #用字典保存特征
    FeatureSet={}
    InData=StopWords(InData)
    words=InData[0]
    #将词进行二元组合
    BigramFinder=BigramCollocationFinder.from_words(words)
    #按照频率降序排序后,取前400个
    bigrams=BigramFinder.nbest(BigramAssocMeasures.raw_freq,400)
    for bigram in bigrams:
        FeatureSet[bigram]=1
    return (FeatureSet,InData[1])
#ps:第三种,组合词式,将词两两组合
def BayesModel(InData):
    model=nltk.NaiveBayesClassifier.train(InData)
    return model
#进行贝叶斯建模
def CheckModel(model,features,DataSetType='Train'):
    acc=nltk.classify.accuracy(model,features)
    print("\n"+DataSetType+"Accuracy=%0.2f"%(acc*100)+"%.")
#检查模型精度并打印
def ShowFeatures(model,FeaturesNO=5):
    print("\nFeatrue Importance:")
    print("==========================\n")
    print(model.show_most_informative_features(FeaturesNO))
#打印模型中各特征的影响状况
##对照三种特征集构造方式,设立测试模型并观察指标的函数
def BuildModelNormal(TrainData,DevData,TestData):
    #训练集特征
    TrainFea=list(map(BuildWordFeatures,TrainData))
    #调优测试集特征
    DevFea=list(map(BuildWordFeatures,DevData))
    #最终测试集特征
    TestFea=list(map(BuildWordFeatures,TestData))
    #建模
    model=BayesModel(TrainFea)
    #模型探测
    CheckModel(model,TrainFea)
    CheckModel(model,DevFea,'Dev')
    CheckModel(model,TestFea,'Test')
    return model
#直接用每个分词
def BuildModelNeg(TrainData,DevData,TestData):
    #训练集特征
    TrainFea=list(map(BuildNegFeatures,TrainData))
    #调优测试集特征
    DevFea=list(map(BuildNegFeatures,DevData))
    #最终测试集特征
    TestFea=list(map(BuildNegFeatures,TestData))
    #建模
    model=BayesModel(TrainFea)
    #模型探测
    CheckModel(model,TrainFea)
    CheckModel(model,DevFea,'Dev')
    CheckModel(model,TestFea,'Test')
    return model
#单词进阶式,将负面词修饰一下。
def BuildModelKeyPhrase(TrainData,DevData,TestData):
    #训练集特征
    TrainFea=list(map(BuildKeyPhraseFeatrues,TrainData))
    #调优测试集特征
    DevFea=list(map(BuildKeyPhraseFeatrues,DevData))
    #最终测试集特征
    TestFea=list(map(BuildKeyPhraseFeatrues,TestData))
    #建模
    model=BayesModel(TrainFea)
    #模型探测
    CheckModel(model,TrainFea)
    CheckModel(model,DevFea,'Dev')
    CheckModel(model,TestFea,'Test')
    return model
#组合词式,将词两两组合
if __name__=="__main__":
    DataSet,YLabels=GetData()
    Train,AllTest,TrainY,AllTestY=GetTrainTest(DataSet,YLabels)
    Dev,Test,DevY,TestY=GetTrainTest(AllTest,AllTestY)
    #查看各数据集大小
    print("\nDataSet Size: %d"%(len(DataSet)))
    print("\nTrain Size: %d"%(len(Train)))
    print("\nDev Size: %d"%(len(Dev)))
    print("\nTest Size: %d"%(len(Test)))
    #分别建模并打印信息
    NormalModel=BuildModelNormal(Train,Dev,Test)
    ShowFeatures(NormalModel)
    NegModel=BuildModelNeg(Train,Dev,Test)
    ShowFeatures(NegModel)
    KPModel=BuildModelKeyPhrase(Train,Dev,Test)
    ShowFeatures(KPModel)
#编写主程序,调用各函数完成贝叶斯建模并测试 
#假设model为调试好的分类模型名,NewData为{“特征”:value }字典形式的待分类数据,
#接上,可用以下语句进行分类: model.classify(NewData)


不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7503599
  • 这篇博客也不错, 你可以看下朴素贝叶斯中朴素是什么含义?
  • 你还可以看下sklearn参考手册中的 标签传播的数字。展示性能
  • 除此之外, 这篇博客: 特征顺序对模型的影响中的 两次入模变量的列顺序不一致! 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    以前一致认为lgb/xgb这样的模型时可以识别列名的,只要输入的特征相同就没有问题,但这种观点是错误的,做了一个简单的实验:

    from sklearn import datasets
    import lightgbm as lgb
    import pandas as pd
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    X = pd.DataFrame(X)
    lgb_train = lgb.Dataset(X, y)
    params = {
        'task': 'train',
        'boosting_type': 'gbdt',  # 设置提升类型
        'objective': 'regression', # 目标函数
        'metric': {'l2', 'auc'},  # 评估函数
        'num_leaves': 31,   # 叶子节点数
        'learning_rate': 0.05,  # 学习速率
        'feature_fraction': 0.9, # 建树的特征选择比例
        'bagging_fraction': 0.8, # 建树的样本采样比例
        'bagging_freq': 5,  # k 意味着每 k 次迭代执行bagging
        'verbose': 1 # <0 显示致命的, =0 显示错误 (警告), >0 显示信息
    }
    gbm = lgb.train(params,lgb_train,num_boost_round=20)
    

    使用鸢尾花数据集做训练,然后从中间抽出一条数据做预测,结果如下

    test = pd.DataFrame([[5.1],[3.5],[1.4],[0.2]]).T
    print(gbm.predict(test))
    [0.35976825]
    

    变换测试集列顺序,结果如下

    test = pd.DataFrame([[0.2],[3.5],[1.4],[5.1]]).T
    print(gbm.predict(test))
    [0.59565977]
    

    参考这篇博客https://blog.csdn.net/hshuihui/article/details/53258111,可能是由于数据传入时调用了as_matrix()方法,直接传入的矩阵,列什么的sklearn或者lgb并不会关心。
    所以,
    在训练模型时一定要保证训练集、验证集、测试集列顺序一致!

  • 您还可以看一下 CSDN讲师老师的如何一次通过软考?课程中的 如何一次通过软考?小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    我很乐意帮您解决问题!

    首先,您使用的编程语言和库是什么?朴素贝叶斯算法有很多实现方式,不同的编程语言和库也有不同的用法和问题。

    其次,您能否提供具体的报错信息和代码?这样才能更好地定位问题并给出解决方案。如果您的数据预处理和特征提取没有问题,通常报错信息会给出一些提示,比如哪一行代码出错,错误类型等等。

    最后,您的数据集的格式和特征选取有没有问题?朴素贝叶斯算法对特征选取非常敏感,如果您的特征选取得不好,模型效果就会很差。

    如果您能提供更多的信息,我会尽力帮您解决问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^