日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python自然语言处理 | 分析句子结构

發布時間:2023/12/20 python 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python自然语言处理 | 分析句子结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 本章解決的問題
  • 我們如何使用形式化語法來描述無限的句子集合的結構
  • 我們如何使用句法樹來表示句子結構
  • 語法分析器如何分析一個句子并自動構建句法樹?
  • 這里寫目錄標題

    • 1 一些語法困境
      • 1.1 語言數據和無限可能性
      • 1.2 普遍存在的歧義
    • 2 文法有什么用?
      • 2.1 超越 n-grams
    • 3 上下文無關文法
      • 3.1 一種簡單的文法
      • 3.2 寫你自己的文法
      • 3.3 句法結構中的遞歸
    • 4 上下文無關文法分析
      • 4.2 4.2 移進-歸約分析
      • 4.3 左角落分析器
      • 4.4 符合語句規則的子串表 WFST
    • 5 依存關系和依存文法
      • 5.1 配價與詞匯
      • 5.2 擴大規模
    • 6 文法開發
      • 6.1 樹庫和文法
      • 6.2 有害的歧義
      • 6.3 加權文法
    • 7 小結

    1 一些語法困境

    1.1 語言數據和無限可能性

    1.2 普遍存在的歧義

    #讓我們仔細看看短語 I shot an elephant in my pajamas 中的歧義。 #首先,我們需要定義一個簡單的文法: import nltk groucho_grammar = nltk.CFG.fromstring("""S -> NP VPPP -> P NPNP -> Det N | Det N PP | 'I'VP -> V NP | VP PPDet -> 'an' | 'my'N -> 'elephant' | 'pajamas'V -> 'shot'P -> 'in'""") #這個文法允許以兩種方式分析句子,取決于介詞短語 in my pajamas 是描述大象還是槍擊事件。 sent = ['I', 'shot', 'an', 'elephant', 'in', 'my', 'pajamas'] parser = nltk.ChartParser(groucho_grammar) for tree in parser.parse(sent):print(tree)tree.draw()""" (S(NP I)(VP(VP (V shot) (NP (Det an) (N elephant)))(PP (P in) (NP (Det my) (N pajamas))))) (S(NP I)(VP(V shot)(NP (Det an) (N elephant) (PP (P in) (NP (Det my) (N pajamas))))))"""

    本章介紹文法和分析,以形式化可計算的方法調查和建模我們一直在討論的語言現象正如我們所看到的,詞序列中符合語法規則的和不符合語法規則的模式相對于短語結構和依賴是可以被理解的。我們可以開發使用文法和分析的這些結構的形式化模型。與以前一樣,一個重要的動機是自然語言理解。當我們能可靠地識別一個文本所包含的語言結構時,我們從中可以獲得多少文本的含義?

    2 文法有什么用?

    2.1 超越 n-grams

    • 成分結構基于對詞與其他詞結合在一起形成單元的觀察。一個詞序列形成這樣一個單元的證據是它是可替代的——也就是說,在一個符合語法規則的句子中的詞序列可以被一個更小的序列替代而不會導致句子不符合語法規則


    3 上下文無關文法

    3.1 一種簡單的文法

    """ #首先,讓我們看一個簡單的上下文無關文法 # 按照慣例, 第一條生產式的左端是文法的開始符號,通常是 S(句子),所有符合語法規則的樹都必須有這個符 號作為它們的根標簽。 # NLTK中,上下文無關文法定義在 nltk.grammar 模塊。 """#上下文無關文法 grammar1 = nltk.CFG.fromstring("""S -> NP VPVP -> V NP | V NP PPPP -> P NPV -> "saw" | "ate" | "walked"NP -> "John" | "Mary" | "Bob" | Det N | Det N PPDet -> "a" | "an" | "the" | "my"N -> "man" | "dog" | "cat" | "telescope" | "park"P -> "in" | "on" | "by" | "with"""") sent = "Mary saw Bob".split() rd_parser = nltk.RecursiveDescentParser(grammar1) for tree in rd_parser.parse(sent):print(tree)tree.draw()

    文法組成部分的不同提取方式會產生不一樣的意思:

    3.2 寫你自己的文法

    import nltkdef yours_grammar(gram):sent = "Mary saw Bob".split()rd_parser = nltk.RecursiveDescentParser(gram)for tree in rd_parser.parse(sent):print(tree)tree.draw()grammar1 =nltk.data.load('file:mygrammar.cfg') # #確保你的文件名后綴為.cfg,并且字符串'file:mygrammar.cfg中'間沒有空格符 print(yours_grammar(grammar1))

    3.3 句法結構中的遞歸

    #一個文法被認為是遞歸的,如果文法類型出現在產生式左側也出現在右側, #如例 8-2 所 示。產生式 Nom -> Adj Nom(其中 Nom 是名詞性的類別)包含 Nom 類型的直接遞歸, #而 S 上的間接遞歸來自于兩個產生式的組合:S -> NP VP 與 VP -> V S。#例. 遞歸的上下文無關文法。 grammar2 = nltk.CFG.fromstring("""S -> NP VPNP -> Det Nom | PropNNom -> Adj Nom | NVP -> V Adj | V NP | V S | V NP PPPP -> P NPPropN -> 'Buster' | 'Chatterer' | 'Joe'| 'Today'Det -> 'the' | 'a'N -> 'bear' | 'squirrel' | 'tree' | 'fish' | 'log' | 'Sunday' Adj -> 'angry' | 'frightened' | 'little' | 'tall' | 'sunny'V -> 'chased' | 'saw' | 'said' | 'thought' | 'was' | 'put' | 'is'P -> 'on'""") def yours_grammar(sent, gram):rd_parser = nltk.RecursiveDescentParser(gram)for tree in rd_parser.parse(sent):print(tree)tree.draw() sent1 = "the angry bear chased the frightened little squirrel".split() sent2 = "Chatterer said Buster thought the tree was tall".split() sent3 = "Today is sunny".split() print("sent1: ") print(yours_grammar(sent1, grammar2)) print("sent2: ") print(yours_grammar(sent2, grammar2)) print("sent3: ") print(yours_grammar(sent3, grammar2)) # 不添加會報錯 Grammar does not cover some of the input words: "'Today', 'is', 'Sunday'".

    4 上下文無關文法分析

  • 分析器根據文法產生式處理輸入的句子,并建立一個或多個符合文法的組成結構。
  • 文法 是一個格式良好的聲明規范——它實際上只是一個字符串,而不是程序。
  • 分析器是文法的解釋程序。它搜索符合文法的所有樹的空間找出一棵邊緣有所需句子的樹。
  • 分析器允許使用一組測試句子評估一個文法,幫助語言學家發現在他們的文法分析中存 在的錯誤。
  • 分析器可以作為心理語言處理模型,幫助解釋人類處理某些句法結構的困難。
  • """ 1 一種最簡單的分析器將一個文法作為如何將一個高層次的目標分解成幾個低層次的子目標的規范來解釋。 2 遞歸下降分析器在上述過程中建立分析樹。帶著最初的目標(找到一個 S),創建 S 根節點。 3 隨著上述過程使用文法的產生式遞歸擴展,分析樹不斷向下延伸(故名為遞歸下降) 4 我們可以在圖形化示范 nltk.app.rdparser()中看到這個過程 """nltk.app.rdparser()grammar1 = nltk.CFG.fromstring("""S -> NP VPVP -> V NP | V NP PPPP -> P NPV -> "saw" | "ate" | "walked"NP -> "John" | "Mary" | "Bob" | Det N | Det N PPDet -> "a" | "an" | "the" | "my"N -> "man" | "dog" | "cat" | "telescope" | "park"P -> "in" | "on" | "by" | "with"""")#NLTK 提供了一個遞歸下降分析器: rd_parser = nltk.RecursiveDescentParser(grammar1) sent = "Mary saw a dog".split() for tree in rd_parser.parse(sent):print(tree)""" 遞歸下降分析有三個主要的缺點。 1 首先,左遞歸產生式,如:NP -> NP PP,會進入死循環。 2 第二,分析器浪費了很多時間處理不符合輸入句子的詞和結構。 3 第三,回溯過程中可 能會丟棄分析過的成分,它們將需要在之后再次重建。 #例如:從VP -> V NP上回溯將放 棄為 NP 創建的子樹。 #如果分析器之后處理 VP -> V NP PP,那么 NP 子樹必須重新創建。 """

    4.2 4.2 移進-歸約分析

    簡單的自下而上分析器是移進-歸約分析器。

    """ 1 簡單的自下而上分析器是移進-歸約分析器。 2 嘗試找到對應文法生產式右側的詞和短語的序列,用左側的替換它們,直到整個句子歸約為一個 S。 3 移進-歸約分析器的六個階段:分析器一開始把輸入的第一個詞轉移到堆棧; 4 一旦堆 棧頂端的項目與一個文法產生式的右側匹配,就可以將它們用那個產生式的左側替換; 5 當所有輸入都被使用過且堆棧中只有剩余一個項目 S 時,分析成功。 6 用nltk.app.srparser()示意流程 """ nltk.app.srparser() #NLTK 中提供了 ShiftReduceParser(),移進-歸約分析器的一個簡單的實現。 sr_parse = nltk.ShiftReduceParser(grammar1) sent = 'Mary saw a dog'.split() for tree in sr_parse.parse(sent):print(tree)

    移進-規約分析器缺點可能會到達一個死胡同,而不能找到任何解析,即使輸入的句子是符合語法的。這種情況發生時,沒有剩余的輸入,而堆棧包含不能被規約到一個S的項目。

    問題出現的原因是:較早前做出的選擇不能被分析器撤銷(雖然圖形演示中用戶可以撤消它們的選擇)。

    分析器可以做兩種選擇:(a)當有多種規約可能時選擇哪個規約,(b)當移進和規約都可以時選擇哪個動作。

    移進-規約分析器可以改進執行策略來解決這些沖突。例如:它可以通過只有在不能規約時才移進,解決移進-規約沖突;它可以通過優先執行規約操作,解決規約-規約沖突;它可以從堆棧移除更多的項目。(一個通用的移進-規約分析器,是一個“超前LR分析器”,普遍使用在編程語言編譯器中。)

    移進-規約分析器相比遞歸下降分析器的好處是,它們只建立與輸入中的詞對應的結構。此外,每個結構它們只建立一次。例如:NP(Det(the),N(man))只建立和壓入棧一次,不管以后VP -> V NPPP規約或者NP ->NPPP規約會不會用到。

    4.3 左角落分析器

    4.4 符合語句規則的子串表 WFST

    """ #運用動態 規劃算法設計技術分析問題 #動態規劃存儲中間結果,并在 適當的時候重用它們,能顯著提高效率。#這種技術可以應用到句法分析,使我們能夠存儲分析任務的部分解決方案, #然后在必要的時候查找它們,直到達到最終解決方案。這種分析方法被稱為圖表分析。#動態規劃使我們能夠只建立一次 PP in my pajamas。 #第一次我們建立時就把它存入一 個表格中,然后在我們需要作為對象 NP 或更高的 VP 的組成部分用到它時我們就查找表格。 #這個表格被稱為符合語法規則的子串表 或簡稱為 WFST。 """#使用符合語句規則的子串表的接收器。 def init_wfst(tokens, grammar):numtokens = len(tokens)wfst = [[None for i in range(numtokens+1)] for j in range(numtokens+1)]for i in range(numtokens):productions = grammar.productions(rhs=tokens[i])wfst[i][i+1] = productions[0].lhs()return wfstdef complete_wfst(wfst, tokens, grammar, trace=False):index = dict((p.rhs(), p.lhs()) for p in grammar.productions())numtokens = len(tokens)for span in range(2, numtokens+1):for start in range(numtokens+1-span):end = start + spanfor mid in range(start+1, end):nt1, nt2 = wfst[start][mid], wfst[mid][end]if nt1 and nt2 and (nt1,nt2) in index:wfst[start][end] = index[(nt1,nt2)]if trace:print("[%s] %3s [%s] %3s [%s] ==> [%s] %3s [%s]" % \(start, nt1, mid, nt2, end, start, index[(nt1,nt2)], end))return wfstdef display(wfst, tokens):print('\nWFST ' + ' '.join(("%-4d" % i) for i in range(1, len(wfst))))for i in range(len(wfst)-1):print("%d " % i, end=" ")for j in range(1, len(wfst)):print("%-4s" % (wfst[i][j] or '.'), end=" ")print() tokens = "I shot an elephant in my pajamas".split() wfst0 = init_wfst(tokens, groucho_grammar) display(wfst0, tokens) wfst1 = complete_wfst(wfst0, tokens, groucho_grammar) display(wfst1, tokens) wfst1 = complete_wfst(wfst0, tokens, groucho_grammar, trace=True) # 找出過程 設置參數trace

    5 依存關系和依存文法

  • 短語結構文法是關于詞和詞序列如何結合起來形成句子成分的。
  • 一個獨特的和互補的方式,依存文法,集中關注的是詞與其他詞之間的關系。
  • 依存關系是一個中心詞與它的依賴之間的二元對稱關系。
  • 一個句子的中心詞通常是動詞,所有其他詞要么依賴于中心詞,要么依 賴路徑與它聯通。
  • 依存關系表示是一個加標簽的有向圖,其中節點是詞匯項,加標簽的弧表示依賴關系,從中心詞到依賴。
  • """#下面是 NLTK 為依存文法編碼的一種方式 ——注意它只能捕捉依存關系信息,不能指定依存關系類型:"""groucho_dep_grammar = nltk.DependencyGrammar.fromstring("""'shot' -> 'I' | 'elephant' | 'in''elephant' -> 'an' | 'in''in' -> 'pajamas''pajamas' -> 'my'""") print(groucho_dep_grammar)


  • 依存關系圖是一個投影,當所有的詞都按線性順序書寫 ,邊可以在詞上繪制而不會交叉。
  • 這等于是說一個詞及其所有后代依賴(依賴及其依賴的依賴,等等)在句子中形成一個連續 的詞序列
  • #依存關系圖是一個投影,當所有的詞都按線性順序書寫 ,邊可以在詞上繪制而不會交叉。 #這等于是說一個詞及其所有后代依賴(依賴及其依賴的依賴,等等)在句子中形成一個連續 的詞序列 pdp = nltk.ProjectiveDependencyParser(groucho_dep_grammar) sent = 'I shot an elephant in my pajamas'.split() trees = pdp.parse(sent) for tree in trees:print(tree)tree.draw()

    5.1 配價與詞匯

    • 動詞和它們的依賴

    • 依賴 ADJ、NP、PP 和 S 通常被稱為各自動詞的補語,什么動詞可以和什么補語一起出現 具有很強的約束。

    • 在依存文法的傳統中,在表 8-3 中的動詞被認為具有不同的配價。配價限制不僅適用于 動詞,也適用于其他類的中心詞。

    • 介詞短語、形容詞和副詞通常充當修飾語。與補充不同修飾語是可選的,經常可以進行 迭代,不會像補語那樣被中心詞選擇。

    5.2 擴大規模

    到目前為止,我們只考慮了“玩具文法”,演示分析的關鍵環節的少量的文法,但有一個明顯的問題就是這種做法是否可以擴大到覆蓋自然語言的大型語料庫。

    很難將文法模塊化,每部分文法可以獨立開發。反過來這意味著,在一個語言學家團隊中分配編寫文法的任 務是很困難的。

    另一個困難是當文法擴展到包括更加廣泛的成分時,適用于任何一個句子的分析的數量也相應增加。 換句話說,歧義隨著覆蓋而增加。

    6 文法開發

    分析器根據短語結構文法在句子上建立樹。現在,我們上面給出的所有例子只涉及玩具文法包含少數的產生式。如果我們嘗試擴大這種方法的規模來處理現實的語言語料庫會發生什么?在本節中,我們將看到如何訪問樹庫,并看看開發廣泛覆蓋的文法的挑戰。

    6.1 樹庫和文法

    # corpus 模塊定義了樹庫語料的閱讀器,其中包含了賓州樹庫語料的 10%的樣本。 from nltk.corpus import treebank t = treebank.parsed_sents('wsj_0001.mrg')[0] print(t) #我們可以利用這些數據來幫助開發一個文法。 #搜索樹庫找出句子的補語。 def filter(tree):child_nodes = [child.label() for child in tree if isinstance(child, nltk.Tree)]return (tree.label() == 'VP') and ('S' in child_nodes) from nltk.corpus import treebank print([subtree for tree in treebank.parsed_sents() for subtree in tree.subtrees(filter)][1]) #NLTK 語料庫也收集了中央研究院樹庫語料,包括 10000 句已分析的句子,來自現代漢 語中央研究院平衡語料庫。 #讓我們加載并顯示這個語料庫中的一棵樹。 print(nltk.corpus.sinica_treebank.parsed_sents()[3449].draw())

    6.2 有害的歧義

    不幸的是,隨著文法覆蓋范圍的增加和輸入句子長度的增長,分析樹的數量也迅速增長事實上,它以天文數字的速度增長。

    grammar = nltk.CFG.fromstring("""S -> NP V NPNP -> NP SbarSbar -> NP VNP -> 'fish'V -> 'fish'""") tokens = ['fish'] * 5 cp = nltk.ChartParser(grammar) for tree in cp.parse(tokens):print(tree) #隨著句子長度增加到(3,5,7,...),我們得到的分析樹的數量是:1; 2; 5; 14; 42; 132; 429; 1,430; 4,862; 16,796; 58,786; 208,012; ....

    6.3 加權文法

  • 處理歧義是開發廣泛覆蓋的分析器的主要挑戰。
  • 圖表分析器提高 了計算一個句子的多個分析的效率,但它們仍然因可能的分析的數量過多而不堪重負。
  • 加權文法和概率分析算法為這些問題提供了一個有效的解決方案。
  • #賓州樹庫樣本中give和gave的用法。 def give(t):return t.label() == 'VP' and len(t) > 2 and t[1].label() == 'NP'\and (t[2].label() == 'PP-DTV' or t[2].label() == 'NP')\and ('give' in t[0].leaves() or 'gave' in t[0].leaves()) def sent(t):return ' '.join(token for token in t.leaves() if token[0] not in '*-0') def print_node(t, width):output = "%s %s: %s / %s: %s" %\(sent(t[0]), t[1].label(), sent(t[1]), t[2].label(), sent(t[2]))if len(output) > width:output = output[:width] + "..."print(output)for tree in nltk.corpus.treebank.parsed_sents():for t in tree.subtrees(give):print_node(t, 72)
    • 概率上下文無關文法(probabilistic context-free grammar,PCFG)
  • 概率上下文無關文法(probabilistic context-free grammar,PCFG)是一種上下文無關文 法,
  • 它的每一個產生式關聯一個概率。它會產生與相應的上下文無關文法相同的文本解析, 并給每個解析分配一個概率。
  • PCFG 產生的一個解析的概率僅僅是它用到的產生式的概率的乘積。
  • #概率上下文無關文法(probabilistic context-free grammar,PCFG)是一種上下文無關文 法, #它的每一個產生式關聯一個概率。它會產生與相應的上下文無關文法相同的文本解析, 并給每個解析分配一個概率。 #PCFG 產生的一個解析的概率僅僅是它用到的產生式的概率的乘積。grammar = nltk.PCFG.fromstring("""S -> NP VP [1.0]VP -> TV NP [0.4]VP -> IV [0.3]VP -> DatV NP NP [0.3]TV -> 'saw' [1.0]IV -> 'ate' [1.0]DatV -> 'gave' [1.0]NP -> 'telescopes' [0.8]NP -> 'Jack' [0.2]""") print(grammar)viterbi_parser = nltk.ViterbiParser(grammar) for tree in viterbi_parser.parse(['Jack', 'saw', 'telescopes']):print(tree)# 現在,分析樹被分配了概率,一個給定的句子可能有數量龐大的可能的解析就不再是問題。分析器將負責尋找最有可能的解析。

    7 小結

    總結

    以上是生活随笔為你收集整理的python自然语言处理 | 分析句子结构的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。