如何使用gensim wikicorpus获取带标点符号的维基百科语料库文本?

问题描述 投票:2回答:2

我试图用标点符号来获取文本,因为在我的doc2vec模型中考虑后者是很重要的。但是,wikicorpus只检索文本。搜索网页后,我找到了以下网页:

  1. 来自gensim github的页面问题部分。这是一个人的问题,其答案是子类WikiCorpus(由Piskvorky回答)。幸运的是,在同一页面中,有一个代表建议的“子类”解决方案的代码。该代码由Rhazegh提供。 (link
  2. 来自stackoverflow的页面标题为:“在解析维基语料库时禁用Gensim删除标点符号等”。但是,没有提供明确的答案,并在spaCy的背景下进行了处理。 (link

我决定使用第1页中提供的代码。我当前的代码(mywikicorpus.py):

import sys
import os
sys.path.append('C:\\Users\\Ghaliamus\\Anaconda2\\envs\\wiki\\Lib\\site-packages\\gensim\\corpora\\')

from wikicorpus import *

def tokenize(content):
    # override original method in wikicorpus.py
    return [token.encode('utf8') for token in utils.tokenize(content, lower=True, errors='ignore')
        if len(token) <= 15 and not token.startswith('_')]

def process_article(args):
   # override original method in wikicorpus.py
    text, lemmatize, title, pageid = args
    text = filter_wiki(text)
    if lemmatize:
        result = utils.lemmatize(text)
    else:
        result = tokenize(text)
    return result, title, pageid


class MyWikiCorpus(WikiCorpus):
def __init__(self, fname, processes=None, lemmatize=utils.has_pattern(), dictionary=None, filter_namespaces=('0',)):
    WikiCorpus.__init__(self, fname, processes, lemmatize, dictionary, filter_namespaces)

    def get_texts(self):
        articles, articles_all = 0, 0
        positions, positions_all = 0, 0
        texts = ((text, self.lemmatize, title, pageid) for title, text, pageid in extract_pages(bz2.BZ2File(self.fname), self.filter_namespaces))
        pool = multiprocessing.Pool(self.processes)
        for group in utils.chunkize(texts, chunksize=10 * self.processes, maxsize=1):
            for tokens, title, pageid in pool.imap(process_article, group):  # chunksize=10):
                articles_all += 1
                positions_all += len(tokens)
            if len(tokens) < ARTICLE_MIN_WORDS or any(title.startswith(ignore + ':') for ignore in IGNORED_NAMESPACES):
                continue
            articles += 1
            positions += len(tokens)
            if self.metadata:
                yield (tokens, (pageid, title))
            else:
                yield tokens
    pool.terminate()

    logger.info(
        "finished iterating over Wikipedia corpus of %i documents with %i positions"
        " (total %i articles, %i positions before pruning articles shorter than %i words)",
        articles, positions, articles_all, positions_all, ARTICLE_MIN_WORDS)
    self.length = articles  # cache corpus length

然后,我使用了Pan Yang(link)的另一个代码。此代码启动WikiCorpus对象并检索文本。我当前代码中唯一的变化是启动MyWikiCorpus而不是WikiCorpus。代码(process_wiki.py):

from __future__ import print_function
import logging
import os.path
import six
import sys
import mywikicorpus as myModule



if __name__ == '__main__':
    program = os.path.basename(sys.argv[0])
    logger = logging.getLogger(program)

    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    # check and process input arguments
    if len(sys.argv) != 3:
        print("Using: python process_wiki.py enwiki-20180601-pages-    articles.xml.bz2 wiki.en.text")
        sys.exit(1)
    inp, outp = sys.argv[1:3]
    space = " "
    i = 0

    output = open(outp, 'w')
    wiki = myModule.MyWikiCorpus(inp, lemmatize=False, dictionary={})
    for text in wiki.get_texts():
        if six.PY3:
            output.write(bytes(' '.join(text), 'utf-8').decode('utf-8') + '\n')
        else:
            output.write(space.join(text) + "\n")
        i = i + 1
        if (i % 10000 == 0):
            logger.info("Saved " + str(i) + " articles")

    output.close()
    logger.info("Finished Saved " + str(i) + " articles")

通过命令行我运行了process_wiki.py代码。我在命令提示符中输入了最后一行语料库的文本:

(2018-06-05 09:18:16,480:INFO:已完成保存4526191篇)

当我在python中读取文件时,我检查了第一篇文章,它没有标点符号。例:

(无政府主义是一种主张基于自愿制度的自治社会的政治哲学,这些社会通常被描述为无国籍社会,尽管有几位作者将其更具体地定义为基于非等级或自由联合的制度,无政府主义认为国家是不必要的有害和有害的。对国家的反对是中央无政府主义,特别需要反对权威或等级制度)

我的两个相关问题,我希望你能帮助我,请:

  1. 我报告的管道上面有什么问题吗?
  2. 无论这样的管道,如果我打开gensim wikicorpus python代码(wikicorpus.py)并想编辑它,我应该添加或删除它或更新它(如果可能的话)得到相同的结果但标点符号的行是什么?

非常感谢你花时间阅读这篇长篇文章。

最好的祝愿,

Ghulams

python nlp gensim doc2vec
2个回答
2
投票

问题在于您定义的tokenize func

def tokenize(content):
    return [token.encode('utf8') for token in utils.tokenize(content, 
            lower=True, errors='ignore') if len(token) <= 15 and not 
            token.startswith('_')]

func utils.tokenize(content,lower = True,errors ='ignore')简单地将文章标记为标记列表。但是,在... / site-packages / gensim / utils.py中实现此func会忽略标点符号。

例如,当你调用utils.tokenize(“我爱吃香蕉,苹果”)时,它会返回[“我”,“爱”,“吃”,“香蕉”,“苹果”]

无论如何,您可以定义自己的tokenize func,如下所示,以保留标点符号。

def tokenize(content):
    #override original method in wikicorpus.py
    return [token.encode('utf8') for token in content.split() 
           if len(token) <= 15 and not token.startswith('_')]

1
投票

在gensim / utils.py中,您可以找到该方法

def save_as_line_sentence(corpus, filename):
    with smart_open(filename, mode='wb', encoding='utf8') as fout:
        for sentence in corpus:
            line = any2unicode(' '.join(sentence) + '\n')
            fout.write(line)

您可以使用将语料库写入文本文件。您可以覆盖它或将其作为示例并编写您自己的版本(可能您希望在每个标点处打破行)

def save_sentence_each_line(corpus, filename):
    with utils.smart_open(filename, mode='wb', encoding='utf8') as fout:
        for sentence in corpus:
            line = utils.any2unicode(' '.join(sentence) + '\n')
            line = line.replace('. ', '\n').replace('!', '\n').replace('?', '\n') # <- !!
            ...

你可以称之为

save_sentence_each_line(wiki.get_texts(), out_f)

但是你也需要从utils覆盖PAT_ALPHABETIC,因为标点符号被删除的地方:

PAT_ALPHABETIC = re.compile(r'(((?![\d])[\w\\.\\!\\?])+)', re.UNICODE)

然后,您可能需要覆盖utils.tokenize和utils.simple_tokenize,以防您想要对代码进行进一步更改。

© www.soinside.com 2019 - 2024. All rights reserved.