5. TÌM HIỂU MỘT SỐ CHỨC NĂNG TRONG NLTK
5.4.3. Shift-Reduce Parsing
Một loại đơn giản của bottom-up parser là Shift-Reduce Parsing. Cách thực hiên chung nhất của phương pháp này là cố gắng để tìm thứ tự các từ và cụm từ tương ứng với phía bên tay phải của một luật sinh văn phạm, và thay thế chúng với phía bên tay trái, cho đến khi toàn bộ câu được rút ngắn về S.
The shift-reduce parser lặp lại việc đẩy từ đầu vào kế tiếp vào stack(ngăn xếp) gọi là thao tác shift. Nếu n phần tử trên cùng của stack khớp với n phần tử bên phải của một số luật, chúng sẽ được lấy khỏi stack, và phần tử bên trái của luật sẽ được đưa vào stack. Việc thay thế này của n phần tử trên cùng với một phần tử đơn được gọi là thao tác reduce. Các thao tác này chỉ được thực hiện trên cùng stack, việc giảm số phần tử thấp hơn trong stack phải được thực hiện trước khi những phần tử sau đó được đẩy vào stack. Bộ phân tích hoàn tất khi tất cả các đầu vào được sử dụng và chỉ có một phần tử còn lại trong stack, một cây cú pháp với node S là gốc của cây. Shift-reduce parser xây dựng cây trong suốt quá trình xử lý trên. Mỗi lần nó
lấy n phần tử ra khỏi stack nó kết hợp chúng thành cây một phần (patial parse tree) và đẩy ngược vào stack.
Chúng ta có thể xem biểu diễn thuật toán trong NLTK với lệnh nltk.app.srparser(). Chạy các luật văn phạm tương tự với câu “Mary saw a dog”.
1. Khởi tạo
2. Shift ‘Mary’
3. Lấy 1 phần tử từ Stack , khớp NP ‘Mary’: reduce lấy NP đẩy vào stack
4. Tương tự cho đến khi hết câu 5. Tiếp tục các phần tử trên cùng của stack: lấy 2 phần tử từ
stack khớp với luật NP->Det NP
6. Reduce VPV NP 7. Kết thúc
NLTK cung cấp bộ phân tích nltk.ShiftReduceParser (grammar). Bộ phân tích này
không cung cấp cơ chế quay lùi, không đảm bảo tìm được kết quả và cũng chỉ tìm được tối đa một kết quả duy nhất cho dù thật sự có nhiều kết quả hơn.
Quay lại với ví dụ đầu tiên nếu sử dụng ShiftReduceParser
>>> sent = 'the dog saw a man in the park'.split() >>> sent1 = 'Mary saw a dog'.split()
>>> g = nltk.parse_cfg(""" S -> NP VP
VP -> V NP | V NP PP PP -> P NP
V -> "saw" | "ate" | "walked"
NP -> "John" | "Mary" | "Bob" | Det N | Det N PP Det -> "a" | "an" | "the" | "my"
N -> "man" | "dog" | "cat" | "telescope" | "park" P -> "in" | "on" | "by" | "with"
""")
>>> sr_parse = nltk.ShiftReduceParser(g) >>> print sr_parse.parse(sent)
None
>>> print sr_parse.parse(sent1)
Câu sent không cho ra kết quả trong khi sent1 có 1 kết quả. Trong khi với top-down thì sent với cùng văn phạm cho ra 2 kết quả.
Ưu điểm của phương pháp này là xây dựng xử lý dựa vào câu đầu vào và chỉ duyệt duy nhất một lần.