Übungsblatt 9

Präsenzaufgaben

Aufgabe 1     Unifikation I


In [1]:
from nltk.featstruct import FeatStruct

Gegeben seien folgende Merkmalstrukturen:


In [2]:
f1 = FeatStruct(
    '[Vorname=Max, Nachname=Mustermann,' + 
    'Privat=[Strasse=Hauptstrasse, Ort=[Muenchen]]]'
)
f2 = FeatStruct(
    '[Arbeit=[Strasse="Oettingenstrasse", Ort=(1)["Muenchen"]],' +
    'Privat=[Ort->(1)]]')
f3 = FeatStruct(
    '[Strasse="Hauptstrasse"]'
)
f4 = FeatStruct(
    '[Privat=[Strasse="Hauptstrasse", Ort=["Passau"]]]'
)

Unifizieren Sie:

  • f1 mit f2

In [ ]:
print(f1.unify(f2).__repr__())
  • f2 mit f4

In [ ]:
print(f2.unify(f4).__repr__())

Aufgabe 2     Typhierarchie im NLTK

Gegeben sei folgende Typhierarchie:

$$\bot \sqsubseteq \text{Genitiv}$$
$$\bot \sqsubseteq \text{nicht-Genitiv}$$
$$\text{nicht-Genitiv} \sqsubseteq \text{Nominativ-Akkusativ}$$
$$\text{nicht-Genitiv} \sqsubseteq \text{Dativ}$$
$$\text{Nominativ-Akkusativ} \sqsubseteq \text{Nominativ}$$
$$\text{Nominativ-Akkusativ} \sqsubseteq \text{Akkusativ}$$

Implementieren Sie mithilfe der Klasse HierarchicalFeature, die Sie sich von der Kurs-Website herunterladen können, ein Feature CASE, das der vorgegebenen Typhierarchie entspricht.

Nutzen Sie dieses Feature dann, um Übergenerierung in folgender Grammatik zu vermeiden:


In [3]:
grammar = """
S -> NP VP
NP -> DET NOM
NOM -> N NP | N
VP -> V

V -> "schläft"
DET[GEN=mask] -> "der" | "des"
DET[GEN=fem] -> "die" | "der"
DET[GEN=neut] -> "das" | "des"
N[GEN=mask] -> "Mann" | "Mannes"
N[GEN=fem] -> "Frau"
N[GEN=neut] -> "Kind" | "Kindes"
"""

In [4]:
import nltk
from typed_features import HierarchicalFeature, TYPE

Hier muss die Typhierarchie in Form eines Dictionary definiert werden:


In [5]:
type_hierarchy = {
    
}

In [6]:
CASE = HierarchicalFeature("CASE", type_hierarchy)
compiled_grammar = nltk.grammar.FeatureGrammar.fromstring(
    grammar, features=(CASE, TYPE)
)
parser = nltk.FeatureEarleyChartParser(compiled_grammar)

Folgendes sollte funktionieren:


In [7]:
for t in parser.parse("das Kind des Mannes schläft".split()):
    print(t)


(S[]
  (NP[]
    (DET[] das)
    (NOM[] (N[] Kind) (NP[] (DET[] des) (NOM[] (N[] Mannes)))))
  (VP[] (V[] schläft)))

Folgendes sollte leer sein:


In [8]:
list(parser.parse("des Mannes schläft".split()))


Out[8]:
[Tree(S[], [Tree(NP[], [Tree(DET[], ['des']), Tree(NOM[], [Tree(N[], ['Mannes'])])]), Tree(VP[], [Tree(V[], ['schläft'])])])]

Hausaufgaben

Aufgabe 3     Unifikation II

Es seien wieder die Merkmalstrukturen aus Aufgabe 1 gegeben.

Unifizieren Sie:

  • f1 mit f4

In [ ]:
print(f1.unify(f4).__repr__())
  • f2 mit f3

In [ ]:
print(f2.unify(f3).__repr__())

Aufgabe 4     Weniger Redundanz dank besonderer Merkmale

Beseitigen Sie die Redundanz in den lexikalischen Regeln (Zeilen 8 - 32) der folgenden Grammatik durch eine Typhierarchie (wo dies nötig ist). Achten Sie darauf, die Menge der akzeptierten Sätze weder zu verkleinern noch zu vergrößern!

Anzugeben sind die neuen Grammatikregeln, sowie Ihre Typhierarchie (z. B. in graphischer Form).


In [9]:
redundant_grammar = """
S -> NP[KAS=nom] VP

NP[KAS=?y] -> DET[GEN=?x,KAS=?y] NOM[GEN=?x,KAS=?y]
NOM[GEN=?x,KAS=?y] -> N[GEN=?x,KAS=?y] NP[KAS=gen]
NOM[GEN=?x,KAS=?y] -> N[GEN=?x,KAS=?y]

DET[GEN=mask,KAS=nom] -> "der"
DET[GEN=mask,KAS=gen] -> "des"
DET[GEN=mask,KAS=dat] -> "dem"
DET[GEN=mask,KAS=akk] -> "den"
DET[GEN=fem,KAS=nom] -> "die"
DET[GEN=fem,KAS=gen] -> "der"
DET[GEN=fem,KAS=dat] -> "der"
DET[GEN=fem,KAS=akk] -> "die"
DET[GEN=neut,KAS=nom] -> "das"
DET[GEN=neut,KAS=gen] -> "des"
DET[GEN=neut,KAS=dat] -> "dem"
DET[GEN=neut,KAS=akk] -> "das"

N[GEN=mask,KAS=nom] -> "Mann"
N[GEN=mask,KAS=gen] -> "Mannes"
N[GEN=mask,KAS=dat] -> "Mann"
N[GEN=mask,KAS=akk] -> "Mann"
N[GEN=fem,KAS=nom] -> "Frau"
N[GEN=fem,KAS=gen] -> "Frau"
N[GEN=fem,KAS=dat] -> "Frau"
N[GEN=fem,KAS=akk] -> "Frau"
N[GEN=neut,KAS=nom] -> "Buch"
N[GEN=neut,KAS=gen] -> "Buches"
N[GEN=neut,KAS=dat] -> "Buch"
N[GEN=neut,KAS=akk] -> "Buch"

VP -> V NP[KAS=dat] NP[KAS=akk]
V -> "gibt" | "schenkt"
"""

In [10]:
pos_sentences = [
    "der Mann gibt der Frau das Buch",
    "die Frau des Mannes gibt dem Mann der Frau das Buch des Buches"
]

Testen Sie mit Ihren eigenen Negativbeispielen!


In [11]:
neg_sentences = [
    
]

In [12]:
from IPython.display import display

def test_grammar(grammar, sentences):
    cfg = nltk.grammar.FeatureGrammar.fromstring(grammar)
    parser = nltk.parse.FeatureEarleyChartParser(cfg)
    
    for i, sent in enumerate(sentences, 1):
        print("Satz {}: {}".format(i, sent))
        results = parser.parse(sent.split())
        analyzed = False
        for tree in results:
            print(tree)  # oder display(tree)
            analyzed = True
        if not analyzed:
            print("Keine Analyse möglich", file=sys.stderr)

In [13]:
test_grammar(redundant_grammar, pos_sentences)


Satz 1: der Mann gibt der Frau das Buch
(S[]
  (NP[KAS='nom']
    (DET[GEN='mask', KAS='nom'] der)
    (NOM[GEN='mask', KAS='nom'] (N[GEN='mask', KAS='nom'] Mann)))
  (VP[]
    (V[] gibt)
    (NP[KAS='dat']
      (DET[GEN='fem', KAS='dat'] der)
      (NOM[GEN='fem', KAS='dat'] (N[GEN='fem', KAS='dat'] Frau)))
    (NP[KAS='akk']
      (DET[GEN='neut', KAS='akk'] das)
      (NOM[GEN='neut', KAS='akk'] (N[GEN='neut', KAS='akk'] Buch)))))
Satz 2: die Frau des Mannes gibt dem Mann der Frau das Buch des Buches
(S[]
  (NP[KAS='nom']
    (DET[GEN='fem', KAS='nom'] die)
    (NOM[GEN='fem', KAS='nom']
      (N[GEN='fem', KAS='nom'] Frau)
      (NP[KAS='gen']
        (DET[GEN='mask', KAS='gen'] des)
        (NOM[GEN='mask', KAS='gen']
          (N[GEN='mask', KAS='gen'] Mannes)))))
  (VP[]
    (V[] gibt)
    (NP[KAS='dat']
      (DET[GEN='mask', KAS='dat'] dem)
      (NOM[GEN='mask', KAS='dat']
        (N[GEN='mask', KAS='dat'] Mann)
        (NP[KAS='gen']
          (DET[GEN='fem', KAS='gen'] der)
          (NOM[GEN='fem', KAS='gen'] (N[GEN='fem', KAS='gen'] Frau)))))
    (NP[KAS='akk']
      (DET[GEN='neut', KAS='akk'] das)
      (NOM[GEN='neut', KAS='akk']
        (N[GEN='neut', KAS='akk'] Buch)
        (NP[KAS='gen']
          (DET[GEN='neut', KAS='gen'] des)
          (NOM[GEN='neut', KAS='gen']
            (N[GEN='neut', KAS='gen'] Buches)))))))