如何避免使用 sklearn 特征提取进行标记化

数据挖掘 Python scikit-学习 特征提取 标记化
2022-03-14 16:19:46

我正在尝试分析一些机器日志文件,而我正在查看的列可能具有“Part.C1.11.Reading Status”之类的值。我想将完整的字符串视为一个标记,我不希望将其拆分为“Part”、“C1”、“11”和“Reading#”和“Status”。

我有一种模糊的感觉,token_pattern 是我需要调整的参数,所以我尝试指定字符串的开头和结尾,如下所示:

from sklearn.feature_extraction.text import CountVectorizer
cvo = CountVectorizer(token_pattern='^$',lowercase=False)
OriginCV = cvo.fit_transform(log['Message_Origin']).toarray()

然而,最后一行抛出了一个错误:ValueError:空词汇;也许文档只包含停用词

我还尝试在 token_pattern 中明确包含点和空格,如下所示:

cvo = CountVectorizer(lowercase=False, token_pattern=r"(?u)\b\w\w+\b|\.|\s")

不抛出任何错误但不成功(除了一个额外的标记“。”之外没有任何变化)

但是,不更改默认 token_pattern 确实会在空格和冒号处拆分字符串。我找到了这个解决方案,但是它通过删除例如冒号来修改字符串。任何其他想法如何解决这个问题?

谢谢,马克

4个回答

您可以更改标记器而不是标记模式。标记器使用标记模式。您可以将任何返回字符串列表的函数设置为标记器。例如,str.split

tokenizer=str.split

从官方文档

标记器可调用,默认=无

覆盖字符串标记化步骤,同时保留预处理和 n-gram 生成步骤。仅在分析器 == 'word' 时适用。

我想通了 :-) 确实是我缺乏正则表达式专业知识。使用时发生了什么

token_pattern='.*'

是每个与总长度无关的字符串组合都被视为一个标记。这包括 0 次重复,因此我得到一个消息标记和一个无标记 ('')。我将其修改为

token_pattern='.+'

其中不包括 0 次重复。

的默认值token_pattern转换为的(?u)\b\w\w+\b位置(可以写为)。这匹配 2 个或更多字母数字字符(如方括号之间的定义)。\w\w+[a-zA-Z0-9_][a-zA-Z0-9_]+[a-zA-Z0-9_]{2,}

\b匹配单词边界:任何不是字母数字字符的东西,旁边是字母数字字符这包括空格和标点符号,因此它还包括点并导致分隔。

(?u)激活 unicode 匹配,但它对您的问题并不那么重要

如果我们还想将点作为单词的一部分进行匹配,我们可以复制默认的正则表达式,替换\w为它的扩展版本并在其中添加点:(?u)\b[a-zA-Z0-9_.]{2,}\b如本网站所示要添加“状态”一词,您可以明确将其列为选项:(?u)\b[a-zA-Z0-9_.]{2,}(=? Status)?\b.

或者,您可以将函数传递给tokenizer参数以定义更复杂的标记化算法。

编辑:如果您想完全避免标记化(如您自己的答案所述),CountVectorizer作为标记计数器的 可能不是选择的正确预处理步骤:它只会使所有内容成为单个标记并返回计数 1 . (或者我误解了你的问题)

如果您所有的“标记”都以开头Part和结尾为特征,Status并且您可以在两者之间有任何内容,请尝试token_pattern='^Part[.]*Status$'为任何以 Part 开头并以 Status 结尾的字符串指定正则表达式,或者尝试使其适应您的需要。

旁注,如果您使用 Vectorizer,则很可能在每次观察中都需要多个标记,因为否则 Vectorize 没有多大意义。我不确定每次观察是否有多个标记,但如果每次观察只有一个标记,那将是某种 OneHotEncoding,所以在这种情况下可能会查看sklearn OneHotEcoderor pandas.get_dummies()