Commit d839a2fb authored by ZHENQIN WU's avatar ZHENQIN WU
Browse files

Merge remote-tracking branch 'remotes/mine/GPGO' into MPNN

parents 86481311 599f8319
Loading
Loading
Loading
Loading
+153 −0
Original line number Diff line number Diff line
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 28 17:30:59 2017

@author: zqwu
"""

from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import numpy as np
import deepchem
from deepchem.molnet.preset_hyper_parameters import hps
import csv
import copy
from deepchem.utils.dependencies import pyGPGO_covfunc, pyGPGO_acquisition, \
    pyGPGO_surrogates_GaussianProcess, pyGPGO_GPGO


def GaussianProcessHyperparamOpt(dataset='tox21',
                                 model='tf',
                                 split='random',
                                 max_iter=20,
                                 search_range=4,
                                 hp_invalid_list=[
                                     'seed', 'nb_epoch', 'penalty_type',
                                     'dropouts', 'bypass_dropouts',
                                     'n_pair_feat'
                                 ]):
  hyper_parameters = copy.deepcopy(hps[model])
  # Extract parameters
  hp_list = hyper_parameters.keys()
  for hp in hp_invalid_list:
    if hp in hp_list:
      hp_list.remove(hp)

  hp_list_class = [hyper_parameters[hp].__class__ for hp in hp_list]
  assert set(hp_list_class) <= set([list, int, float])
  # Float or int hyper parameters(ex. batch_size, learning_rate)
  hp_list1 = [
      hp_list[i] for i in range(len(hp_list)) if not hp_list_class[i] is list
  ]
  # List of float or int hyper parameters(ex. layer_sizes)
  hp_list2 = [(hp_list[i], len(hyper_parameters[hp_list[i]]))
              for i in range(len(hp_list)) if hp_list_class[i] is list]

  # Number of parameters
  n_param = len(hp_list1) + sum([hp[1] for hp in hp_list2])
  # Range of optimization
  param_range = []
  for hp in hp_list1:
    if hyper_parameters[hp].__class__ is int:
      param_range.append((('int'), [
          hyper_parameters[hp] / search_range,
          hyper_parameters[hp] * search_range
      ]))
    else:
      param_range.append((('cont'), [
          hyper_parameters[hp] / search_range,
          hyper_parameters[hp] * search_range
      ]))
  for hp in hp_list2:
    if hyper_parameters[hp[0]][0].__class__ is int:
      param_range.extend([(('int'), [
          hyper_parameters[hp[0]][i] / search_range,
          hyper_parameters[hp[0]][i] * search_range
      ]) for i in range(hp[1])])
    else:
      param_range.extend([(('cont'), [
          hyper_parameters[hp[0]][i] / search_range,
          hyper_parameters[hp[0]][i] * search_range
      ]) for i in range(hp[1])])

  # Dummy names
  param_name = ['l' + format(i, '02d') for i in range(20)]
  param = dict(zip(param_name[:n_param], param_range))

  def f(l00=0,
        l01=0,
        l02=0,
        l03=0,
        l04=0,
        l05=0,
        l06=0,
        l07=0,
        l08=0,
        l09=0,
        l10=0,
        l11=0,
        l12=0,
        l13=0,
        l14=0,
        l15=0,
        l16=0,
        l17=0,
        l18=0,
        l19=0):
    args = locals()
    # Input hyper parameters
    i = 0
    for hp in hp_list1:
      hyper_parameters[hp] = float(args[param_name[i]])
      if param_range[i][0] == 'int':
        hyper_parameters[hp] = int(hyper_parameters[hp])
      i = i + 1
    for hp in hp_list2:
      hyper_parameters[hp[0]] = [
          float(args[param_name[j]]) for j in range(i, i + hp[1])
      ]
      if param_range[i][0] == 'int':
        hyper_parameters[hp[0]] = map(int, hyper_parameters[hp[0]])
      i = i + hp[1]

    print(hyper_parameters)
    # Run benchmark
    deepchem.molnet.run_benchmark(
        [dataset],
        str(model),
        split=str(split),
        hyper_parameters=hyper_parameters,
        out_path='/tmp')
    # Read results
    with open('/tmp/results.csv', 'r') as f:
      reader = csv.reader(f)
      # Return valid set performances
      return float(list(reader)[-1][8])

  cov = pyGPGO_covfunc.matern32()
  gp = pyGPGO_surrogates_GaussianProcess.GaussianProcess(cov)
  acq = pyGPGO_acquisition.Acquisition(mode='ExpectedImprovement')
  gpgo = pyGPGO_GPGO.GPGO(gp, acq, f, param)
  gpgo.run(max_iter=max_iter)

  hp_opt, valid_performance_opt = gpgo.getResult()

  # Readout best hyper parameters
  i = 0
  for hp in hp_list1:
    hyper_parameters[hp] = float(hp_opt[param_name[i]])
    if param_range[i][0] == 'int':
      hyper_parameters[hp] = int(hyper_parameters[hp])
    i = i + 1
  for hp in hp_list2:
    hyper_parameters[hp[0]] = [
        float(hp_opt[param_name[j]]) for j in range(i, i + hp[1])
    ]
    if param_range[i][0] == 'int':
      hyper_parameters[hp[0]] = map(int, hyper_parameters[hp[0]])
    i = i + hp[1]

  return hyper_parameters, valid_performance_opt
+3 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@ from operator import mul
from deepchem.utils.evaluate import Evaluator
from deepchem.utils.save import log


class HyperparamOpt(object):
  """
  Provides simple hyperparameter search capabilities.
@@ -111,3 +110,6 @@ class HyperparamOpt(object):
    log("train_score: %f" % train_score, self.verbose)
    log("validation_score: %f" % best_validation_score, self.verbose)
    return best_model, best_hyperparams, all_scores


from deepchem.hyper.gaussian_process import GaussianProcessHyperparamOpt
 No newline at end of file
+167 −0
Original line number Diff line number Diff line
"""
Contains basic hyperparameter optimizations.
"""
import numpy as np
import os
import itertools
import tempfile
import shutil
import collections
from functools import reduce
from operator import mul
from deepchem.utils.evaluate import Evaluator
from deepchem.utils.save import log
from deepchem.hyper import HyperparamOpt
from deepchem.molnet.run_benchmark_models import benchmark_classification, benchmark_regression

class GaussianProcessHyperparamOpt(HyperparamOpt):
  """
  Gaussian Process Global Optimization(GPGO)
  """
  def hyperparam_search(self,
                        params_dict,
                        train_dataset,
                        valid_dataset,
                        output_transformers,
                        metric,
                        n_features=1024,
                        n_tasks=1,
                        max_iter=20,
                        search_range=4,
                        hp_invalid_list=[
                            'seed', 'nb_epoch', 'penalty_type',
                            'dropouts', 'bypass_dropouts',
                            'n_pair_feat'
                        ],
                        logdir=None):
    assert len(metric) == 1, 'Only use one metric'
    hyper_parameters = params_dict
    hp_list = hyper_parameters.keys()
    for hp in hp_invalid_list:
      if hp in hp_list:
        hp_list.remove(hp)

    hp_list_class = [hyper_parameters[hp].__class__ for hp in hp_list]
    assert set(hp_list_class) <= set([list, int, float])
    # Float or int hyper parameters(ex. batch_size, learning_rate)
    hp_list1 = [
        hp_list[i] for i in range(len(hp_list)) if not hp_list_class[i] is list
    ]
    # List of float or int hyper parameters(ex. layer_sizes)
    hp_list2 = [(hp_list[i], len(hyper_parameters[hp_list[i]]))
                for i in range(len(hp_list)) if hp_list_class[i] is list]

    # Number of parameters
    n_param = len(hp_list1) + sum([hp[1] for hp in hp_list2])
    # Range of optimization
    param_range = []
    for hp in hp_list1:
      if hyper_parameters[hp].__class__ is int:
        param_range.append((('int'), [
            hyper_parameters[hp] / search_range,
            hyper_parameters[hp] * search_range
        ]))
      else:
        param_range.append((('cont'), [
            hyper_parameters[hp] / search_range,
            hyper_parameters[hp] * search_range
        ]))
    for hp in hp_list2:
      if hyper_parameters[hp[0]][0].__class__ is int:
        param_range.extend([(('int'), [
            hyper_parameters[hp[0]][i] / search_range,
            hyper_parameters[hp[0]][i] * search_range
        ]) for i in range(hp[1])])
      else:
        param_range.extend([(('cont'), [
            hyper_parameters[hp[0]][i] / search_range,
            hyper_parameters[hp[0]][i] * search_range
        ]) for i in range(hp[1])])

    # Dummy names
    param_name = ['l' + format(i, '02d') for i in range(20)]
    param = dict(zip(param_name[:n_param], param_range))

    def f(l00=0,
          l01=0,
          l02=0,
          l03=0,
          l04=0,
          l05=0,
          l06=0,
          l07=0,
          l08=0,
          l09=0,
          l10=0,
          l11=0,
          l12=0,
          l13=0,
          l14=0,
          l15=0,
          l16=0,
          l17=0,
          l18=0,
          l19=0):
      args = locals()
      # Input hyper parameters
      i = 0
      for hp in hp_list1:
        hyper_parameters[hp] = float(args[param_name[i]])
        if param_range[i][0] == 'int':
          hyper_parameters[hp] = int(hyper_parameters[hp])
        i = i + 1
      for hp in hp_list2:
        hyper_parameters[hp[0]] = [
            float(args[param_name[j]]) for j in range(i, i + hp[1])
        ]
        if param_range[i][0] == 'int':
          hyper_parameters[hp[0]] = map(int, hyper_parameters[hp[0]])
        i = i + hp[1]

      print(hyper_parameters)
      # Run benchmark
      if isinstance(self.model_class, str) or isinstance(self.model_class, unicode):
        try:
          train_scores, valid_scores, _ = benchmark_classification(
              train_dataset, valid_dataset, None, ['task_placeholder']*n_tasks,
              output_transformers, n_features, metric, model, 
              hyper_parameters=hyper_parameters)
        except AssertionError:
          train_scores, valid_scores, _ = benchmark_regression(
              train_dataset, valid_dataset, None, ['task_placeholder']*n_tasks,
              output_transformers, n_features, metric, model, 
              hyper_parameters=hyper_parameters)
        return valid_scores[model][metric[0].name]
      else:
        model_dir = tempfile.mkdtemp()
        model = self.model_class(hyper_parameters, model_dir)
        model.fit(train_dataset, **hyper_parameters)
        model.save()
        evaluator = Evaluator(model, valid_dataset, output_transformers)
        multitask_scores = evaluator.compute_model_performance([metric])
        return multitask_scores[metric.name]

    cov = pyGPGO_covfunc.matern32()
    gp = pyGPGO_surrogates_GaussianProcess.GaussianProcess(cov)
    acq = pyGPGO_acquisition.Acquisition(mode='ExpectedImprovement')
    gpgo = pyGPGO_GPGO.GPGO(gp, acq, f, param)
    gpgo.run(max_iter=max_iter)

    hp_opt, valid_performance_opt = gpgo.getResult()

    # Readout best hyper parameters
    i = 0
    for hp in hp_list1:
      hyper_parameters[hp] = float(hp_opt[param_name[i]])
      if param_range[i][0] == 'int':
        hyper_parameters[hp] = int(hyper_parameters[hp])
      i = i + 1
    for hp in hp_list2:
      hyper_parameters[hp[0]] = [
          float(hp_opt[param_name[j]]) for j in range(i, i + hp[1])
      ]
      if param_range[i][0] == 'int':
        hyper_parameters[hp[0]] = map(int, hyper_parameters[hp[0]])
      i = i + hp[1]

    return hyper_parameters, valid_performance_opt
+6 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ def import_lazy(module_name):
    return module
  except:
    print("Warning: No %s installed on your system" % module_name)
    print("Attempting to run %s will throw runtime errors")
    print("Attempting to run %s will throw runtime errors" % module_name)
    return None


@@ -18,3 +18,8 @@ xgboost = import_lazy("xgboost")
pdbfixer = import_lazy("pdbfixer")
simtk = import_lazy("simtk")
mdtraj = import_lazy("mdtraj")
pyGPGO_covfunc = import_lazy("pyGPGO.covfunc")
pyGPGO_acquisition = import_lazy("pyGPGO.acquisition")
pyGPGO_surrogates_GaussianProcess = import_lazy(
    "pyGPGO.surrogates.GaussianProcess")
pyGPGO_GPGO = import_lazy("pyGPGO.GPGO")
+0 −119
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 07 22:41:34 2016

@author: Zhenqin Wu
"""
import numpy as np
import deepchem as dc
import os
import time
import sys
from scipy.stats import truncnorm

# main layer
layer_sizes_0 = [1200]
weight_init_stddevs_0 = [0.02]
bias_init_consts_0 = [1.]
dropouts_0 = [0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7]

#bypass layer
bypass_layer_sizes_0 = truncnorm(-1, 1, loc=200, scale=150)
bypass_weight_init_stddevs_0 = [.02]
bypass_bias_init_consts_0 = [1.]
bypass_dropouts_0 = [0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7]

#penalty
penalty_0 = truncnorm(-1, 1, loc=0.3, scale=0.2)
penalty_type_0 = ['l2']

#general figure
batch_size_0 = [50]
nb_epoch_0 = [12]

#learning rate
learning_rate_0 = truncnorm(-1, 1, loc=-3.2, scale=1.2)

#for graph-conv and random forest
n_filters_0 = [64, 96, 128]
n_fully_connected_nodes_0 = [100, 120, 140, 160, 200, 240, 300]
n_estimators_0 = [500]
seed = None

out_path = '.'

dname = sys.argv[1]
model = sys.argv[2]

parameters_printed = {
    'tf': [
        'layer_sizes', 'weight_init_stddevs', 'bias_init_consts', 'dropouts',
        'penalty', 'penalty_type', 'batch_size', 'nb_epoch', 'learning_rate'
    ],
    'tf_robust': [
        'layer_sizes', 'weight_init_stddevs', 'bias_init_consts', 'dropouts',
        'bypass_layer_sizes', 'bypass_weight_init_stddevs',
        'bypass_bias_init_consts', 'bypass_dropouts', 'penalty', 'penalty_type',
        'batch_size', 'nb_epoch', 'learning_rate'
    ],
    'logreg':
    ['penalty', 'penalty_type', 'batch_size', 'nb_epoch', 'learning_rate'],
    'graphconv': [
        'batch_size', 'nb_epoch', 'learning_rate', 'n_filters',
        'n_fully_connected_nodes'
    ],
    'rf': ['n_estimators']
}
hps = {}
for i in range(int(sys.argv[3])):
  layer_sizes = layer_sizes_0
  weight_init_stddevs = weight_init_stddevs_0
  bias_init_consts = bias_init_consts_0
  dropouts = [np.random.choice(dropouts_0)]

  bypass_layer_sizes = [int(bypass_layer_sizes_0.rvs())]
  bypass_weight_init_stddevs = bypass_weight_init_stddevs_0
  bypass_bias_init_consts = bypass_bias_init_consts_0
  bypass_dropouts = [np.random.choice(bypass_dropouts_0)]

  penalty = penalty_0.rvs()
  penalty_type = np.random.choice(penalty_type_0)

  batch_size = np.random.choice(batch_size_0)
  nb_epoch = np.random.choice(nb_epoch_0)

  learning_rate = 10**(learning_rate_0.rvs())

  n_filters = np.random.choice(n_filters_0)
  n_fully_connected_nodes = np.random.choice(n_fully_connected_nodes_0)
  n_estimators = np.random.choice(n_estimators_0)

  hps[model] = {
      'layer_sizes': layer_sizes,
      'weight_init_stddevs': weight_init_stddevs,
      'bias_init_consts': bias_init_consts,
      'dropouts': dropouts,
      'bypass_layer_sizes': bypass_layer_sizes,
      'bypass_weight_init_stddevs': bypass_weight_init_stddevs,
      'bypass_bias_init_consts': bypass_bias_init_consts,
      'bypass_dropouts': bypass_dropouts,
      'penalty': penalty,
      'penalty_type': penalty_type,
      'batch_size': batch_size,
      'nb_epoch': nb_epoch,
      'learning_rate': learning_rate,
      'n_filters': n_filters,
      'n_fully_connected_nodes': n_fully_connected_nodes,
      'n_estimators': n_estimators,
      'seed': seed
  }

  with open(os.path.join(out_path, 'hps.csv'), 'a') as f:
    f.write('\n' + str(i) + ',' + dname + ',')
    for item in hps[model][i]:
      if item in parameters_printed[model]:
        f.write(item + ',')
        f.write(str(hps[model][i][item]) + ',')

  dc.molnet.run_benchmark(
      [dname], str(model), out_path=out_path, hyper_parameters=hps)