在 pig 中进行标记(使用 python udf)

Posted

技术标签:

【中文标题】在 pig 中进行标记(使用 python udf)【英文标题】:Tokenizing in pig (using python udf) 【发布时间】:2016-07-26 09:11:16 【问题描述】:

这是我在猪中标记化的内容, 我的猪脚本

--set the debugg mode
SET debug 'off'
-- Registering the python udf
REGISTER /home/hema/phd/work1/coding/myudf.py USING streaming_python as myudf

RAWDATA =LOAD '/home/hema/temp' USING TextLoader() AS content;
LOWERCASE_DATA =FOREACH RAWDATA GENERATE LOWER(content) AS con;
TOKENIZED_DATA =FOREACH LOWERCASE_DATA GENERATE myudf.special_tokenize(con) as conn;
DUMP TOKENIZED_DATA;

我的 Python UDF

from pig_util import outputSchema
import nltk

@outputSchema('word:chararray')
def special_tokenize(input):
    tokens=nltk.word_tokenize(input)
    return tokens

代码运行良好,但输出混乱。如何删除不需要的下划线和竖线。输出如下所示

(|_|(_additionalcontext|)_|,_|(_in|)_|,_|(_namefinder|)_|_)
(|_|(_is|)_|,_|(_there|)_|,_|(_any|)_|,_|(_possibility|)_|,_|(_to|)_|,_|(_use|)_|,_|(_additionalcontext|)_|,_|(_with|)_|,_|(_the|)_|,_|(_namefinderme.train|)_|,_|(_?|)_|,_|(_if|)_|,_|(_so|)_|,_|(_,|)_|,_|(_how|)_|,_|(_?|)_|,_|(_if|)_|,_|(_there|)_|,_|(_is|)_|,_|(_n't|)_|,_|(_maybe|)_|,_|(_this|)_|,_|(_should|)_|,_|(_be|)_|,_|(_an|)_|,_|(_issue|)_|,_|(_to|)_|,_|(_be|)_|,_|(_added|)_|,_|(_in|)_|,_|(_the|)_|,_|(_future|)_|,_|(_releases|)_|,_|(_?|)_|_)
(|_|(_i|)_|,_|(_would|)_|,_|(_really|)_|,_|(_greatly|)_|,_|(_appreciate|)_|,_|(_if|)_|,_|(_someone|)_|,_|(_can|)_|,_|(_help|)_|,_|(_(|)_|,_|(_give|)_|,_|(_me|)_|,_|(_some|)_|,_|(_sample|)_|,_|(_code/show|)_|,_|(_me|)_|,_|(_)|)_|,_|(_how|)_|,_|(_to|)_|,_|(_add|)_|,_|(_pos|)_|,_|(_tag|)_|,_|(_features|)_|,_|(_while|)_|,_|(_training|)_|,_|(_and|)_|,_|(_testing|)_|,_|(_namefinder|)_|,_|(_.|)_|_)
(|_|(_if|)_|,_|(_the|)_|,_|(_incoming|)_|,_|(_data|)_|,_|(_is|)_|,_|(_just|)_|,_|(_tokens|)_|,_|(_with|)_|,_|(_no|)_|,_|(_pos|)_|,_|(_tag|)_|,_|(_information|)_|,_|(_,|)_|,_|(_where|)_|,_|(_is|)_|,_|(_the|)_|,_|(_information|)_|,_|(_taken|)_|,_|(_then|)_|,_|(_?|)_|,_|(_a|)_|,_|(_new|)_|,_|(_file|)_|,_|(_?|)_|,_|(_run|)_|,_|(_a|)_|,_|(_pos|)_|,_|(_tagging|)_|,_|(_model|)_|,_|(_before|)_|,_|(_training|)_|,_|(_?|)_|,_|(_or|)_|,_|(_?|)_|_)
(|_|(_and|)_|,_|(_what|)_|,_|(_is|)_|,_|(_the|)_|,_|(_purpose|)_|,_|(_of|)_|,_|(_the|)_|,_|(_resources|)_|,_|(_(|)_|,_|(_i.e|)_|,_|(_.|)_|,_|(_collection.|)_|,_|(_<|)_|,_|(_string|)_|,_|(_,|)_|,_|(_object|)_|,_|(_>|)_|,_|(_emptymap|)_|,_|(_(|)_|,_|(_)|)_|,_|(_)|)_|,_|(_in|)_|,_|(_the|)_|,_|(_namefinderme.train|)_|,_|(_method|)_|,_|(_?|)_|,_|(_what|)_|,_|(_should|)_|,_|(_be|)_|,_|(_ideally|)_|,_|(_included|)_|,_|(_in|)_|,_|(_there|)_|,_|(_?|)_|_)
(|_|(_i|)_|,_|(_just|)_|,_|(_ca|)_|,_|(_n't|)_|,_|(_get|)_|,_|(_these|)_|,_|(_things|)_|,_|(_from|)_|,_|(_the|)_|,_|(_java|)_|,_|(_doc|)_|,_|(_api|)_|,_|(_.|)_|_)
(|_|(_in|)_|,_|(_advance|)_|,_|(_!|)_|_)
(|_|(_best|)_|,_|(_,|)_|_)
(|_|(_svetoslav|)_|_)

原始数据

AdditionalContext in NameFinder 
Is there any possibility to use additionalContext with the NameFinderME.train? If so, how? If there isn't maybe this should be an issue to be added in the future releases?
I would REALLY greatly appreciate if someone can help (give me some sample code/show me)  how to add POS tag features while training and testing NameFinder.
If the incoming data is just tokens with NO POS tag information, where is the information taken then? A new file? Run a POS tagging model before training? Or?
And what is the purpose of the resources (i.e. Collection.<String,Object>emptyMap()) in the NameFinderME.train method? What should be ideally included in there?
I just can't get these things from the Java doc API.
 in advance!
Best,
Svetoslav

我想要一个令牌列表作为我的最终输出。在此先感谢。

【问题讨论】:

@cricket_007 我已将我的原始数据发布为编辑。我认为 NLTK 不会生成下划线和竖线。当我在 grunt shell 中执行时,相同的 Word_tokenize() 方法可以正常工作。 好的,第二个问题。你期望的输出是什么? (旁注:您将字符串传递给 python,那么为什么额外的 map-reduce 工作以小写 Pig 中的字符串?) 我期待一个标记化字符串的元组作为输出。例如('additionalcontext','in','namefinder')。实际上我想在猪中进行所有预处理。 pig 的内置函数 (tokenize) 并没有按照我喜欢的方式进行标记,这就是我想到使用 NLTK 的原因。 你能解释一下为什么插入下划线和竖线吗?是装饰者造成的吗? 我真的不确定,从来没有在 python 中写过 Pig UDF 【参考方案1】:

对 '_' 和 '|' 使用 REPLACE然后使用 TOKENIZE 作为令牌。

NEW_TOKENIZED_DATA =FOREACH TOKENINZED_DATA GENERATE REPLACE(REPLACE($0,'_',''),'|','');
TOKENS = FOREACH NEW_TOKENIZED_DATA GENERATE TOKENIZE($0);
DUMP TOKENS;

【讨论】:

你想让我分两次。为什么这些下划线和竖线会进入 udf 返回的包中。不能避免这种情况,而是替换它们并进行第二轮标记化。 我不确定它来自哪里。您可以轻松地对输入进行标记以获取标记而不是 UDF。我发布的脚本是针对您获得的输出,而不是针对原始数据。 内置标记器不会以我喜欢的方式标记文本。这就是我使用 UDF 和 NLTK 的原因 然后再使用replace和tokenize。【参考方案2】:
from pig_util import outputSchema
import nltk
import re 

@outputSchema('word:chararray')
def special_tokenize(input):
    #splitting camel-case here
    temp_data = re.sub(r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])'," ",input)
    tokens = nltk.word_tokenize(temp_data.encode('utf-8'))
    final_token = ','.join(tokens) 
    return final_token   

输入的编码存在一些问题。将其更改为 utf-8 即可解决问题。

【讨论】:

以上是关于在 pig 中进行标记(使用 python udf)的主要内容,如果未能解决你的问题,请参考以下文章

在 Pig 中使用 Python UDF 时,如何让 Hadoop 查找导入的 Python 模块?

PIG UDF (Python) 字符集编码

如何从 Pig 中的 Python UDF 打印?

对于 Apache Pig,如何在 python 中编写 Load UDF

通过python UDF将文本文件导入pig

Pig的Python UDF:数据类型转换错误