Commit b7da7209 authored by Bharath Ramsundar's avatar Bharath Ramsundar
Browse files

First round of changes for subcommand architecture

parent 4777a227
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -12,18 +12,17 @@ from deep_chem.utils.preprocess import tensor_dataset_to_numpy
from deep_chem.utils.evaluate import eval_model
from deep_chem.utils.evaluate import compute_r2_scores

def fit_3D_convolution(per_task_data, task_types, axis_length=32, **training_params):
def fit_3D_convolution(per_task_data, task_types, **training_params):
  """
  Perform stochastic gradient descent for a 3D CNN.
  """
  models = {}
  (X_train, y_train, W_train, train), (X_test, y_test, W_test, test) = (
      per_task_data["all"] 
  (train, X_train, y_train, _), _ = per_task_data["all"]
  nb_classes = 2
  models["all"] = train_3D_convolution(X_train, y_train, axis_length, **training_params)
  models["all"] = train_3D_convolution(X_train, y_train, **training_params)
  return models

def train_3D_convolution(X, y, axis_length=32, batch_size=50, nb_epoch=1):
def train_3D_convolution(X, y, batch_size=50, nb_epoch=1):
  """
  Fit a keras 3D CNN to datat.

+95 −43
Original line number Diff line number Diff line
"""
Convenience script to train basic models on supported datasets.
Top level script to featurize input, train models, and evaluate them.
"""
import argparse
import numpy as np
@@ -11,75 +11,129 @@ from deep_chem.utils.load import get_target_names
from deep_chem.utils.load import process_datasets
from deep_chem.utils.evaluate import results_to_csv

# TODO(rbharath): Factor this into subcommands. The interface is too
# complicated now to effectively use.
def parse_args(input_args=None):
  """Parse command-line arguments."""
  parser = argparse.ArgumentParser()
  parser.add_argument("--task-type", default="classification",
  subparsers = parser.add_subparsers(title='Modes')

  # TODO(rbharath): This function should invoke process_dataset under the hood
  # to avoid having to invoke two scripts.
  featurize_cmd = subparsers.add_parser("featurize",
                      help="Featurize raw input data.")
  featurize_cmd.add_argument("--input-file", required=1,
                      help="Input file with data.")
  featurize_cmd.add_argument("--input-type", default="csv",
                      choices=["xlsx", "csv", "pandas", "sdf"],
                      help="Type of input file. If pandas, input must be a pkl.gz\n"
                           "containing a pandas dataframe. If sdf, should be in\n"
                           "(perhaps gzipped) sdf file.")
  featurize_cmd.add_argument("--delimiter", default="\t",
                      help="If csv input, delimiter to use for read csv file")
  featurize_cmd.add_argument("--fields", required=1, nargs="+",
                      help = "Names of fields.")
  featurize_cmd.add_argument("--field-types", required=1, nargs="+",
                      choices=["string", "float", "list-string", "list-float", "ndarray"],
                      help="Type of data in fields.")
  featurize_cmd.add_argument("--feature-endpoint", type=str,
                      help="Optional endpoint that holds pre-computed feature vector")
  featurize_cmd.add_argument("--prediction-endpoint", type=str, required=1,
                       help="Name of measured endpoint to predict.")
  featurize_cmd.add_argument("--split-endpoint", type=str, default=None,
                       help="Name of endpoint specifying train/test split.")
  featurize_cmd.add_argument("--threshold", type=float, default=None,
                      help="If specified, will be used to binarize real-valued prediction-endpoint.")
  featurize_cmd.add_argument("--has-colnames", type=bool, default=False,
                      help="Input has column labels which should be skipped (only for csv/xlsx).")
  featurize_cmd.add_argument("--name", required=1,
                      help="Name of the dataset.")
  featurize_cmd.add_argument("--out", required=1,
                      help="Folder to generate processed dataset in.")
  featurize_cmd.set_defaults(func=featurize_input)

  train_cmd = subparsers.add_parser("train",
                  help="Train a model on specified data.")
  group = train_cmd.add_argument_group("load-and-transform")
  group.add_argument("--task-type", default="classification",
                      choices=["classification", "regression"],
                      help="Type of learning task.")
  parser.add_argument("--input-transforms", nargs="+", default=[],
  group.add_argument("--input-transforms", nargs="+", default=[],
                      choices=["normalize", "truncate-outliers"],
                      help="Transforms to apply to input data.")
  parser.add_argument("--output-transforms", nargs="+", default=[],
  group.add_argument("--output-transforms", nargs="+", default=[],
                      choices=["log", "normalize"],
                      help="Transforms to apply to output data.")
  parser.add_argument("--feature-types", nargs="+", required=1,
  group.add_argument("--feature-types", nargs="+", required=1,
                      help="Types of featurizations to use.")
  parser.add_argument("--paths", nargs="+", required=1,
  group.add_argument("--paths", nargs="+", required=1,
                      help="Paths to input datasets.")
  parser.add_argument("--mode", default="singletask",
  group.add_argument("--splittype", type=str, default="scaffold",
                       choices=["scaffold", "random", "specified"],
                       help="Type of train/test data-splitting.\n"
                            "scaffold uses Bemis-Murcko scaffolds.\n"
                            "specified requires that split be in original data.")

  group = train_cmd.add_argument_group("model")
  group.add_argument("--mode", default="singletask",
                      choices=["singletask", "multitask"],
                      help="Type of model being built.")
  parser.add_argument("--model", required=1,
  group.add_argument("--model", required=1,
                      choices=["logistic", "rf_classifier", "rf_regressor",
                      "linear", "ridge", "lasso", "lasso_lars", "elastic_net",
                      "singletask_deep_network", "multitask_deep_network",
                      "3D_cnn"])
  parser.add_argument("--splittype", type=str, default="scaffold",
                       choices=["scaffold", "random", "specified"],
                       help="Type of train/test data-splitting.\n"
                            "scaffold uses Bemis-Murcko scaffolds.\n"
                            "specified requires that split be in original data.")
  parser.add_argument("--csv-out", type=str, default=None,
                  help="Outputted predictions on the test set.")
  #TODO(rbharath): These two arguments (prediction/split-endpoint) should be
  #moved to process_datataset to simplify the invocation here.
  parser.add_argument("--prediction-endpoint", type=str, required=1,
                       help="Name of measured endpoint to predict.")
  parser.add_argument("--split-endpoint", type=str, default=None,
                       help="Name of endpoint specifying train/test split.")

  # SUBCOMMAND Training params
  parser.add_argument("--n-hidden", type=int, default=500,
  group.add_argument("--n-hidden", type=int, default=500,
                      help="Number of hidden neurons for NN models.")
  parser.add_argument("--learning-rate", type=float, default=0.01,
  group.add_argument("--learning-rate", type=float, default=0.01,
                  help="Learning rate for NN models.")
  parser.add_argument("--dropout", type=float, default=0.5,
  group.add_argument("--dropout", type=float, default=0.5,
                  help="Learning rate for NN models.")
  parser.add_argument("--n-epochs", type=int, default=50,
  group.add_argument("--n-epochs", type=int, default=50,
                  help="Number of epochs for NN models.")
  parser.add_argument("--batch-size", type=int, default=32,
  group.add_argument("--batch-size", type=int, default=32,
                  help="Number of examples per minibatch for NN models.")
  parser.add_argument("--decay", type=float, default=1e-4,
  group.add_argument("--decay", type=float, default=1e-4,
                  help="Learning rate decay for NN models.")
  parser.add_argument("--validation-split", type=float, default=0.0,
  group.add_argument("--validation-split", type=float, default=0.0,
                  help="Percent of training data to use for validation.")
  parser.add_argument("--weight-positives", type=bool, default=False,
  group.add_argument("--weight-positives", type=bool, default=False,
                  help="Weight positive examples to have same total weight as negatives.")
  parser.add_argument("--axis-length", type=int, default=32,
                  help="Size of a grid axis for 3D CNN input.")

  # SUBCOMMAND Evaluation types
  parser.add_argument("--compute-aucs", type=bool, default=False,
  group = train_cmd.add_argument_group("save")
  group.add_argument("--saved-out", type=str, required=1,
                  help="Location to save trained model.")

  eval_cmd = subparsers.add_parser("eval",
                help="Evaluate trained model on specified data.")
  eval_cmd.add_argument("--splittype", type=str, default="scaffold",
                       choices=["scaffold", "random", "specified"],
                       help="Type of train/test data-splitting.\n"
                            "scaffold uses Bemis-Murcko scaffolds.\n"
                            "specified requires that split be in original data.")
  eval_cmd.add_argument("--compute-aucs", type=bool, default=False,
                      help="Compute AUC for trained models on test set.")
  parser.add_argument("--compute-r2s", type=bool, default=False,
  eval_cmd.add_argument("--compute-r2s", type=bool, default=False,
                      help="Compute R^2 for trained models on test set.")
  parser.add_argument("--compute-rms", type=bool, default=False,
  eval_cmd.add_argument("--compute-rms", type=bool, default=False,
                      help="Compute RMS for trained models on test set.")
  eval_cmd.add_argument("--csv-out", type=str, default=None,
                  help="Outputted predictions on the test set.")

  return parser.parse_args(input_args)

def featurize_input(args):
  """Featurizes raw input data."""
  if len(args.fields) != len(args.field_types):
    raise ValueError("number of fields does not equal number of field types")
  out_x_pkl, out_y_pkl, out_sdf = generate_directories(args.name, args.out, 
      args.feature_endpoint)
  df, mols = extract_data(args.input_file, args.input_type, args.fields,
      args.field_types, args.prediction_endpoint,
      args.threshold, args.delimiter, args.has_colnames)
  generate_targets(df, mols, args.prediction_endpoint, args.split_endpoint, out_y_pkl, out_sdf)
  generate_features(df, args.feature_endpoint, out_x_pkl)
  generate_fingerprints(args.name, args.out)
  generate_descriptors(args.name, args.out)

def main():
  args = parse_args()
  paths = {}
@@ -106,8 +160,7 @@ def main():
    models = fit_singletask_mlp(per_task_data, task_types, n_hidden=args.n_hidden,
      learning_rate=args.learning_rate, dropout=args.dropout,
      nb_epoch=args.n_epochs, decay=args.decay, batch_size=args.batch_size,
      validation_split=args.validation_split,
      num_to_train=args.num_to_train)
      validation_split=args.validation_split)
  elif args.model == "multitask_deep_network":
    models = fit_multitask_mlp(per_task_data, task_types,
      n_hidden=args.n_hidden, learning_rate = args.learning_rate,
@@ -119,8 +172,7 @@ def main():
        axis_length=args.axis_length, nb_epoch=args.n_epochs,
        batch_size=args.batch_size)
  else:
    models = fit_singletask_models(per_task_data, args.model, task_types,
                                    num_to_train=args.num_to_train)
    models = fit_singletask_models(per_task_data, args.model, task_types)

  results, aucs, r2s, rms = compute_model_performance(per_task_data, models,
    args.compute_aucs, args.compute_r2s, args.compute_rms) 

deep_chem/utils/dataset_arxiv.py

deleted100644 → 0
+0 −18
Original line number Diff line number Diff line
"""
Code for processing the Google vs-datasets.
"""
__author__ = "Bharath Ramsundar"
__copyright__ = "Copyright 2015, Stanford University"
__license__ = "LGPL"

import os
import numpy as np
import gzip
import cPickle as pickle
import csv
import pandas as pd
from sklearn.metrics import roc_auc_score
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
from sklearn.metrics import roc_curve
from sklearn.metrics import confusion_matrix
+0 −46
Original line number Diff line number Diff line
@@ -16,34 +16,6 @@ from vs_utils.utils import SmilesGenerator, ScaffoldGenerator
def parse_args(input_args=None):
  """Parse command-line arguments."""
  parser = argparse.ArgumentParser()
  parser.add_argument("--input-file", required=1,
                      help="Input file with data.")
  parser.add_argument("--input-type", default="csv",
                      choices=["xlsx", "csv", "pandas", "sdf"],
                      help="Type of input file. If pandas, input must be a pkl.gz\n"
                           "containing a pandas dataframe. If sdf, should be in\n"
                           "(perhaps gzipped) sdf file.")
  parser.add_argument("--fields", required=1, nargs="+",
                      help = "Names of fields.")
  parser.add_argument("--field-types", required=1, nargs="+",
                      choices=["string", "float", "list-string", "list-float", "ndarray"],
                      help="Type of data in fields.")
  parser.add_argument("--name", required=1,
                      help="Name of the dataset.")
  parser.add_argument("--out", required=1,
                      help="Folder to generate processed dataset in.")
  parser.add_argument("--feature-endpoint", type=str,
                      help="Optional endpoint that holds pre-computed feature vector")
  parser.add_argument("--prediction-endpoint", type=str, required=1,
                      help="Name of measured endpoint to predict.")
  parser.add_argument("--threshold", type=float, default=None,
                      help="Used to turn real-valued data into binary.")
  parser.add_argument("--delimiter", default="\t",
                      help="Delimiter in csv file")
  parser.add_argument("--has-colnames", type=bool, default=False,
                      help="Input has column names.")
  parser.add_argument("--split-endpoint", type=str, default=None,
                      help="User-specified train-test split.")
  return parser.parse_args(input_args)

def generate_directories(name, out, feature_endpoint):
@@ -250,21 +222,3 @@ def extract_data(input_file, input_type, fields, field_types,
    rows.append(row)
  df = pd.DataFrame(rows)
  return(df, mols)


def main():
  args = parse_args()
  if len(args.fields) != len(args.field_types):
    raise ValueError("number of fields does not equal number of field types")
  out_x_pkl, out_y_pkl, out_sdf = generate_directories(args.name, args.out, 
      args.feature_endpoint)
  df, mols = extract_data(args.input_file, args.input_type, args.fields,
      args.field_types, args.prediction_endpoint,
      args.threshold, args.delimiter, args.has_colnames)
  generate_targets(df, mols, args.prediction_endpoint, args.split_endpoint, out_y_pkl, out_sdf)
  generate_features(df, args.feature_endpoint, out_x_pkl)
  generate_fingerprints(args.name, args.out)
  generate_descriptors(args.name, args.out)

if __name__ == "__main__":
  main()