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
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)
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
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']
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': [
_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')