ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python3自然语言处理——语言处理与Python

2020-01-26 14:02:58  阅读:340  来源: 互联网

标签:plot fdist1 Python cumulative freqs 处理 kwargs Python3


Python3自然语言处理——语言处理与Python

注:转载请联系博主,或关注微信公众号"引文空间",后台提出转载申请,等待回复。否则将举报抄袭!

《Python自然语言处理》是美国斯坦福大学Steven Bird,Edward Loper和Ewan Klein编著的NLP实用书籍,该书条理清晰,内容详尽,适合各种技术水平的读者,非常值得推荐,但是书中所用的Python版本为Python2,而目前Python使用和学习的主流为Python3,这给学习NLP的读者们可能造成困扰,因为Python3并不向下兼容Python2。
笔者通过对该书的学习,并尝试利用Python3来实现书中的功能,将自己的学习心得发表在公众号"引文空间"上,为了使更多人能够看到,转载到了该平台,内容将不断更新。由于本人水平有限,有一些功能可能在用Python3操作时考虑不周,或者方法不够简易,恳请读者谅解,若读者对内容有新见解或新方法,欢迎提出探讨。在这里插入图片描述
第一章 语言处理与Python
首先要安装NLTK,可以从http://www.nltk.org上下载,也可以通过pip下载,即:

pip install nltk

安装完成后,启动Python解释器,输入如下代码:

import nltk
nltk.download()

选择book标记所在行,下载数据。数据下载完成后可将模块导入Python:

from nltk.book import *

回车后,编辑器显示如下:

*** Introductory Examples for the NLTK Book ***
Loading text1, ..., text9 and sent1, ..., sent9
Type the name of the text or sentence to view it.
Type: 'texts()' or 'sents()' to list the materials.
text1: Moby Dick by Herman Melville 1851
text2: Sense and Sensibility by Jane Austen 1811
text3: The Book of Genesis
text4: Inaugural Address Corpus
text5: Chat Corpus
text6: Monty Python and the Holy Grail
text7: Wall Street Journal
text8: Personals Corpus
text9: The Man Who Was Thursday by G . K . Chesterton 1908

需要找这些文本的时候,只要输入名字(如text1)即可:

>>>text1
<Text: Moby Dick by Herman Melville 1851>

后面的一些部分都是Python的一些基础功能,在此不再赘述,在“频率分布”部分,Python3的操作与Python2有所差别。书上的例子为利用FreqDist寻找《白鲸记》中出现的的前50个高频词,原代码如下:

fdist1=FreqDist(text1)
vocabulary1=fdist1.keys()
vocabulary1[:50]

在Python3中运行此代码,会如此报错:

Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    vocabulary1[:50]
TypeError: 'dict_keys' object is not subscriptable

解决这个问题我们可以把字典的键放到列表里,再用列表进行切片,但是这样的话会发现列表中的元素是乱序的,FreqDist没起作用。通过观察发现,上述代码中fdist1的值及类型为:

>>>fdist1
FreqDist({',': 18713, 'the': 13721, '.': 6862, 'of': 6536, 'and': 6024, 'a': 4569, 'to': 4542, ';': 4072, 'in': 3916, 'that': 2982, ...})
>>>type(fdist1)
<class 'nltk.probability.FreqDist'>

可以看出fdist1的类型是nltk中的一个特殊类,类似于字典,并且在fdist1中,key是按照value从大到小排列的,因此,我们可以通过对value的排序来使key列表(及单词列表)根据出现频次大小进行排列,代码如下:

fdist1=FreqDist(text1)
vocabulary1=sorted(fdist1,key=lambda k:fdist1[k],reverse=True)
vocabulary1[:50]

代码运行结果如下:

[',', 'the', '.', 'of', 'and', 'a', 'to', ';', 'in', 'that', "'", '-', 'his', 'it', 'I', 's', 'is', 'he', 'with', 'was', 'as', '"', 'all', 'for', 'this', '!', 'at', 'by', 'but', 'not', '--', 'him', 'from', 'be', 'on', 'so', 'whale', 'one', 'you', 'had', 'have', 'there', 'But', 'or', 'were', 'now', 'which', '?', 'me', 'like']

与书上结果相同。

除此之外,我们可以将这些词汇生成统计图,书上生成的为累积频率图,代码为:

fdist1.plot(50,cumulative=True)

书上利用Python2生成的是一个横轴为50个高频词,纵轴为Cumulative Percentage的一个统计图,但是在Python3中,生成的图是这样的:在这里插入图片描述
可以看见,这张图不是累积频率图,而是累积频数图,横轴为Sample,纵轴为Cumulative Count。问题出在哪里呢?我们可以看到在plot中有一个cumulative=True,这个不难看出是累积的意思,如果将这一条去掉,即只留下:

fdist1.plot(50)

就会是下图这样:在这里插入图片描述
这张图是词频统计图,没有累积,按照频次从大到小排列的前50个高频词。但是也没有成为书上的频率图,纵轴仍然为Count。
为了解决这个问题,我看了一下plot方法的源码,我使用的版本为Python3.8,安装路径为默认,plot方法的源码路径为:

C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages\nltk

在这个路径下有一个文件名为probability.py,打开源码后找到plot方法,发现plot方法的代码如下:

 def plot(self, *args, **kwargs):
        """
        Plot samples from the frequency distribution
        displaying the most frequent sample first.  If an integer
        parameter is supplied, stop after this many samples have been
        plotted.  For a cumulative plot, specify cumulative=True.
        (Requires Matplotlib to be installed.)

        :param title: The title for the graph
        :type title: str
        :param cumulative: A flag to specify whether the plot is cumulative (default = False)
        :type title: bool
        """
        try:
            import matplotlib.pyplot as plt
        except ImportError:
            raise ValueError(
                'The plot function requires matplotlib to be installed.'
                'See http://matplotlib.org/'
            )

        if len(args) == 0:
            args = [len(self)]
        samples = [item for item, _ in self.most_common(*args)]

        cumulative = _get_kwarg(kwargs, 'cumulative', False)
        percents = _get_kwarg(kwargs, 'percents', False)
        if cumulative:
            freqs = list(self._cumulative_frequencies(samples))
            ylabel = "Cumulative Counts"
            if percents:
                freqs = [f / freqs[len(freqs) - 1] * 100 for f in freqs]
                ylabel = "Cumulative Percents"
        else:
            freqs = [self[sample] for sample in samples]
            ylabel = "Counts"
        # percents = [f * 100 for f in freqs]  only in ProbDist?

        ax = plt.gca()
        ax.grid(True, color = "silver")

        if "linewidth" not in kwargs:
            kwargs["linewidth"] = 2
        if "title" in kwargs:
            ax.set_title(kwargs["title"])
            del kwargs["title"]

        ax.plot(freqs, **kwargs)
        ax.set_xticks(range(len(samples)))
        ax.set_xticklabels([text_type(s) for s in samples], rotation=90)
        ax.set_xlabel("Samples")
        ax.set_ylabel(ylabel)

        plt.show()

        return ax

我们把第26行和第27行单拎出来:

cumulative = _get_kwarg(kwargs, 'cumulative', False)
percents = _get_kwarg(kwargs, 'percents', False)

再查看一下_get_kwarg方法:

def _get_kwarg(kwargs, key, default):
    if key in kwargs:
        arg = kwargs[key]
        del kwargs[key]
    else:
        arg = default
    return arg

可以看出cumulative的默认(default)值为False,与cumulative并列的还有一个参数为pertcents,即为百分数频率。再来分析代码28-33行:

if cumulative:
            freqs = list(self._cumulative_frequencies(samples))
            ylabel = "Cumulative Counts"
            if percents:
                freqs = [f / freqs[len(freqs) - 1] * 100 for f in freqs]
                ylabel = "Cumulative Percents"

可以看出,percents在cumulative为真的循环内,所以要绘制频率图,一定会累积,因此用这样的方法,我们只可以以绘制这几种图:词频统计图,累积频数图,累积频率图。前两种图已经给出示范,还差一个和书上一样的累积频率图通过对源码的查阅,加入percents参数:

fdist1.plot(50,cumulative=True,percents=True)

得到的图是这样的:
在这里插入图片描述
乍一看似乎没有问题,但是这张图的样本仅仅只是50个词,因此最终累积频率为100%,而书上的图的样本为所有词汇,因此最后的累积频率不会达到100%。出现这种情况的原因目前尚不清楚,可能是Python3与Python2的本身差异造成的,也可能是由于我的知识体系不健全,在哪里造成了疏漏,欢迎各位读者留言讨论。

zh的莫莫 发布了1 篇原创文章 · 获赞 1 · 访问量 28 私信 关注

标签:plot,fdist1,Python,cumulative,freqs,处理,kwargs,Python3
来源: https://blog.csdn.net/weixin_45930839/article/details/104087000

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有