<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _tflearn_features(train_config, args):
 """Builds the tf.learn feature list. All numerical features are just given real_valued_column because all the preprocessing transformations are done in preprocess_input. Categoriacl features are processed here depending if the vocab map (from string to int) was applied in preprocess_input. Args: train_config: our train config object args: command line args. Returns: List of TF lean feature columns. Raises: ValueError: if wrong transforms are used for the model type. """

  feature_columns = []
  target_name = train_config['target_column']
  key_name = train_config['key_column']

  for name in train_config['numerical_columns']:
    if name != target_name and name != key_name:
      feature_columns.append(tf.contrib.layers.real_valued_column(
          name,
          dimension=1))

      # Supported transforms:
      # for DNN
      # 1) string -> make int -> embedding (embedding)
      # 2) string -> make int -> one_hot (one_hot, default)
      # for linear
      # 1) string -> sparse_column_with_hash_bucket (embedding)
      # 2) string -> make int -> sparse_column_with_integerized_feature (one_hot, default)
      # It is unfortunate that tf.layers has different feature transforms if the
      # model is linear or DNN. This pacakge should not expose to the user that
      # we are using tf.layers. It is crazy that DNN models support more feature
      # types (like string -> hash sparse column -> embedding)
  for name in train_config['categorical_columns']:
    if name != target_name and name != key_name:
      transform_config = train_config['transforms'].get(name, {})
      transform_name = transform_config.get('transform', None)

      if is_dnn_model(args.model_type):
        if transform_name == 'embedding':
          sparse = tf.contrib.layers.sparse_column_with_integerized_feature(
              name,
              bucket_size=train_config['vocab_stats'][name]['n_classes'])
          learn_feature = tf.contrib.layers.embedding_column(
              sparse,
              dimension=transform_config['embedding_dim'])
        elif transform_name == 'one_hot' or transform_name is None:
          sparse = tf.contrib.layers.sparse_column_with_integerized_feature(
              name,
              bucket_size=train_config['vocab_stats'][name]['n_classes'])
          learn_feature = tf.contrib.layers.one_hot_column(sparse)
        else:
          raise ValueError(('Unknown transform name. Only \'embedding\' '
                            'and \'one_hot\' transforms are supported. Got %s')
                           % transform_name)
      elif is_linear_model(args.model_type):
        if transform_name == 'one_hot' or transform_name is None:
          learn_feature = tf.contrib.layers.sparse_column_with_integerized_feature(
              name,
              bucket_size=train_config['vocab_stats'][name]['n_classes'])
        elif transform_name == 'embedding':
          learn_feature = tf.contrib.layers.sparse_column_with_hash_bucket(
              name,
              hash_bucket_size=transform_config['embedding_dim'])
        else:
          raise ValueError(('Unknown transform name. Only \'embedding\' '
                            'and \'one_hot\' transforms are supported. Got %s')
                           % transform_name)

      # Save the feature
      feature_columns.append(learn_feature)
  return feature_columns