Пример #1
0
def strip_functional_tags(tree: Tree) -> None:
    """
    Removes all functional tags from constituency labels in an NLTK tree.
    We also strip off anything after a =, - or | character, because these
    are functional tags which we don't want to use.
    This modification is done in-place.
    """
    clean_label = tree.label().split("=")[0].split("-")[0].split("|")[0]
    tree.set_label(clean_label)
    for child in tree:
        if not isinstance(child[0], str):
            strip_functional_tags(child)
Пример #2
0
    def _strip_functional_tags(self, tree: Tree) -> None:
        """
        Removes all functional tags from constituency labels in an NLTK tree.
        We also strip off anything after a =, - or | character, because these
        are functional tags which we don't want to use.

        This modification is done in-place.
        """
        clean_label = tree.label().split("=")[0].split("-")[0].split("|")[0]
        tree.set_label(clean_label)
        for child in tree:
            if not isinstance(child[0], str):
                self._strip_functional_tags(child)
Пример #3
0
def build_tree(node,chain): # -> handle function tags
    """ -> PS tree of node's projection chain """
    preterminal = node['tag']
    if 'lemma' in node: # not a trace-node
        if (node['lemma'].lower() in wh_lemmas) and \
           node['tag']!='CONJ': #WH feature
            preterminal += '-WH'    
    output = Tree(preterminal,[node['word']])
    for l in chain[0][::-1]:
        for i in range(l[1]):
            output = Tree(l[0],[output])
    if chain[1]:
        if chain[1]=='PRN':
            output = Tree(chain[1],[output])
        else:
            output.set_label(output.label()+'-'+chain[1])
    return output
Пример #4
0
  def forward(self, word_list, gold_op_list, unary_limit):
    is_training = gold_op_list is not None

    # check args
    if len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if is_training:
      n_shift = 0
      n_binary = 0
      for op, _ in gold_op_list:
        if op == OP_SHIFT: n_shift += 1
        if op == OP_BINARY: n_binary += 1
      if n_shift != len(word_list) or n_binary != len(word_list) - 1:
        raise ValueError(
            'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)' %
            (n_shift, n_binary, len(word_list), len(word_list) - 1))
      if gold_op_list[-1] != (OP_FINISH, None):
        raise ValueError('Last operation is not OP_FINISH.')

    # initial values
    EMBED_ZEROS = XP.fzeros((1, self.n_embed))
    QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
    STACK_ZEROS = XP.fzeros((1, self.n_stack))
    SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
    NEG_INF = -1e20

    # queue encoding
    xq_list = []
    qc = QUEUE_ZEROS
    q = QUEUE_ZEROS
    
    for text, wid in reversed(word_list):
      x = self.net_embed(XP.iarray([wid]))
      qc, q = self.net_encoder(qc, x, q)
      xq_list.insert(0, (text, x, q))

    # estimate
    s_list = []
    zc = SRSTATE_ZEROS
    z = SRSTATE_ZEROS
    unary_chain = 0
    if is_training:
      loss = XP.fzeros(())

    for i in itertools.count():
      text, x, q = xq_list[0] if xq_list else ('', EMBED_ZEROS, QUEUE_ZEROS)
      t1, sc1, s1 = s_list[-1] if s_list else (None, STACK_ZEROS, STACK_ZEROS)
      t2, sc2, s2 = s_list[-2] if len(s_list) >= 2 else (None, STACK_ZEROS, STACK_ZEROS)
      t3, sc3, s3 = s_list[-3] if len(s_list) >= 3 else (None, STACK_ZEROS, STACK_ZEROS)

      zc, z = self.net_sr(zc, q, s1, z)  
      o = self.net_operation(z)

      if is_training:
        loss += functions.softmax_cross_entropy(o, XP.iarray([gold_op_list[i][0]]))
        o_argmax = gold_op_list[i][0]
      else:
        o_filter = [0.0 for _ in range(NUM_OP)]
        filtered = 0
        if not xq_list:
          o_filter[OP_SHIFT] = NEG_INF
          filtered += 1
        if not s_list or unary_chain >= unary_limit:
          o_filter[OP_UNARY] = NEG_INF
          filtered += 1
        if len(s_list) < 2:
          o_filter[OP_BINARY] = NEG_INF
          filtered += 1
        if xq_list or len(s_list) > 1:
          o_filter[OP_FINISH] = NEG_INF
        if filtered == NUM_OP:
          raise RuntimeError('No possible operation!')

        o += XP.farray([o_filter])
        o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = (STACK_ZEROS, self.net_shift(x, q, s1, z))
        xq_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc1, q, s1, s2, z)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc1, sc2, q, s1, s2, s3, z)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      if is_training:
        loss += functions.softmax_cross_entropy(label, XP.iarray([gold_op_list[i][1]]))
        label_argmax = gold_op_list[i][1]
      else:
        label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0))

      '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op_list[i][0] else ' ',
            '*' if label_est == gold_op_list[i][1] else ' ',
            gold_op_list[i][0], gold_op_list[i][1],
            o_est, label_est,
            len(s_list), len(xq_list)))
      '''

    if is_training:
      return loss
    else:
      # combine multiple trees if they exists, and return the result.
      t0, _, __ = s_list.pop()
      if s_list:
        raise RuntimeError('There exist multiple subtrees!')
      return t0
Пример #5
0
    def forward(self, word_list, gold_op_list, unary_limit):
        is_training = gold_op_list is not None

        # check args
        if len(word_list) < 1:
            raise ValueError('Word list is empty.')
        if is_training:
            n_shift = 0
            n_binary = 0
            for op, _ in gold_op_list:
                if op == OP_SHIFT: n_shift += 1
                if op == OP_BINARY: n_binary += 1
            if n_shift != len(word_list) or n_binary != len(word_list) - 1:
                raise ValueError(
                    'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)'
                    % (n_shift, n_binary, len(word_list), len(word_list) - 1))
            if gold_op_list[-1] != (OP_FINISH, None):
                raise ValueError('Last operation is not OP_FINISH.')

        # default values
        EMBED_ZEROS = XP.fzeros((1, self.n_embed))
        CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
        QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
        STACK_ZEROS = XP.fzeros((1, self.n_stack))
        SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
        QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS,
                         QUEUE_ZEROS, QUEUE_ZEROS)
        STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS)
        NEG_INF = -1e20

        # word embedding
        x_list = [self.net_embed(XP.iarray([wid])) for _, wid in word_list]
        jk_list = [self.net_cembed(text) for text, _ in word_list]

        # forward encoding
        a_list = []
        ac = QUEUE_ZEROS
        a = QUEUE_ZEROS
        for x, (j, k) in zip(x_list, jk_list):
            ac, a = self.net_forward(ac, x, j, k, a)
            a_list.append(a)

        # backward encoding
        b_list = []
        bc = QUEUE_ZEROS
        b = QUEUE_ZEROS
        for x, (j, k) in zip(reversed(x_list), reversed(jk_list)):
            bc, b = self.net_backward(bc, x, j, k, b)
            b_list.insert(0, b)

        q_list = [
          (text, x, j, k, a, b) \
          for (text, _), x, (j, k), a, b \
          in zip(word_list, x_list, jk_list, a_list, b_list)]

        # estimate
        s_list = []
        zc = SRSTATE_ZEROS
        z = SRSTATE_ZEROS
        unary_chain = 0
        if is_training:
            loss = XP.fzeros(())

        for i in itertools.count():
            text, x, j, k, a, b = q_list[0] if q_list else QUEUE_DEFAULT
            t1, sc1, s1 = s_list[-1] if s_list else STACK_DEFAULT
            t2, sc2, s2 = s_list[-2] if len(s_list) >= 2 else STACK_DEFAULT
            t3, sc3, s3 = s_list[-3] if len(s_list) >= 3 else STACK_DEFAULT

            zc, z = self.net_sr(zc, a, b, s1, s2, z)
            o = self.net_operation(z)

            if is_training:
                loss += functions.softmax_cross_entropy(
                    o, XP.iarray([gold_op_list[i][0]]))
                o_argmax = gold_op_list[i][0]
            else:
                o_filter = [0.0 for _ in range(NUM_OP)]
                filtered = 0
                if not q_list:
                    o_filter[OP_SHIFT] = NEG_INF
                    filtered += 1
                if not s_list or unary_chain >= unary_limit:
                    o_filter[OP_UNARY] = NEG_INF
                    filtered += 1
                if len(s_list) < 2:
                    o_filter[OP_BINARY] = NEG_INF
                    filtered += 1
                if q_list or len(s_list) > 1:
                    o_filter[OP_FINISH] = NEG_INF
                if filtered == NUM_OP:
                    raise RuntimeError('No possible operation!')

                o += XP.farray([o_filter])
                o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

            if o_argmax == OP_SHIFT:
                t0 = Tree(None, [text])
                sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, a, b, s1, z))
                q_list.pop(0)
                unary_chain = 0
                label = self.net_semiterminal(a, b, s1, s2)
            elif o_argmax == OP_UNARY:
                t0 = Tree(None, [t1])
                sc0, s0 = self.net_unary(sc1, a, b, s1, s2, z)
                s_list.pop()
                unary_chain += 1
                label = self.net_phrase(a, b, s1, s2)
            elif o_argmax == OP_BINARY:
                t0 = Tree(None, [t2, t1])
                sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3, z)
                s_list.pop()
                s_list.pop()
                unary_chain = 0
                label = self.net_phrase(a, b, s1, s2)
            else:  # OP_FINISH
                break

            if is_training:
                loss += functions.softmax_cross_entropy(
                    label, XP.iarray([gold_op_list[i][1]]))
                label_argmax = gold_op_list[i][1]
            else:
                label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

            t0.set_label(label_argmax)
            s_list.append((t0, sc0, s0))
            '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op_list[i][0] else ' ',
            '*' if label_est == gold_op_list[i][1] else ' ',
            gold_op_list[i][0], gold_op_list[i][1],
            o_est, label_est,
            len(s_list), len(q_list)))
      '''

        if is_training:
            return loss
        else:
            # combine multiple trees if they exists, and return the result.
            t0, _, __ = s_list.pop()
            if s_list:
                raise RuntimeError('There exist multiple subtrees!')
            return t0
Пример #6
0
  def forward(self, word_list, gold_op_list, unary_limit):
    is_training = gold_op_list is not None

    # check args
    if len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if is_training:
      n_shift = 0
      n_binary = 0
      for op, _ in gold_op_list:
        if op == OP_SHIFT: n_shift += 1
        if op == OP_BINARY: n_binary += 1
      if n_shift != len(word_list) or n_binary != len(word_list) - 1:
        raise ValueError(
            'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)' %
            (n_shift, n_binary, len(word_list), len(word_list) - 1))
      if gold_op_list[-1] != (OP_FINISH, None):
        raise ValueError('Last operation is not OP_FINISH.')

    # initial values
    OP_ZEROS = XP.fzeros((1, NUM_OP))
    QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
    STACK_ZEROS = XP.fzeros((1, self.n_stack))
    NEG_INF = -1e20

    # queue encoding
    q_list = []
    qc = QUEUE_ZEROS
    q = QUEUE_ZEROS
    
    for text, wid in reversed(word_list):
      qc, q = self.net_encoder(qc, XP.iarray([wid]), q)
      q_list.insert(0, (text, q))

    # estimate
    s_list = []
    oc = OP_ZEROS
    o = OP_ZEROS
    unary_chain = 0
    if is_training:
      loss = XP.fzeros(())

    for i in itertools.count():
      text, q = q_list[0] if q_list else ('', QUEUE_ZEROS)
      t1, sc1, s1 = s_list[-1] if s_list else (None, STACK_ZEROS, STACK_ZEROS)
      t2, sc2, s2 = s_list[-2] if len(s_list) >= 2 else (None, STACK_ZEROS, STACK_ZEROS)
      t3, sc3, s3 = s_list[-3] if len(s_list) >= 3 else (None, STACK_ZEROS, STACK_ZEROS)

      oc, o = self.net_operation(oc, q, s1, o)

      if is_training:
        loss += functions.softmax_cross_entropy(o, XP.iarray([gold_op_list[i][0]]))
        o_argmax = gold_op_list[i][0]
      else:
        o_filter = [0.0 for _ in range(NUM_OP)]
        filtered = 0
        if not q_list:
          o_filter[OP_SHIFT] = NEG_INF
          filtered += 1
        if not s_list or unary_chain >= unary_limit:
          o_filter[OP_UNARY] = NEG_INF
          filtered += 1
        if len(s_list) < 2:
          o_filter[OP_BINARY] = NEG_INF
          filtered += 1
        if q_list or len(s_list) > 1:
          o_filter[OP_FINISH] = NEG_INF
        if filtered == NUM_OP:
          raise RuntimeError('No possible operation!')

        o += XP.farray([o_filter])
        o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = self.net_shift(sc1, q, s1)
        q_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc2, s1, s2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc3, s1, s2, s3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      if is_training:
        loss += functions.softmax_cross_entropy(label, XP.iarray([gold_op_list[i][1]]))
        label_argmax = gold_op_list[i][1]
      else:
        label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0))

      '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op_list[i][0] else ' ',
            '*' if label_est == gold_op_list[i][1] else ' ',
            gold_op_list[i][0], gold_op_list[i][1],
            o_est, label_est,
            len(s_list), len(q_list)))
      '''

    if is_training:
      return loss
    else:
      # combine multiple trees if they exists, and return the result.
      t0, _, __ = s_list.pop()
      if s_list:
        raise RuntimeError('There exist multiple subtrees!')
      return t0
Пример #7
0
  def forward(self, word_list, gold_op_list, unary_limit, embed_cache):
    is_training = gold_op_list is not None

    # check args
    if len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if is_training:
      n_shift = 0
      n_binary = 0
      for op, *_ in gold_op_list:
        if op == OP_SHIFT: n_shift += 1
        if op == OP_BINARY: n_binary += 1
      if n_shift != len(word_list) or n_binary != len(word_list) - 1:
        raise ValueError(
            'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)' %
            (n_shift, n_binary, len(word_list), len(word_list) - 1))
      if gold_op_list[-1][0] != OP_FINISH:
        raise ValueError('Last operation is not OP_FINISH.')

    # word embedding
    x_list = []
    jk_list = []
    for text, wid in word_list:
      if text in embed_cache:
        x, jk = embed_cache[text]
      else:
        x = self.net_embed(wid)
        jk = self.net_cembed(text)
        embed_cache[text] = (x, jk)
      x_list.append(x)
      jk_list.append(jk)

    # forward encoding
    a_list = []
    ac = self.QUEUE_ZEROS
    a = self.QUEUE_ZEROS
    for x, (j, k) in zip(x_list, jk_list):
      ac, a = self.net_forward(ac, x, j, k, a)
      a_list.append(a)

    # backward encoding
    b_list = []
    bc = self.QUEUE_ZEROS
    b = self.QUEUE_ZEROS
    for x, (j, k) in zip(reversed(x_list), reversed(jk_list)):
      bc, b = self.net_backward(bc, x, j, k, b)
      b_list.insert(0, b)

    q_list = [
      (text, x, j, k, a, b) \
      for (text, _), x, (j, k), a, b \
      in zip(word_list, x_list, jk_list, a_list, b_list)]

    # estimate
    s_list = []
    zc = self.SRSTATE_ZEROS
    z = self.SRSTATE_ZEROS
    unary_chain = 0
    if is_training:
      loss = XP.fzeros(())

    for i in itertools.count():
      if is_training:
        gold_op, gold_label, gold_op_vram, gold_label_vram = gold_op_list[i]
      text, x, j, k, a, b = q_list[0] if q_list else self.QUEUE_DEFAULT
      t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else self.STACK_DEFAULT
      t2, sc2, s2, rc2, r2 = s_list[-2] if len(s_list) >= 2 else self.STACK_DEFAULT
      t3, sc3, s3, rc3, r3 = s_list[-3] if len(s_list) >= 3 else self.STACK_DEFAULT

      zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)  
      o = self.net_operation(z)

      if is_training:
        loss += functions.softmax_cross_entropy(o, gold_op_vram)
        o_argmax = gold_op
      else:
        o_filter = [0.0 for _ in range(NUM_OP)]
        filtered = 0
        if not q_list:
          o_filter[OP_SHIFT] = self.NEG_INF
          filtered += 1
        if not s_list or unary_chain >= unary_limit:
          o_filter[OP_UNARY] = self.NEG_INF
          filtered += 1
        if len(s_list) < 2:
          o_filter[OP_BINARY] = self.NEG_INF
          filtered += 1
        if q_list or len(s_list) > 1:
          o_filter[OP_FINISH] = self.NEG_INF
        if filtered == NUM_OP:
          raise RuntimeError('No possible operation!')

        o += XP.farray([o_filter])
        o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = (self.STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
        rc0, r0 = self.net_stack(rc1, s0, r1)
        q_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
        rc0, r0 = self.net_stack(rc2, s0, r2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
        rc0, r0 = self.net_stack(rc3, s0, r3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      if is_training:
        loss += functions.softmax_cross_entropy(label, gold_label_vram)
        label_argmax = gold_label
      else:
        label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0, rc0, r0))

      '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op else ' ',
            '*' if label_est == gold_label else ' ',
            gold_op, gold_label,
            o_est, label_est,
            len(s_list), len(q_list)))
      '''

    if is_training:
      return loss
    else:
      # combine multiple trees if they exists, and return the result.
      t0, *_ = s_list.pop()
      if s_list:
        raise RuntimeError('There exist multiple subtrees!')
      return t0
Пример #8
0
    def forward(self, word_list, op_list, unary_limit):
        is_training = op_list is not None

        # check args
        if len(word_list) < 1:
            raise ValueError('Word list is empty.')
        if is_training:
            n_shift = 0
            n_binary = 0
            for op, _ in op_list:
                if op == OP_SHIFT: n_shift += 1
                if op == OP_BINARY: n_binary += 1
            if n_shift != len(word_list) or n_binary != len(word_list) - 1:
                raise ValueError(
                    'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)'
                    % (n_shift, n_binary, len(word_list), len(word_list) - 1))
            if op_list[-1] != (OP_FINISH, None):
                raise ValueError('Last operation is not OP_FINISH.')

        # initial values
        EMBED_ZEROS = my_zeros((1, self.n_embed), np.float32)
        QUEUE_ZEROS = my_zeros((1, self.n_queue_state), np.float32)
        STACK_ZEROS = my_zeros((1, self.n_stack_state), np.float32)
        NEG_INF = -1e20

        # queue encoding
        xq_list = []
        c = QUEUE_ZEROS
        q = QUEUE_ZEROS
        for text, wid in reversed(word_list):
            x = self.net_embed(my_array([wid], np.int32))
            c, q = self.net_encoder(c, x, q)
            xq_list.insert(0, (text, x, q))

        s_list = []
        unary_chain = 0
        if is_training:
            loss = my_zeros((), np.float32)

        # estimate
        for i in itertools.count():
            text, x, q = xq_list[0] if xq_list else ('', EMBED_ZEROS,
                                                     QUEUE_ZEROS)
            t1, s1 = s_list[-1] if s_list else (None, STACK_ZEROS)
            t2, s2 = s_list[-2] if len(s_list) > 1 else (None, STACK_ZEROS)
            t3, s3 = s_list[-3] if len(s_list) > 2 else (None, STACK_ZEROS)

            op = self.net_operation(x, q, s1, s2, s3)

            if is_training:
                loss += functions.softmax_cross_entropy(
                    op, my_array([op_list[i][0]], np.int32))
                op_argmax = op_list[i][0]
            else:
                op_filter = [0.0 for _ in range(NUM_OP)]
                filtered = 0
                if not xq_list:
                    op_filter[OP_SHIFT] = NEG_INF
                    filtered += 1
                if not s_list or unary_chain >= unary_limit:
                    op_filter[OP_UNARY] = NEG_INF
                    filtered += 1
                if len(s_list) < 2:
                    op_filter[OP_BINARY] = NEG_INF
                    filtered += 1
                if xq_list or len(s_list) > 1:
                    op_filter[OP_FINISH] = NEG_INF
                if filtered == NUM_OP:
                    raise RuntimeError('No possible operation!')

                op += my_array([op_filter], np.float32)
                op_argmax = int(cuda.to_cpu(op.data.argmax(1)))

            if op_argmax == OP_SHIFT:
                t0 = Tree(None, [text])
                s0 = self.net_shift(x, q, s1)
                xq_list.pop(0)
                unary_chain = 0
                label = self.net_semi_label(s0)
            elif op_argmax == OP_UNARY:
                t0 = Tree(None, [t1])
                s0 = self.net_unary(q, s1, s2)
                s_list.pop()
                unary_chain += 1
                label = self.net_phrase_label(s0)
            elif op_argmax == OP_BINARY:
                t0 = Tree(None, [t2, t1])
                s0 = self.net_binary(q, s1, s2, s3)
                s_list.pop()
                s_list.pop()
                unary_chain = 0
                label = self.net_phrase_label(s0)
            else:  # OP_FINISH
                break

            if is_training:
                loss += functions.softmax_cross_entropy(
                    label, my_array([op_list[i][1]], np.int32))
                label_argmax = op_list[i][1]
            else:
                label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

            t0.set_label(label_argmax)
            s_list.append((t0, s0))
            '''
      if is_training:
        op_est = int(cuda.to_cpu(op.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if op_est == op_list[i][0] else ' ',
            '*' if label_est == op_list[i][1] else ' ',
            op_list[i][0], op_list[i][1],
            op_est, label_est,
            len(s_list), len(xq_list)))
      '''

        if is_training:
            return loss
        else:
            # combine multiple trees if they exists, and return the result.
            t0, _ = s_list.pop()
            if s_list:
                raise RuntimeError('There exist multiple subtrees!')
            return t0
Пример #9
0
  def forward_train(self, word_list, gold_op_list):
    # check args
    if not isinstance(word_list, list) or len(word_list) < 1:
      raise ValueError('Word list is empty.')
    n_shift = 0
    n_binary = 0
    for op, _ in gold_op_list:
      if op == OP_SHIFT: n_shift += 1
      if op == OP_BINARY: n_binary += 1
    if n_shift != len(word_list) or n_binary != len(word_list) - 1:
      raise ValueError(
          'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)' %
          (n_shift, n_binary, len(word_list), len(word_list) - 1))
    if gold_op_list[-1] != (OP_FINISH, None):
      raise ValueError('Last operation is not OP_FINISH.')

    # default values
    EMBED_ZEROS = XP.fzeros((1, self.n_embed))
    CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
    QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
    STACK_ZEROS = XP.fzeros((1, self.n_stack))
    SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
    QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS, QUEUE_ZEROS, QUEUE_ZEROS)
    STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS)
    NEG_INF = -1e20

    q_list = make_queue(word_list, QUEUE_ZEROS)

    # estimate
    s_list = []
    zc = SRSTATE_ZEROS
    z = SRSTATE_ZEROS
    unary_chain = 0
    loss = XP.fzeros(())

    for i in itertools.count():
      text, x, j, k, a, b = q_list[0] if q_list else QUEUE_DEFAULT
      t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else STACK_DEFAULT
      t2, sc2, s2, rc2, r2 = s_list[-2] if len(s_list) >= 2 else STACK_DEFAULT
      t3, sc3, s3, rc3, r3 = s_list[-3] if len(s_list) >= 3 else STACK_DEFAULT

      zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)  
      o = self.net_operation(z)

      loss += functions.softmax_cross_entropy(o, XP.iarray([gold_op_list[i][0]]))
      o_argmax = gold_op_list[i][0]

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
        rc0, r0 = self.net_stack(rc1, s0, r1)
        q_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
        rc0, r0 = self.net_stack(rc2, s0, r2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
        rc0, r0 = self.net_stack(rc3, s0, r3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      loss += functions.softmax_cross_entropy(label, XP.iarray([gold_op_list[i][1]]))
      label_argmax = gold_op_list[i][1]

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0, rc0, r0))

    return loss
Пример #10
0
    def forward(self, word_list, gold_op_list, unary_limit, embed_cache):
        is_training = gold_op_list is not None

        # check args
        if len(word_list) < 1:
            raise ValueError('Word list is empty.')
        if is_training:
            n_shift = 0
            n_binary = 0
            for op, *_ in gold_op_list:
                if op == OP_SHIFT: n_shift += 1
                if op == OP_BINARY: n_binary += 1
            if n_shift != len(word_list) or n_binary != len(word_list) - 1:
                raise ValueError(
                    'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)'
                    % (n_shift, n_binary, len(word_list), len(word_list) - 1))
            if gold_op_list[-1][0] != OP_FINISH:
                raise ValueError('Last operation is not OP_FINISH.')

        # word embedding
        x_list = []
        jk_list = []
        for text, wid in word_list:
            if text in embed_cache:
                x, jk = embed_cache[text]
            else:
                x = self.net_embed(wid)
                jk = self.net_cembed(text)
                embed_cache[text] = (x, jk)
            x_list.append(x)
            jk_list.append(jk)

        # forward encoding
        a_list = []
        ac = self.QUEUE_ZEROS
        a = self.QUEUE_ZEROS
        for x, (j, k) in zip(x_list, jk_list):
            ac, a = self.net_forward(ac, x, j, k, a)
            a_list.append(a)

        # backward encoding
        b_list = []
        bc = self.QUEUE_ZEROS
        b = self.QUEUE_ZEROS
        for x, (j, k) in zip(reversed(x_list), reversed(jk_list)):
            bc, b = self.net_backward(bc, x, j, k, b)
            b_list.insert(0, b)

        q_list = [
          (text, x, j, k, a, b) \
          for (text, _), x, (j, k), a, b \
          in zip(word_list, x_list, jk_list, a_list, b_list)]

        # estimate
        s_list = []
        zc = self.SRSTATE_ZEROS
        z = self.SRSTATE_ZEROS
        unary_chain = 0
        if is_training:
            loss = XP.fzeros(())

        for i in itertools.count():
            if is_training:
                gold_op, gold_label, gold_op_vram, gold_label_vram = gold_op_list[
                    i]
            text, x, j, k, a, b = q_list[0] if q_list else self.QUEUE_DEFAULT
            t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else self.STACK_DEFAULT
            t2, sc2, s2, rc2, r2 = s_list[-2] if len(
                s_list) >= 2 else self.STACK_DEFAULT
            t3, sc3, s3, rc3, r3 = s_list[-3] if len(
                s_list) >= 3 else self.STACK_DEFAULT

            zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)
            o = self.net_operation(z)

            if is_training:
                loss += functions.softmax_cross_entropy(o, gold_op_vram)
                o_argmax = gold_op
            else:
                o_filter = [0.0 for _ in range(NUM_OP)]
                filtered = 0
                if not q_list:
                    o_filter[OP_SHIFT] = self.NEG_INF
                    filtered += 1
                if not s_list or unary_chain >= unary_limit:
                    o_filter[OP_UNARY] = self.NEG_INF
                    filtered += 1
                if len(s_list) < 2:
                    o_filter[OP_BINARY] = self.NEG_INF
                    filtered += 1
                if q_list or len(s_list) > 1:
                    o_filter[OP_FINISH] = self.NEG_INF
                if filtered == NUM_OP:
                    raise RuntimeError('No possible operation!')

                o += XP.farray([o_filter])
                o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

            if o_argmax == OP_SHIFT:
                t0 = Tree(None, [text])
                sc0, s0 = (self.STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
                rc0, r0 = self.net_stack(rc1, s0, r1)
                q_list.pop(0)
                unary_chain = 0
                label = self.net_semiterminal(s0)
            elif o_argmax == OP_UNARY:
                t0 = Tree(None, [t1])
                sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
                rc0, r0 = self.net_stack(rc2, s0, r2)
                s_list.pop()
                unary_chain += 1
                label = self.net_phrase(s0)
            elif o_argmax == OP_BINARY:
                t0 = Tree(None, [t2, t1])
                sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
                rc0, r0 = self.net_stack(rc3, s0, r3)
                s_list.pop()
                s_list.pop()
                unary_chain = 0
                label = self.net_phrase(s0)
            else:  # OP_FINISH
                break

            if is_training:
                loss += functions.softmax_cross_entropy(label, gold_label_vram)
                label_argmax = gold_label
            else:
                label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

            t0.set_label(label_argmax)
            s_list.append((t0, sc0, s0, rc0, r0))
            '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op else ' ',
            '*' if label_est == gold_label else ' ',
            gold_op, gold_label,
            o_est, label_est,
            len(s_list), len(q_list)))
      '''

        if is_training:
            return loss
        else:
            # combine multiple trees if they exists, and return the result.
            t0, *_ = s_list.pop()
            if s_list:
                raise RuntimeError('There exist multiple subtrees!')
            return t0
Пример #11
0
  def forward(self, word_list, op_list, unary_limit):
    is_training = op_list is not None

    # check args
    if len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if is_training:
      n_shift = 0
      n_binary = 0
      for op, _ in op_list:
        if op == OP_SHIFT: n_shift += 1
        if op in [OP_PARTIAL, OP_REDUCE]: n_binary += 1
      if n_shift != len(word_list) or n_binary != len(word_list) - 1:
        raise ValueError(
            'Invalid operation number: SHIFT=%d (required: %d), PARTIAL+REDUCE=%d (required: %d)' %
            (n_shift, n_binary, len(word_list), len(word_list) - 1))
      if op_list[-1] != (OP_FINISH, None):
        raise ValueError('Last operation is not FINISH.')

    # initial values
    EMBED_ZEROS = my_zeros((1, self.n_embed), np.float32)
    QUEUE_ZEROS = my_zeros((1, self.n_queue_state), np.float32)
    STACK_ZEROS = my_zeros((1, self.n_stack_state), np.float32)
    NEG_INF = -1e20

    # queue encoding
    xq_list = []
    c = QUEUE_ZEROS
    q = QUEUE_ZEROS
    for text, wid in reversed(word_list):
      x = self.net_embed(my_array([wid], np.int32))
      c, q = self.net_encoder(c, x, q)
      xq_list.insert(0, (text, x, q))

    s_list = [] # [(tree, state)]
    unary_chain = 0
    if is_training:
      loss = my_zeros((), np.float32)

    # estimate
    for i in itertools.count():
      text, x, q = xq_list[0] if xq_list else ('', EMBED_ZEROS, QUEUE_ZEROS)
      t1, s1 = s_list[-1] if s_list else (None, STACK_ZEROS)
      t2, s2 = s_list[-2] if len(s_list) > 1 else (None, STACK_ZEROS)
      t3, s3 = s_list[-3] if len(s_list) > 2 else (None, STACK_ZEROS)
      p1 = (t1.label() == -1) if t1 is not None else False
      p2 = (t2.label() == -1) if t2 is not None else False

      op = self.net_operation(x, q, s1, s2, s3)

      if is_training:
        loss += functions.softmax_cross_entropy(op, my_array([op_list[i][0]], np.int32))
        op_argmax = op_list[i][0]
      else:
        op_filter = [0.0 for _ in range(NUM_OP)]
        filtered = 0
        if not xq_list or p2:
          op_filter[OP_SHIFT] = NEG_INF
          filtered += 1
        if not s_list or unary_chain >= unary_limit or p1:
          op_filter[OP_UNARY] = NEG_INF
          filtered += 1
        if not xq_list or len(s_list) < 2 or p1:
          op_filter[OP_PARTIAL] = NEG_INF
          filtered += 1
        if len(s_list) < 2 or p1:
          op_filter[OP_REDUCE] = NEG_INF
          filtered += 1
        if xq_list or len(s_list) > 1:
          op_filter[OP_FINISH] = NEG_INF
        if filtered == NUM_OP:
          raise RuntimeError('No possible operation!')

        op += my_array([op_filter], np.float32)
        op_argmax = int(cuda.to_cpu(op.data.argmax(1)))

      if op_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        s0 = self.net_shift(x, q, s1)
        xq_list.pop(0)
        unary_chain = 0
        label = self.net_semi_label(s0)
      elif op_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        s0 = self.net_unary(q, s1, s2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase_label(s0)
      elif op_argmax == OP_PARTIAL:
        t0 = Tree(None, [t2, t1])
        s0 = self.net_partial(q, s1, s2, s3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_partial_label(s0)
      elif op_argmax == OP_REDUCE:
        t0 = Tree(None, [t2, t1])
        s0 = self.net_reduce(q, s1, s2, s3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase_label(s0)
      else: # OP_FINISH
        break

      if is_training:
        loss += functions.softmax_cross_entropy(label, my_array([op_list[i][1]], np.int32))
        label_argmax = op_list[i][1] if op_argmax != OP_PARTIAL else -1
      else:
        label_argmax = int(cuda.to_cpu(label.data.argmax(1))) if op_argmax != OP_PARTIAL else -1
      t0.set_label(label_argmax)

      s_list.append((t0, s0))

      '''
      if is_training:
        op_est = int(cuda.to_cpu(op.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1))) if op_argmax != OP_PARTIAL else -1
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if op_est == op_list[i][0] else ' ',
            '*' if label_est == op_list[i][1] else ' ',
            op_list[i][0], op_list[i][1],
            op_est, label_est,
            len(s_list), len(xq_list)))
      '''
    
    if is_training:
      return loss
    else:
      # combine multiple trees if they exists, and return the result.
      t0, _ = s_list.pop()
      if s_list:
        raise RuntimeError('There exist multiple subtrees!')
      return unbinarize(t0)
 def _strip_functional_tags(self, tree: Tree) -> None:
     clean_label = tree.label().split("=")[0].split("-")[0].split("|")[0]
     tree.set_label(clean_label)
     for child in tree:
         if not isinstance(child[0], str):
             self._strip_functional_tags(child)
Пример #13
0
    def CYK(self, sentence, verbose=False):
        """
        Parse a sentence or a table of words to get the more likely graph
        :param sentence: list of words
        :param verbose: bool print data
        """

        if isinstance(sentence, str):
            words = sentence.split(" ")
        else:
            words = sentence

        if verbose:
            print("Original sentence :")
            print(sentence)

        self.dic_replacement = {}
        new_sentence = ""

        back = [[{} for i in range(len(words) - i)] for i in range(len(words))]
        log_pr = [[{} for i in range(len(words) - i)]
                  for i in range(len(words))]

        for k in range(0, len(words)):
            # Treating OOV :
            if words[k] not in self.lexicon:
                liste = closest(words[k], self.lexicon, self.embeddings,
                                self.word_id, self.id_word)
                if verbose:
                    print(f"{words[k]} is replaced by {liste}")
            else:
                liste = [(words[k], 1.0)]
                if words[k][0].isupper() and words[k].lower() in self.lexicon:
                    liste.append(
                        (words[k].lower(),
                         0.5))  # Try the lowercase with lower probability

            # Create the auxiliary sentence that will be treated
            for i, element in enumerate(liste):
                word = element[0]
                if i == 0:
                    new_sentence += word
                else:
                    new_sentence += "/" + word

            # Create the first line with self.lexicon
            for element in liste:
                proba = element[1]
                word = element[0]

                for s in self.lexicon[word]:
                    currentProb = np.log(self.lexicon[word][s]) + np.log(proba)
                    self.dic_replacement[k, word] = words[k]
                    if s not in back[0][k]:
                        log_pr[0][k][s] = (currentProb, 0, k, word)
                        back[0][k][s] = (0, k, word)

                    elif currentProb > log_pr[0][k][s][0]:
                        log_pr[0][k][s] = (currentProb, 0, k, word)
                        back[0][k][s] = (0, k, word)

            new_sentence += " "

        if verbose:
            print("Auxiliary sentence :")
            print(new_sentence)

        # If only one words, we reconstruct the tree :
        if len(words) == 1:
            result, element = check_Sent(log_pr[0][0])
            if result:
                origin, pos = str(element[0]).split("&", 1)
                tree = Tree(origin, [Tree(pos, [back[0][0][element][2]])])
                return tree
            else:
                elementTrue = None
                proba = -float("inf")
                for element in back[0][0].keys():
                    if back[0][0][element][0] > proba:
                        proba = back[0][0][element][0]
                        elementTrue = element
                tree = Tree(
                    "SENT",
                    [Tree(str(elementTrue[0]), [back[0][0][element][2]])])
                return tree

        # Check the upper cells of the pyramid
        for i in range(
                1,
                len(words)):  # Place in the row of the pyramid (lenght is i+1)
            for init in range(len(words) -
                              i):  # Place in the column of the pyramid
                for length_init in range(1, i +
                                         1):  # Where to split in the sentence
                    length_end = (i + 1) - length_init
                    init_list = back[length_init - 1][init].keys()
                    end_list = back[length_end - 1][init + length_init].keys()
                    for element1 in init_list:
                        for element2 in end_list:
                            inputElement = element1 + element2
                            if inputElement in self.rules:
                                for s in self.rules[inputElement]:
                                    if self.rules[inputElement][
                                            s] == 0:  # There should be no element here
                                        currentProb = -float("inf")
                                    else:
                                        currentProb = log_pr[length_init-1][init][element1][0] \
                                            + log_pr[length_end-1][init+length_init][element2][0] \
                                            + np.log(self.rules[inputElement][s])
                                    if s not in back[i][init]:
                                        log_pr[i][init][s] = (currentProb,
                                                              length_init - 1,
                                                              init, element1,
                                                              length_end - 1,
                                                              init +
                                                              length_init,
                                                              element2)
                                        back[i][init][s] = (length_init - 1,
                                                            init, element1,
                                                            length_end - 1,
                                                            init + length_init,
                                                            element2)
                                    elif currentProb > log_pr[i][init][s][0]:
                                        log_pr[i][init][s] = (currentProb,
                                                              length_init - 1,
                                                              init, element1,
                                                              length_end - 1,
                                                              init +
                                                              length_init,
                                                              element2)
                                        back[i][init][s] = (length_init - 1,
                                                            init, element1,
                                                            length_end - 1,
                                                            init + length_init,
                                                            element2)

        resultParsable, element = check_Sent(log_pr[-1][0])
        if not resultParsable:
            return False
        else:
            tree = self.build_tree(back, i, 0, element)
            tree.set_label("SENT")
            return tree
Пример #14
0
  def forward_test(self, word_list, unary_limit):
    # check args
    if not isinstance(word_list, list) or len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if not isinstance(unary_limit, int) or unary_limit < 0:
      raise ValueError('unary_limit must be non-negative integer.')

    # default values
    EMBED_ZEROS = XP.fzeros((1, self.n_embed))
    CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
    QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
    STACK_ZEROS = XP.fzeros((1, self.n_stack))
    SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
    QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS, QUEUE_ZEROS, QUEUE_ZEROS)
    STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS)
    NEG_INF = -1e20

    q_list = make_queue(word_list, QUEUE_ZEROS)

    # estimate
    s_list = []
    zc = SRSTATE_ZEROS
    z = SRSTATE_ZEROS
    unary_chain = 0

    for i in itertools.count():
      text, x, j, k, a, b = q_list[0] if q_list else QUEUE_DEFAULT
      t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else STACK_DEFAULT
      t2, sc2, s2, rc2, r2 = s_list[-2] if len(s_list) >= 2 else STACK_DEFAULT
      t3, sc3, s3, rc3, r3 = s_list[-3] if len(s_list) >= 3 else STACK_DEFAULT

      zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)  
      o = self.net_operation(z)

      o_filter = [0.0 for _ in range(NUM_OP)]
      filtered = 0
      if not q_list:
        o_filter[OP_SHIFT] = NEG_INF
        filtered += 1
      if not s_list or unary_chain >= unary_limit:
        o_filter[OP_UNARY] = NEG_INF
        filtered += 1
      if len(s_list) < 2:
        o_filter[OP_BINARY] = NEG_INF
        filtered += 1
      if q_list or len(s_list) > 1:
        o_filter[OP_FINISH] = NEG_INF
      if filtered == NUM_OP:
        raise RuntimeError('No possible operation!')

      o += XP.farray([o_filter])
      o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
        rc0, r0 = self.net_stack(rc1, s0, r1)
        q_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
        rc0, r0 = self.net_stack(rc2, s0, r2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
        rc0, r0 = self.net_stack(rc3, s0, r3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0, rc0, r0))

    # combine multiple trees if they exists, and return the result.
    t0, *_ = s_list.pop()
    if s_list:
      raise RuntimeError('There exist multiple subtrees!')
    return t0
Пример #15
0
    def forward_train(self, word_list, gold_op_list):
        # check args
        if not isinstance(word_list, list) or len(word_list) < 1:
            raise ValueError('Word list is empty.')
        n_shift = 0
        n_binary = 0
        for op, _ in gold_op_list:
            if op == OP_SHIFT: n_shift += 1
            if op == OP_BINARY: n_binary += 1
        if n_shift != len(word_list) or n_binary != len(word_list) - 1:
            raise ValueError(
                'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)'
                % (n_shift, n_binary, len(word_list), len(word_list) - 1))
        if gold_op_list[-1] != (OP_FINISH, None):
            raise ValueError('Last operation is not OP_FINISH.')

        # default values
        EMBED_ZEROS = XP.fzeros((1, self.n_embed))
        CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
        QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
        STACK_ZEROS = XP.fzeros((1, self.n_stack))
        SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
        QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS,
                         QUEUE_ZEROS, QUEUE_ZEROS)
        STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS,
                         STACK_ZEROS)
        NEG_INF = -1e20

        q_list = make_queue(word_list, QUEUE_ZEROS)

        # estimate
        s_list = []
        zc = SRSTATE_ZEROS
        z = SRSTATE_ZEROS
        unary_chain = 0
        loss = XP.fzeros(())

        for i in itertools.count():
            text, x, j, k, a, b = q_list[0] if q_list else QUEUE_DEFAULT
            t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else STACK_DEFAULT
            t2, sc2, s2, rc2, r2 = s_list[-2] if len(
                s_list) >= 2 else STACK_DEFAULT
            t3, sc3, s3, rc3, r3 = s_list[-3] if len(
                s_list) >= 3 else STACK_DEFAULT

            zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)
            o = self.net_operation(z)

            loss += functions.softmax_cross_entropy(
                o, XP.iarray([gold_op_list[i][0]]))
            o_argmax = gold_op_list[i][0]

            if o_argmax == OP_SHIFT:
                t0 = Tree(None, [text])
                sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
                rc0, r0 = self.net_stack(rc1, s0, r1)
                q_list.pop(0)
                unary_chain = 0
                label = self.net_semiterminal(s0)
            elif o_argmax == OP_UNARY:
                t0 = Tree(None, [t1])
                sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
                rc0, r0 = self.net_stack(rc2, s0, r2)
                s_list.pop()
                unary_chain += 1
                label = self.net_phrase(s0)
            elif o_argmax == OP_BINARY:
                t0 = Tree(None, [t2, t1])
                sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
                rc0, r0 = self.net_stack(rc3, s0, r3)
                s_list.pop()
                s_list.pop()
                unary_chain = 0
                label = self.net_phrase(s0)
            else:  # OP_FINISH
                break

            loss += functions.softmax_cross_entropy(
                label, XP.iarray([gold_op_list[i][1]]))
            label_argmax = gold_op_list[i][1]

            t0.set_label(label_argmax)
            s_list.append((t0, sc0, s0, rc0, r0))

        return loss
Пример #16
0
    def forward_test(self, word_list, unary_limit):
        # check args
        if not isinstance(word_list, list) or len(word_list) < 1:
            raise ValueError('Word list is empty.')
        if not isinstance(unary_limit, int) or unary_limit < 0:
            raise ValueError('unary_limit must be non-negative integer.')

        # default values
        EMBED_ZEROS = XP.fzeros((1, self.n_embed))
        CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
        QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
        STACK_ZEROS = XP.fzeros((1, self.n_stack))
        SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
        QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS,
                         QUEUE_ZEROS, QUEUE_ZEROS)
        STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS,
                         STACK_ZEROS)
        NEG_INF = -1e20

        q_list = make_queue(word_list, QUEUE_ZEROS)

        # estimate
        s_list = []
        zc = SRSTATE_ZEROS
        z = SRSTATE_ZEROS
        unary_chain = 0

        for i in itertools.count():
            text, x, j, k, a, b = q_list[0] if q_list else QUEUE_DEFAULT
            t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else STACK_DEFAULT
            t2, sc2, s2, rc2, r2 = s_list[-2] if len(
                s_list) >= 2 else STACK_DEFAULT
            t3, sc3, s3, rc3, r3 = s_list[-3] if len(
                s_list) >= 3 else STACK_DEFAULT

            zc, z = self.net_sr(zc, a, b, s1, r1, s2, r2, z)
            o = self.net_operation(z)

            o_filter = [0.0 for _ in range(NUM_OP)]
            filtered = 0
            if not q_list:
                o_filter[OP_SHIFT] = NEG_INF
                filtered += 1
            if not s_list or unary_chain >= unary_limit:
                o_filter[OP_UNARY] = NEG_INF
                filtered += 1
            if len(s_list) < 2:
                o_filter[OP_BINARY] = NEG_INF
                filtered += 1
            if q_list or len(s_list) > 1:
                o_filter[OP_FINISH] = NEG_INF
            if filtered == NUM_OP:
                raise RuntimeError('No possible operation!')

            o += XP.farray([o_filter])
            o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

            if o_argmax == OP_SHIFT:
                t0 = Tree(None, [text])
                sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, a, b, s1))
                rc0, r0 = self.net_stack(rc1, s0, r1)
                q_list.pop(0)
                unary_chain = 0
                label = self.net_semiterminal(s0)
            elif o_argmax == OP_UNARY:
                t0 = Tree(None, [t1])
                sc0, s0 = self.net_unary(sc1, a, b, s1, s2)
                rc0, r0 = self.net_stack(rc2, s0, r2)
                s_list.pop()
                unary_chain += 1
                label = self.net_phrase(s0)
            elif o_argmax == OP_BINARY:
                t0 = Tree(None, [t2, t1])
                sc0, s0 = self.net_binary(sc1, sc2, a, b, s1, s2, s3)
                rc0, r0 = self.net_stack(rc3, s0, r3)
                s_list.pop()
                s_list.pop()
                unary_chain = 0
                label = self.net_phrase(s0)
            else:  # OP_FINISH
                break

            label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

            t0.set_label(label_argmax)
            s_list.append((t0, sc0, s0, rc0, r0))

        # combine multiple trees if they exists, and return the result.
        t0, *_ = s_list.pop()
        if s_list:
            raise RuntimeError('There exist multiple subtrees!')
        return t0
Пример #17
0
  def forward(self, word_list, gold_op_list, unary_limit):
    is_training = gold_op_list is not None

    # check args
    if len(word_list) < 1:
      raise ValueError('Word list is empty.')
    if is_training:
      n_shift = 0
      n_binary = 0
      for op, _ in gold_op_list:
        if op == OP_SHIFT: n_shift += 1
        if op == OP_BINARY: n_binary += 1
      if n_shift != len(word_list) or n_binary != len(word_list) - 1:
        raise ValueError(
            'Invalid operation number: SHIFT=%d (required: %d), BINARY=%d (required: %d)' %
            (n_shift, n_binary, len(word_list), len(word_list) - 1))
      if gold_op_list[-1] != (OP_FINISH, None):
        raise ValueError('Last operation is not OP_FINISH.')

    # default values
    EMBED_ZEROS = XP.fzeros((1, self.n_embed))
    CEMBED_ZEROS = XP.fzeros((1, self.n_char_embed))
    QUEUE_ZEROS = XP.fzeros((1, self.n_queue))
    QUEUE_ONES = XP.fones((1, self.n_queue))
    STACK_ZEROS = XP.fzeros((1, self.n_stack))
    STACK_ONES = XP.fzeros((1, self.n_stack))
    SRSTATE_ZEROS = XP.fzeros((1, self.n_srstate))
    QUEUE_DEFAULT = ('', EMBED_ZEROS, CEMBED_ZEROS, CEMBED_ZEROS, QUEUE_ZEROS)
    STACK_DEFAULT = (None, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS, STACK_ZEROS)
    NEG_INF = -1e20

    # word embedding
    x_list = [self.net_embed(XP.iarray([wid])) for _, wid in word_list]
    jk_list = [self.net_cembed(text) for text, _ in word_list]

    # backward encoding
    b_list = []
    bc = QUEUE_ZEROS
    b = QUEUE_ZEROS
    bf = XP.dropout(QUEUE_ONES)
    for x, (j, k) in zip(reversed(x_list), reversed(jk_list)):
      bc, b = self.net_backward(bc, x, j, k, b)
      b *= bf
      b_list.insert(0, b)

    q_list = [
      (text, x, j, k, b) \
      for (text, _), x, (j, k), b \
      in zip(word_list, x_list, jk_list, b_list)]

    # estimate
    s_list = []
    zc = SRSTATE_ZEROS
    z = SRSTATE_ZEROS
    rf = XP.dropout(STACK_ONES)
    unary_chain = 0
    if is_training:
      loss = XP.fzeros(())

    for i in itertools.count():
      text, x, j, k, b = q_list[0] if q_list else QUEUE_DEFAULT
      t1, sc1, s1, rc1, r1 = s_list[-1] if s_list else STACK_DEFAULT
      t2, sc2, s2, rc2, r2 = s_list[-2] if len(s_list) >= 2 else STACK_DEFAULT
      t3, sc3, s3, rc3, r3 = s_list[-3] if len(s_list) >= 3 else STACK_DEFAULT

      zc, z = self.net_sr(zc, b, r1, z)  
      o = self.net_operation(z)

      if is_training:
        loss += functions.softmax_cross_entropy(o, XP.iarray([gold_op_list[i][0]]))
        o_argmax = gold_op_list[i][0]
      else:
        o_filter = [0.0 for _ in range(NUM_OP)]
        filtered = 0
        if not q_list:
          o_filter[OP_SHIFT] = NEG_INF
          filtered += 1
        if not s_list or unary_chain >= unary_limit:
          o_filter[OP_UNARY] = NEG_INF
          filtered += 1
        if len(s_list) < 2:
          o_filter[OP_BINARY] = NEG_INF
          filtered += 1
        if q_list or len(s_list) > 1:
          o_filter[OP_FINISH] = NEG_INF
        if filtered == NUM_OP:
          raise RuntimeError('No possible operation!')

        o += XP.farray([o_filter])
        o_argmax = int(cuda.to_cpu(o.data.argmax(1)))

      if o_argmax == OP_SHIFT:
        t0 = Tree(None, [text])
        sc0, s0 = (STACK_ZEROS, self.net_shift(x, j, k, b, s1))
        rc0, r0 = self.net_stack(rc1, s0, r1)
        q_list.pop(0)
        unary_chain = 0
        label = self.net_semiterminal(s0)
      elif o_argmax == OP_UNARY:
        t0 = Tree(None, [t1])
        sc0, s0 = self.net_unary(sc1, b, s1, s2)
        rc0, r0 = self.net_stack(rc2, s0, r2)
        s_list.pop()
        unary_chain += 1
        label = self.net_phrase(s0)
      elif o_argmax == OP_BINARY:
        t0 = Tree(None, [t2, t1])
        sc0, s0 = self.net_binary(sc1, sc2, b, s1, s2, s3)
        rc0, r0 = self.net_stack(rc3, s0, r3)
        s_list.pop()
        s_list.pop()
        unary_chain = 0
        label = self.net_phrase(s0)
      else: # OP_FINISH
        break

      r0 *= rf

      if is_training:
        loss += functions.softmax_cross_entropy(label, XP.iarray([gold_op_list[i][1]]))
        label_argmax = gold_op_list[i][1]
      else:
        label_argmax = int(cuda.to_cpu(label.data.argmax(1)))

      t0.set_label(label_argmax)
      s_list.append((t0, sc0, s0, rc0, r0))

      '''
      if is_training:
        o_est = int(cuda.to_cpu(o.data.argmax(1)))
        label_est = int(cuda.to_cpu(label.data.argmax(1)))
        trace('%c %c gold=%d-%2d, est=%d-%2d, stack=%2d, queue=%2d' % (
            '*' if o_est == gold_op_list[i][0] else ' ',
            '*' if label_est == gold_op_list[i][1] else ' ',
            gold_op_list[i][0], gold_op_list[i][1],
            o_est, label_est,
            len(s_list), len(q_list)))
      '''

    if is_training:
      return loss
    else:
      # combine multiple trees if they exists, and return the result.
      t0, *_ = s_list.pop()
      if s_list:
        raise RuntimeError('There exist multiple subtrees!')
      return t0