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

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

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

《Python自然语言处理》是美国斯坦福大学Steven Bird,Edward Loper和Ewan Klein编著的NLP实用书籍,该书条理清晰,内容详尽,适合各种技术水平的读者,非常值得推荐,但是书中所用的Python版本为Python2,而目前Python使用和学习的主流为Python3,这给学习NLP的读者们可能造成困扰,因为Python3并不向下兼容Python2。
笔者通过对该书的学习,并尝试利用Python3来实现书中的功能,将自己的学习心得发表在公众号"引文空间"上,为了使更多人能够看到,转载到了该平台,内容将不断更新。由于本人水平有限,有一些功能可能在用Python3操作时考虑不周,或者方法不够简易,恳请读者谅解,若读者对内容有新见解或新方法,欢迎提出探讨。Python3自然语言处理——语言处理与Python
第一章 语言处理与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中,生成的图是这样的:Python3自然语言处理——语言处理与Python
可以看见,这张图不是累积频率图,而是累积频数图,横轴为Sample,纵轴为Cumulative Count。问题出在哪里呢?我们可以看到在plot中有一个cumulative=True,这个不难看出是累积的意思,如果将这一条去掉,即只留下:

fdist1.plot(50)

就会是下图这样:Python3自然语言处理——语言处理与Python
这张图是词频统计图,没有累积,按照频次从大到小排列的前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)

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

Python3自然语言处理——语言处理与PythonPython3自然语言处理——语言处理与Python zh的莫莫 发布了1 篇原创文章 · 获赞 1 · 访问量 28 私信 关注
上一篇:以太坊存储类型(memory,storage)及变量存储详解


下一篇:以太坊Dapp开发之完整demo