[Python] Why is this dependency parser choosing the same action over again?

Discussão em 'Python' iniciado por Stack, Agosto 5, 2025.

  1. Stack

    Stack Membro Participativo

    I am attempting to write a small dependency parser using a multiclass perceptron as the learner. The parser is a simple machine that has a few actions: START_ARC, MOVE_RIGHT, END_ARC and to move forwards to the next token that should be treated. I have the code for it below:

    class DependencyParser1:

    """
    self.token_index must be manually increased along with the sentence,
    as each token has been processed. Do it as soon as self.start_arc()
    has been called. self.move_right() only moves the move pointer to the
    next token, while self.token_index keeps track of the token that is
    to be assigned a head.

    Each arc is a tuple [x, y] where x is the start, and y is the head.
    """
    def __init__(self):
    self.move_index = 0
    self.token_index = -1
    self.arcs = []
    self.arc = [0, 0]

    def move_right(self):
    self.move_index += 1

    def start_arc(self):
    self.arc[0] = self.token_index + 1

    def end_arc(self):
    self.arc[1] = 0 if self.move_index == 0 else self.move_index + 1
    self.arcs.append(self.arc)
    self.arc = [0, 0]
    self.move_index = 0

    def reset(self):
    self.arcs = []
    self.arc = [0, 0]
    self.token_index = - 1
    self.move_index = 0


    The trainer looks like this:

    class Trainer:

    def __init__(self, parser):
    self.parser = parser
    self.features = []
    self.classes = []

    def train(self, sentence):
    arc_start_index = 0 # 0 is the first token. The root
    # is numbered 0, the rest of the
    # tokens are numbered as the index
    # plus 1.

    sentence_length = len(sentence)

    while arc_start_index < sentence_length:
    self.parser.token_index += 1
    self.parser.start_arc()
    self.features.append(FeaturesRecorder.record(locals()))
    self.classes.append(START_ARC)

    arc_end_index = 0
    head = int(sentence[arc_start_index].head) - 1

    while arc_end_index < head:
    arc_end_index += 1
    self.parser.move_right()
    self.features.append(FeaturesRecorder.record(locals()))
    self.classes.append(MOVE_RIGHT)

    self.parser.end_arc()
    self.features.append(FeaturesRecorder.record(locals()))
    self.classes.append(END_ARC)
    arc_start_index += 1


    The trainer can accurately reproduce the arcs of existing treebank data when being fed the actions that the trainer learned.

    class ParserRunner:

    def __init__(self, parser, perceptron):
    self.parser = parser
    self.perceptron = perceptron

    def cheat(self, sentence, actions):
    actions_copy = actions.copy()
    arc_start_index = 0

    sentence_length = len(sentence)

    while actions_copy:
    action = actions_copy.pop(0)
    if action == START_ARC:
    self.parser.token_index += 1
    self.parser.start_arc()
    elif action == MOVE_RIGHT:
    self.parser.move_right()
    elif action == END_ARC:
    self.parser.end_arc()

    return self.parser.arcs

    def parse(self, sentence):
    arc_start_index = 0
    sentence_length = len(sentence)
    arc_is_started = 0

    while arc_start_index < sentence_length:
    recording = FeaturesRecorder.record(locals())
    print(recording)
    action = self.perceptron.predict([recording])
    print(action)
    #print(action)
    if action == START_ARC:
    self.parser.token_index += 1
    self.parser.start_arc()
    arc_is_started = 1
    elif action == MOVE_RIGHT:
    self.parser.move_right()
    elif action == END_ARC:
    self.parser.end_arc()
    arc_start_index += 1

    return self.parser.arcs


    I have encountered an error where the predictions that the perceptron makes are just to end the current arc without doing anything else, and it does this for each token. I would be happy to post more information on request. This is my first time writing a dependency parser from scratch.

    I was expecting the ParserRunner.parse() method to choose a different action than to end the arc.

    Continue reading...

Compartilhe esta Página