/// <summary>
        /// Saves the prediction values to entity.
        /// </summary>
        /// <typeparam name="T">The type of predicted values.</typeparam>
        /// <param name="schemaUId">The entity schema's identifier, which should be saved.</param>
        /// <param name="entityId">The entity identifier.</param>
        /// <param name="predictedValues">The predicted values of entity for the several models.</param>
        /// <param name="valueTransformer">
        /// Optional mapping function, that should be applied to predicted value before saving.
        /// </param>
        /// <returns>
        /// <c>true</c> if the entity was saved, otherwise - <c>false</c>.
        /// </returns>
        protected virtual bool SaveEntityPredictedValues <T>(Guid schemaUId, Guid entityId,
                                                             Dictionary <MLModelConfig, T> predictedValues, Func <T, object> valueTransformer)
        {
            if (predictedValues.IsNullOrEmpty())
            {
                return(false);
            }
            Entity entity = GetEntity(schemaUId, entityId);

            if (entity == null)
            {
                return(false);
            }
            foreach (KeyValuePair <MLModelConfig, T> prediction in predictedValues)
            {
                MLModelConfig      model  = prediction.Key;
                EntitySchemaColumn column = entity.FindEntityColumnValue(model.PredictedResultColumnName).Column;
                if (valueTransformer != null)
                {
                    object transformedPredictionValue = valueTransformer(prediction.Value);
                    entity.SetColumnValue(column, transformedPredictionValue);
                }
                else
                {
                    entity.SetColumnValue(column, prediction.Value);
                }
            }
            return(entity.Save());
        }
Beispiel #2
0
        private void AddQueryOutputColumn(Select query, MLModelConfig modelConfig)
        {
            string metadataOutputName = GetMetadataOutputName();

            if (metadataOutputName.IsNotNullOrEmpty())
            {
                return;
            }
            if (GetIsCFModel(modelConfig))
            {
                query.Column(Column.Const(1)).As(DefaultOutputColumnAlias);
                return;
            }
            if (query.Columns.ExistsByAlias(DefaultOutputColumnAlias))
            {
                return;
            }
            if (modelConfig.TrainingOutputFilterData?.Length > 0)
            {
                _queryBuilder.AddTrainingOutputExpression(query, modelConfig.TrainingOutputFilterData,
                                                          DefaultOutputColumnAlias);
                return;
            }
            if (_modelConfig.TrainingTargetColumnName.IsNullOrEmpty())
            {
                throw new ValidateException($"No output defined for the model {_modelConfig.Id}");
            }
            string sourceExpressionAlias = query.SourceExpression.Alias ?? query.SourceExpression.SchemaName;

            query.Column(sourceExpressionAlias, _modelConfig.TrainingTargetColumnName).As(DefaultOutputColumnAlias);
        }
Beispiel #3
0
 private static void ReadCollaborativeFilteringModelColumns(MLModelConfig modelConfig,
                                                            List <MLColumnExpression> columns)
 {
     columns.Add(new MLColumnExpression {
         ColumnPath = modelConfig.CFItemColumnPath,
         Alias      = "item_id"
     });
     columns.Add(new MLColumnExpression {
         ColumnPath = modelConfig.CFUserColumnPath,
         Alias      = "user_id"
     });
     if (modelConfig.CFInteractionValueColumnPath.IsNotNullOrEmpty())
     {
         columns.Add(new MLColumnExpression {
             ColumnPath = modelConfig.CFInteractionValueColumnPath,
             Alias      = "value"
         });
     }
     else
     {
         columns.Add(new MLColumnExpression {
             ExpressionType = EntitySchemaQueryExpressionType.Parameter,
             Parameter      = new Parameter {
                 DataValueType = Nui.ServiceModel.DataContract.DataValueType.Integer,
                 Value         = 1
             },
             Alias = "value"
         });
     }
 }
        private static MLModelConfig FetchModelConfig(UserConnection userConnection, IDataReader reader)
        {
            DateTime batchPredictedOn = reader.GetColumnValue <DateTime>("BatchPredictedOn");

            batchPredictedOn = DateTime.SpecifyKind(batchPredictedOn, DateTimeKind.Utc);
            var rootSchemaUId   = reader.GetColumnValue <Guid>("RootSchemaUId");
            var targetColumnUId = FindValue <Guid>(reader, "TargetColumnUId", Guid.Empty);
            var modelConfig     = new MLModelConfig {
                Id                        = reader.GetColumnValue <Guid>("Id"),
                MetaData                  = reader.GetColumnValue <string>("MetaData"),
                TrainingSetQuery          = reader.GetColumnValue <string>("TrainingSetQuery"),
                ServiceUrl                = reader.GetColumnValue <string>("ServiceUrl"),
                PredictionEndpoint        = reader.GetColumnValue <string>("PredictionEndpoint"),
                TrainingEndpoint          = reader.GetColumnValue <string>("TrainingEndpoint"),
                BatchPredictionQuery      = reader.GetColumnValue <string>("BatchPredictionQuery"),
                ProblemType               = reader.GetColumnValue <Guid>("MLProblemTypeId"),
                ModelInstanceUId          = reader.GetColumnValue <Guid>("ModelInstanceUId"),
                TrainingFilterData        = reader.GetColumnValue <byte[]>("TrainingFilterData"),
                BatchPredictionFilterData = reader.GetColumnValue <byte[]>("BatchPredictionFilterData"),
                TrainingTargetColumnName  = FindEntityColumnValueName(userConnection, rootSchemaUId, targetColumnUId),
                EntitySchemaId            = rootSchemaUId,
                BatchPredictedOn          = batchPredictedOn
            };

            if (modelConfig.BatchPredictionQuery.IsNullOrEmpty() && modelConfig.TrainingSetQuery.IsNotNullOrEmpty())
            {
                modelConfig.BatchPredictionQuery = modelConfig.TrainingSetQuery;
            }
            SetPredictedResultColumnName(modelConfig, userConnection, reader);
            modelConfig.CurrentState = GetTypedState(reader.GetColumnValue <string>("StateCode"));
            LoadMLModelColumns(userConnection, modelConfig);
            return(modelConfig);
        }
        private static void SetPredictedResultColumnName(MLModelConfig modelConfig, UserConnection userConnection,
                                                         IDataReader reader)
        {
            if (modelConfig.PredictedResultColumnName.IsNotNullOrEmpty())
            {
                return;
            }
            Guid predictedResultColumnUId = FindValue <Guid>(reader, "PredictedResultColumnUId", Guid.Empty);

            if (predictedResultColumnUId.IsNotEmpty())
            {
                modelConfig.PredictedResultColumnName =
                    FindEntityColumnValueName(userConnection, modelConfig.EntitySchemaId, predictedResultColumnUId);
                return;
            }
            if (modelConfig.TrainingTargetColumnName.IsNotNullOrEmpty())
            {
                modelConfig.PredictedResultColumnName = modelConfig.TrainingTargetColumnName;
                return;
            }

            //TODO #CRM-40303 Remove when PredictedResultColumnUId will be set for all known customer models
            ModelSchemaMetadata metadata = modelConfig.GetModelSchemaMetadata();
            string outputName            = metadata.Output?.Name;

            if (IsEntityColumnExists(userConnection.EntitySchemaManager, modelConfig.EntitySchemaId, outputName))
            {
                _log.Warn("Neither PredictedResultColumnUId nor TargetColumnUId is set. " +
                          $"Using metadata's output as PredictedResultColumn in model {modelConfig.Id}");
                modelConfig.PredictedResultColumnName = outputName;
            }
        }
        /// <summary>
        /// Tries to load the model for prediction by its id.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="modelId">The model identifier.</param>
        /// <param name="model">The model.</param>
        /// <returns><c>true</c> - if model successfully loaded, otherwise - <c>false</c>.</returns>
        public bool TryLoadModelForPrediction(UserConnection userConnection, Guid modelId, out MLModelConfig model)
        {
            userConnection.LicHelper.CheckHasOperationLicense(MLConsts.LicOperationCode);
            var select = (Select)GetModelBaseSelectQuery(userConnection)
                         .Where("m", "Id").IsEqual(Column.Parameter(modelId, "Guid"));
            MLModelConfig modelConfig = null;

            select.ExecuteReader(reader => {
                bool isPredictionEnabled = reader.GetColumnValue <bool>("PredictionEnabled");
                if (!isPredictionEnabled)
                {
                    _log.WarnFormat("Prediction is not enabled for model with id {0}", modelId);
                    return;
                }
                string modelInstanceUId = reader.GetColumnValue <string>("ModelInstanceUId");
                if (modelInstanceUId.IsNullOrEmpty())
                {
                    _log.WarnFormat("Instance uid is not set for model with id {0}", modelId);
                    return;
                }
                modelConfig = FetchModelConfig(userConnection, reader);
            });
            model = modelConfig;
            return(model != null);
        }
        /// <summary>
        /// Predicts numeric value for the specified model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="dataForPrediction">The data for prediction.</param>
        /// <param name="proxy">The proxy.</param>
        /// <returns>
        /// Numeric value result.
        /// </returns>
        protected override List <double> Predict(MLModelConfig model,
                                                 IList <Dictionary <string, object> > dataForPrediction, IMLServiceProxy proxy)
        {
            List <double> predictionResults = proxy.Regress(model.ModelInstanceUId, dataForPrediction);

            return(predictionResults);
        }
        /// <summary>
        /// Predicts data by the specified machine learning model.
        /// </summary>
        /// <param name="modelConfig">Machine learning model configuration.</param>
        /// <param name="chunkPredictedHandler">Handler on each chunk predicted event. Invokes with dictionary where
        /// key is entity identifier and value is predicted result for that entity.</param>
        /// <exception cref="AggregateException">When at least one of chunk failed to predict.</exception>
        public void Predict(MLModelConfig modelConfig, Action <Dictionary <Guid, object> > chunkPredictedHandler)
        {
            var parameters = new Dictionary <string, object> {
                { "BatchPredictedOn", modelConfig.BatchPredictedOn }
            };
            int  chunkNumber         = 0;
            var  exceptions          = new List <Exception>();
            Guid modelId             = modelConfig.Id;
            var  modelQueryAssembler = ClassFactory.Get <IMLModelQueryBuilder>(
                new ConstructorArgument("userConnection", _userConnection));
            Select select = modelQueryAssembler.BuildSelect(modelConfig.EntitySchemaId,
                                                            modelConfig.BatchPredictionQuery, modelConfig.ColumnExpressions, modelConfig.BatchPredictionFilterData,
                                                            parameters);

            DataLoader.LoadDataForPrediction(select, dataForPrediction => {
                chunkNumber++;
                if (dataForPrediction.Count == 0)
                {
                    return;
                }
                IList <TOut> predictedValues;
                try {
                    predictedValues = Predict(modelConfig, dataForPrediction);
                } catch (Exception ex) {
                    _log.Warn($"Batch predict for chunk #{chunkNumber} failed - skipping. ModelId = {modelId}",
                              ex);
                    exceptions.Add(ex);
                    return;
                }
                var results = new Dictionary <Guid, object>();
                for (int i = 0; i < dataForPrediction.Count; i++)
                {
                    Dictionary <string, object> record = dataForPrediction[i];
                    if (record.TryGetValue("Id", out object id) && Guid.TryParse(id.ToString(), out Guid recordId))
                    {
                        if (results.ContainsKey(recordId))
                        {
                            _log.Warn($"Prediction results for model " +
                                      $"{modelId} already contain key {recordId}. Check that select query " +
                                      $"for batch prediction returns unique value for column Id");
                        }
                        else
                        {
                            results.Add(recordId, predictedValues[i]);
                            SavePredictionResult(modelId, modelConfig.ModelInstanceUId, recordId, predictedValues[i]);
                        }
                    }
                    else
                    {
                        exceptions.Add(new Exception($"Rowset for model {modelId} contains a record without Id"));
                    }
                }
                chunkPredictedHandler(results);
            });
            if (!exceptions.IsNullOrEmpty())
            {
                throw new AggregateException(exceptions);
            }
        }
        /// <summary>
        /// Scores value for the specified model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="dataForPrediction">The data for prediction.</param>
        /// <param name="proxy">The proxy.</param>
        /// <returns>
        /// Numeric value result.
        /// </returns>
        protected override List <double> Predict(MLModelConfig model,
                                                 IList <Dictionary <string, object> > dataForPrediction, IMLServiceProxy proxy)
        {
            List <ScoringOutput> predictionResults = proxy.Score(model, dataForPrediction, false);
            List <double>        scores            = predictionResults.Select(output => output.Score).ToList();

            return(scores);
        }
Beispiel #10
0
        private static void UpdateBatchDate(MLModelConfig modelConfig, UserConnection userConnection)
        {
            var query = new Update(userConnection, "MLModel")
                        .Set("BatchPredictedOn", Column.Parameter(modelConfig.BatchPredictedOn))
                        .Where("Id").IsEqual(Column.Parameter(modelConfig.Id));

            query.Execute();
        }
        /// <summary>
        /// Saves the predicted result in entity.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="entityId">The entity identifier.</param>
        /// <param name="predictedResult">The predicted result.</param>
        protected override void SaveEntityPredictedValues(MLModelConfig model, Guid entityId, double predictedResult)
        {
            var predictedValues = new Dictionary <MLModelConfig, double> {
                { model, predictedResult }
            };

            PredictionSaver.SaveEntityRegressionValues(model.EntitySchemaId, entityId, predictedValues);
        }
        /// <summary>
        /// Predicts data for the given list of records.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="dataList">The data for prediction.</param>
        /// <returns>Batch prediction result list.</returns>
        protected virtual List <TOut> Predict(MLModelConfig model, IList <Dictionary <string, object> > dataList)
        {
            var connectionArg = new ConstructorArgument("userConnection", _userConnection);
            var predictor     =
                ClassFactory.Get <IMLPredictor <TOut> >(model.ProblemType.ToString().ToUpper(), connectionArg);

            return(predictor.Predict(model, dataList));
        }
Beispiel #13
0
        /// <summary>
        /// Saves the predicted result in entity.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="entityId">The entity identifier.</param>
        /// <param name="predictedResult">The predicted result.</param>
        protected override void SaveEntityPredictedValues(MLModelConfig model, Guid entityId,
                                                          ScoringOutput predictedResult)
        {
            var predictedValues = new Dictionary <MLModelConfig, double> {
                { model, predictedResult.Score }
            };

            PredictionSaver.SaveEntityScoredValues(model.EntitySchemaId, entityId, predictedValues);
        }
        /// <summary>
        /// Tries to load the model by its id.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="modelId">Identifier of the model.</param>
        /// <param name="model">Loaded model.</param>
        /// <returns><c>true</c> - if model successfully loaded, otherwise - <c>false</c>.</returns>
        public bool TryLoadModel(UserConnection userConnection, Guid modelId, out MLModelConfig model)
        {
            var models = LoadModels(userConnection, false, false, new List <Guid> {
                modelId
            });

            model = models.FirstOrDefault();
            return(model != null);
        }
        /// <summary>
        /// Predicts using the specified proxy.
        /// </summary>
        /// <param name="proxy">The proxy.</param>
        /// <param name="model">The model.</param>
        /// <param name="data">The input data.</param>
        /// <returns>
        /// Predicted result.
        /// </returns>
        protected override double Predict(IMLServiceProxy proxy, MLModelConfig model,
                                          Dictionary <string, object> data)
        {
            var wrappedData = new List <Dictionary <string, object> > {
                data
            };

            return(proxy.Regress(model.ModelInstanceUId, wrappedData).FirstOrDefault());
        }
Beispiel #16
0
 /// <summary>
 /// Saves the predicted data to entities.
 /// </summary>
 /// <param name="modelConfig">Machine learning model configuration.</param>
 /// <param name="predictedData">Dictionary where key is entity identifier and value is predicted
 /// result for that entity.</param>
 public void SavePredictedData(MLModelConfig modelConfig, Dictionary <Guid, object> predictedData)
 {
     if (predictedData.IsNullOrEmpty())
     {
         _log.Info("MLBatchNumericPredictor.SavePredictedData: predictedData is empty. " +
                   $"Model {modelConfig.Id}");
         return;
     }
     UpdateEntitiesTargetColumn(modelConfig, predictedData);
 }
Beispiel #17
0
        /// <summary>
        /// Scores rates for list of items with the given data using the specified model.
        /// </summary>
        /// <param name="model">Model, that should perform scoring.</param>
        /// <param name="dataList">The list of data of items that should be scored.</param>
        /// <param name="predictContributions">
        /// Indicates, if service should return individual feature contributions to overall prediction.
        /// </param>
        /// <returns>Predicted score rates.</returns>
        public List <ScoringOutput> Score(MLModelConfig model, IList <Dictionary <string, object> > dataList,
                                          bool predictContributions)
        {
            int             count    = Math.Min(1, dataList.Count);
            int             timeout  = Math.Max(ScoreTimeoutSec * count, BatchScoreTimeoutSec);
            ScoringResponse response = Predict <ScoringRequest, ScoringResponse>(model.ModelInstanceUId,
                                                                                 dataList, model.PredictionEndpoint, timeout, predictContributions);

            return(response.Outputs);
        }
Beispiel #18
0
        /// <summary>
        /// Scores rate for item with the given data using the specified model.
        /// </summary>
        /// <param name="model">Model, that should perform scoring.</param>
        /// <param name="data">The data of the item that should be scored.</param>
        /// <param name="predictContributions">
        /// Indicates, if service should return individual feature contributions to overall prediction.
        /// </param>
        /// <returns>Predicted score rate.</returns>
        public ScoringOutput Score(MLModelConfig model, Dictionary <string, object> data, bool predictContributions)
        {
            ScoringResponse response = Predict <ScoringRequest, ScoringResponse>(model.ModelInstanceUId,
                                                                                 new List <Dictionary <string, object> > {
                data
            }, model.PredictionEndpoint,
                                                                                 ScoreTimeoutSec, predictContributions);

            return(response.Outputs.FirstOrDefault());
        }
        private MLModelConfig GetModelConfig(Guid modelId)
        {
            MLModelConfig model = _modelLoader.LoadModelForTraining(UserConnection, modelId);

            if (model == null)
            {
                throw new ItemNotFoundException($"Model not found by id {modelId}");
            }
            return(model);
        }
Beispiel #20
0
        protected override void SaveEntityPredictedValues(MLModelConfig model, Guid entityId,
                                                          List <ClassificationResult> predictedResult)
        {
            var connectionArg   = new ConstructorArgument("userConnection", _userConnection);
            var filter          = ClassFactory.Get <MLBasePredictedValueFilter>(connectionArg);
            var predictedValues = new Dictionary <MLModelConfig, List <ClassificationResult> > {
                { model, predictedResult }
            };

            PredictionSaver.SaveEntityPredictedValues(model.EntitySchemaId, entityId, predictedValues,
                                                      filter.OnSetupPredictedValue);
        }
Beispiel #21
0
        private static void LoadMLModelColumns(UserConnection userConnection, MLModelConfig modelConfig)
        {
            modelConfig.ColumnUIds = new List <Guid>();
            var columnExpressions = new List <MLColumnExpression>();

            modelConfig.ColumnExpressions = columnExpressions;
            if (modelConfig.ProblemType == new Guid(MLConsts.CollaborativeFiltering))
            {
                ReadCollaborativeFilteringModelColumns(modelConfig, columnExpressions);
                return;
            }
            var esq = new EntitySchemaQuery(userConnection.EntitySchemaManager, "MLModelColumn")
            {
                IgnoreDisplayValues = true
            };

            esq.AddAllSchemaColumns(skipSystemColumns: true);
            esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "MLModel", modelConfig.Id));
            var entities   = esq.GetEntityCollection(userConnection);
            var rootSchema = userConnection.EntitySchemaManager.FindInstanceByUId(modelConfig.EntitySchemaId);

            foreach (var entity in entities)
            {
                Guid   columnUId  = entity.GetTypedColumnValue <Guid>("ColumnUId");
                string columnPath = entity.GetTypedColumnValue <string>("ColumnPath");
                string subFilters = entity.GetTypedColumnValue <string>("SubFilters") ?? string.Empty;
                if (columnPath.IsNotNullOrEmpty())
                {
                    columnExpressions.Add(new MLColumnExpression {
                        ColumnPath      = columnPath,
                        AggregationType = (AggregationType)entity.GetTypedColumnValue <int>("AggregationType"),
                        SubFilters      = JsonConvert.DeserializeObject <Filters>(subFilters),
                        Caption         = entity.GetTypedColumnValue <string>("Caption")
                    });
                }
                else if (columnUId.IsNotEmpty())
                {
                    var column = rootSchema.Columns.FindByUId(columnUId);
                    if (column == null)
                    {
                        _log.WarnFormat("Column '{0}' was not found in schema {1} while loading columns for model {2}",
                                        columnUId, rootSchema.Name, modelConfig.Id);
                    }
                    else
                    {
                        columnExpressions.Add(new MLColumnExpression {
                            ColumnPath = column.Name,
                            Caption    = entity.GetTypedColumnValue <string>("Caption")
                        });
                    }
                }
            }
        }
 private static void SetupTrainingInfo(UserConnection userConnection, MLModelConfig modelConfig,
                                       IDataReader reader)
 {
     modelConfig.TrainingMinimumRecordsCount = reader.GetColumnValue <int>("TrainingMinimumRecordsCount");
     if (modelConfig.TrainingMinimumRecordsCount == 0)
     {
         modelConfig.TrainingMinimumRecordsCount =
             SysSettings.GetValue(userConnection, TrainingMinimumRecordsCountSysSettingsName, 0);
     }
     modelConfig.TrainSessionId           = reader.GetColumnValue <Guid>("TrainSessionId");
     modelConfig.MetricThreshold          = reader.GetColumnValue <double>("MetricThreshold");
     modelConfig.TrainingOutputFilterData = reader.GetColumnValue <byte[]>("TrainingOutputFilterData");
 }
Beispiel #23
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MLModelTrainer"/> class.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="modelConfig">The model configuration.</param>
        public MLModelTrainer(UserConnection userConnection, MLModelConfig modelConfig)
        {
            userConnection.CheckArgumentNull("userConnection");
            modelConfig.CheckArgumentNull("modelConfig");
            modelConfig.Id.CheckArgumentEmpty("MLModelConfig.Id");
            _userConnection = userConnection;
            _modelConfig    = modelConfig;
            _proxy          = InitServiceProxy();
            ConstructorArgument userConnectionArg = new ConstructorArgument("userConnection", _userConnection);

            _modelEventsNotifier = ClassFactory.Get <MLModelEventsNotifier>(userConnectionArg);
            _metadataGenerator   = ClassFactory.Get <IMLMetadataGenerator>();
            _queryBuilder        = ClassFactory.Get <IMLModelQueryBuilder>(userConnectionArg);
        }
Beispiel #24
0
        private IList <MLModelConfig> LoadModels(UserConnection userConnection, bool enabledForPredictionOnly,
                                                 bool useAutoBatchMode, IList <Guid> modelIds = null, bool safe = false)
        {
            userConnection.LicHelper.CheckHasOperationLicense(MLConsts.LicOperationCode);
            var select         = GetModelBaseSelectQuery(userConnection);
            var mlModelConfigs = new List <MLModelConfig>();

            if (enabledForPredictionOnly)
            {
                select
                .Where("PredictionEnabled").IsEqual(Column.Parameter(true, "Boolean"))
                .And(Func.Len("ModelInstanceUId")).IsGreater(Column.Const(0))
                .And(Func.Len("ServiceUrl")).IsGreater(Column.Const(0));
            }
            if (modelIds != null)
            {
                var condition = new QueryCondition(QueryConditionType.In)
                {
                    LeftExpression = new QueryColumnExpression("m", "Id")
                };
                condition.RightExpressions.AddExpressionsRange(Column.Parameters(modelIds));
                AddCondition(select, condition);
            }
            if (useAutoBatchMode)
            {
                var condition = new QueryCondition(QueryConditionType.Equal)
                {
                    LeftExpression = new QueryColumnExpression("m", "BatchPredictionStartMethodId")
                };
                condition.RightExpressions.Add(Column.Parameter(new Guid(MLConsts.MaintenanceWindowStartMethod)));
                AddCondition(select, condition);
            }
            select.ExecuteReader(reader => {
                if (useAutoBatchMode && !CheckBatchFrequency(reader, userConnection))
                {
                    return;
                }
                try {
                    MLModelConfig modelConfig = FetchModelConfig(userConnection, reader);
                    mlModelConfigs.Add(modelConfig);
                } catch (Exception e) {
                    _log.Error($"Failed to load model {reader.GetColumnValue<Guid>("Id")}. Exception is {e}");
                    if (!safe)
                    {
                        throw;
                    }
                }
            });
            return(mlModelConfigs);
        }
        /// <summary>
        /// Loads the model metadata captions. Sets enriched metadata to <see cref="MLModelConfig.MetaData"/> property.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="model">Loaded model.</param>
        public void LoadModelMetadataCaptions(UserConnection userConnection, MLModelConfig model)
        {
            if (model.MetaData.IsNullOrEmpty())
            {
                return;
            }
            ModelSchemaMetadata metadata = model.GetModelSchemaMetadata();

            if (metadata.Inputs.IsNullOrEmpty() && metadata.Output == null)
            {
                return;
            }
            var modelSchema = userConnection.EntitySchemaManager.GetInstanceByName("MLModel");
            var modelEntity = modelSchema.CreateEntity(userConnection);

            modelEntity.PrimaryColumnValue = model.Id;
            if (!modelEntity.FetchFromDB(new[] { "MetaDataLcz" }, false))
            {
                return;
            }
            string serializedMetadataLcz = modelEntity.GetTypedColumnValue <string>("MetaDataLcz");

            if (serializedMetadataLcz.IsNullOrEmpty())
            {
                return;
            }
            ModelSchemaMetadata metaDataLcz;

            try {
                metaDataLcz = JsonConvert.DeserializeObject <ModelSchemaMetadata>(serializedMetadataLcz);
            } catch (Exception e) {
                _log.Warn($"Can't localize metadata for {model.Id}, because MetaDataLcz has incorrect format: " +
                          serializedMetadataLcz, e);
                return;
            }
            metadata.Inputs?.ForEach(input => {
                var inputLcz = metaDataLcz.Inputs.Find(schemaInput => schemaInput.Name == input.Name);
                if (inputLcz == null)
                {
                    return;
                }
                input.Caption = inputLcz.Caption;
            });
            if (metadata.Output != null)
            {
                metadata.Output.Caption = metaDataLcz.Output?.Caption;
            }
            model.MetaData = JsonConvert.SerializeObject(metadata, Formatting.Indented);
        }
Beispiel #26
0
        private void UpdateEntitiesTargetColumn(MLModelConfig model, Dictionary <Guid, object> predictedData)
        {
            if (predictedData.IsNullOrEmpty())
            {
                return;
            }
            var entitySchema     = _userConnection.EntitySchemaManager.GetInstanceByUId(model.EntitySchemaId);
            var entitySchemaName = entitySchema.Name;

            foreach (KeyValuePair <Guid, object> prediction in predictedData)
            {
                Guid   entityId = prediction.Key;
                double value    = Convert.ToDouble(prediction.Value);
                UpdateEntityTargetColumn(entitySchemaName, model.PredictedResultColumnName, entityId, value);
            }
        }
        /// <summary>
        /// Loads the ml model config by id with fields needed for training.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="modelId">The model identifier.</param>
        /// <returns>Loaded model.</returns>
        public MLModelConfig LoadModelForTraining(UserConnection userConnection, Guid modelId)
        {
            userConnection.LicHelper.CheckHasOperationLicense(MLConsts.LicOperationCode);
            var select = (Select)GetModelBaseSelectQuery(userConnection)
                         .Column("m", "TrainingMinimumRecordsCount")
                         .Column("m", "TrainSessionId")
                         .Column("m", "MetricThreshold")
                         .Column("m", "TrainingOutputFilterData")
                         .Where("m", "Id").IsEqual(Column.Parameter(modelId, "Guid"));
            MLModelConfig modelConfig = null;

            select.ExecuteReader(reader => {
                modelConfig = FetchModelConfig(userConnection, reader);
                SetupTrainingInfo(userConnection, modelConfig, reader);
            });
            return(modelConfig);
        }
Beispiel #28
0
        private static MLModelConfig FetchModelConfig(UserConnection userConnection, IDataReader reader)
        {
            DateTime batchPredictedOn = reader.GetColumnValue <DateTime>("BatchPredictedOn");

            batchPredictedOn = DateTime.SpecifyKind(batchPredictedOn, DateTimeKind.Utc);
            var rootSchemaUId   = reader.GetColumnValue <Guid>("RootSchemaUId");
            var targetColumnUId = FindValue <Guid>(reader, "TargetColumnUId", Guid.Empty);
            var modelConfig     = new MLModelConfig {
                Id                           = reader.GetColumnValue <Guid>("Id"),
                MetaData                     = reader.GetColumnValue <string>("MetaData"),
                TrainingSetQuery             = reader.GetColumnValue <string>("TrainingSetQuery"),
                ServiceUrl                   = reader.GetColumnValue <string>("ServiceUrl"),
                PredictionEndpoint           = reader.GetColumnValue <string>("PredictionEndpoint"),
                TrainingEndpoint             = reader.GetColumnValue <string>("TrainingEndpoint"),
                BatchPredictionQuery         = reader.GetColumnValue <string>("BatchPredictionQuery"),
                ProblemType                  = reader.GetColumnValue <Guid>("MLProblemTypeId"),
                ModelInstanceUId             = reader.GetColumnValue <Guid>("ModelInstanceUId"),
                TrainingFilterData           = reader.GetColumnValue <byte[]>("TrainingFilterData"),
                BatchPredictionFilterData    = reader.GetColumnValue <byte[]>("BatchPredictionFilterData"),
                TrainingTargetColumnName     = FindEntityColumnValueName(userConnection, rootSchemaUId, targetColumnUId),
                EntitySchemaId               = rootSchemaUId,
                BatchPredictedOn             = batchPredictedOn,
                ConfidentValueMethodId       = reader.GetColumnValue <Guid>("MLConfidentValueMethodId"),
                ConfidentValueLowEdge        = reader.GetColumnValue <double>("ConfidentValueLowEdge"),
                CFItemColumnPath             = reader.GetColumnValue <string>("CFItemColumnPath"),
                CFUserColumnPath             = reader.GetColumnValue <string>("CFUserColumnPath"),
                CFInteractionValueColumnPath = reader.GetColumnValue <string>("CFInteractionValueColumnPath"),
                CFResultSchemaUId            = reader.GetColumnValue <Guid>("CFResultSchemaUId"),
                CFResultUserColumnName       = reader.GetColumnValue <string>("CFResultUserColumnName"),
                CFResultItemColumnName       = reader.GetColumnValue <string>("CFResultItemColumnName"),
                CFResultValueColumnName      = reader.GetColumnValue <string>("CFResultValueColumnName"),
                CFResultModelColumnName      = reader.GetColumnValue <string>("CFResultModelColumnName"),
                CFResultTimestampColumnName  = reader.GetColumnValue <string>("CFResultTimestampColumnName")
            };

            modelConfig.RegularizationValues = ParseValueListColumnAsHashSet <double>(reader, "RegularizationValues");
            modelConfig.FactorsCounts        = ParseValueListColumnAsHashSet <int>(reader, "FactorsCounts");
            if (modelConfig.BatchPredictionQuery.IsNullOrEmpty() && modelConfig.TrainingSetQuery.IsNotNullOrEmpty())
            {
                modelConfig.BatchPredictionQuery = modelConfig.TrainingSetQuery;
            }
            SetPredictedResultColumnName(modelConfig, userConnection, reader);
            modelConfig.CurrentState = GetTypedState(reader.GetColumnValue <string>("StateCode"));
            LoadMLModelColumns(userConnection, modelConfig);
            return(modelConfig);
        }
Beispiel #29
0
        /// <summary>
        /// Loads the ready for training models on the check point date.
        /// </summary>
        /// <param name="userConnection">The user connection.</param>
        /// <param name="checkPoint">The check point.</param>
        /// <returns>List of models.</returns>
        public virtual IList <MLModelConfig> LoadReadyForTrainingModels(UserConnection userConnection,
                                                                        DateTime checkPoint)
        {
            userConnection.LicHelper.CheckHasOperationLicense(MLConsts.LicOperationCode);
            var mlModelConfigs = new List <MLModelConfig>();

            object[] needToTrainModelStates =
            {
                TrainSessionState.NotStarted.ToString(),
                TrainSessionState.Done.ToString(),
                TrainSessionState.Error.ToString()
            };
            var select = (Select)GetModelBaseSelectQuery(userConnection)
                         .Column("m", "TrainFrequency")
                         .Column("m", "TriedToTrainOn")
                         .Column("m", "TrainingMinimumRecordsCount")
                         .Column("m", "TrainingMaxRecordsCount")
                         .Column("m", "TrainSessionId")
                         .Column("m", "MetricThreshold")
                         .Column("m", "TrainingOutputFilterData")
                         .Where(Func.Len("ServiceUrl")).IsGreater(Column.Const(0))
                         .And(Func.Len("MetaData")).IsGreater(Column.Const(0))
                         .And("TrainFrequency").IsGreater(Column.Const(0))
                         .And(Func.Len("TrainingSetQuery")).IsGreater(Column.Const(0))
                         .And("s", "Code").In(Column.Parameters(needToTrainModelStates));

            select.ExecuteReader(reader => {
                DateTime triedToTrainOn = reader.GetColumnValue <DateTime>("TriedToTrainOn");
                int trainFrequencyDays  = reader.GetColumnValue <int>("TrainFrequency");
                Guid modelId            = reader.GetColumnValue <Guid>("Id");
                if (triedToTrainOn != default(DateTime))
                {
                    DateTime plannedDate = triedToTrainOn.AddDays(trainFrequencyDays);
                    if (plannedDate > checkPoint)
                    {
                        _log.DebugFormat("Training for model id '{0}' not started. PlannedDate is {1}.",
                                         modelId, plannedDate);
                        return;
                    }
                }
                MLModelConfig modelConfig = FetchModelConfig(userConnection, reader);
                SetupTrainingInfo(userConnection, modelConfig, reader);
                mlModelConfigs.Add(modelConfig);
            });
            return(mlModelConfigs);
        }
Beispiel #30
0
        private List <double> Predict(MLModelConfig model,
                                      IList <Dictionary <string, object> > dataForPrediction)
        {
            var             apiKey        = BpmonlineCloudEngine.GetAPIKey(_userConnection);
            var             serviceUrlArg = new ConstructorArgument("serviceUrl", model.ServiceUrl);
            var             apiKeyArg     = new ConstructorArgument("apiKey", apiKey);
            IMLServiceProxy proxy;

            try {
                proxy = ClassFactory.Get <IMLServiceProxy>(serviceUrlArg, apiKeyArg);
            } catch (IncorrectConfigurationException ex) {
                _log.WarnFormat($"Can't predict value for model {model.Id}", ex);
                throw;
            }
            var predictionResults = Predict(model, dataForPrediction, proxy);

            return(predictionResults);
        }