text: import json
  import logging
  import numpy as np
  import os
  import shutil
  
  from keras.preprocessing.sequence import pad_sequences
  from keras.utils import to_categorical
  
  
  class Params():
      """Class that loads hyperparameters from a json file.
  
      Example:
      ```
      params = Params(json_path)
      print(params.learning_rate)
      params.learning_rate = 0.5  # change the value of learning_rate in params
      ```
      """
  
      def __init__(self, json_path):
          with open(json_path) as f:
              params = json.load(f)
              self.__dict__.update(params)
  
      def save(self, json_path):
          with open(json_path, 'w') as f:
              json.dump(self.__dict__, f, indent=4)
  
      def update(self, json_path):
          """Loads parameters from json file"""
          with open(json_path) as f:
              params = json.load(f)
              self.__dict__.update(params)
  
      @property
      def dict(self):
          """Gives dict-like access to Params instance by `params.dict['learning_rate']"""
          return self.__dict__
  
  
  class RunningAverage():
      """A simple class that maintains the running average of a quantity
  
      Example:
      ```
      loss_avg = RunningAverage()
      loss_avg.update(2)
      loss_avg.update(4)
      loss_avg() = 3
      ```
      """
  
      def __init__(self):
          self.steps = 0
          self.total = 0
  
      def update(self, val):
          self.total += val
          self.steps += 1
  
      def __call__(self):
          return self.total / float(self.steps)
  
  
  def process_data_for_keras(label_size, X, y=None):
      word_ids = pad_sequences(X, padding='post')
      # lengths = np.array([len(sent) for sent in X], dtype='int32')
      # features = [word_ids, lengths]
      features = [word_ids]
      if y is not None:
          y = pad_sequences(y, padding='post')
          y = to_categorical(y, label_size).astype(int)
          y = y if len(y.shape) == 3 else np.expand_dims(y, axis=0)
          return features, y
      else:
          return features
  
  
  def set_logger(log_path):
      """Set the logger to log info in terminal and file `log_path`.
  
      In general, it is useful to have a logger so that every output to the terminal is saved
      in a permanent file. Here we save it to `model_dir/train.log`.
  
      Example:
      ```
      logging.info("Starting training...")
      ```
  
      Args:
          log_path: (string) where to log
      """
      logger = logging.getLogger()
      logger.setLevel(logging.INFO)
  
      if not logger.handlers:
          # Logging to a file
          file_handler = logging.FileHandler(log_path)
          file_handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s: %(message)s'))
          logger.addHandler(file_handler)
  
          # Logging to console
          stream_handler = logging.StreamHandler()
          stream_handler.setFormatter(logging.Formatter('%(message)s'))
          logger.addHandler(stream_handler)
  
  
  def save_dict_to_json(d, json_path):
      """Saves dict of floats in json file
  
      Args:
          d: (dict) of float-castable values (np.float, int, float, etc.)
          json_path: (string) path to json file
      """
      with open(json_path, 'w') as f:
          # We need to convert the values to float for json (it doesn't accept np.array, np.float, )
          d = {k: float(v) for k, v in d.items()}
          json.dump(d, f, indent=4)
  