V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
BarryLu
V2EX  ›  Python

「英文词组」分词问题

  •  
  •   BarryLu · 2020-11-16 20:51:05 +08:00 · 2778 次点击
    这是一个创建于 1261 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前已经有一个提问了: https://www.v2ex.com/t/340752#reply13

    关于这个问题搜索了挺久还不是很明白,于是开了这个帖子。

    我想做英文词组分词(可能不这么叫),比如 I love New York,我希望分词出来的是 I / love / New York,而不是:I / love / New / York 。New York 分开原本的意思就变了。

    中文分词有非常多的工具,比如结巴( https://github.com/fxsjy/jieba ),但是找英文词组分词工具就非常难(我甚至不知道用什么单词去搜索,比如是 Tokenizer 、Chunking 、还是 text segmentation ),请问英文有没有比较方便可以直接分词的工具。


    比如斯坦福的 stanza ( https://github.com/stanfordnlp/stanza ) 可以用于分词。中文分词结果没问题,但是英文只是按照空格做分词。

    text = """英国首相约翰逊 6 日晚因病情恶化。"""
    
    zh_nlp = stanza.Pipeline('zh')
    doc = zh_nlp(text)
    
    for sent in doc.sentences:
      print("Sentence:" + sent.text) # 断句
      print("Tokenize:" + ' '.join(token.text for token in sent.tokens)) # 中文分词
    

    它的输出结果是分词后的结果,这没问题:

    Tokenize:英国 首相 约翰逊 6 日 晚因 病情 恶化 , 被 转入 重症 监护 室 治疗 。
    

    但是英文分词:

    import stanza
    
    nlp = stanza.Pipeline(lang='en', processors='tokenize', tokenize_no_ssplit=True)
    doc = nlp('This is a sentence.\n\nThis is a second. This is a third.')
    for i, sentence in enumerate(doc.sentences):
        print(f'====== Sentence {i+1} tokens =======')
        print(*[f'id: {token.id}\ttext: {token.text}' for token in sentence.tokens], sep='\n')
    

    输出结果为:

    ====== Sentence 1 tokens =======
    id: (1,)	text: This
    id: (2,)	text: is
    id: (3,)	text: a
    id: (4,)	text: sentence
    id: (5,)	text: .
    ====== Sentence 2 tokens =======
    id: (1,)	text: This
    id: (2,)	text: is
    id: (3,)	text: a
    id: (4,)	text: second
    id: (5,)	text: .
    id: (6,)	text: This
    id: (7,)	text: is
    id: (8,)	text: a
    id: (9,)	text: third
    id: (10,)	text: .
    
    10 条回复    2021-01-05 15:23:34 +08:00
    heiheidewo
        1
    heiheidewo  
       2020-11-16 21:13:53 +08:00
    自己写一个吧,一般分词是按双向最长匹配来的,你把 New York 当做一个词处理即可
    TimePPT
        2
    TimePPT  
       2020-11-16 21:21:10 +08:00 via Android
    没明白,你举的 stanza 用 en pipeline 分出来哪里不对吗?
    chizuo
        3
    chizuo  
       2020-11-16 21:31:29 +08:00
    可以试试 nltk/spacy 这类库,一般以 word-level 为级别的分词,很难避免你说的这个问题。你可以试试 sub-word level 以及结合 named entity 、pos_tag 这类判断

    以 nlp tokenizer segmenter 为关键词看看相关论文
    BarryLu
        4
    BarryLu  
    OP
       2020-11-16 21:43:01 +08:00   ❤️ 1
    @TimePPT 想说的是,Stanza 的英文分词只是按照空格分开的,但是中文是 “真正分词”。另外比如 Tensorflow Keras 的英文分词( Tokenizer )也只是按照空格分开,现成的,做到类似于中文分词的「英文分词」工具,没找到。。。
    BarryLu
        5
    BarryLu  
    OP
       2020-11-16 21:49:01 +08:00
    @heiheidewo 自己写 😭 很有难度。另外如果需要处理一大批数据,我也不知道里面到底有多少「名词」不应该分开。
    TimePPT
        6
    TimePPT  
       2020-11-16 22:25:39 +08:00 via Android
    @BarryLu 很难做,LS 也提到了,通过 NER 之类的可以做到一部分,或者直接拿词典匹配。但没法完全避免。
    另外,其实中文分词颗粒度问题更难,根据业务需要要微调的。
    mxalbert1996
        7
    mxalbert1996  
       2020-11-16 22:52:37 +08:00 via Android
    英文里这种情况本来就很少,其中很大一部分都是专有名词,其实没太大影响,而且现在 NLP 都是 RNN,能识别前后关系,就更无所谓了。
    jhdxr
        8
    jhdxr  
       2020-11-16 23:04:37 +08:00
    其实你要的并不是分词,比如 I want to have a cup of green apple juice.
    在你定义的『分词』中,green apple juice 是一个『词』还是多个词?

    如果你认为那是一个词,那你可以考虑 syntax parsing
    如果你认为那是多个词,那我猜你想要的其实是识别专有名词(请尝试分词中文:『南京市长江大桥』),可以考虑 NER/NEM
    Merlini
        9
    Merlini  
       2020-11-16 23:16:00 +08:00
    这种一般是需要知识图谱辅助的,或者就直接用训练好的 NER 。比如 Spacy 的 NER:
    ```python
    import spacy

    nlp = spacy.load("en_core_web_sm")
    doc = nlp("Apple is looking at buying U.K. startup for $1 billion")

    for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)
    ```



    https://spacy.io/usage/linguistic-features#named-entities-101
    yucongo
        10
    yucongo  
       2021-01-05 15:23:34 +08:00
    不知道楼主有没有找到解决方法?找到了话能不能分享一下?

    如果只是对名词词组感兴趣,spacy/textaxy/textblob 里的 noun_chunks/noun phrases/NER 或许有用。但我也是希望能像 jieba 做中文分词那样将英语句子分成有意义的词组,例如:A match / is / a tool / for starting / a fire. Typically, / modern matches / are made of / small wooden sticks or stiff paper.

    搜了一下,好像没有现成的工具,最接近的办法可能是用 spacy 的 rule based matching 匹配出 noun phrase (比较简单,有现成的)和 verb phrase 。textacy 里有个极简的 VP 常数('<AUX>* <ADV>* <VERB>')。

    总之,离英语“词组分词”还很远
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2279 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:09 · PVG 12:09 · LAX 21:09 · JFK 00:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.