//  [python]
def _build_sampler(self):
        """Build the sampler ops and the log_prob ops."""
        self.logger.info(">>> Building Controller Sampler\n")

        hidden_size = self.controller_hidden_size

        arc_seq = []
        sample_log_probs = []
        sample_entropies = []

        skip_penalties = []
        skip_count = []

        all_h = []
        all_h_w = []

        prev_c = tf.zeros([1, hidden_size], tf.float32)
        prev_h = tf.zeros([1, hidden_size], tf.float32)

        skip_targets = tf.constant([1.0 - self.controller_skip_target, self.controller_skip_target],
                                   dtype=tf.float32)

        inputs = self.g_emb

        for layer_id in range(self.num_layers):

            next_c, next_h = _lstm(inputs, prev_c, prev_h, self.w_lstm)
            prev_c, prev_h = next_c, next_h

            logits = tf.matmul(next_h, self.w_soft)

            if self.controller_temperature is not None:
                logits /= self.controller_temperature
            if self.controller_tanh_const is not None:
                logits = self.controller_tanh_const * tf.tanh(logits)

            func = tf.random.categorical(logits, 1)
            func = tf.dtypes.cast(func, tf.int32)
            func = tf.reshape(func, [1])

            arc_seq.append(func)

            log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(
                logits=logits, labels=func)

            sample_log_probs.append(log_prob)
            entropy = log_prob * tf.exp(-log_prob)
            entropy = tf.stop_gradient(entropy)
            sample_entropies.append(entropy)
            inputs = tf.nn.embedding_lookup(params=self.w_emb, ids=func)

            next_c, next_h = _lstm(inputs, prev_c, prev_h, self.w_lstm)
            prev_c, prev_h = next_c, next_h

            if layer_id > 0:

                query = tf.matmul(next_h, self.attn_w_2)
                query = query + tf.concat(all_h_w, axis=0)
                query = tf.tanh(query)
                query = tf.matmul(query, self.attn_v)

                logits = tf.concat([-query, query], axis=1)

                if self.controller_temperature is not None:
                    logits /= self.controller_temperature
                if self.controller_tanh_const is not None:
                    logits = self.controller_tanh_const * tf.tanh(logits)

                skip_index = tf.random.categorical(logits, 1)
                skip_index = tf.dtypes.cast(skip_index, tf.int32)

                skip_index = tf.reshape(skip_index, [layer_id])
                arc_seq.append(skip_index)

                skip_prob = tf.sigmoid(logits)
                kl = skip_prob * tf.math.log(skip_prob/skip_targets)
                kl = tf.reduce_sum(input_tensor=kl)
                skip_penalties.append(kl)

                log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(
                    logits=logits, labels=skip_index)

                sample_log_probs.append(tf.reduce_sum(input_tensor=log_prob, keepdims=True))

                entropy = tf.stop_gradient(
                    tf.reduce_sum(input_tensor=log_prob * tf.exp(-log_prob), keepdims=True))
                sample_entropies.append(entropy)

                skip_index = tf.dtypes.cast(skip_index, tf.float32)
                skip_index = tf.reshape(skip_index, [1, layer_id])

                skip_count.append(tf.reduce_sum(input_tensor=skip_index))

                inputs = tf.matmul(skip_index, tf.concat(all_h, axis=0))

                inputs /= (1.0 + tf.reduce_sum(input_tensor=skip_index))
            else:
                inputs = self.g_emb

            all_h.append(next_h)
            all_h_w.append(tf.matmul(next_h, self.attn_w_1))

        arc_seq = tf.concat(arc_seq, axis=0)
        self.sample_arc = tf.reshape(arc_seq, [-1])

        sample_entropies = tf.stack(sample_entropies)
        self.sample_entropy = tf.reduce_sum(input_tensor=sample_entropies)

        sample_log_probs = tf.stack(sample_log_probs, axis=0)
        self.sample_log_probs = tf.reduce_sum(input_tensor=sample_log_probs)

        skip_penalties = tf.stack(skip_penalties)
        self.skip_penalties = tf.reduce_mean(input_tensor=skip_penalties)

        skip_count = tf.stack(skip_count)
        self.skip_count = tf.reduce_sum(input_tensor=skip_count)