如何处理转换后模式与模型之间的不匹配?

我在探索ML.Net,打算预测员工离职情况。我有一个包含数值和字符串值的数据集可用。

这完全是探索性质的尝试,目的是为了更好地了解ML.Net。所以我的方法是,逐步探索各种选项,尽可能深入理解每一个步骤。

  1. 加载数据
  2. 准备数据集并对字符串特征进行分类转换
  3. 显示应用转换后的数据集
  4. 然后将数据集拆分为训练和测试数据集
  5. 使用分类算法训练模型
  6. 针对测试数据集进行评估
  7. 输出模型的特征权重
  8. 用它做一些有趣的事情

模型如下,基于IBM的开源员工流失数据集。 https://www.kaggle.com/pavansubhasht/ibm-hr-analytics-attrition-dataset

模型如下:

public class Employee    {        [LoadColumn(0)]        public int Age { get; set; }        [LoadColumn(1)]        //[ColumnName("Label")]        public string Attrition { get; set; }        [LoadColumn(2)]        public string BusinessTravel { get; set; }        [LoadColumn(3)]        public int DailyRate { get; set; }        [LoadColumn(4)]        public string Department { get; set; }        [LoadColumn(5)]        public int DistanceFromHome { get; set; }        [LoadColumn(6)]        public int Education { get; set; }        [LoadColumn(7)]        public string EducationField { get; set; }        [LoadColumn(8)]        public int EmployeeCount { get; set; }        [LoadColumn(9)]        public int EmployeeNumber { get; set; }        [LoadColumn(10)]        public int EnvironmentSatisfaction { get; set; }        [LoadColumn(11)]        public string Gender { get; set; }        [LoadColumn(12)]        public int HourlyRate { get; set; }        [LoadColumn(13)]        public int JobInvolvement { get; set; }        [LoadColumn(14)]        public int JobLevel { get; set; }        [LoadColumn(15)]        public string JobRole { get; set; }        [LoadColumn(16)]        public int JobSatisfaction { get; set; }        [LoadColumn(17)]        public string MaritalStatus { get; set; }        [LoadColumn(18)]        public int MonthlyIncome { get; set; }        [LoadColumn(19)]        public int MonthlyRate { get; set; }        [LoadColumn(20)]        public int NumCompaniesWorked { get; set; }        [LoadColumn(21)]        public string Over18 { get; set; }        [LoadColumn(22)]        public string OverTime { get; set; }        [LoadColumn(23)]        public int PercentSalaryHike { get; set; }        [LoadColumn(24)]        public int PerformanceRating{ get; set; }        [LoadColumn(25)]        public int RelationshipSatisfaction{ get; set; }        [LoadColumn(26)]        public int StandardHours{ get; set; }        [LoadColumn(27)]        public int StockOptionLevel{ get; set; }        [LoadColumn(28)]        public int TotalWorkingYears{ get; set; }        [LoadColumn(29)]        public int TrainingTimesLastYear{ get; set; }        [LoadColumn(30)]        public int WorkLifeBalance{ get; set; }        [LoadColumn(31)]        public int YearsAtCompany{ get; set; }        [LoadColumn(32)]        public int YearsInCurrentRole{ get; set; }        [LoadColumn(33)]        public int YearsSinceLastPromotion{ get; set; }        [LoadColumn(34)]        public int YearsWithCurrManager { get; set; }    }

然后对字符串属性进行转换(如这里所解释的 https://learn.microsoft.com/en-us/dotnet/machine-learning/how-to-guides/prepare-data-ml-net#work-with-categorical-data

var categoricalEstimator = mlContext.Transforms.Categorical.OneHotEncoding("Attrition")            .Append(mlContext.Transforms.Categorical.OneHotEncoding("BusinessTravel"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("EducationField"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("Gender"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("JobRole"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("MaritalStatus"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("Over18"))            .Append(mlContext.Transforms.Categorical.OneHotEncoding("OverTime"));            ITransformer categoricalTransformer = categoricalEstimator.Fit(dataView);            IDataView transformedData = categoricalTransformer.Transform(dataView);

现在我想检查发生了什么变化(https://learn.microsoft.com/en-us/dotnet/machine-learning/how-to-guides/inspect-intermediate-data-ml-net#convert-idataview-to-ienumerable)。我现在面临的挑战是,在对字符串属性应用转换后,模式已经改变,现在包含了预期的向量。

所以发生了以下情况。Employee模型的模式不再与transformedData对象的模式匹配,并试图将Vector属性适配到String属性中,从而抛出以下错误 “无法将类型为’Vector’的IDataView列’Attrition’绑定到类型为’System.String’的字段或属性’Attrition’。”

  IEnumerable<Employee> employeeDataEnumerable =                    mlContext.Data.CreateEnumerable<Employee>(transformedData, reuseRowObject: true);

CreateEnumerable还有一个SchemaDefinition参数,所以我的第一反应是提取transformedData的模式,并将其提供给CreateEnumerable。然而它期望一个Microsoft.ML.DataViewSchema,而转换产生的模式是Microsoft.ML.Data.SchemaDefinition。所以这也没用。

希望有人能给我一些建议。我应该做些什么不同的吗?

完整的控制器操作:

public ActionResult Turnover(){    MLContext mlContext = new MLContext();    var _appPath = AppDomain.CurrentDomain.BaseDirectory;    var _dataPath = Path.Combine(_appPath, "Datasets", "WA_Fn-UseC_-HR-Employee-Attrition.csv");    // 从文件加载数据    IDataView dataView = mlContext.Data.LoadFromTextFile<Employee>(_dataPath, hasHeader: true);    // 0. 获取输入特征的列名。    string[] featureColumnNames =        dataView.Schema            .Select(column => column.Name)            .Where(columnName => columnName != "Label")            .ToArray();    // 定义分类转换估计器    var categoricalEstimator = mlContext.Transforms.Categorical.OneHotEncoding("Attrition")    .Append(mlContext.Transforms.Categorical.OneHotEncoding("BusinessTravel"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("EducationField"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("Gender"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("JobRole"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("MaritalStatus"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("Over18"))    .Append(mlContext.Transforms.Categorical.OneHotEncoding("OverTime"));    ITransformer categoricalTransformer = categoricalEstimator.Fit(dataView);    IDataView transformedData = categoricalTransformer.Transform(dataView);    // 检查(失败,因为Employee(35列)无法映射到新模式(52列))    IEnumerable<Employee> employeeDataEnumerable =        mlContext.Data.CreateEnumerable<Employee>(transformedData, reuseRowObject: true, schemaDefinition : transformedData.Schema);    // 将转换后的数据集拆分为训练和测试数据集    DataOperationsCatalog.TrainTestData dataSplit = mlContext.Data.TrainTestSplit(transformedData, testFraction: 0.2);    IDataView trainData = dataSplit.TrainSet;    IDataView testData = dataSplit.TestSet;    return View();}

回答:

我最近遇到了这个问题,作为一个快速解决方案,我简单地创建了一个与转换后数据模式匹配的新类。例如,您可以创建一个EmoloyeeTransformed类,包含正确的属性(即向量而不是字符串),然后这样使用它:

CreateEnumerable<EmployeeTransformed>

如果您要创建各种转换后的模式,这不是最佳选择,但它确实有效。

希望这对您有帮助。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注