skip 기반thoughts vectors의sentence2vec 신경 네트워크 구현

32321 단어 NLP
1. 논문 요약
우리는 통용되고 분포식 문장 인코더의 무감독 학습 방법을 묘사했다.책에서 추출한 연속 텍스트를 사용하여 우리는 인코딩 단락 주위의 문장을 재구성하기 위해 인코더 - 디코더 모형을 훈련했다.어의와 문법 속성이 일치하는 문장은 이로 인해 비슷한 벡터 표시에 비친다.우리는 이어서 예상한 단어를 훈련하지 않고 어휘량을 백만 단어로 확장하는 간단한 어휘 확장 방법을 도입했다.훈련 모델을 사용한 후에 우리는 선형 모델로 8개 임무에서 우리의 벡터를 추출하고 평가한다. 이는 의미 관련성, 해석 검측, 이미지 문장 순서, 문제 유형 분류, 그리고 4개의 기준 정서와 주관적인 데이터 집합을 포함한다.최종 결과는 비전문적으로 설계된 인코더로 고도의 통용성을 가진 문장 표시를 생성하여 실천에서 양호하게 표현할 수 있다.
2. 모형 상해
코드 출처https://github.com/tensorflow/models/tree/master/research/skip_thoughts모형은 크게 3단계로 나뉜다. 1. 상하문 3원조를 구축한다.2. 인코더 구축;3. 디코더를 구축한다.
2.1 상하문 삼원조 구축(skip thoughts/data/process dataset.py)
def _process_input_file(filename, vocab, stats):
  """Processes the sentences in an input file.
  Args:
    filename: Path to a pre-tokenized input .txt file.
    vocab: A dictionary of word to id.
    stats: A Counter object for statistics.
  Returns:
    processed: A list of serialized Example protos
  """
  tf.logging.info("Processing input file: %s", filename)
  processed = []

  predecessor = None  # Predecessor sentence (list of words).
  current = None  # Current sentence (list of words).
  successor = None  # Successor sentence (list of words).

  for successor_str in tf.gfile.FastGFile(filename):
    stats.update(["sentences_seen"])
    successor = successor_str.split()

    # The first 2 sentences per file will be skipped.
    if predecessor and current and successor:
      stats.update(["sentences_considered"])

      # Note that we are going to insert <EOS> later, so we only allow
      # sentences with strictly less than max_sentence_length to pass.
      if FLAGS.max_sentence_length and (
          len(predecessor) >= FLAGS.max_sentence_length or len(current) >=
          FLAGS.max_sentence_length or len(successor) >=
          FLAGS.max_sentence_length):
        stats.update(["sentences_too_long"])
      else:
        serialized = _create_serialized_example(predecessor, current, successor,
                                                vocab)
        processed.append(serialized)
        stats.update(["sentences_output"])

    predecessor = current
    current = successor

    sentences_seen = stats["sentences_seen"]
    sentences_output = stats["sentences_output"]
    if sentences_seen and sentences_seen % 100000 == 0:
      tf.logging.info("Processed %d sentences (%d output)", sentences_seen,
                      sentences_output)
    if FLAGS.max_sentences and sentences_output >= FLAGS.max_sentences:
      break

  tf.logging.info("Completed processing file %s", filename)
  return processed

목적: 미리 문서를 문장으로 나눈다. 예를 들어 문서는 [S1, S2, S3, S4]로 구성되어 있다.그러면 p r e d e c e s o r = [S 1, S 2] predecessor=[S1, S2] predecessor=[S1, S2] c u r e n t = [32, S 3] current = [32, S3] current=[32, S3] s u c c e s o r = [S 3, S 4] successor=[S3, S4] successor=[S3, S4] successor=[S3, S4] 사전 대응 id로 전환할 수 있다.
2.2 인코더 구축(skip thoughts/skip thoughts model.py)
 def build_encoder(self):
    """Builds the sentence encoder.
    Inputs:
      ##self.encode_ids    2.1  current  CBOW  
      self.encode_emb## 2.1  current  word embedding(cbow)      
      self.encode_mask## 2.1  current  one-hot  
    Outputs:
      self.thought_vectors
    Raises:
      ValueError: if config.bidirectional_encoder is True and config.encoder_dim
        is odd.
    """
    with tf.variable_scope("encoder") as scope:
      length = tf.to_int32(tf.reduce_sum(self.encode_mask, 1), name="length")

      if self.config.bidirectional_encoder:
        if self.config.encoder_dim % 2:
          raise ValueError(
              "encoder_dim must be even when using a bidirectional encoder.")
        num_units = self.config.encoder_dim // 2
        cell_fw = self._initialize_gru_cell(num_units)  # Forward encoder
        cell_bw = self._initialize_gru_cell(num_units)  # Backward encoder
        _, states = tf.nn.bidirectional_dynamic_rnn(
            cell_fw=cell_fw,
            cell_bw=cell_bw,
            inputs=self.encode_emb,
            sequence_length=length,
            dtype=tf.float32,
            scope=scope)
        thought_vectors = tf.concat(states, 1, name="thought_vectors")
      else:
        cell = self._initialize_gru_cell(self.config.encoder_dim)
        _, state = tf.nn.dynamic_rnn(
            cell=cell,
            inputs=self.encode_emb,
            sequence_length=length,
            dtype=tf.float32,
            scope=scope)
        # Use an identity operation to name the Tensor in the Graph.
        thought_vectors = tf.identity(state, name="thought_vectors")

    self.thought_vectors = thought_vectors

목적:current(텍스트)를 인코딩(양방향gru/단방향gru로 출력), 텍스트 인코딩 벡터 출력
2.3 디코더 구축(skip thoughts/skip thoughts model.py)
  def _build_decoder(self, name, embeddings, targets, mask, initial_state,
                     reuse_logits):
    """Builds a sentence decoder.
    Args:
      name: Decoder name.
      embeddings: Batch of sentences to decode; a float32 Tensor with shape
        [batch_size, padded_length, emb_dim].
      targets: Batch of target word ids; an int64 Tensor with shape
        [batch_size, padded_length].
      mask: A 0/1 Tensor with shape [batch_size, padded_length].
      initial_state: Initial state of the GRU. A float32 Tensor with shape
        [batch_size, num_gru_cells].
      reuse_logits: Whether to reuse the logits weights.
    """
    # Decoder RNN.
    cell = self._initialize_gru_cell(self.config.encoder_dim)
    with tf.variable_scope(name) as scope:
      # Add a padding word at the start of each sentence (to correspond to the
      # prediction of the first word) and remove the last word.
      decoder_input = tf.pad(
          embeddings[:, :-1, :], [[0, 0], [1, 0], [0, 0]], name="input")
      length = tf.reduce_sum(mask, 1, name="length")
      decoder_output, _ = tf.nn.dynamic_rnn(
          cell=cell,
          inputs=decoder_input,
          sequence_length=length,
          initial_state=initial_state,
          scope=scope)

    # Stack batch vertically.
    decoder_output = tf.reshape(decoder_output, [-1, self.config.encoder_dim])
    targets = tf.reshape(targets, [-1])
    weights = tf.to_float(tf.reshape(mask, [-1]))

    # Logits.
    with tf.variable_scope("logits", reuse=reuse_logits) as scope:
      logits = tf.contrib.layers.fully_connected(
          inputs=decoder_output,
          num_outputs=self.config.vocab_size,
          activation_fn=None,
          weights_initializer=self.uniform_initializer,
          scope=scope)

    losses = tf.nn.sparse_softmax_cross_entropy_with_logits(
        labels=targets, logits=logits)
    batch_loss = tf.reduce_sum(losses * weights)
    tf.losses.add_loss(batch_loss)

    tf.summary.scalar("losses/" + name, batch_loss)

    self.target_cross_entropy_losses.append(losses)
    self.target_cross_entropy_loss_weights.append(weights)

  def build_decoders(self):
    """Builds the sentence decoders.
    Inputs:## 2.2  encode,decode_pre  2.1  predecessor  ,decode_post  2.2  successor  
      self.decode_pre_emb
      self.decode_post_emb
      self.decode_pre_ids
      self.decode_post_ids
      self.decode_pre_mask
      self.decode_post_mask
      self.thought_vectors
    Outputs:
      self.target_cross_entropy_losses
      self.target_cross_entropy_loss_weights
    """
    if self.mode != "encode":
      # Pre-sentence decoder.
      self._build_decoder("decoder_pre", self.decode_pre_emb,
                          self.decode_pre_ids, self.decode_pre_mask,
                          self.thought_vectors, False)

      # Post-sentence decoder. Logits weights are reused.
      self._build_decoder("decoder_post", self.decode_post_emb,
                          self.decode_post_ids, self.decode_post_mask,
                          self.thought_vectors, True)

목적: 2.2 출력된 텍스트 벡터 인코딩에 따라 상문과 하문을 각각 디코딩하고 상문 디코딩 벡터와 하문 디코딩 벡터를 출력하며 상문 디코딩 벡터는 decodepre_ids 손실, 손실 곱하기 및 decodepre_mask 방해 제거
알고리즘의 사고방식은 비교적 간단하다. 나는 이 알고리즘에bilstm와self 를 따로 증가시켰다.attention 두 모델 코드 주소https://github.com/jinjiajia/skip_thoughts

좋은 웹페이지 즐겨찾기