【问题标题】:Python NLP: How to map tokenized text back into original structures?Python NLP:如何将标记化的文本映射回原始结构?
【发布时间】:2014-11-08 07:26:23
【问题描述】:

目标:矢量化标记化文本以创建术语文档矩阵,支持对非结构化文本数据进行 NLP 分析。预测和文本分类将是分析的重要组成部分,因此能够将标签/类与每个文本相关联至关重要。为此,我需要对术语文档矩阵进行结构化,使得每一行代表一个文本,每一列代表整个语料库中出现的单词之一。文本的类/标签也将是矩阵中的向量。

问题:文本中的每条记录都表示为列表中的一项(第一条记录是列表中的第一项,第二条记录是列表中的第二项,依此类推)。标记列表中每条记录的内容并生成每个单词的巨大列表很容易。我的问题是,在标记化之后,我无法保留原始列表结构并将每个标记与原始列表中的记录进行映射。这使得矢量化变得不可能。

举例说明:

record_one = 'I like ham. I also like pineapple.'
record_two = 'I love cheese. I enjoy tomato sauce and dough too.'
record_three = 'Hence, I dig Hawaiian pizza. And beer.'
recordList = [record_one, record_two, record_three]

结果(列表三条记录,每条两句):

['I like ham. I also like pineapple.', 'I love cheese. I enjoy tomato sauce and dough too.', 'Hence, I dig Hawaiian pizza. And beer.']

标记化:

from nltk.tokenize import word_tokenize
wordList= []
for r in recordList:
    temp = word_tokenize(r)
    for token in temp:
        wordList.append(token)

结果(recordList 中每个单词的巨大列表):

['I', 'like', 'ham.', 'I', 'also', 'like', 'pineapple', '.', 'I', 'love', 'cheese.', 'I', 'enjoy', 'tomato', 'sauce', 'and', 'dough', 'too', '.', 'Hence', ',', 'I', 'dig', 'Hawaiian', 'pizza.', 'And', 'beer', '.']

这就是我卡住的地方。此时矢量化给了我一个 28x18 矩阵,而我需要的是一个 3x18 矩阵。我需要以某种方式将每个术语映射到它在 recordList 中的记录,以提供 3x18 矩阵,但我不知道该怎么做。我知道我缺少一些明显的东西。

我是 Python 和 NLP 的新手,所以我试图让事情尽可能简单。这意味着使用列表、创建循环来处理这些列表以及列表推导。我知道还有其他模块和函数可以做到这一点(scikit),但我试图强迫自己使用基本的 Python 数据结构来提高我对语言的理解。如果可以使用基本的 Python 数据结构创建解决方案,那将是非常棒的。

提前致谢!

【问题讨论】:

    标签: python list matrix nlp text-mining


    【解决方案1】:

    这里的问题是您没有为每个文档设置单词。这就是为什么你最终得到一个 28x18 矩阵而不是 3x18 的原因。

    这是一种基于 Python 的方法,您可以尝试 -

    In [22]: doc_words = [set() for _ in recordList]
    In [24]: for index, record in enumerate(recordList):
        token_generator = word_tokenize(record)
        for token in token_generator:
            doc_words[index].add(token)
    In [28]: all_words = {word for doc_word_set in doc_words for word in doc_word_set}
    In [31]: all_words_list = list(all_words)
    In [32]: [[1 if word in doc_word_set else 0 for word in all_words_list] for doc_word_set in doc_words]
    Out[32]: 
    [[0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
     [1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0]]
    In [48]: all_words_list
    Out[48]: 
    ['enjoy',
     'cheese',
     'and',
     'love',
     'like',
     'Hawaiian',
     'I',
     'too',
     'dig',
     ',',
     '.',
     'And',
     'also',
     'beer',
     'dough',
     'tomato',
     'pineapple',
     'Hence',
     'pizza',
     'sauce',
     'ham']
    

    一些步骤的解释-

    22:我们使用doc_words 来跟踪每个文档中的单词。我们将其初始化为集合列表;每个集合用于一个文档。

    24:我们填充词集

    28:我们收集所有单词的集合

    31:我们把集合转换成列表,这样单词的顺序就固定了

    32:我们打印出矩阵;我们迭代每个文档的词集,然后测试每个词在文档的词集中的存在。

    输出以all_words_list 的顺序显示单词。您可以考虑将 all_words_list 排序为 31 以获得更清晰的输出。

    【讨论】:

      【解决方案2】:

      应该这样做:

      from sklearn.feature_extraction.text import CountVectorizer
      cv = CountVectorizer()
      words_csm = cv.fit_transform(records)
      words_csm.todense()
      
      matrix([[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1, 0, 0, 0, 0],
              [0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1],
              [0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0]], dtype=int64)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-03
        • 2017-05-04
        • 1970-01-01
        • 2015-02-17
        • 2023-03-12
        • 1970-01-01
        • 2016-03-15
        • 1970-01-01
        相关资源
        最近更新 更多