精华内容
下载资源
问答
  • 朴素贝叶斯分类器:假设特征之间相互独立 另外,有两种模式 词集set(一个词在文档中只出现一次,即词向量中每个词的权重相等),伯努利模型;词袋bag,多项式模型 code:...

    朴素贝叶斯分类器:假设特征之间相互独立

    另外,有两种模式 词集set(一个词在文档中只出现一次,即词向量中每个词的权重相等),伯努利模型;词袋bag,多项式模型

    code:https://github.com/apachecn/AiLearning/blob/master/src/py2.x/ml/4.NaiveBayes/bayes.py

    import numpy as np
    
    def loadDataSet():
        postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], #[0,0,1,1,1......]
                       ['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]
        return postingList,classVec
    
    
    def createVocabList(dataSet):
        vocabSet  = set([])
        for document in dataSet:
            vocabSet = vocabSet | set(document)
        return list(vocabSet)
    
    def setOfWords2Vec(vocabList,inputSet):
        returnVec = [0]*len(vocabList)
        for word in inputSet:
            if word in vocabList:
                returnVec[vocabList.index(word)] = 1
        return returnVec
    
    def bagOfWords2VecMN(vocabList, inputSet):
        returnVec = [0]*len(vocabList)
        for word in inputSet:
            if word in vocabList:
                returnVec[vocabList.index(word)] += 1
        return returnVec
    
    def trainNB(trainMatirx,trainCategory):
    
        '''
    
        :param trainMatirx:  将文档转为了词向量矩阵
        :param trainCategory:   文档每个句子所属类别
        :return:   贝叶斯公式,需要有先验、每个特征的条件概率
        '''
    
        numTrainDocs = len(trainMatirx)
        numTrainWords = len(trainMatirx[0])   # 将每一个句子转为 用词向量表示
    
        #   (1)    pA :A的先验
        pA = sum(trainCategory) / float(numTrainDocs)
    
        #   (2)   由于存储每个特征的条件概率
        p0Num = np.ones(numTrainWords)         #  每个 单词特征的 初始值 ,列表 [] 的每个元素用于统计每个单词出现的次数
        p1Num = np.ones(numTrainWords)
    
        p0Sum = 2.0                         #  整文本 词向量中一共出现的单词个数。 0类别一共的个数,初始值
        p1Sum = 2.0
    
        for i in range(numTrainDocs):
            if trainCategory[i]==0:
                p0Num += trainMatirx[i]
                p0Sum += sum(trainMatirx[i])
    
            else:
                p1Num += trainMatirx[i]
                p1Sum += sum(trainMatirx[i])
    
        p0Vec = np.log(p0Num/p0Sum)
        p1Vec = np.log(p1Num/p1Sum)
    
        return p0Vec,p1Vec,pA
    
    
    def classifyNB(vec2Classify,p0Vec,p1Vec,pA):
    
        '''
    
        :param vec2Classify:  [1,0,0,1……] 类型的词向量,分别和p1Vec、p2Vec每个元素相乘,表示 在测试样本中,只用样本出现的特征进行相乘,
                                从而求得某个类别后验概率最大    (即书中提到的 伯努利模型 实现)
        :param p0Vec:
        :param p1Vec:
        :param pA:
        :return:
        '''
    
        p1 = np.sum(vec2Classify*p1Vec) + np.log(pA)
        p2 = np.sum(vec2Classify*p0Vec) + np.log(1-pA)
    
        if p1>p2:
            return 1
        else:
            return 0
    
    def testingNB():
        data,label = loadDataSet()
    
        VocabList = createVocabList(data)
    
        print("set: ")
        print(VocabList)
        print("----------------")
    
        trainMat = []
        for d in data:
            trainMat.append(setOfWords2Vec(VocabList,d))
    
        p0V,p1V,pA = trainNB(trainMat,label)
    
    
        print("template: ")
        print("p0: ",p0V)
        print("p1: ",p1V)
        print("pa: ",pA)
        print("----------------------------------------------------")
        #test = ['love', 'my', 'dalmation']
        test =  ['stupid', 'garbage']
        array_test = np.array(setOfWords2Vec(VocabList,test))
        print(test,"classified as: ",classifyNB(array_test,p0V,p1V,pA))
    
    
    
    
    if __name__ =="__main__":
        testingNB()
    
    
    
    
    
    
    展开全文
  • 基于朴素贝叶斯分类器文本分类

    千次阅读 2016-11-18 17:26:30
    1、用MapReduce算法实现贝叶斯分类器的训练过程,并输出训练模型; 2、用输出的模型对测试集文档进行分类测试。测试过程可基于单机Java程序,也可以是MapReduce程序。输出每个测试文档的分类结果; 3、利用测试...
    1. 实验要求
    2. 题目要求

    1、用MapReduce算法实现贝叶斯分类器的训练过程,并输出训练模型;

    2、用输出的模型对测试集文档进行分类测试。测试过程可基于单机Java程序,也可以是MapReduce程序。输出每个测试文档的分类结果;

    3、利用测试文档的真实类别,计算分类模型的PrecisionRecallF1值。

    2.实验环境

    实验平台:VMware Workstation10

    虚拟机系统:Suse11

    集群环境:主机名master  ip:192.168.226.129

    从机名slave1  ip:192.168.226.130

    1. 贝叶斯分类器理论介绍

    贝叶斯分类器的分类原理是通过某对象的先验概率,利用贝叶斯公式计算出其后验概率,即该对象属于某一类的概率,选择具有最大后验概率的类作为该对象所属的类。

    应用贝叶斯分类器进行分类主要分成两阶段。第一阶段是贝叶斯统计分类器的学习阶段,即根据训练数据集训练得出训练模型;第二阶段是贝叶斯分类器的推理阶段,即根据训练模型计算属于各个分类的概率,进行分类。

    贝叶斯公式如下:

    IMG_256

    其中AB分别为两个不同的事件,P(A)A先验概率P(A|B)是已知B发生后A条件概率,也由于得自B的取值而被称作A后验概率。而上式就是用事件B的先验概率来求它的后验概率。

    1. 贝叶斯分类器训练的MapReduce算法设计

    3.1贝叶斯文本分类流程图

    3.2贝叶斯文本分类详细步骤

           整个文档归类过程可以分为以下步骤:

      1. 测试数据打包。将训练数据集中的大量小文本打包为SequencedFileMapReduce程序)。
      2. 文档统计以及单词统计。将1中输出的SequencedFile作为输入,分别进行文档个数统计DocCount(MapReduce程序)和各个分类下单词个数统计WordCount(MapReduce程序)
      3. 测试数据打包。将测试数据集中的大量小文本打包为SequcedFileMapReduce程序)。
      4. 文档归类。将2中输出的文档统计和单词统计的结果,分别计算文档的先验概率和单词在各个分类下的条件概率,然后将3中输出的SequencedFile作为输入,计算测试文本属于各个分类的概率,并选择其中最大概率的分类作为该文档的所属分类。

    3.3具体算法设计

    一个Country有多个news.txt, 一个news 有多个word

    我们所设计的算法最后是要得到随机抽取一个txt文档,它最有可能属于哪个国家类别,也就是我们要得到它属于哪个国家的概率最大,把它转化为数学公式也就是:

             3-1

    为了便于比较,我们将上式取对数得到:

           3-2

    其中Num(Wi)表示该txt文档中单词Wi的个数;P(C|Wi) 表示拿出一个单词Wi,其属于国家C的后验概率。根据贝叶斯公式有:P(C|W) = P(W|C)*P(C)/P(W),其中:

    P(W|C):国家Cnews中单词W出现的概率,根据式3-2,不能使该概率为0,所以我们约定每个国家都至少包含每个单词一次,也就是在统计单词数量时,都自动的加1,就有:

         3-3

    P(C):国家C出现的概率(正比于其所含txt文件数);

    P(W):单词W在整个测试集中出现的概率。

    根据上面的贝叶斯公式我们设计的MapReduce算法如下:

    1. 按比例选取测试文档,其比例大致为国家包含文档数的相对比例;
    2. Map操作:一一遍历文档,得到<<C, Wi> , 1>
    3. Reduce操作:

    合并<<C, W> , 1> 得到国家C中含有单词Wi的个数<<C, Wi> , ni>+1,记为N(C,Wi)

    得到国家C中含有的单词总数,记为N(C)

    得到测试集中单词W的总数,记为N(W)

    再由得到测试集的单词总数,记为N

    则可求得P(W|C) = N(C,W)/N(C)P(C) = N(C)/NP(W) = N(W)/N

     

    3.4MapReduceData Flow示意图

    1. 源代码清单

    本实验中的主要代码如下所示

    4.1 SmallFilesToSequenceFileConverter.java      小文件集合打包工具类MapReduce程序

    4.2 WholeFileInputFormat.java      支持类:递归读取指定目录下的所有文件

    4.3 WholeFileRecordReader.java 支持类:读取单个文件的全部内容

    4.4 DocCount.java     文档统计MapReduce程序

    4.5 WordCount.java   单词统计MapReduce程序

    4.6 DocClassification.java   测试文档分类MapReduce程序

    详细代码如下:

    4.1 SmallFilesToSequenceFileConverter.java 其中MapReduce关键代码如下:

    publicclass SmallFilesToSequenceFileConverter extends Configured implements Tool {

     

        staticclass SequenceFileMapper extends Mapper<NullWritable, BytesWritable, Text, BytesWritable> {

     

           private String fileNameKey; // 被打包的小文件名作为key,表示为Text对象

           private String classNameKey; // 当前文档所在的分类名

     

           @Override// 重新实现setup方法,进行map任务的初始化设置

           protectedvoid setup(Context context) throws IOException, InterruptedException {

               InputSplit split = context.getInputSplit(); // context获取split

               Path path = ((FileSplit) split).getPath(); // split获取文件路径

               fileNameKey = path.getName(); // 将文件路径实例化为key对象

               classNameKey = path.getParent().getName();

           }

     

           @Override// 实现map方法

           protectedvoid map(NullWritable key, BytesWritable value, Context context)

                  throws IOException, InterruptedException {

               // 注意sequencefilekeyvalue key:分类,文档名  value:文档的内容)

               context.write(new Text(classNameKey + "/" + fileNameKey), value);

           }

        }

    }

    4.2 WholeFileInputFormat.java 其中关键代码如下:

    publicclass WholeFileInputFormat extends FileInputFormat<NullWritable, BytesWritable> {

        /**

         * <p>方法描述:递归遍历输入目录下的所有文件</p>

         * <p>备注:该写FileInputFormat,使支持多层目录的输入</p>

         *  @authormeify DateTime 2015113下午2:37:49

         *  @param fs

         *  @param path

         */

        void search(FileSystem fs, Path path) {

           try {

               if (fs.isFile(path)) {

                  fileStatus.add(fs.getFileStatus(path));

               } elseif (fs.isDirectory(path)) {

                  FileStatus[] fileStatus = fs.listStatus(path);

                  for (inti = 0; i < fileStatus.length; i++) {

                      FileStatus fileStatu = fileStatus[i];

                      search(fs, fileStatu.getPath());

                  }

               }

           } catch (IOException e) {

               e.printStackTrace();

           }

        }

        @Override

        public RecordReader<NullWritable, BytesWritable> createRecordReader(InputSplit split, TaskAttemptContext context)

               throws IOException, InterruptedException {

           WholeFileRecordReader reader = new WholeFileRecordReader();

           reader.initialize(split, context);

           returnreader;

        }

        @Override

        protected List<FileStatus> listStatus(JobContext job) throws IOException {

          

           FileSystem fs = FileSystem.get(job.getConfiguration());

           // 输入根目录

           String rootDir = job.getConfiguration().get("mapred.input.dir", "");

           // 递归获取输入目录下的所有文件

           search(fs, new Path(rootDir));

           returnthis.fileStatus;

        }

    }

    4.3 WholeFileRecordReader.java 其中关键代码如下:

    publicclass WholeFileRecordReader extends RecordReader<NullWritable, BytesWritable>{

     

        private FileSplit fileSplit; //保存输入的分片,它将被转换成一条( key value)记录

        private Configuration conf; //配置对象

        private BytesWritable value = new BytesWritable(); //value对象,内容为空

        privatebooleanprocessed = false; //布尔变量记录记录是否被处理过

        @Override

        publicboolean nextKeyValue() throws IOException, InterruptedException {

           if (!processed) { //如果记录没有被处理过

               //fileSplit对象获取split的字节数,创建byte数组contents

               byte[] contents = newbyte[(int) fileSplit.getLength()];

               Path file = fileSplit.getPath(); //fileSplit对象获取输入文件路径

               FileSystem fs = file.getFileSystem(conf); //获取文件系统对象

               FSDataInputStream in = null; //定义文件输入流对象

               try {

                  in = fs.open(file); //打开文件,返回文件输入流对象

    //从输入流读取所有字节到contents

                  IOUtils.readFully(in, contents, 0, contents.length);          value.set(contents, 0, contents.length); //contens内容设置到value对象中

               } finally {

                  IOUtils.closeStream(in); //关闭输入流

               }

              

               processed = true; //将是否处理标志设为true,下次调用该方法会返回false

               returntrue;

           }

               returnfalse; //如果记录处理过,返回false,表示split处理完毕

        }

    }

    4.4 DocCount.java  其中MapReduce关键代码如下:

    publicclass DocCount extends Configured implements Tool{

     

        publicstaticclass Map extends Mapper<Text, BytesWritable, Text, IntWritable> {

           @Override

           publicvoid map(Text key, BytesWritable value, Context context) {

               try {

                  String currentKey = key.toString();

                  String[] arr = currentKey.split("/");

                  String className = arr[0];

                  String fileName = arr[1];

                  System.out.println(className + "," + fileName);

                  context.write(new Text(className), new IntWritable(1));

               } catch (IOException e) {

                  e.printStackTrace();

               } catch (InterruptedException e) {

                  e.printStackTrace();

               }

           }

        }

       

        publicstaticclass Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {

           private IntWritable result = new IntWritable();

           publicvoid reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {

               intsum = 0;

               for (IntWritable val : values) {

                  sum ++;

               }

               result.set(sum);

               context.write(key, result);  // 输出结果key: 分类 ,  value: 文档个数

           }

        }

    }

    4.5 WordCount.java  其中MapReduce关键代码如下:

    publicclass WordCount extends Configured implements Tool{

     

        publicstaticclass Map extends Mapper<Text, BytesWritable, Text, IntWritable> {

     

           @Override

           publicvoid map(Text key, BytesWritable value, Context context) {

               try {

                 

                  String[] arr = key.toString().split("/");

                  String className = arr[0];

                  String fileName = arr[1];

                  value.setCapacity(value.getSize()); // 剔除多余空间

                  // 文本内容

                   String content = new String(value.getBytes(), 0, value.getLength());

                  StringTokenizer itr = new StringTokenizer(content);

                  while (itr.hasMoreTokens()) {

                      String word = itr.nextToken();

                      if(StringUtil.isValidWord(word))

                      {

                         System.out.println(className + "/" + word);

                         context.write(new Text(className + "/" + word), new IntWritable(1));

                      }

                  }

               } catch (IOException e) {

                  e.printStackTrace();

               } catch (InterruptedException e) {

                  e.printStackTrace();

               }

           }

        }

       

        publicstaticclass Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {

           private IntWritable result = new IntWritable();

           publicvoid reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {

               intsum = 1; // 注意这里单词的个数从1开始计数

               for (IntWritable val : values) {

                  sum ++;

               }

               result.set(sum);

               context.write(key, result);  // 输出结果key: 分类/ 单词 ,  value: 频次

           }

        }

    }

    4.6 DocClassification.java 其中MapReduce关键代码如下:

    publicclass DocClassification extends Configured implements Tool {

        // 所有分类集合

        privatestatic List<String> classList = new ArrayList<String>();

        // 所有分类的先验概率(其中的概率取对数log

        privatestatic HashMap<String, Double> classProMap = new HashMap<String, Double>();

        // 所有单词在各个分类中的出现的频次

        privatestatic HashMap<String, Integer> classWordNumMap = new HashMap<String, Integer>();

        // 分类下的所有单词出现的总频次

        privatestatic HashMap<String, Integer> classWordSumMap = new HashMap<String, Integer>();

        privatestatic Configuration conf = new Configuration();

        static {

           // 初始化分类先验概率词典

           initClassProMap("hdfs://192.168.226.129:9000/user/hadoop/doc");

           // 初始化单词在各个分类中的条件概率词典

           initClassWordProMap("hdfs://192.168.226.129:9000/user/hadoop/word");

        }

       

        publicstaticclass Map extends Mapper<Text, BytesWritable, Text, Text> {

           @Override

           publicvoid map(Text key, BytesWritable value, Context context) {

               String fileName = key.toString();

               value.setCapacity(value.getSize()); // 剔除多余空间

               String content = new String(value.getBytes(), 0, value.getLength());

               try {

                  for (String className : classList) {

                      doubleresult = Math.log(classProMap.get(className));

                      StringTokenizer itr = new StringTokenizer(content);

                      while (itr.hasMoreTokens()) {

                         String word = itr.nextToken();

                         if (StringUtil.isValidWord(word)) {

                             intwordSum = 1;

                             if(classWordNumMap.get(className + "/" + word) != null){

                                wordSum = classWordNumMap.get(className + "/" + word);

                             }

                             intclassWordSum = classWordSumMap.get(className);

                             doublepro_class_word = Math.log(((double)wordSum)/classWordSum);

                             result += pro_class_word;

                         }

                      }

                      // 输出的形式 key:文件名 value:分类名/概率

                      context.write(new Text(fileName), new Text(className + "/" + String.valueOf(result)));

                  }

               } catch (IOException e) {

                  e.printStackTrace();

               } catch (InterruptedException e) {

                  e.printStackTrace();

               }

           }

        }

     

        publicstaticclass Reduce extends Reducer<Text, Text, Text, Text> {

     

           publicvoid reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {

               String fileName = key.toString().split("/")[1];

        doublemaxPro = Math.log(Double.MIN_VALUE);

               String maxClassName = "unknown";

               for (Text value : values) {

                  String[] arr = value.toString().split("/");

                  String className = arr[0];

                  doublepro = Double.valueOf(arr[1]);

                  if (pro > maxPro) {

                      maxPro = pro;

                      maxClassName = className;

                  }

               }

               System.out.println("fileName:" + fileName + ",belong class:" + maxClassName);

               // 输出 key:文件名 value:所属分类名以及概率

               context.write(new Text(fileName), new Text(maxClassName + ",pro=" + maxPro));

           }

        }

    }

    四、数据集说明

    训练集:CHINA  文档数255

    INDIA   文档数326

    TAIWAN  文档数43.

    测试集:CHINA   文档个数15

    INDIA    文档个数20

    TAIWAN  文档个数15

    1. 程序运行说明

    5.1训练数据集打包程序

    Map任务个数624(所有小文件的个数)   Reduce任务个数1

    截图如下

     

    5.2训练文档统计程序

    Map任务个数1(输入为1SequencedFile   Reduce任务个数1

    5.3训练单词统计程序

    Map任务个数1(输入为1SequencedFile)   Reduce任务个数1

    5.4测试数据集打包程序

    Map任务个数50(测试数据集小文件个数为50)   Reduce任务个数1

    5.5测试文档归类程序

    Map任务个数1(输入为1SequencedFile   Reduce任务个数1

     

    1. 实验结果分析

    测试集文档归类结果截图如下:

     针对CHINA TAIWAN INDIA三个分类下的测试文档进行测试结果如下表所示:

    类别(国家)

    正确率

    召回率

    F1

    CHINA

    18.4%

    46.667%

    26.38%

    INDIA

    42.1%

    80%

    55.67%

    TAIWAN

    39.47%

    100%

    56.60%

    展开全文
  • 结合文本分类的传统模型-词袋模型,进行简单分类,效果还不错。比如,输入:‘这个孩子不好,昨天生气打人了, 糟糕’,分类结果为: neg,0.6577 '这个孩子虽然 打人 ,但非常优秀' ,分类结果为:pos,0.7067第一步,...

    3b245b5170e50158f5b331da52221525.png

    朴素贝叶斯模型因为其简单实用,在分类中有广泛的应用。结合文本分类的传统模型-词袋模型,进行简单分类,效果还不错。

    比如,输入:

    ‘这个孩子不好,昨天生气打人了, 糟糕’,分类结果为: neg,0.6577

    '这个孩子虽然 打人 ,但非常优秀' ,分类结果为:pos,0.7067

    第一步,首先建立词袋对象

    9497ea5169705fab4c36792ade111b77.png

    Sublime Text显示非常漂亮。

    我们看,词袋对象word_tags一共三个成员:

    bags :词袋,用词典,key:word项,value:word在类别中出现的次数

    counts: word的总数量

    unk : 表示未见过的词语

    然后,定义了相关成员,关键函数包括:

    update_bags(self,key,value):模型训练过程中,更新词袋的对象和计数

    get_word_frequency(self,key): 获取词项对应的词频

    然后,定义Bayes模型对象:

    05adccf565349f080c735b6be15db9ca.png

    包括训练和预测两个函数。

    之后,来定义情感分类对象:

    e05543b4456048eea0677782be12f797.png

    Sentiment_analysis通过预处理数据以后,调用Bayes_model进行训练和预测。

    最后,进行训练和分类:

    f11c351a00e4e8cbf6053e8a7e448a1d.png

    效果还不错:

    ('neg', 0.657748544497328)

    ('pos', 0.7067436447326716)

    以上只是简单验证,完整的处理还应包括文本的预处理,词频统计算法的修改,统计和可视化,但这些不是本文重点,略过。

    如果需要完整代码请留言。

    展开全文
  • 朴素贝叶斯分类最适合的场景就是文本分类、情感分析和垃圾邮件识别。其中情感分析和垃圾邮件识别都是通过文本来进行判断。所以朴素贝叶斯也常用于自然语言处理 NLP 的工具。sklearn 机器学习包sklearn 的全称叫 ...

    朴素贝叶斯分类最适合的场景就是文本分类、情感分析和垃圾邮件识别。其中情感分析和垃圾邮件识别都是通过文本来进行判断。所以朴素贝叶斯也常用于自然语言处理 NLP 的工具。

    sklearn 机器学习包

    sklearn 的全称叫 Scikit-learn,它给我们提供了 3 个朴素贝叶斯分类算法,分别是高斯朴素贝叶斯(GaussianNB)、多项式朴素贝叶斯MultinomialNB)和伯努利朴素贝叶斯(BernoulliNB)。

    这三种算法适合应用在不同的场景下,我们应该根据特征变量的不同选择不同的算法:

    高斯朴素贝叶斯:特征变量是连续变量,符合高斯分布,比如说人的身高,物体的长度。

    多项式朴素贝叶斯:特征变量是离散变量,符合多项分布,在文档分类中特征变量体现在一个单词出现的次数,或者是单词的 TF-IDF 值等。

    伯努利朴素贝叶斯:**特征变量是布尔变量,符合 0/1 分布**,在文档分类中特征是单词是否出现。

    伯努利朴素贝叶斯是以文件为粒度,如果该单词在某文件中出现了即为 1,否则为 0。而多项式朴素贝叶斯是以单词为粒度,会计算在某个文件中的具体次数。

    > 如身高、体重这种自然界的现象就比较适合用高斯朴素贝叶斯来处理。而文本分类是使用多项式朴素贝叶斯或者伯努利朴素贝叶斯。

    什么是 TF-IDF 值呢?

    TF-IDF 是一个统计方法,用来评估某个词语对于一个文件集或文档库中的其中一份文件的重要程度。

    词频 TF计算了一个单词在文档中出现的次数,它认为一个单词的重要性和它在文档中出现的次数呈正比。

    逆向文档频率 IDF,是指一个单词在文档中的区分度。它认为一个单词出现在的文档数越少,就越能通过这个单词把该文档和其他文档区分开。IDF 越大就代表该单词的区分度越大。

    所以 TF-IDF 实际上是词频 TF 和逆向文档频率 IDF 的乘积。这样我们倾向于找到 TF 和 IDF 取值都高的单词作为区分,即这个单词在一个文档中出现的次数多,同时又很少出现在其他文档中。这样的单词适合用于分类。

    TF-IDF 如何计算

    78c51a44dd27973a566cef782f7a7656.png
    929da53f9cdc33244af754979e18e3b6.png

    些单词可能不会存在文档中,为了避免分母为 0,统一给单词出现的文档数都加 1。

    举个例子假设一个文件夹里一共有 10 篇文档,其中一篇文档有 1000 个单词,“this”这个单词出现 20 次,“bayes”出现了 5 次。“this”在所有文档中均出现过,而“bayes”只在 2 篇文档中出现过。

    针对“this”,计算 TF-IDF 值:

    800ac62a0607599a16d9e80fd00ca475.png

    所以 TF-IDF=0.02*(-0.0414)=-8.28e-4。

    针对“bayes”,计算 TF-IDF 值:

    10d41c741adee26605e1472bca9ee431.png

    TF-IDF=0.005*0.5229=2.61e-3。

    很明显“bayes”的 TF-IDF 值要大于“this”的 TF-IDF 值。这就说明用“bayes”这个单词做区分比单词“this”要好。

    如何求 TF-IDF

    在 sklearn 中我们直接使用 TfidfVectorizer 类,它可以帮我们计算单词 TF-IDF 向量的值。

    在这个类中,取 sklearn 计算的对数 log 时,底数是 e,不是 10。

    创建 TfidfVectorizer 的方法是:

    TfidfVectorizer(stop_words=stop_words, token_pattern=token_pattern)

    dcd1bd128ffdc8cd2ac8553c0456807e.png

    604587aa5b9695c9456d984baba13f4a.png

    当我们创建好 TF-IDF 向量类型时,可以用 fit_transform 帮我们计算,返回给我们文本矩阵,该矩阵表示了每个单词在每个文档中的 TF-IDF 值。

    5f670ea8fde13e6e23f29604ad4109c0.png

    在我们进行 fit_transform 拟合模型后,我们可以得到更多的 TF-IDF 向量属性,比如,我们可以得到词汇的对应关系(字典类型)和向量的 IDF 值,当然也可以获取设置的停用词 stop_words。

    03f975f634b77e8a2fbc51ac193f6fff.png
    ab0396c3e7664311fba9cabcd6511061.png

    现在想要计算文档里都有哪些单词,这些单词在不同文档中的 TF-IDF 值是多少呢?

    首先我们创建 TfidfVectorizer 类:

    from sklearn.feature_extraction.text import TfidfVectorizertfidf_vec = TfidfVectorizer()documents = [    'this is the bayes document',    'this is the second second document',    'and the third one',    'is this the document']tfidf_matrix = tfidf_vec.fit_transform(documents)print('不重复的词:', tfidf_vec.get_feature_names())print('每个单词的 ID:', tfidf_vec.vocabulary_)#输出每个单词在每个文档中的 TF-IDF 值,向量里的顺序是按照词语的 id 顺序来的:print('每个单词的 tfidf 值:', tfidf_matrix.toarray())输出不重复的词: ['and', 'bayes', 'document', 'is', 'one', 'second', 'the', 'third', 'this']每个单词的 ID: {'this': 8, 'is': 3, 'the': 6, 'bayes': 1, 'document': 2, 'second': 5, 'and': 0, 'third': 7, 'one': 4}每个单词的 tfidf 值: [[0.         0.63314609 0.40412895 0.40412895 0.         0.  0.33040189 0.         0.40412895] [0.         0.         0.27230147 0.27230147 0.         0.85322574  0.22262429 0.         0.27230147] [0.55280532 0.         0.         0.         0.55280532 0.  0.28847675 0.55280532 0.        ] [0.         0.         0.52210862 0.52210862 0.         0.  0.42685801 0.         0.52210862]]

    如何对文档进行分类

    103c625cea6cb81b22a6ec4940fe060f.png

    1. 基于分词的数据准备,包括分词、单词权重计算、去掉停用词;

    2. 应用朴素贝叶斯分类进行分类,首先通过训练集得到朴素贝叶斯分类器,然后将分类器应用于测试集,并与实际结果做对比,最终得到测试集的分类准确率。

    一般来说 NTLK 包适用于英文文档,而 jieba 适用于中文文档。我们可以根据文档选择不同的包,对文档提取分词。这些分词就是贝叶斯分类中最重要的特征属性。基于这些分词,我们得到分词的权重,即特征矩阵。

    在这个链接下下载数据集:github.com/cystanford/t

    95010b9b86fc2685acb05cdd2b5b9a70.png

    train_contents=[]train_labels=[]test_contents=[]test_labels=[]#  导入文件import osimport iostart=os.listdir(r'C:/Users/baihua/Desktop/text classification/train')for item in start:    test_path='C:/Users/baihua/Desktop/text classification/test/'+item+'/'    train_path='C:/Users/baihua/Desktop/text classification/train/'+item+'/'    for file in os.listdir(test_path):        with open(test_path+file,encoding="GBK") as f:            test_contents.append(f.readline())            #print(test_contents)            test_labels.append(item)    for file in os.listdir(train_path):        with open(train_path+file,encoding='gb18030', errors='ignore') as f:            train_contents.append(f.readline())            train_labels.append(item)print(len(train_contents),len(test_contents))# 导入stop wordimport jiebafrom sklearn import metricsfrom sklearn.naive_bayes import MultinomialNB#stop_words = [line.strip() for line in io.open(r'C:/Users/baihua/Desktop/stopword.txt').readlines()]with open(r'C:/Users/baihua/Desktop/stopword.txt', 'rb') as f:    stop_words = [line.strip() for line in f.readlines()]# 分词方式使用jieba,计算单词的权重tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5)##注意数据结构:stop_words是list,过滤词token_parten是正则表达式train_features = tf.fit_transform(train_contents)#该函数返回文本矩阵,表示每个单词在每个文档中的TF-IDF值print(train_features.shape)#模块 4:生成朴素贝叶斯分类器# 多项式贝叶斯分类器clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels)#模块 5:使用生成的分类器做预测test_tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5, vocabulary=tf.vocabulary_)test_features=test_tf.fit_transform(test_contents)predicted_labels=clf.predict(test_features)#模块六,计算准确性from sklearn import metricsprint (metrics.accuracy_score(test_labels, predicted_labels))#print(test_features.shape)#print(metrics.accuracy_score(test_labels, predicted_labels))
    3a8856f9e9f05105a809c57ae3ae484d.png
    End.作者:求知鸟来源:知乎
    展开全文
  • 使用sklearn自带的贝叶斯分类器进行文本分类和参数调优数据挖掘入门与实战公众号:datadwPart1:本篇内容简介在前一篇文章完整手写一个朴素贝叶斯分类器,完成文本分类,我们使用首先假设在文档中出现的单词彼此独立...
  • 在特征独立性假设的基础上, 讨论了朴素贝叶斯分类器的原理, 以及训练朴素贝叶斯分类器和应用朴素贝叶斯分类器进行分类的问题。
  • 15 朴素贝叶斯分类器

    2020-05-20 23:40:36
    文章目录15.5 用朴素贝叶斯二分类 15.5 用朴素贝叶斯二分类 用朴素贝叶斯分类器进行简单的英文文本分类。 数据集依然用经典的二分类数据集   准备数据集  
  • 我们已经讲解过朴素贝叶斯分类器的基本原理和实现:动手实现朴素贝叶斯分类器进行文档分类 在此基础上,我们实现垃圾邮件的过滤,数据为50封txt邮件 (1)将text文本文件,分成单词列表 使用正则表达式,使用除...
  • 基于朴素贝叶斯的文本分类方法一、朴素贝叶斯原理的介绍二、朴素贝叶斯分类器的代码实现分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同时会给出这个猜测的概率估计值。朴素贝叶斯分类...
  • 读取20类新闻文本的数据细节# 从sklearn.datasets里导入新闻数据抓取fetch_20newsgroup from sklearn.datasets import fetch_20newsgroups # 与之前预存的数据不同,fetch_20newsgroup需要即时从互联网下载数据 ...
  • 朴素贝叶斯进行文档分类 文本分类代码 文档词袋模型 实例:朴素贝叶斯过滤垃圾邮件 朴素贝叶斯理论概述 朴素贝叶斯(navie bayes)是贝叶斯决策理论的一部分,只考虑最简单的假设,用 Python 将文本切分为词向量,...
  • 朴素贝叶斯分类器 贝叶斯公式 贝叶斯决策论的理解 极大似然估计 朴素贝叶斯分类器 TextRNN TextCNN TextRCNN FastText HAN Highway Networks 简介 通常,进行文本分类的主要...
  • 基本数学假设:各个维度上的特征被分类的条件概率之间是...# 从sklearn.datasets里导入新闻数据抓取fetch_20newsgroups。 from sklearn.datasets import fetch_20newsgroups # 从sklearn.model_selection中导入...
  • 最后,通过实例讨论贝叶斯分类中最简单的一种:朴素贝叶斯分类。 分类问题综述 对于分类问题,其实谁都不会陌生,说我们每个人每天都在执行分类操作一点都不夸张,只是我们没有意识到罢了。例
  • 01 先用已知样本训练贝叶斯分类器。 假定现在只有c0c_0c0​和c1c_1c1​两类text,且每类text都包含f0f_0f0​…fnf_nfn​种特征,则很容易统计出每个类对应的各个特征的概率,即p(fi∣c0)p(f_i|c_0)p(fi​∣
  • 朴素贝叶斯分类器是一个非常简单,但是非常实用的分类模型。贝叶斯分类算法是统计学的一种分类方法,它是一类利用概率统计知识进行分类的算法。由于贝叶斯定理假设一个属性值(特征)对给定类的影响独立于其它属性的...
  • 朴素贝叶斯(二)文本分类朴素贝叶斯的一般流程用python进行文本分类准备数据:从文本中构建词向量训练算法:从词向量计算概率测试算法:朴素贝叶斯分类函数文档词袋模型 朴素贝叶斯的一般流程 (1)收集数据:任何...
  • 对英文文件进行过滤 训练测试集下载地址github 步骤 1、有标签的文件文本数据导入 2、分词、去除网络符号(网址除外)、统一小写 3、利用Lemmatizer词还原将单词变为原型 4、标注”not_” 或 “no_”...
  • 朴素贝叶斯算法进行文本分类

    千次阅读 2018-12-21 13:01:37
    在机器学习中,朴素贝叶斯分类器是一系列以假设特征之间强(朴素)独立下运用贝叶斯定理为基础的简单概率分类照片器。朴素贝叶斯算法其实就是根据数学中的贝叶斯公式来进行计算概率,在通过概率来进行分类。使用这个...
  • 机器学习 --- 朴素贝叶斯分类器 python

    千次阅读 多人点赞 2020-10-22 21:07:42
    本实训项目的主要内容是基于 Python 语言搭建朴素贝叶斯分类器,并使用sklearn 实现新闻文本进行主题分类的功能。 朴素贝叶斯分类算法流程 import numpy as np class NaiveBayesClassifier(ob
  • 转自:NLP系列(2)_用朴素贝叶斯进行文本分类(上) 转自:朴素贝叶斯分类器的应用 转自:算法杂货铺——分类算法之朴素贝叶斯分类(Naive Bayesian classification) 转自:机器学习实战笔记(Python实现) ...
  • 朴素贝叶斯分类器模型(Naive Bayles)Model basic introduction:朴素贝叶斯分类器是通过数学家贝叶斯的贝叶斯理论构造的,下面先简单介绍贝叶斯的几个公式:先验概率: P(X) or P(Y)条件概率: P(X|Y)=P(XY)\P(Y) =>...
  • 本文是个人学习笔记,内容主要涉及MultinomialNB(Naive Bayes)对sklearn内置的fetch_20newsgroups——新闻数据抓取从互联网上即时下载的新闻文本数据进行多类分类朴素贝叶斯模型被广泛应用于互联网新闻的分类、...
  • 朴素贝叶斯分类贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验概率计算出其后验概率(即该对象属于某一类的概率),然后...
  • 点击上方关注,All in AI中国探索没有TensorFlow API的纯Kotlin语言中的贝叶斯文本分类文本分类是自然语言处理中的一项重要任务,具有广泛的应用前景。我们将学习如何以非深度学习的方式使用该技术,而无需使用...
  • 基于朴素贝叶斯的文本分类方法一、朴素贝叶斯原理的介绍二、朴素贝叶斯分类器的代码实现分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同时会给出这个猜测的概率估计值。朴素贝叶斯分类...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 206
精华内容 82
关键字:

朴素贝叶斯分类器进行文本分类