首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成共现矩阵

生成共现矩阵
EN

Code Review用户
提问于 2020-01-15 06:48:13
回答 1查看 7.1K关注 0票数 3

我正在用Python生成共现矩阵(2000X2000)。

  • “语料库”是语料库中2000年前几个单词的列表。它并不包含语料库中的所有单词。
  • 语料库是由30000 (行)句组成的Pandas数据集。是语料库中单个排的一个例子:能源教室高,满屋的学者们渴望学习,他们开始学习旅程,不像这些学者要求的那样,学习时间,快速变化的技术交流,因为老师的工作,给我们学校带来成功的工具,我们学校的特殊方式,总是给学生最好的教育,可能的话,我的四年级学生计数,提供必要的成功,我想保持爱的成功,让学生们在21世纪的学习环境中获得关键的成功,21世纪的学习环境,我们使用不同的应用程序,让孩子们合作建立批判性的思考技能,尽管ipad键盘笨重,难度很大,所以我要求15个键盘,插头,ipad,有有线键盘,允许孩子练习键盘。技能标准协作他人有效利用技术访问键盘增强协作选择批判性思考

我的代码目前每次迭代需要120秒,完成运行需要364小时。我在Google中运行这个代码,内存为25 in。

该代码可以很好地处理10行语料库和5个单词的小数据。是否有更好的方法来完成这项任务或加快这一进程?

tqdm是必需的,因为如果代码运行时间超过12小时,那么它就会与Google断开连接。

代码语言:javascript
复制
coocur_matrix = np.zeros((len(voca), len(voca)),np.float64)
代码语言:javascript
复制
#python
from tqdm import tqdm


window_size=5
corpus=corpu1
vocab = voca

for word1 in tqdm(vocab):
  for word2 in vocab:
    for sent in corpus:
      doc_tokens = []
      doc_tokens=sent.split()

      p1= [i for i in range(len(doc_tokens)) if doc_tokens[i] == word1]
      p2= [i for i in range(len(doc_tokens)) if doc_tokens[i] == word2]
      for k in p1:
        print(9)
        for l in p2:
          if (abs(l-k)<=window_size):
            if(word1!=word2):
              coocur_matrix[vocab.index(word1),vocab.index(word2)] += 1

print(coocur_matrix)
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-01-15 07:52:51

可读性

您的代码在视觉上没有吸引力。您有多个PEP 8违规行为,并且您的变量名称实际上无法说明问题。您有两个缩进空间,这在Python中几乎是闻所未闻的。如果我们将您的代码移动到一个函数中并执行一些清理,我们可以得到如下内容:

代码语言:javascript
复制
import numpy as np


def get_indexes(tokens, word):
    return [
        index
        for index, token in enumerate(tokens)
        if token == word
    ]


def co_occurrence_matrix(corpus, vocabulary, window_size=5):
    matrix = np.zeros((len(vocabulary), len(vocabulary)), np.float64)
    for word_1 in vocabulary:
        for word_2 in vocabulary:
            for sent in corpus:
                tokens = sent.split()
                tokens_1 = get_indexes(tokens, word_1)
                tokens_2 = get_indexes(tokens, word_2)
                for k in tokens_1:
                    for l in tokens_2:
                        if abs(l - k) > window_size:
                            continue
                        if word_1 == word_2:
                            continue
                        matrix[
                            vocabulary.index(word_1),
                            vocabulary.index(word_2),
                        ] += 1
    return matrix


print(co_occurrence_matrix(corpu1, voca))

性能

现在看起来不算太糟,但看起来并不是很好。从这里我们可以清楚地看到,word_1word_2是在前两个循环中定义的,但是check word_1 == word_2位于循环的最内部级别。这意味着您在senttokens_1tokens_2上进行不必要的循环。这些循环总数约为12000000,毫无用处,浪费时间。

虽然很难看到,但是vocabulary.index(word_1)中有一个for循环。不然它是怎么得到指数的?这意味着您要循环2000次,这是一种浪费,因为您可以在遍历vocabulary时定义一个变量来存储索引。

您不需要在vocabulary上迭代,只需在corpus上迭代即可。这是因为如果word_1word_2不在tokens中,那么for循环将在空列表上迭代,因此什么也不会做。因此,我们可以从word_1word_2中得到corpus

因为vocabulary只包含corpus中的前2000个单词。那么,简单的循环翻转仍然会浪费一些周期。所以我们只需将sent过滤成vocabulary中的。为了实现这一点,我选择使用闭包,因为我认为它使代码更简洁,更易于阅读。这是因为我没有Python3.7上的walrus,并且希望使用dict.get,而不是每个令牌的每个过滤器执行两个字典查找。

代码语言:javascript
复制
import numpy as np
import itertools


def by_indexes(iterable):
    output = {}
    for index, key in enumerate(iterable):
        output.setdefault(key, []).append(index)
    return output


def co_occurrence_matrix(corpus, vocabulary, window_size=5):
    def split_tokens(tokens):
        for token in tokens:
            indexs = vocabulary_indexes.get(token)
            if indexs is not None:
                yield token, indexs[0]

    matrix = np.zeros((len(vocabulary), len(vocabulary)), np.float64)
    vocabulary_indexes = by_indexes(vocabulary)

    for sent in corpus:
        tokens = by_indexes(split_tokens(sent.split())).items()
        for ((word_1, x), indexes_1), ((word_2, y), indexes_2) in itertools.permutations(tokens, 2):
            for k in indexes_1:
                for l in indexes_2:
                    if abs(l - k) <= window_size:
                        matrix[x, y] += 1
    return matrix


print(co_occurrence_matrix(corpu1, voca))

这目前还没有完全优化,因为您可以使用combinations而不是permutations,但是这需要镜像矩阵的非空值。这很可能是运行所需时间的一半,但需要额外的代码。

这是完全假设的答案。这意味着使用两次dict[]而不是dict.get可能会更快。这也意味着,由于Python的方式,我所做的许多假设可能无法转化为性能好处。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/235633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档