Ejemplo n.º 1
0
    def test_multiarg(self):
        """Test making descriptions with more than one argument"""

        # Initialize the model
        model = PythonStaticMethodModel.from_function_pointer(max)
        model.set_name('test').set_title('test')

        # Define the inputs and outputs
        model.set_inputs('tuple',
                         'Two numbers',
                         element_types=[
                             compose_argument_block('float', 'A number'),
                             compose_argument_block('float', 'A second number')
                         ])
        model.set_outputs('float', 'Maximum of the two numbers')

        # Mark that the inputs should be unpacked
        model.set_unpack_inputs(True)

        # Check the description
        self.assertEqual(
            model['servable']['methods']['run'], {
                'input': {
                    'type':
                    'tuple',
                    'description':
                    'Two numbers',
                    'element_types': [{
                        'type': 'float',
                        'description': 'A number'
                    }, {
                        'type': 'float',
                        'description': 'A second number'
                    }]
                },
                'output': {
                    'type': 'float',
                    'description': 'Maximum of the two numbers'
                },
                'method_details': {
                    'module': 'builtins',
                    'method_name': 'max',
                    'unpack': True,
                    'autobatch': False
                },
                'parameters': {}
            })

        validate_against_dlhub_schema(model.to_dict(), 'servable')
Ejemplo n.º 2
0
def test_multiargs():
    # Make the maximum function
    model = PythonStaticMethodModel.from_function_pointer(max) \
        .set_name('test').set_title('test')

    # Describe the inputs
    model.set_inputs('tuple', 'Two numbers',
                     element_types=[
                         compose_argument_block('float', 'A number'),
                         compose_argument_block('float', 'A second number')
                     ])
    model.set_outputs('float', 'Maximum of the two numbers')
    model.set_unpack_inputs(True)

    # Make sure the shim works
    servable = PythonStaticMethodServable(**model.to_dict())
    assert servable.run((1, 2))[0] == 2
Ejemplo n.º 3
0
def _read_tf_inputs_and_outputs(arg_def):
    """Create a DLHub-compatible description from a Google ProtoBuf description of
    the inputs or outputs to a function

    Args:
        arg_def (MessageMap): Description of the inputs/outputs
    Returns:
        - (dict) Description of the input/output data in DLHub format
        - ([string]) Names of the input and output nodes
    """

    # Convert the tensor descriptions to a format compatible with DLHub,
    #   and fetch the names of the corresponding node on the graph
    dlhub_arg_defs = []
    node_names = []
    for name, arg_def in arg_def.items():
        # Get the shape of the Tensor (assuming all inputs are tensors)
        shape = [
            d.size if d.size != -1 else None for d in arg_def.tensor_shape.dim
        ]

        # Append the node name
        node_names.append(arg_def.name)

        # Different case if it is a scalar or a tensor
        if len(shape) == 0:
            dlhub_arg_defs.append(
                compose_argument_block(_convert_dtype(arg_def.dtype), name))
        else:
            dlhub_arg_defs.append(
                compose_argument_block('ndarray', name, shape,
                                       _convert_dtype(arg_def.dtype)))

    # If the function has only one argument, return that
    if len(dlhub_arg_defs) == 1:
        return dlhub_arg_defs[0], node_names

    # Otherwise, create a "tuple" type
    #   First sort arguments by description, to ensure a deterministic order to them between runs
    dlhub_arg_defs, node_names = zip(*sorted(
        zip(dlhub_arg_defs, node_names), key=lambda x: x[0]['description']))
    return compose_argument_block(
        'tuple',
        'Arguments',
        shape=[len(dlhub_arg_defs)],
        element_types=dlhub_arg_defs), list(node_names)
Ejemplo n.º 4
0
    def format_layer_spec(self, layers):
        """Make a description of a list of input or output layers

        Args:
            layers (tuple or [tuple]): Shape of the layers
        Return:
            (dict) Description of the inputs / outputs
        """
        if isinstance(layers, tuple):
            return compose_argument_block("ndarray",
                                          "Tensor",
                                          shape=list(layers))
        else:
            return compose_argument_block(
                "tuple",
                "Tuple of tensors",
                element_types=[self.format_layer_spec(i) for i in layers])
Ejemplo n.º 5
0
    def format_layer_spec(self, layers, datatypes):
        """Make a description of a list of input or output layers

        Args:
            layers (tuple or [tuple]): Shape of the layers
            datatypes (str or [str]): Data type of each input layer
        Return:
            (dict) Description of the inputs / outputs
        """
        if isinstance(layers, tuple):
            return ArgumentTypeMetadata.parse_obj(compose_argument_block("ndarray", "Tensor",
                                                                         shape=list(layers), item_type=datatypes))
        else:
            if isinstance(datatypes, str):
                datatypes = [datatypes] * len(layers)
            return ArgumentTypeMetadata.parse_obj(
                compose_argument_block("tuple", "Tuple of tensors",
                                       element_types=[self.format_layer_spec(i, t)
                                                      for i, t in zip(layers, datatypes)]))
Ejemplo n.º 6
0
def test_multiargs_autobatch():
    # Make the maximum function
    model = PythonStaticMethodModel.from_function_pointer(max, autobatch=True) \
        .set_name('test').set_title('test')

    # Describe the inputs
    model.set_inputs('list', 'List of pairs of numbers',
                     item_type=compose_argument_block(
                         'tuple', 'Two numbers',
                         element_types=[
                             compose_argument_block('float', 'A number'),
                             compose_argument_block('float', 'A second number')
                         ]))
    model.set_outputs('list', 'Maximum of each pair', item_type='float')
    model.set_unpack_inputs(True)

    # Make sure the shim works
    servable = PythonStaticMethodServable(**model.to_dict())
    out, _ = servable.run([(1, 2)])
    assert out == [2]
Ejemplo n.º 7
0
def _read_tf_v2_function_signature(signature: List[tf.Tensor]) -> dict:
    """Generate a DLHub type specification from a Tensor object

    Args:
        sig: Function signature as a list of tensor
    Returns:
        (dict) Type specification
    """

    # Get the tensor shapes
    output = []
    for sig in signature:
        if sig.dtype != tf.resource:  # Sometimes gets added for single-input functions
            output.append(compose_argument_block('ndarray', sig.name, shape=list(sig.shape),
                                                 item_type=simplify_numpy_dtype(
                                                     np.dtype(sig.dtype.as_numpy_dtype))))
    if len(output) == 1:
        return output[0]
    else:
        return compose_argument_block('tuple', 'Several tensors', element_types=output)
Ejemplo n.º 8
0
def test_file_multiinput():
    model = PythonStaticMethodModel.from_function_pointer(multifile_input)
    model.set_name('test')
    model.set_title('test')
    model.set_inputs('tuple', 'Several things', element_types=[
        compose_argument_block('file', 'Single file'),
        compose_argument_block('list', 'Multiple files', item_type='file'),
        compose_argument_block('boolean', 'Something random')
    ])
    model.set_outputs('bool', 'Should be True')
    model.set_unpack_inputs(True)

    # Make the servable
    servable = PythonStaticMethodServable(**model.to_dict())

    # Test it
    assert servable.run([
        {'url': __file__},
        [{'url': __file__}],
        True
    ])[0]
Ejemplo n.º 9
0
    def set_outputs(self,
                    data_type,
                    description,
                    shape=(),
                    item_type=None,
                    **kwargs):
        """Define the outputs to the default ("run") function

        Args:
            data_type (string): Type of the output data
            description (string): Human-friendly description of the data
            shape (list): Required for data_type of ndarray. Use `None` for dimensions that
                can have any numbers of values
            item_type (string): Description of the type of item in a list
        """

        args = compose_argument_block(data_type, description, shape, item_type,
                                      **kwargs)
        self._output["servable"]["methods"]["run"]["output"] = args
        return self
Ejemplo n.º 10
0
    def set_inputs(self,
                   data_type,
                   description,
                   shape=(),
                   item_type=None,
                   **kwargs):
        """Define the inputs to the default ("run") function

        Args:
            data_type (string): Type of the input data
            description (string): Human-friendly description of the data
            shape (list): Required for data_type of list or ndarray. Use `None` for dimensions that
                can have any numbers of values
            item_type (string/dict): Description of the item type. Required for data_type = list
        """
        args = compose_argument_block(data_type, description, shape, item_type,
                                      **kwargs)

        # Set the inputs
        self.servable.methods["run"].input = ArgumentTypeMetadata.parse_obj(
            args)
        return self
Ejemplo n.º 11
0
def test_multiargs_pickle(tmpdir):
    # Make an example class
    x = ExampleClass(2)

    # Save a pickle
    filename = str(tmpdir / 'test.pkl')
    with open(filename, 'wb') as fp:
        pkl.dump(x, fp)

    # Make the metadata file
    model = PythonClassMethodModel.create_model(filename, 'f')
    model.set_title('Example function')
    model.set_name('function')
    model.set_inputs('tuple', 'inputs',
                     element_types=[compose_argument_block('float', 'Number')] * 2)
    model.set_outputs('float', 'Output')
    model.set_unpack_inputs(True)

    # Make the servable
    validate_against_dlhub_schema(model.to_dict(), 'servable')
    servable = PythonClassMethodServable(**model.to_dict())

    # Test the servable
    assert 4 == servable.run([1, 2])[0]
# Describe the encoding step
#  The first step is to turn a string into a list of integers
string_length = model.input['shape'][-1]
model = PythonStaticMethodModel('app',
                                'encode_string',
                                function_kwargs={'length': string_length},
                                autobatch=True)

#  Describe the inputs and outputs
model.set_inputs('list', 'List of SMILES strings', item_type='string')
model.set_outputs('list',
                  'List of encoded strings.',
                  item_type=compose_argument_block(
                      'list', 'Encoded string. List of integers where each '
                      'value is the index of the character in the '
                      'library, or 0 if it is padded',
                      item_type='integer'))
#  Add provenance information
model.set_authors(["Zhu, Mengyuan"], ["Georgia State University"])
model.set_title("String Encoder for Classification Model for AMDET Properties")
model.set_name("deep-smiles_enocoder")
model.set_abstract("String encoding step for Deep-SMILES model")
model.add_alternate_identifier("https://github.com/MengyuanZhu/Deep-SMILES",
                               "URL")

#  Add the library and file to be run
model.add_files(['app.py', os.path.join('data', 'character_library.json')])

# Sanity Check: Make sure it fits the schema
metadata = model.to_dict()
parser = ArgumentParser(description='''Publish model to DLHub''')
parser.add_argument('--test', help='Just test out the submission and print the metadata', action='store_true')
args = parser.parse_args()
logging.info(f'Starting publication')

# Load in the model
tf_model = load_model('model_19-0.00.h5')

# Write out the model description
model = PythonStaticMethodModel.from_function_pointer(inference)

#   Descriptions of the model interface
model.set_inputs('ndarray', 'Gravity waveform measurement', shape=tf_model.input_shape)
model.set_outputs('dict', 'Estimated of properties of merging black holes',
    properties={
        'q': compose_argument_block('list', 'Mass ratio', item_type='float'),
        's1': compose_argument_block('list', 'Spin of primary', item_type='float'),
        's2': compose_argument_block('list', 'Spin of primary', item_type='float'),
        'S_eff': compose_argument_block('list', 'Effective spin', item_type='float'),
        'chi': compose_argument_block('list', 'Effective spin parameter', item_type='float'),
    }
)

# Provenance information for the model
model.add_related_identifier("2004.09524", "arXiv", "IsDescribedBy")

#   DLHub searchable
model['datacite']['subjects'] = [{'subject': 'cosmology'}]
logging.info('Initialized model with generic metadata')

# Add the needed files
Ejemplo n.º 14
0
    def test_compose(self):
        self.assertEquals({'type': 'string', 'description': 'Test'},
                          compose_argument_block('string', 'Test'))

        # Test ndarray
        with self.assertRaises(ValueError):
            compose_argument_block("ndarray", 'Test')
        self.assertEquals({'type': 'ndarray', 'description': 'Test', 'shape': [2, 2]},
                          compose_argument_block('ndarray', 'Test', shape=[2, 2]))

        # Test Python object
        with self.assertRaises(ValueError):
            compose_argument_block('python object', 'Test')
        self.assertEquals({'type': 'python object', 'description': 'Test', 'python_type': 'fk.Cls'},
                          compose_argument_block('python object', 'Test', python_type='fk.Cls'))

        # Test list object
        with self.assertRaises(ValueError):
            compose_argument_block('list', 'Test')
        self.assertEquals({'type': 'list', 'description': 'Test', 'item_type': {'type': 'string'}},
                          compose_argument_block('list', 'Test', item_type='string'))

        # Test tuple object
        with self.assertRaises(ValueError):
            compose_argument_block('tuple', 'Test')
        correct_block = {
            'type': 'tuple',
            'description': 'Test',
            'element_types': [{
                'type': 'string', 'description': 'Item 1'
            }, {
                'type': 'string', 'description': 'Item 2'
            }]
        }
        self.assertEquals(correct_block, compose_argument_block(
                                            'tuple', 'Test', element_types=[
                                                compose_argument_block('string', 'Item 1'),
                                                compose_argument_block('string', 'Item 2')]))

        # Test Python object
        with self.assertRaises(ValueError):
            compose_argument_block('dict', 'Test')
        correct_block = {
            'type': 'dict',
            'description': 'Test',
            'properties': {
                'test': {
                    'type': 'string',
                    'description': 'A string'
                }
            }
        }
        self.assertEquals(correct_block,
                          compose_argument_block('dict', 'Test',
                                                 properties={
                                                    'test': compose_argument_block('string',
                                                                                   'A string')}))
Ejemplo n.º 15
0
# Load in the model and featurizer steps

with open('model_info.pkl', 'rb') as fp:
    model_info = pkl.load(fp)

# Make a new step that reads files in from disk
read_info = PythonStaticMethodModel.from_function_pointer(
    imread, autobatch=True, function_kwargs={'as_gray': True})
read_info.set_title("Read in a list of pictures to a grayscale file")
read_info.set_name("read_grayscale_image")
read_info.set_inputs("list", "List of paths to files", item_type="string")
read_info.set_outputs("list",
                      "List of images as ndarrays",
                      item_type=compose_argument_block('ndarray',
                                                       'Image',
                                                       shape=[None, None]))
read_info.add_requirement('scikit-image', 'detect')

# Make a step to reshape the to 28x28x1
resize_info = PythonStaticMethodModel.from_function_pointer(
    resize,
    autobatch=True,
    function_kwargs={
        'output_shape': [28, 28, 1],
        'anti_aliasing': True
    })
resize_info.set_title("Reshape images to a specific size")
resize_info.set_name('reshape_image')
resize_info.set_inputs("list",
                       "List of images as ndarrays",
cifar_classes = [
    "airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse",
    "ship", "truck"
]

# Describe the deep learning model
model = KerasModel.create_model(os.path.join('models', 'cifar10vgg.h5'),
                                cifar_classes)

#  Describe the inputs and outputs
model.set_inputs('list',
                 'List of images. Each image must be standardized by the mean'
                 ' and standard deviation of the training set',
                 item_type=compose_argument_block('ndarray',
                                                  'Image',
                                                  shape=[32, 32, 3]))
model.set_outputs('ndarray',
                  'Probabilities of being in each of the cifar classes',
                  shape=[None, 10])

#  Add provenance information
model.set_authors(["Geifman, Yonatan"], ["Technion"])
model.set_title("Keras Model for Cifar10 based on VGGNet")
model.set_name("cifar10_model")
model.set_abstract(
    "A deep learning model that labels images as 10 different common objects (e.g., cats). "
    "Trained using the CIFAR10 dataset and based on the VGG16 architecture. Achieves an accuracy of"
    "~90% on the benchmark provided in Keras.")
model.add_alternate_identifier(
    "https://github.com/geifmany/cifar-vgg/blob/master/cifar10vgg.py", "URL")
Ejemplo n.º 17
0
           "Foster, Ian", "Curtiss, Larry A."]
affil = ["Argonne National Laboratory"] * 3 + ["University of Louisville"] + ["Argonne National Laboratory"] * 4

# Parse the user input
parser = ArgumentParser(description='''Post a MPNN-based solvation energy model to DLHub.''')
parser.add_argument('--test', help='Just test out the submission and print the metadata', action='store_true')
args = parser.parse_args()

# Write out the generic components of the model
model = PythonStaticMethodModel.from_function_pointer(evaluate_molecules)

#   Descriptions of the model interface
model.set_outputs(
    'dict', 'Solvation energy predictions',
    properties={
        'smiles': compose_argument_block('list', 'List of molecules run with the model', item_type='string'),
        'solvation-energies': compose_argument_block(
            'ndarray', 'Predicted solvation energy for each molecule in each solvent', shape=[None, None]
        ),
        'dielectric-constants': compose_argument_block('list', 'Dielectric constants for solvents', item_type='float'),
        'training-set-distance': compose_argument_block('list', 'Distance to nearest molecules in training set.'
                                                                ' Normalized based on the distances in the test set',
                                                        item_type='float'),
        'expected-error': compose_argument_block('list', 'Estimated uncertainty in the prediction based on distance'
                                                         ' from training set',
                                                 item_type='float'),
        'likelihood-error-above-1kcal/mol': compose_argument_block('list',
                                                                   'Probability of the error being above 1kcal/mol, '
                                                                   'based on based on distance from training set',
                                                 item_type='float'),
        'warnings': compose_argument_block('list', 'Warnings about predictions', item_type='string')
Ejemplo n.º 18
0
import json
import os

# Create a model that invokes the "run" function from the
model = PythonStaticMethodModel.create_model('app',
                                             'run',
                                             function_kwargs={'relax': False})

#  Describe the inputs and outputs
model.set_inputs('string', 'Molecule in XYZ format')
model.set_outputs(
    'dict',
    'Forces and energies of the molecule',
    properties={
        'energy':
        compose_argument_block('number', 'Energy of the whole system'),
        'forces':
        compose_argument_block('ndarray',
                               'Forces acting on each atom in each direction',
                               shape=[None, 3])
    })

#  Add provenance information
model.set_title("SchNet C20 Force and Energy Predictor")
model.set_name('schnet_c20')
model.set_domains(['physics'])
model.set_abstract(
    "A model based on the SchNet architecture that predicts the energy and forces of a C20 molecule. Useful for molecular dynmaics simulations."
)
model.set_authors([
    "Schütt, K. T.", "Sauceda, H. E.", "Kindermans, P.-J.", "Tkatchenko, A.",