Ejemplo n.º 1
0
    def test_create_model(self):
        # Count the current # of models in the environment
        models = mr.list_models()
        assert isinstance(models, list)
        model_count = len(models)

        # Create a new model
        model = mr.create_model(self.model_name, self.project_name, force=True)
        assert isinstance(model, RestObj)
        assert model.name == self.model_name

        # Total number of models should have increased
        models = mr.list_models()
        assert len(models) == model_count + 1
Ejemplo n.º 2
0
 def test_project_missing(self):
     # Creating a model in a non-existent project should fail
     with pytest.raises(ValueError):
         mr.create_model(self.model_name, self.project_name)
Ejemplo n.º 3
0
def register_model(model,
                   name,
                   project,
                   repository=None,
                   input=None,
                   version='latest',
                   files=None,
                   force=False):
    """Register a model in the model repository.

    Parameters
    ----------
    model : swat.CASTable or sklearn.BaseEstimator
        The model to register.  If an instance of ``swat.CASTable`` the table is assumed to hold an ASTORE, which will
        be downloaded and used to construct the model to register.  If a scikit-learn estimator, the model will be
        pickled and uploaded to the registry and score code will be generated for publishing the model to MAS.
    name : str
        Designated name for the model in the repository.
    project : str or dict
        The name or id of the project, or a dictionary representation of the project.
    repository : str or dict, optional
        The name or id of the repository, or a dictionary representation of the repository.  If omitted, the default
        repository will be used.
    input
    version : {'new', 'latest', int}, optional
        Version number of the project in which the model should be created.
    files :
    force : bool, optional
        Create dependencies such as projects and repositories if they do not already exist.

    Returns
    -------
    model : RestObj
        The newly registered model as an instance of ``RestObj``

    Notes
    -----
    If the specified model is a CAS table the model data and metadata will be written to a temporary zip file and then
    imported using model_repository.import_model_from_zip.

    If the specified model is from the Scikit-Learn package, the model will be created using
    model_repository.create_model and any additional files will be uploaded as content.

    Examples
    --------

    """

    # TODO: Create new version if model already exists
    # TODO: Allow file info to be specified
    # TODO: Performance stats

    files = files or []

    # Find the project if it already exists
    p = mr.get_project(project) if project is not None else None

    # Do we need to create the project first?
    create_project = True if p is None and force else False

    if p is None and not create_project:
        raise ValueError("Project '{}' not found".format(project))

    repository = mr.default_repository(
    ) if repository is None else mr.get_repository(repository)

    # Unable to find or create the repo.
    if repository is None:
        raise ValueError("Unable to find repository '{}'".format(repository))

    # If model is a CASTable then assume it holds an ASTORE model.
    # Import these via a ZIP file.
    if 'swat.cas.table.CASTable' in str(type(model)):
        zipfile = utils.create_package_from_astore(model)

        if create_project:
            project = mr.create_project(project, repository)

        model = mr.import_model_from_zip(name,
                                         project,
                                         zipfile,
                                         version=version)
        return model

    # If the model is an scikit-learn model, generate the model dictionary from it and pickle the model for storage
    elif all(
            hasattr(model, attr)
            for attr in ['_estimator_type', 'get_params']):
        # Pickle the model so we can store it
        model_pkl = pickle.dumps(model)
        files.append({
            'name': 'model.pkl',
            'file': model_pkl,
            'role': 'Python Pickle'
        })

        # Extract model properties
        model = _sklearn_to_dict(model)
        model['name'] = name

        # Generate PyMAS wrapper
        try:
            mas_module = from_pickle(model_pkl,
                                     'predict',
                                     input_types=input,
                                     array_input=True)
            assert isinstance(mas_module, PyMAS)

            # Include score code files from ESP and MAS
            files.append({
                'name': 'dmcas_packagescorecode.sas',
                'file': mas_module.score_code(),
                'role': 'Score Code'
            })
            files.append({
                'name': 'dmcas_espscorecode.sas',
                'file': mas_module.score_code(dest='ESP'),
                'role': 'Score Code'
            })

            model['inputVariables'] = [
                var.as_model_metadata() for var in mas_module.variables
                if not var.out
            ]
            model['outputVariables'] = [
                var.as_model_metadata() for var in mas_module.variables
                if var.out
            ]
        except ValueError:
            # PyMAS creation failed, most likely because input data wasn't provided
            warnings.warn(
                'Unable to determine input/output variables.  Model variables will not be specified.'
            )

    else:
        # Otherwise, the model better be a dictionary of metadata
        assert isinstance(model, dict)

    if create_project:
        vars = model.get('inputVariables', []) + model.get(
            'outputVariables', [])
        target_level = 'Interval' if model.get(
            'function') == 'Regression' else None
        project = mr.create_project(project,
                                    repository,
                                    variables=vars,
                                    targetLevel=target_level)

    model = mr.create_model(model, project)

    assert isinstance(model, RestObj)

    # Upload any additional files
    for file in files:
        if isinstance(file, dict):
            mr.add_model_content(model, **file)
        else:
            mr.add_model_content(model, file)

    return model
Ejemplo n.º 4
0
def test_create_model():

    MODEL_NAME = 'Test Model'
    PROJECT_NAME = 'Test Project'
    PROJECT_ID = '12345'
    USER = '******'

    with mock.patch('sasctl.core.requests.Session.request'):
        current_session('example.com', USER, 'password')

    TARGET = {
        'name':
        MODEL_NAME,
        'projectId':
        PROJECT_ID,
        'modeler':
        USER,
        'description':
        'model description',
        'function':
        'Classification',
        'algorithm':
        'Dummy Algorithm',
        'tool':
        'pytest',
        'champion':
        True,
        'role':
        'champion',
        'immutable':
        True,
        'retrainable':
        True,
        'scoreCodeType':
        None,
        'targetVariable':
        None,
        'trainTable':
        None,
        'classificationEventProbabilityVariableName':
        None,
        'classificationTargetEventValue':
        None,
        'location':
        None,
        'properties': [
            {
                'name': 'custom1',
                'value': 123
            },
            {
                'name': 'custom2',
                'value': 'somevalue'
            },
        ],
        'inputVariables': [],
        'outputVariables': [],
        'version':
        '2',
    }

    # Passed params should be set correctly
    target = copy.deepcopy(TARGET)
    with mock.patch(
            'sasctl._services.model_repository.ModelRepository.get_project'
    ) as get_project:
        with mock.patch('sasctl._services.model_repository.ModelRepository'
                        '.get_model') as get_model:
            with mock.patch(
                    'sasctl._services.model_repository.ModelRepository.post'
            ) as post:
                get_project.return_value = {'id': PROJECT_ID}
                get_model.return_value = None
                _ = mr.create_model(
                    MODEL_NAME,
                    PROJECT_NAME,
                    description=target['description'],
                    function=target['function'],
                    algorithm=target['algorithm'],
                    tool=target['tool'],
                    is_champion=True,
                    is_immutable=True,
                    is_retrainable=True,
                    properties=dict(custom1=123, custom2='somevalue'),
                )
                assert post.call_count == 1
            url, data = post.call_args

            # dict isn't guaranteed to preserve order
            # so k/v pairs of properties=dict() may be
            # returned in a different order
            assert sorted(target['properties'],
                          key=lambda d: d['name']) == sorted(
                              data['json']['properties'],
                              key=lambda d: d['name'])

            target.pop('properties')
            data['json'].pop('properties')
            assert target == data['json']

    # Model dict w/ parameters already specified should be allowed
    # Explicit overrides should be respected.
    target = copy.deepcopy(TARGET)
    with mock.patch(
            'sasctl._services.model_repository.ModelRepository.get_project'
    ) as get_project:
        with mock.patch('sasctl._services.model_repository.ModelRepository'
                        '.get_model') as get_model:
            with mock.patch(
                    'sasctl._services.model_repository.ModelRepository.post'
            ) as post:
                get_project.return_value = {'id': PROJECT_ID}
                get_model.return_value = None
                _ = mr.create_model(copy.deepcopy(target),
                                    PROJECT_NAME,
                                    description='Updated Model')
            target['description'] = 'Updated Model'
            assert post.call_count == 1
            url, data = post.call_args

            # dicts don't preserve order so property order may not match
            assert target['properties'] == data['json']['properties']
            target.pop('properties')
            data['json'].pop('properties')
            assert target == data['json']
Ejemplo n.º 5
0
JSONFiles.writeVarJSON(outputs, isInput=False, jPath=path)

### Creating
### don't use this in the real world
model_repository.delete_model(modelname)
#model_exists = model_repository.get_model(modelname, refresh=False)

# #model_repository.delete_model(modelname)
# if model_exists == None:
#     print('Creating new model')
model_repository.create_model(model=modelname,
                              project=project_name,
                              description='My Jenkings automatized',
                              modeler='Hellas',
                              algorithm=algo,
                              tool='R',
                              score_code_type='R',
                              function='Classification',
                              is_champion=False,
                              is_challenger=True,
                              event_prob_variable='P_BAD1')
# else:
#     print('Model exists, creting new verision')
#     model_repository.create_model_version(
#         model = modelname
#     )

#### basic files

filenames = {
    'file': [
Ejemplo n.º 6
0
    _file.write(scode2)

with open('python_wrapper.py', 'w') as _file:
    _file.write(scode3)

### DON'T DO THAT IN PRODUCTION
model_repository.delete_model(modelname)
model_exists = model_repository.get_model(modelname, refresh=False)

#model_repository.delete_model(modelname)
if model_exists == None:
    print('Creating new model')
    model_repository.create_model(model=modelname,
                                  project=project,
                                  function='Classification',
                                  algorithm='Logistic regression',
                                  tool='Python 3',
                                  event_target_value=1,
                                  target_variable='BAD',
                                  score_code_type='ds2MultiType')
else:
    print('Model exists, creting new version')
    #model_repository.delete_model(modelname)
    model_repository.delete_model_contents(modelname)
    model_repository.create_model_version(model=modelname,
                                          project=project,
                                          function='Classification',
                                          algorithm='Logistic regression',
                                          tool='Python 3',
                                          event_target_value=1,
                                          target_variable='BAD',
                                          score_code_type='ds2MultiType')