code: def build_graph(self, feat, labelidx, labelvalue, labelshape, seqlen):
      label = tf.SparseTensor(labelidx, labelvalue, labelshape)
  
      cell = rnn.MultiRNNCell(
          [rnn.LSTMBlockCell(num_units=HIDDEN) for _ in range(NLAYER)]
      )
  
      initial = cell.zero_state(tf.shape(feat)[0], tf.float32)
  
      outputs, last_state = tf.nn.dynamic_rnn(
          cell, feat, seqlen, initial, dtype=tf.float32, scope="rnn"
      )
  
      # o: b x t x HIDDEN
      output = tf.reshape(outputs, [-1, HIDDEN])  # (Bxt) x rnnsize
      logits = FullyConnected(
          "fc",
          output,
          NR_CLASS,
          activation=tf.identity,
          kernel_initializer=tf.truncated_normal_initializer(
              stddev=0.01
          ),
      )
      logits = tf.reshape(logits, (BATCH, -1, NR_CLASS))
  
      loss = tf.nn.ctc_loss(label, logits, seqlen, time_major=False)
  
      cost = tf.reduce_mean(loss, name="cost")
  
      logits = tf.transpose(logits, [1, 0, 2])
  
      if self.training:
          # beam search is too slow to run in training
          predictions = tf.cast(
              tf.nn.ctc_greedy_decoder(logits, seqlen)[0][0], tf.int32
          )
      else:
          predictions = tf.cast(
              tf.nn.ctc_beam_search_decoder(logits, seqlen)[0][0],
              tf.int32,
          )
      err = tf.edit_distance(predictions, label, normalize=True)
      err.set_shape([None])
      err = tf.reduce_mean(err, name="error")
      summary.add_moving_summary(err, cost)
      return cost
  
file_path: tensorpack/examples/CTC-TIMIT/train-timit.py
imports: import argparse
  import os
  import tensorflow
  from tensorpack import *
  from tensorpack.tfutils.gradproc import GlobalNormClip, SummaryGradient
  from timitdata import TIMITBatch
label_desc: Use image node_id 2 for calling the Model obj's underlying member method code with example usage: obj.build_graph(feat, labelidx, labelvalue, labelshape, seqlen) and returns: cost