文本分析

作者: 炼己者 | 来源:发表于2020-01-04 15:53 被阅读0次

    本博客所有内容以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢!

    1.1案例概述

    1.1.1案例简介

    现在是大数据时代,网络上存在着很多很多的文本数据,你可以通过爬虫去爬取它们。拿到数据之后怎么才能展现出它的价值呢,这就要用到自然语言处理了,我们可以对文本进行分析。网上关于自然语言处理大部分都是英文的,这里我们就以中文为例,对文本进行分析,你将会学到如何处理文本,包括分词、去除停用词、做一份词云、关键词提取、LDA主题模型、TFIDF向量以及文本分类。这些都是自然语言处理中很常用的手段,掌握了这些你就算是入门了。

    1.1.2功能概述

    本案例主要是讲解如何对一份文本进行分析,一共实现了四个功能
    1.构建词云。通过词云我们可以一眼看出这份份文本都有哪些主题关键词
    2.关键词提取。通过这个操作我们可以知道一段文本最重要的前几个词
    3.LDA主题模型。通过这个操作可以自动地得出我们文本的主题都有哪些
    4.文本分类。根据训练数据进行模型训练,得出一个分类器,这个分类器可以自动把我们的文本进行分类

    1.1.3数据描述

    这是一份关于新闻文本的数据,里面有十种类别,分别是汽车、财经、科技、健康、体育、教育、文化、军事、娱乐、时尚。具体形式见下面的代码可视化展示。下图就是我们的数据,这里只展示了前五行,然后我们观察数据,数据里面包含了新闻的类别(category),新闻的主题(theme),新闻的网址(URL),新闻的内容(content)。我们的任务就是构造一个新闻的分类器,比如来一段文本,然后我们构造的分类器可以自动地把它归类,看它是汽车类的还是娱乐类的等等。怎么展示出数据呢?通过下面的代码你便可以知道。


    1.2 实现分析

    实验的操作流程如下图所示


    流程概述:
    1)数据获取:从网上下载的数据集
    2)数据分析:这是一份关于新闻文本的数据,里面有十种类别,分别是汽车、财经、科技、健康、体育、教育、文化、军事、娱乐、时尚。
    3)数据预处理,方法:jieba分词、去除停用词、将它们转变为文本向量
    4)预处理过程也可做一些有趣的事情,让我们更好地去了解文本。比如我们可以做词云、关键词提取、主题模型等操作,这些操作都会在下面讲到。
    5)模型构建:其实就是做出一个文本分类器。将文本转化为向量后,我们可以把这些向量输入到机器学习算法里面,比如贝叶斯算法、SVM算法。这些算法就被称为分类器,我们主要就是通过这些数据集来训练它们,然后构造出一个可以自动分类新闻的分类器
    6)模型验证:训练好模型,我们得测试一下这个模型效果的好坏。所以测试数据集也要经过相同的预处理,然后将它输入到分类器中,便可以得到分类结果

    1.3 功能实现

    1.3.1操作环境

    1). anaconda包,这个包非常的好用,基本包含了你做机器学习所需要的各种包
    2). jieba,这个主要是用来进行分词操作。安装非常容易,终端输入pip install jieba即可
    以上的库安装好了以后,你可以在终端输入jupyter notebook,然后你就会来到一个编译环境,这个环境非常的简单易用,最关键的是你运行的代码可以马上看到结果,这样对于我们理清思路非常有帮助,这是anaconda自带的。

    1.3.2项目简介

    1)首先导入需要用到的数据包

    import pandas as pd
    import jieba
    

    2)然后来看一下数据长什么样,运行以下代码

    df_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
    df_news = df_news.dropna()
    df_news.head()
    

    代码解释:
    pd.read_table是把数据读取进来
    df_news.dropna()是把数据里的缺失值去掉
    df_news.head()是读取数据的前五行

    运行结果:

    1.3.3.操作流程

    1)分词:用jieba分词器

    首先要取出我们的数据内容,然后对它进行jieba分词。

    content = df_news.content.values.tolist()
    print (content[500])
    

    代码解释:
    df_news.content.values.tolist()意思是取出数据里,content这一列的数据。然后把它变成一个列表
    content[500]意思是取出第500个文本数据,看看它长什么样子

    运行结果:

    本报讯 (记者周宇)针对民间投资“新三十六条”落地而出台的42项民间投资实施细则已经全部出齐。国家发改委昨日表示,实施细则与社会上迫切要求改善民营企业经营发展环境的热切期望还存在一定差距,需要通过实践不断完善政策体系。接下来要在铁路、市政、能源、电信、卫生、教育等领域抓紧做几件看得见、鼓舞人心的实事,提振民间投资的发展信心。9家发改委表示,42项实施细则首先解决了实施细则的有无问题。从其本身来看,在制定过程中有关部门是力求有所突破的。例如《关于鼓励和引导民间资本进入银行业的实施意见》,将村镇银行主发起行的最低持股比例由20%降低到15%。

    我们发现这些字都是连在一起的,而我们要做的是对它进行分词,把句子变成一个词一个词的。

    content_S = []
    for line in content:
        current_segment = jieba.lcut(line)
        if len(current_segment) > 1 and current_segment != '\r\n': #换行符
            content_S.append(current_segment)
    

    代码解释:
    这段代码主要是取出所有的新闻内容,然后对它们进行jieba分词
    content_S = [] 指定一个空列表,一会儿用来装所有分好词的结果
    content是我们上面构造的一个列表,做一个循环,取出列表里的每句话,分别进行分词操作。
    current_segment = jieba.lcut(line) 意思就是对每句话进行jieba分词
    if len(current_segment) > 1 and current_segment != '\r\n' :
    content_S.append(current_segment)
    意思是给出一个判断条件,如果这句话分词的结果长度大于1,并且它不是一个换行符,那么我们就把它添加到content_S列表中去。
    那么content_S就是我们分好词的结果
    我们来看一下分词的结果,还是看第500句话长什么样

    content_S[500]
    

    运行结果

    ['本报讯',
     '\u3000',
     '(',
     '记者',
     '周宇',
     ')',
     '针对',
     '民间',
     '投资',
     '“',
     '新',
     '三十六条',
     '”',
     '落地',
    ...]
    

    分完词之后我们把这些结果组合成一个DataFrame格式,方便我们操作

    df_content=pd.DataFrame({'content_S':content_S})
    df_content.head()
    

    代码解释:
    df_content=pd.DataFrame({'content_S':content_S})意思就是把我们刚才得到的列表变成DataFrame格式
    df_content.head()看一下我们数据的前五行

    运行结果

    2)去除停用词

    我们观察上面分完词的数据,会发现里面的内容太乱了,有很多没有意义的词。所以我们要对它们进行清洗,这里就要用到停用词表了。停用词表,顾名思义就是收录了很多没有意义的词,比如的,啊,呃等等词,还有一些标点符号,特殊符号。

    首先读取停用词表

    stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')
    stopwords.head()
    

    运行结果


    我们就可以看到停用词表的前五行是什么

    有了停用词表,我们就要开始去除停用词了。思路很简单,对我们分好词的结果进行一个遍历,如果我们的词出现在了停用词表里,就删掉它。不过这样操作会有点麻烦,我们换个思路,如果词没有出现在停用词表,我们把它取出来,那么最终不就得到我们需要的词了么,这不就变向的把我们数据里所有的停用词删掉了么。

    def drop_stopwords(contents,stopwords):
        contents_clean = []
        all_words = []
        for line in contents:
            line_clean = []
            for word in line:
                if word in stopwords:
                    continue
                line_clean.append(word)
                all_words.append(str(word))
            contents_clean.append(line_clean)
        return contents_clean,all_words
    

    代码解释:
    上面的代码就是按着那个思路来操作的。定义了一个函数,这个函数就是专门用来去除停用词的,它传入了两个参数,contents是我们前面分完词的列表,stopwords就是停用词列表。
    contents_clean这个列表就是用来装非停用词的(意思就是只要这个词没出现在停用词表中,我们就把它放在contents_clean这个列表里)。
    all_words这个列表里装着所有的词,也包括出现在停用表里的词。这里是为后面做词云这个功能做准备的,后面详细再说
    line_clean是用来装去除停用词后,分完词的每句话

    contents = df_content.content_S.values.tolist()    
    stopwords = stopwords.stopword.values.tolist()
    contents_clean,all_words = drop_stopwords(contents,stopwords)
    

    代码解析:
    contents就是分好词的列表,它是一个list of list格式
    stopwords就是停用词列表,它是一个list格式
    contents_clean是去除停用词后的结果,它是一个list of list格式
    all_words是所有的词(不包括停用词),它是一个list格式

    这样说可能有点儿迷糊,我们来看一下数据长什么样子
    contents是一个list of list格式
    [['呼叫', '热线', '\u3000',], [ '品牌', '在', '二月', '曾经', '公布', '了', '最新', '的'],[...],...]
    stopwords是一个列表
    ['@', 'A', 'Lex', '[', '\', ']', '【', '】', '^', '_']
    我们来看一下经过去除停用词后的数据长什么样子。contents_clean就是经过去除停用词后的数据,我们把它变成DataFrame格式,依旧看前五行

    df_content=pd.DataFrame({'contents_clean':contents_clean})
    df_content.head()
    

    运行结果

    和前面没去除停用词的数据进行对比,我们发现少了很多没有意义的词,保留下来的都是一些主要的词汇。

    3)词云

    接下来我们可以看一下词云是如何形成的。

    df_all_words=pd.DataFrame({'all_words':all_words})
    words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":numpy.size})
    words_count=words_count.reset_index().sort_values(by=["count"],ascending=False)
    words_count.head()
    

    代码解释:
    df_all_words=pd.DataFrame({'all_words':all_words})把all_words变成DataFrame格式。然后接下来就是groupby操作,统计词频。reset_index操作就是按照词频进行一个排序。我们来看一下前5行数据长什么样子

    all_words这一列就是我们的词语,count这一列就是词频.
    词频可以帮助我们画词云

    from wordcloud import WordCloud
    import matplotlib.pyplot as plt
    %matplotlib inline
    import matplotlib
    matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
    
    wordcloud=WordCloud(font_path="./data/simhei.ttf",background_color="white",max_font_size=80)
    word_frequence = {x[0]:x[1] for x in words_count.head(100).values}
    wordcloud=wordcloud.fit_words(word_frequence)
    plt.imshow(wordcloud)
    

    代码解释:
    词云主要是通过wordcloud这个库实现的,这个库需要安装,非常简单。pip install wordcloud即可。
    matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)设置一下画的这个词云图的大小
    WordCloud(font_path="./data/simhei.ttf",background_color="white",max_font_size=80)里面的参数主要是设置字体,背景颜色,以及最大的字是多大。这些都可以调
    word_frequence = {x[0]:x[1] for x in words_count.head(100).values}这个是看你想取前多少个词来做这个词云。这里是取的前100个词来画词云。

    运行结果


    词云这种可视化展示很有趣,我们可以把新闻的每个类别都做一个词云,这样就可以很明显地看到每个类别都有哪些常用的词

    4)关键词提取

    我们先看代码以及运行结果

    import jieba.analyse
    index = 1000
    print (df_news['content'][index])
    content_S_str = "".join(content_S[index])  
    print ("  ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))
    

    运行结果

    阿里巴巴集团昨日宣布,将在集团管理层面设立首席数据官岗位(Chief Data Officer),阿里巴巴B2B公司CEO陆兆禧将会出任上述职务,向集团CEO马云直接汇报。>菹ぃ和6月初的首席风险官职务任命相同,首席数据官亦为阿里巴巴集团在完成与雅虎股权谈判,推进“one company”目标后,在集团决策层面新增的管理岗位。0⒗锛团昨日表示,“变成一家真正意义上的数据公司”已是战略共识。记者刘夏
    阿里巴巴 集团 首席 岗位 数据

    通过这段代码可以提取出一段文本的前五个关键字。这就是关键字提取

    代码解释:
    index是指索引,你可以随意地选择你要看的段落,这里选择第1000个段落。这里主要是调用jieba这个包来进行关键词提取。代码的最后一行topK参数,我们可以通过控制它的大小,从而选择前几个关键词
    基本操作思路:通过索引取出文本内容以及分好词的文本,然后调用jieba库来提取关键词

    5)LDA主题模型

    假设我们有一堆新闻文本,但是我们也不知道有多少类别,多少主题。那么我们可以假设它有20个主题,然后通过LDA让它自己玩儿,产生20个主题,有点儿无监督学习的感觉,并且给出每个主题的前几个关键词以及这些关键词所起到的重要程度。这个和kmeans很像,我们也不知道要指定多少个主题
    这里需要用到gensim这个库,这个库很强大,很多自然语言处理项目都会用到它,具体操作官网都给出了很详尽的教程。可以看这里,http://radimrehurek.com/gensim/

    看代码和运行结果

    from gensim import corpora, models, similarities
    import gensim
    #做映射,相当于词袋
    dictionary = corpora.Dictionary(contents_clean)
    corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean]
    

    用一个工具我们要先看输入数据的格式,那么contents_clean是什么样的格式呢?它是一个list of list格式,我们来看一下它长什么样子,前面有,这里大概看一眼
    [['经销商', '电话','试驾','订车','U'],[....],...]
    内层的list是分好词的每段话,外层的list是把所有的段落都统一进来

    代码解释:
    dictionary = corpora.Dictionary(contents_clean)就是把我们的词都映射成一个词典,都有一个唯一的身份标识(id号),就好像每个人都有自己唯一的身份证一样。做出一个词袋模型。简单的理解就是比如:我今天踢足球。那么我对应0,今天对应1,踢足球对应2。
    corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean]
    这个操作是对我们每段话都做这样一个词袋模型的操作,构造出一份语料。我们来看一下corpus长什么样,它是一个list of list 的格式
    [[(0, 1), (1, 1),(2, 3),(3, 2), (4, 1), (5, 1),(6, 1),(7, 28)],[(89, 1),(190, 6),(191, 3),
    (193, 5),(194, 1),(196, 1),(203, 2),(209, 2),(210, 2)],[...],...]
    左边是词的id号,右边是词频
    接下来构建LDA模型

    lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) 
    print (lda.print_topic(1, topn=5))
    

    代码解释:
    这里面主要传入三个参数,corpus(语料),id2word(词的id),num_topics(主题数)
    lda.print_topic(1, topn=5)意思是打印第一类主题对应的前5个有代表性的词,并按照从高到低权重进行一个排序
    因为我所采用的语料库比较小,所以看起来效果不是很明显。如果语料库很大,那么这个就会很明显了

    运行结果

    0.007"中" + 0.006"说" + 0.004"观众" + 0.002"赛区" + 0.002*"岁"

    我们来打印一下20个主题分别对应的前5个具有代表性的词,看看效果怎么样

    for topic in lda.print_topics(num_topics=20, num_words=5):
        print (topic[1])
    

    运行结果

    0.007"女人" + 0.006"男人" + 0.006"M" + 0.004"S" + 0.004"说"
    0.004
    "中" + 0.004"训练" + 0.003"说" + 0.003"学校" + 0.002"研究生"
    0.006"戏" + 0.006"导演" + 0.005"该剧" + 0.004"中" + 0.004"演员"
    0.007
    "中" + 0.006"说" + 0.004"观众" + 0.002"赛区" + 0.002"岁"
    0.004"万" + 0.003"号" + 0.003"中" + 0.002"S" + 0.002"R"
    0.014
    "电影" + 0.009"导演" + 0.007"影片" + 0.006"中国" + 0.005"中"
    0.006"中" + 0.005"比赛" + 0.004"说" + 0.003"撒" + 0.002"时间"
    0.006
    "赛季" + 0.005"中" + 0.003"联赛" + 0.003"中国" + 0.002"航母"
    0.005"李小璐" + 0.004"中" + 0.002"贾乃亮" + 0.002"W" + 0.002"皮肤"
    0.004
    "万" + 0.003"号" + 0.003"V" + 0.003"T" + 0.003"刘涛"
    0.021"男人" + 0.008"女人" + 0.007"考生" + 0.004"说" + 0.003"中"
    0.005
    "中" + 0.005"食物" + 0.004"i" + 0.004"a" + 0.004"吃"
    0.006"中" + 0.004"电影" + 0.004"说" + 0.002"中国" + 0.002"高考"
    0.007
    "中" + 0.006"孩子" + 0.004"说" + 0.003"教育" + 0.003"中国"
    0.005"中" + 0.005"节目" + 0.004"说" + 0.004"表演" + 0.003"岁"
    0.007
    "电视剧" + 0.004"中" + 0.003"说" + 0.003"飞行" + 0.002"飞机"
    0.007"中" + 0.006"球队" + 0.005"选手" + 0.004"观众" + 0.004"i"
    0.005
    "中" + 0.005"天籁" + 0.004"产品" + 0.004"肌肤" + 0.003"职场"
    0.008"中国" + 0.008"饰演" + 0.007"中" + 0.004"说" + 0.004"节目"
    0.021
    "e" + 0.021"a" + 0.016"o" + 0.013"i" + 0.013"n"

    这便是对我们上面的数据进行了一个LDA主题建模,我们可以得到20个主题。

    6)文本分类

    首先来看一下我们之前预处理的数据,取出后5行进行观察

    df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
    df_train.tail()
    

    然后我们看一下这些文本一共有多少类别

    df_train.label.unique()
    

    代码解释:
    这个是取出这一列所有不重复的值

    运行结果

    array(['汽车', '财经', '科技', '健康', '体育', '教育', '文化', '军事', '娱乐', '时尚'], dtype=object)

    我们发现一共有十种类别,也就是要做一个十分类。那么我们需要构造一个分类器,让它自己进行分类判断,这就要用到机器学习算法了。
    机器学习我的理解就是把各种原始的东西变成机器可以理解的东西,然后再用各种机器学习算法来做操作。机器可以理解的东西是什么呢?——数字 。所以不管是图片还是文字,要用机器学习算法对它们进行处理,就要把它们转为数字。

    文本向量

    我们要把类别映射成数字

    label_mapping = {"汽车": 1, "财经": 2, "科技": 3, "健康": 4, "体育":5, "教育": 6,"文化": 7,"军事": 8,"娱乐": 9,"时尚": 0}
    df_train['label'] = df_train['label'].map(label_mapping)
    df_train.head()
    

    代码运行结果

    我们发现label这一列都被映射成数字了,一会儿也要把文本内容转为数字,也就是contents_clean这一列。

    接下来对数据进行划分,划分为训练集和测试集,调用sklearn库的操作即可

    from sklearn.model_selection import train_test_split
    x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)
    

    这里是按照默认值来操作,也就是训练集占数据量的70%,测试集占数据量的30%

    接下来我们要把文本内容转为向量,这里为方便理解,先举个小例子

    from sklearn.feature_extraction.text import CountVectorizer
    texts=["dog cat fish","dog cat cat","fish bird", 'bird']
    cv = CountVectorizer()
    cv_fit=cv.fit_transform(texts)
    
    print(cv.get_feature_names())
    print(cv_fit.toarray())
    

    代码解释:
    从sklearn里导入可以把文本转为向量的包
    texts是我们假设的文本,一共是四段
    cv = CountVectorizer()
    cv_fit=cv.fit_transform(texts)
    这两句代码就是把文本转变为向量
    cv.get_feature_names()可以得到整个语料库不重复的文本,从而得出向量的长度
    cv_fit.toarray() 可以看到向量长什么样子

    运行结果

    ['bird', 'cat', 'dog', 'fish']
    [[0 1 1 1]
    [0 2 1 0]
    [1 0 0 1]
    [1 0 0 0]]

    对照着文本来看,我们的文本是texts=["dog cat fish","dog cat cat","fish bird", 'bird']。那么第一份文本"dog cat fish"的向量是[0 1 1 1]。怎么理解呢?['bird', 'cat', 'dog', 'fish']这个是我们所有语料中不重复的文本。bird在第一份文本里没有出现,所以是0;cat在第一份文本里出现一次,所以是1;dog在第一份文本里出现一次,所以是1;fish在第一份文本里出现一次,所以是1。后面的以此类推

    这个例子就是为了让我们看到sklearn的向量构造器需要什么样格式的数据。显而易见,需要的是这样格式的数据:["dog cat fish","dog cat cat","fish bird", 'bird']
    所以我们要想办法把文本数据转换成这种格式
    先来看一下我们的数据集长什么样,也就是x_train长什么样,它是一种list of list格式

    print(x_train[0])
    

    这里取x_train列表里的第一个列表

    且看操作代码及运行结果

    words = []
    for line_index in range(len(x_train)):
        try:
            words.append(' '.join(x_train[line_index]))
        except:
            print (line_index,word_index)
    words[0]        
    

    这里取的words列表里的第一个字符串

    现在这种格式便符合了sklearn向量化的格式要求

    代码解释:看下面就都明白了,前面的引号里可以换成任何内容,然后便可以把列表转换成你所需要的格式

    将文本内容转换格式后,就该把它们转化为向量了

    from sklearn.feature_extraction.text import CountVectorizer
    vec = CountVectorizer(analyzer='word', max_features=4000,  lowercase = False)
    vec.fit(words)
    
    

    转换成向量后,就可以把它们输入到算法中去,进行模型训练和预测

    贝叶斯算法

    from sklearn.naive_bayes import MultinomialNB
    classifier = MultinomialNB()
    classifier.fit(vec.transform(words), y_train)
    

    代码解释:
    从sklearn中导入贝叶斯算法包,然后构造分类器,对训练数据words进行训练
    words是训练数据,y_train是训练数据的标签

    接下来我们把测试数据做同样的处理,也要转换格式

    test_words = []
    for line_index in range(len(x_test)):
        try:
            test_words.append(' '.join(x_test[line_index]))
        except:
             print (line_index,word_index)
    

    然后预测结果,看看精度,模型效果怎么样

    classifier.score(vec.transform(test_words), y_test)
    

    由此可以得到最终分类效果0.804

    SVM分类算法

    from sklearn import svm
    clf = svm.SVC()
    clf.fit(vec.transform(words), y_train)
    clf.score(vec.transform(test_words), y_test)
    

    也是调用sklearn里的算法包,得到的结果是0.5016,效果就不好了。sklearn里还有很多算法包可以调用,大家感兴趣可以去官网看看

    7)TF-IDF向量

    要想提升模型的效果,方法有很多,除了更换算法以外,我们还可以换一种文本向量的表示方式,比如采用TF-IDF向量。那么什么是TF-IDF向量呢?

    很简单,如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性,这就是我们所需要的关键词。比如一篇文章中,我们可能会发现"中国"这个词和"蜜蜂"这个词出现的次数一样多,那么是不是意味着作为关键词,这两个词的重要性是一样的呢?肯定不是的,因为"中国"这个词是很常见的词,而"蜜蜂"这个词却不是很常见。如果这两个词在一篇文章里出现的次数一样多,我们可以认为"蜜蜂"这个词的重要程度要大于"中国"这个词,也就是说如果我们给一篇文章的所有关键词排序的话,"蜜蜂"这个词要在"中国"这个词的前面。如果某个词对文章的重要性越大,那么它的TF-IDF值就越大。这便是TF-IDF的简单解释,具体数学方面我们不必深究,因为sklearn库都帮我们弄好了。我们只要调用即可。

    接下来我们来看一下sklearn库是怎么实现把文本转变为TF-IDF向量的
    先举个例子,有这样一个语料库

    corpus = [
        'this is the first document',
        'this is the second second document',
        'and the third one',
        'is this the first document'
    ]
    

    注意这里的格式,我们的中文语料也要转为这样的格式,这个格式我们上面已经转化好了,要想利用sklearn实现文本向量的转变,我们就得守它的规矩,先把文本变成符合它要求的格式。
    接下来我们看一下处理过程,调用sklearn库

    from sklearn.feature_extraction.text import TfidfVectorizer
    tfidf_vec = TfidfVectorizer()
    tfidf_matrix = tfidf_vec.fit_transform(corpus)
    

    打印一下结果,我们就能明白这里面怎么回事了。

    1.得到语料库所有不重复的词

    print(tfidf_vec.get_feature_names())
    

    通过这行代码,会输出

    ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
    

    2. 得到每个单词对应的id值

    print(tfidf_vec.vocabulary_)
    

    通过这行代码,会输出

    {'this': 8, 'is': 3, 'the': 6, 'first': 2, 'document': 1, 'second': 5, 'and': 0, 'third': 7, 'one': 4}
    

    3. 得到每个句子所对应的向量

    接下来就可以得到每个句子所对应的向量,且向量里数字的顺序是按照词语的id顺序来的

    print(tfidf_matrix.toarray())
    

    通过这行代码,会输出

    [[0.         0.43877674 0.54197657 0.43877674 0.         0.
      0.35872874 0.         0.43877674]
     [0.         0.27230147 0.         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.43877674 0.54197657 0.43877674 0.         0.
      0.35872874 0.         0.43877674]]
    

    这便是用sklearn计算文本向量的过程。
    我们接着上面的操作,看看用TF-IDF向量会让我们的模型产生一个什么样的变化。
    首先把文本数据转化为TF-IDF向量

    from sklearn.feature_extraction.text import TfidfVectorizer
    vectorizer = TfidfVectorizer()
    vectorizer.fit(words)
    

    代码解释:
    里面的words就是我们前面的训练数据集,就是下图的格式

    然后导入贝叶斯算法包,对训练数据集进行训练

    from sklearn.naive_bayes import MultinomialNB
    classifier = MultinomialNB()
    classifier.fit(vectorizer.transform(words),y_train)
    

    最后对测试数据集进行预测,看看模型效果如何。别忘了测试数据集也要和训练数据集的格式一样。

    classifier.score(vectorizer.transform(test_words),y_test)
    

    由此可以得到最终分类效果0.8248.提升了两个百分点。

    1.4本章总结

    文本分类是入门自然语言处理的第一步,完整地走完这个流程可以让你学到很多东西。很多自然语言处理问题最终都可以转化成文本分类问题。比如广告识别、垃圾邮件分类、情感分析等等项目,都是拿到一份文本,让机器判断它是不是广告数据,是不是垃圾邮件,情感是积极的还是消极的,这就是典型的文本分类问题。所以,掌握了基本的操作流程,就相当于拿到了一个公式,可以应对大部分的项目。

    以下是我所有文章的目录,大家如果感兴趣,也可以前往查看
    👉戳右边:打开它,也许会看到很多对你有帮助的文章

    相关文章

      网友评论

        本文标题:文本分析

        本文链接:https://www.haomeiwen.com/subject/rjhlxqtx.html