Python 如何使用NLTK正则表达式模式用向上/向下指示器注释金融新闻?

Python 如何使用NLTK正则表达式模式用向上/向下指示器注释金融新闻?,python,regex,nlp,nltk,Python,Regex,Nlp,Nltk,我正在复制本文中描述的算法: 在最后一页中,它使用以下示例描述了如何提取标记为“NP JJ”的语法中定义的叶:营业利润率为8.3%,而去年为11.8% 我希望看到一个标签为“NP JJ”的叶子,但我没有。我对其原因(对正则表达式来说相对较新)感到非常惊讶 def split_句子(句子作为字符串): ''函数将句子拆分为单词列表 ''' 单词=单词标记化(句子作为字符串) 回话 def词性标签(句子列表): words=nltk.pos标签(句子列表) 回话 def get_regex(句子、语

我正在复制本文中描述的算法:

在最后一页中,它使用以下示例描述了如何提取标记为“NP JJ”的语法中定义的叶:营业利润率为8.3%,而去年为11.8%

我希望看到一个标签为“NP JJ”的叶子,但我没有。我对其原因(对正则表达式来说相对较新)感到非常惊讶

def split_句子(句子作为字符串):
''函数将句子拆分为单词列表
'''
单词=单词标记化(句子作为字符串)
回话
def词性标签(句子列表):
words=nltk.pos标签(句子列表)
回话
def get_regex(句子、语法):
句子=词性标注(分句(句子));
cp=nltk.RegexpParser(语法)
结果=cp.parse(句子)
返回结果
example_Session=“营业利润率为8.3%,而去年同期为11.8%。”
语法=“JJ:{ ∗}
vb:{}
NP:{()∗}
npp:{}
RB:{}
CD:{}
NP JJ:{+(<(>)。∗ > ∗ ) ∗ (
∗ < RB>∗ < JJ>∗ < NP | NP P>)∗ < RB>∗()∗ < V B>(
)∗ < NP | NP P>∗ < CD>∗ < .∗ > ∗ < CD>∗| < NP | NP P><。∗ > ∗ < V B>” 语法=语法。替换('∗','*') tree=get\u regex(例句,语法) 打印(树)
首先,请参见

让我们看看这个句子的词性标签是什么:

from nltk import word_tokenize, pos_tag

text = "Operating profit margin was 8.3%, compared to 11.8% a year earlier."
pos_tag(word_tokenize(text))
[out]:

[('Operating', 'NN'),
 ('profit', 'NN'),
 ('margin', 'NN'),
 ('was', 'VBD'),
 ('8.3', 'CD'),
 ('%', 'NN'),
 (',', ','),
 ('compared', 'VBN'),
 ('to', 'TO'),
 ('11.8', 'CD'),
 ('%', 'NN'),
 ('a', 'DT'),
 ('year', 'NN'),
 ('earlier', 'RBR'),
 ('.', '.')]
Tree('S', [('Operating', 'NN'), ('profit', 'NN'), ('margin', 'NN'), ('was', 'VBD'), 
  Tree('PERCENT', [('8.3', 'CD'), ('%', 'NN')]), 
(',', ','), ('compared', 'VBN'), ('to', 'TO'), 
  Tree('PERCENT', [('11.8', 'CD'), ('%', 'NN')]), 
('a', 'DT'), ('year', 'NN'), ('earlier', 'RBR'), ('.', '.')])
Tree('S', [('Operating', 'NN'), ('profit', 'NN'), ('margin', 'NN'), ('was', 'VBD'), 
           Tree('P2P', [
               Tree('PERCENT', [('8.3', 'CD'), ('%', 'NN')]), 
               (',', ','), ('compared', 'VBN'), ('to', 'TO'), 
               Tree('PERCENT', [('11.8', 'CD'), ('%', 'NN')])]
               ), 
           ('a', 'DT'), ('year', 'NN'), ('earlier', 'RBR'), ('.', '.')]
    )
(S
  Operating/NN
  profit/NN
  margin/NN
  was/VBD
  (P2P
    (PERCENT 8.3/CD %/NN)
    ,/,
    compared/VBN
    to/TO
    (PERCENT 11.8/CD %/NN))
  a/DT
  year/NN
  earlier/RBR
  ./.)
(P2P
  (PERCENT 8.3/CD %/NN)
  ,/,
  compared/VBN
  to/TO
  (PERCENT 11.8/CD %/NN)
  a/DT
  year/NN
  earlier/RBR)
首先,在任何标记中都没有
JJ
那句话中的任何位置都没有
JJ
标记

让我们回到报纸上

尽管如此,思考一下,
npjj
并不是最终目标;最终目标是基于一些启发产生
UP
DOWN
标签。 让我们重新表述以下步骤:

  • 使用解析器分析句子(在本例中,正则表达式解析器使用某种语法)

  • 识别句子有一个模式的信号,该模式可以告诉用户关于最终标签的用法

    2a.遍历解析树以提取另一个模式,该模式告诉我们有关性能指标和数值的信息

    2b.使用提取的数值确定方向性
    向上
    /
    向下
    ,使用一些启发式

    2c.用(2b)中标识的
    向上
    /
    向下
    标记句子

  • 让我们看看我们可以先构建哪个组件。 2b.提取另一个模式,告诉我们绩效指标和数值

    我们知道某些百分比的输出总是
    CD NN
    from

    ('8.3', 'CD'), ('%', 'NN')
    ('11.8', 'CD'), ('%', 'NN')
    
     ('8.3', 'CD'),
     ('%', 'NN'),
     (',', ','),
     ('compared', 'VBN'),
     ('to', 'TO'),
     ('11.8', 'CD'),
     ('%', 'NN'),
    
    让我们试着在语法中抓住它

    patterns = """
    PERCENT: {<CD><NN>}
    """
    
    PChunker = RegexpParser(patterns)
    PChunker.parse(pos_tag(word_tokenize(text)))
    
    现在,我们如何得到这个:

  • 识别一个信号,表明这个句子有一个模式,可以告诉你关于最终标签的用法
  • 我们知道与相比,
    是一个好模式,所以让我们尝试对其进行编码

    我们知道,
    相比,具有标签
    VBN to
    from

    ('8.3', 'CD'), ('%', 'NN')
    ('11.8', 'CD'), ('%', 'NN')
    
     ('8.3', 'CD'),
     ('%', 'NN'),
     (',', ','),
     ('compared', 'VBN'),
     ('to', 'TO'),
     ('11.8', 'CD'),
     ('%', 'NN'),
    
    这个怎么样:

    patterns = """
    PERCENT: {<CD><NN>}
    P2P: {<PERCENT><.*>?<VB.*><TO><PERCENT>}
    """
    
    PChunker = RegexpParser(patterns)
    PChunker.parse(pos_tag(word_tokenize(text)))
    
    但是,这种模式可以是任意数字。我们需要一个信号来指示
    性能指标
    由于我不是金融领域的领域专家,简单地利用
    营业利润率的存在可能是一个好信号,即

    from nltk import word_tokenize, pos_tag, RegexpParser
    
    patterns = """
    PERCENT: {<CD><NN>}
    P2P: {<PERCENT><.*>?<VB.*><TO><PERCENT>}
    """
    
    PChunker = RegexpParser(patterns)
    
    
    text = "Operating profit margin was 8.3%, compared to 11.8% a year earlier."
    
    indicators = ['operating profit margin']
    for i in indicators:
        if i in text.lower():
            print(PChunker.parse(pos_tag(word_tokenize(text))))
    
    现在我们如何使
    上升
    /
    下降
    ? 2b.使用提取的数值,使用一些启发式方法确定上/下方向性

    仅从例句中,除了“早”之外,没有其他任何东西告诉我们数字的先行性

    因此,让我们假设一下,如果我们有模式
    百分比VBN到之前的百分比
    ,我们说第二个百分比是一个旧的数字

    import nltk
    from nltk import word_tokenize, pos_tag, RegexpParser
    
    patterns = """
    PERCENT: {<CD><NN>}
    P2P: {<PERCENT><.*>?<VB.*><TO><PERCENT><.*>*<RBR>}
    """
    
    def traverse_tree(tree, label=None):
        # print("tree:", tree)
        for subtree in tree:
            if type(subtree) == nltk.tree.Tree and subtree.label() == label:
                yield subtree
    
    PChunker = RegexpParser(patterns)
    
    parsed_text = PChunker.parse(pos_tag(word_tokenize(text)))
    for p2p in traverse_tree(parsed_text, 'P2P'):
        print(p2p)
    
    向上
    /
    向下
    标签?
    导入nltk
    从nltk导入单词标记化、pos标记、RegexpParser
    “模式=”“”
    百分比:{}
    P2P:{?*}
    """
    PChunker=RegexpParser(模式)
    def遍历树(树,标签=无):
    #打印(“树:”,树)
    对于树中的子树:
    如果类型(子树)==nltk.tree.tree和subtree.label()==label:
    收益子树
    def labelme(文本):
    parsed_text=PChunker.parse(pos_标记(word_tokenize(text)))
    对于traverse_树中的p2p(已解析的_文本“p2p”):
    #检查子树是否以“早”结尾。
    如果p2p.leaves()[-1]==('previous','RBR'):
    #检查哪个百分比更大。
    p2p.leaves()中num的百分比=[float(num[0]),如果num[1]=='CD']
    #检查我们的模式是否只有两个数字。
    断言长度(百分比)=2
    如果百分比[0]>百分比[1]:
    返回“向下”
    其他:
    返回“向上”
    text=“营业利润率为8.3%,而去年同期为11.8%。”
    labelme(文本)
    
    现在问题开始了。。。 **您想编写这么多规则并使用上面的
    labelme()
    捕捉它们吗**

    您编写的模式是否万无一失?

    例如,是否会出现这样一种情况,即使用指标和“更早”比较百分比的模式不会如预期的那样“向上”或“向下”

    为什么我们要在人工智能时代写规则?


    你是否已经有了人工标注的数据,其中有句子及其相应的上/下标签?如果是这样,让我建议一些类似或

    奇怪的纸张,但让我们试着浏览一下=)感谢Alvas的反馈,真的很有帮助。不确定是谁否决了你的答案,我认为这是非常直观的。