Как я могу обработать несоответствие между схемой и моделью после преобразования? - PullRequest
0 голосов
/ 17 июня 2019

Изучая 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://docs.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://docs.microsoft.com/en-us/dotnet/machine-learning/how-to-guides/inspect-intermediate-data-ml-net#convert-idataview-to-ienumerable). Теперь у меня есть проблема в том, что после применения преобразования к свойствам строки схема изменилась и теперь содержит ожидаемые векторы.

Таким образом, происходит следующее. Модель Employeeсхема больше не соответствует схеме из объекта transformedData и пытается вписать свойство Vector в свойство String и выдает следующую ошибку "Невозможно привязать столбец IDataView 'Attrition' типа 'Vector' к полю или свойству'Attrition' типа 'System.String'. "

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

CreateEnumerable также имеет аргумент SchemaDefinition, поэтому мое первое предположение состояло в том, чтобы извлечь схему из transformData и передать ее вCreateEnumerable. Однако он ожидает Microsoft.ML.DataViewSchema, а схема, созданная преобразованием, является Microsoft.ML.Da.ta.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");

    // Load data from file
    IDataView dataView = mlContext.Data.LoadFromTextFile<Employee>(_dataPath, hasHeader: true);

    // 0. Get the column name of input features.
    string[] featureColumnNames =
        dataView.Schema
            .Select(column => column.Name)
            .Where(columnName => columnName != "Label")
            .ToArray();

    // Define categorical transform estimator
    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);

    // Inspect (fails because Employee (35 cols) cannot be mapped to new schema (52 cols)
    IEnumerable<Employee> employeeDataEnumerable =
        mlContext.Data.CreateEnumerable<Employee>(transformedData, reuseRowObject: true, schemaDefinition : transformedData.Schema);

    // split the transformed dataset into training and a testing datasets
    DataOperationsCatalog.TrainTestData dataSplit = mlContext.Data.TrainTestSplit(transformedData, testFraction: 0.2);
    IDataView trainData = dataSplit.TrainSet;
    IDataView testData = dataSplit.TestSet;

    return View();
}

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Я столкнулся с этим недавно и в качестве быстрого обходного пути я просто создал новый класс, который соответствует преобразованной схеме данных.Например, вы можете создать класс EmoloyeeTransformed с правильными свойствами (т.е. вектор вместо строки) и использовать его следующим образом:

CreateEnumerable<EmployeeTransformed>

Это не оптимально, если вы собираетесь создавать различные преобразованные схемы, но это работает.

Надеюсь, это поможет.

0 голосов
/ 24 июня 2019

В целях отладки вы также можете вызвать transmedData.Preview () и посмотреть на данные и полученную схему.

...