Поделиться через


Подготовка данных к созданию модели

Узнайте, как использовать ML.NET для подготовки данных к дополнительной обработке или созданию модели.

Данные часто нечистые и разреженные. ML.NET алгоритмы машинного обучения ожидают, что входные данные или функции будут находиться в одном числовом векторе. Аналогичным образом, значение для прогнозирования (метки), особенно если это категориальные данные, необходимо закодировать. Поэтому одной из целей подготовки данных является получение данных в формат, ожидаемый алгоритмами ML.NET.

Разделите данные на обучающий набор и тестовый набор &

В следующем разделе описываются распространенные проблемы при обучении модели, такие как переобучение и недообучение. Разделение данных и валидация моделей с использованием отложенного набора поможет вам определить и устранить эти проблемы.

Переобучение & недообучение

Переобучение и недообучение являются двумя наиболее распространенными проблемами, которые возникают при обучении модели. Недостаточное соответствие означает, что выбранный тренер не может достаточно подходит для подготовки набора данных и обычно приводит к высокой потере во время обучения и низкой оценки или метрики в тестовом наборе данных. Чтобы устранить эту проблему, необходимо либо выбрать более мощную модель, либо выполнить более эффективную разработку функций. Переполнение является противоположностью, что происходит, когда модель учит данные обучения слишком хорошо. Обычно это приводит к низкой метрике потери при обучении, но высокой метрике потери в тестовом наборе данных.

Хорошая аналогия для этих понятий — подготовка к экзамену. Предположим, вы знали вопросы и ответы заранее. После изучения вы проходите тест и получаете высший балл. Отличные новости! Тем не менее, когда вам снова дают экзамен с вопросами в другом порядке и с немного изменённой формулировкой, вы получаете более низкую оценку. Это говорит о том, что вы запомнили ответы и фактически не усвоили концепции, по которым вас проверяли. Это пример переобучения. Недообучение является противоположностью, когда учебные материалы, которые вам дали, не точно отражают то, что оценивается на экзамене. В результате вы прибегаете к предположению ответов, так как у вас недостаточно знаний, чтобы правильно ответить.

Разделение данных

Возьмите следующие входные данные и загрузите их в IDataView под названием data.

var homeDataList = new HomeData[]
{
    new()
    {
        NumberOfBedrooms = 1f,
        Price = 100_000f
    },
    new()
    {
        NumberOfBedrooms = 2f,
        Price = 300_000f
    },
    new()
    {
        NumberOfBedrooms = 6f,
        Price = 600_000f
    },
    new()
    {
        NumberOfBedrooms = 3f,
        Price = 300_000f
    },
    new()
    {
        NumberOfBedrooms = 2f,
        Price = 200_000f
    }
};

Чтобы разделить данные на обучающую и тестовую выборки, используйте метод TrainTestSplit(IDataView, Double, String, Nullable<Int32>).

// Apply filter
TrainTestData dataSplit = mlContext.Data.TrainTestSplit(data, testFraction: 0.2);

Параметр testFraction используется для выбора 0,2 или 20% из набора данных для тестирования. Остальные 80%% используются для обучения.

Результат - это DataOperationsCatalog.TrainTestData с двумя IDataViews, доступ к которым можно получить через TrainSet и TestSet.

Фильтрация данных

Иногда не все данные в наборе данных относятся к анализу. Подход к удалению неуместных данных — фильтрация. DataOperationsCatalog содержит набор операций фильтра, принимающих IDataView, содержащий все данные, и возвращающих IDataView, содержащий только интересующие точки данных. Важно отметить, что так как операции фильтрации не являются IEstimator или ITransformer, например в TransformsCatalog, они не могут быть включены в состав конвейера подготовки данных EstimatorChain или TransformerChain.

Возьмите следующие входные данные и загрузите их в IDataView, который называется data.

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=600000f
    }
};

Чтобы отфильтровать данные на основе значения столбца, используйте метод FilterRowsByColumn.

// Apply filter
IDataView filteredData = mlContext.Data.FilterRowsByColumn(data, "Price", lowerBound: 200000, upperBound: 1000000);

Приведенный выше пример принимает строки в наборе данных с ценой от 200000 до 1000000. Результат применения этого фильтра возвращает только последние две строки в данных и исключает первую строку, так как ее цена составляет 1000000, а не между указанным диапазоном.

Замена отсутствующих значений

Отсутствующие значения являются распространенным явлением в наборах данных. Один из подходов к работе с отсутствующими значениями заключается в том, чтобы заменить их значением по умолчанию для данного типа, если оно есть, или другим значимым значением, например средним значением в данных.

Возьмите следующие входные данные и загрузите их в IDataView, названный data.

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=float.NaN
    }
};

Обратите внимание, что последний элемент в списке имеет отсутствующее значение для Price. Чтобы заменить отсутствующие значения в столбце Price, используйте метод ReplaceMissingValues, чтобы заполнить это отсутствующее значение.

Важный

ReplaceMissingValue работает только с числовыми данными.

// Define replacement estimator
var replacementEstimator = mlContext.Transforms.ReplaceMissingValues("Price", replacementMode: MissingValueReplacingEstimator.ReplacementMode.Mean);

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer replacementTransformer = replacementEstimator.Fit(data);

// Transform data
IDataView transformedData = replacementTransformer.Transform(data);

ML.NET поддерживает различные режимы замены . В приведенном выше примере используется режим замены Mean, который заполняет отсутствующее значение средним значением этого столбца. Результат замены заполняет свойство Price для последнего элемента в данных значением 200 000, так как оно является средним значением между 100 000 и 300 000.

Использование нормализаторов

нормализация — это метод предварительной обработки данных, используемый для масштабирования функций в одном диапазоне( обычно от 0 до 1), чтобы их можно было более точно обрабатывать алгоритмом машинного обучения. Например, диапазоны для возраста и дохода значительно варьируются: возраст обычно находится в пределах от 0 до 100, а доход — в диапазоне от нуля до нескольких тысяч. Перейдите на страницу преобразования для получения более подробного списка и описания преобразований нормализации.

Нормализация методом минимального и максимального значения

Возьмите следующие входные данные и загрузите их в IDataView с именем data.

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms = 2f,
        Price = 200000f
    },
    new ()
    {
        NumberOfBedrooms = 1f,
        Price = 100000f
    }
};

Нормализация может применяться к столбцам с одним числовым значением, а также к векторам. Нормализуйте данные в столбце Price, используя нормализацию по min-max методом NormalizeMinMax.

// Define min-max estimator
var minMaxEstimator = mlContext.Transforms.NormalizeMinMax("Price");

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer minMaxTransformer = minMaxEstimator.Fit(data);

// Transform data
IDataView transformedData = minMaxTransformer.Transform(data);

Исходные значения цен [200000,100000] преобразуются в [ 1, 0.5 ] с помощью формулы нормализации MinMax, которая создает выходные значения в диапазоне от 0 до 1.

Binning

Binning преобразует непрерывные значения в дискретное представление входных данных. Например, предположим, что одна из ваших характеристик — возраст. Вместо использования фактического значения возраста, метод группировки создает диапазоны для этого значения. 0-18 может быть одной корзиной, другой может быть 19-35 и т. д.

Возьмите следующие входные данные и загрузите их в IDataView, называемый data.

HomeData[] homeDataList = new HomeData[]
{
    new ()
    {
        NumberOfBedrooms=1f,
        Price=100000f
    },
    new ()
    {
        NumberOfBedrooms=2f,
        Price=300000f
    },
    new ()
    {
        NumberOfBedrooms=6f,
        Price=600000f
    }
};

Нормализуйте данные в ячейки с помощью метода NormalizeBinning. Параметр maximumBinCount позволяет указать количество ячеек, необходимых для классификации данных. В этом примере данные будут помещены в две ячейки.

// Define binning estimator
var binningEstimator = mlContext.Transforms.NormalizeBinning("Price", maximumBinCount: 2);

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
var binningTransformer = binningEstimator.Fit(data);

// Transform Data
IDataView transformedData = binningTransformer.Transform(data);

Результат бинирования создает границы ячеек [0,200000,Infinity]. Поэтому полученные ячейки [0,1,1], так как первое наблюдение составляет от 0 до 2000000 и другие больше 200000, но меньше бесконечности.

Работа с категориальными данными

Одним из наиболее распространенных типов данных является категориальные данные. Категориальные данные имеют конечное число категорий. Например, штаты США или список видов животных, найденных в наборе изображений. Независимо от того, являются ли категориальные данные функциями или метками, они должны быть сопоставлены с числовым значением, чтобы их можно было использовать для создания модели машинного обучения. Существует ряд способов работы с категориальными данными в ML.NET в зависимости от решения проблемы.

Сопоставление значений ключа

В ML.NET ключ представляет собой целочисленное значение, представляющее категорию. Сопоставление значений ключа чаще всего используется для сопоставления строковых меток с уникальными целыми значениями для обучения, а затем обратно к их строковым значениям, когда модель используется для прогнозирования.

Преобразования, используемые для сопоставления значений ключей, представляют собой MapValueToKey и MapKeyToValue.

MapValueToKey добавляет словарь сопоставлений в модели, чтобы MapKeyToValue могли выполнять обратное преобразование при создании прогноза.

Одна горячая кодировка

Одна горячая кодировка принимает конечный набор значений и сопоставляет их с целыми числами, двоичное представление которых имеет одно 1 значение в уникальных позициях в строке. Одна горячая кодировка может быть лучшим выбором, если нет неявного порядка категориальных данных. В следующей таблице показан пример с почтовыми кодами в виде необработанных значений.

Необработанное значение Одно горячее закодированное значение
98052 00...01
98100 00...10
... ...
98109 10...00

Преобразование, превращающее категориальные данные в one-hot закодированные числа, - это OneHotEncoding.

Хэширование

Хэширование — это другой способ преобразования категориальных данных в числа. Хэш-функция сопоставляет данные произвольного размера (например, строки текста) с числом с фиксированным диапазоном. Хэширование может быть быстрым и эффективным способом векторизации функций. Одним из заметных примеров хэширования в машинном обучении является фильтрация нежелательной почты, где вместо поддержания словаря известных слов каждое слово в сообщении хэшируется и добавляется в большой вектор функций. Использование хэширования таким образом позволяет избежать проблемы фильтрации вредоносных спамов путем использования слов, которые не находятся в словаре.

ML.NET предоставляет преобразование хэша для хэширования текста, дат и числовых данных. Как и сопоставление ключей значений, выходные данные преобразования хэша — это типы ключей.

Работа с текстовыми данными

Как и категориальные данные, текстовые данные необходимо преобразовать в числовые функции, прежде чем использовать его для создания модели машинного обучения. Посетите страницу преобразований для получения более подробного списка и описания преобразований текста.

Использование таких данных, как приведенные ниже данные, загруженные в IDataView:

ReviewData[] reviews = new ReviewData[]
{
    new ReviewData
    {
        Description="This is a good product",
        Rating=4.7f
    },
    new ReviewData
    {
        Description="This is a bad product",
        Rating=2.3f
    }
};

ML.NET предоставляет преобразование FeaturizeText, которое принимает строковое значение текста и создает набор признаков из текста, применяя ряд отдельных преобразований.

// Define text transform estimator
var textEstimator  = mlContext.Transforms.Text.FeaturizeText("Description");

// Fit data to estimator
// Fitting generates a transformer that applies the operations of defined by estimator
ITransformer textTransformer = textEstimator.Fit(data);

// Transform data
IDataView transformedData = textTransformer.Transform(data);

Результирующее преобразование преобразует текстовые значения в столбце Description в числовый вектор, похожий на выходные данные ниже:

[ 0.2041241, 0.2041241, 0.2041241, 0.4082483, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0.2041241, 0, 0, 0, 0, 0.4472136, 0.4472136, 0.4472136, 0.4472136, 0.4472136, 0 ]

Преобразования, составляющие FeaturizeText, также могут применяться отдельно для более точного контроля над созданием функций.

// Define text transform estimator
var textEstimator = mlContext.Transforms.Text.NormalizeText("Description")
    .Append(mlContext.Transforms.Text.TokenizeIntoWords("Description"))
    .Append(mlContext.Transforms.Text.RemoveDefaultStopWords("Description"))
    .Append(mlContext.Transforms.Conversion.MapValueToKey("Description"))
    .Append(mlContext.Transforms.Text.ProduceNgrams("Description"))
    .Append(mlContext.Transforms.NormalizeLpNorm("Description"));

textEstimator содержит подмножество операций, выполняемых методом FeaturizeText. Преимуществом более сложного конвейера является контроль и видимость преобразований, применяемых к данным.

Используя первую запись в качестве примера, ниже приведено подробное описание результатов, созданных этапами преобразования, определенными textEstimator:

исходный текст: это хороший продукт

Преобразовать Описание Результат
1. Нормализация текста Преобразует все буквы в строчные буквы по умолчанию это хороший продукт
2. TokenizeWords Разбивает строку на отдельные слова ["это","хороший","продукт"]
3. Удалить стандартные стоп-слова Удаляет слова остановки, такие как , и . ["хороший","продукт"]
4. MapValueToKey Сопоставляет значения с ключами (категориями) на основе входных данных [1,2]
5. Создание диаграмм Преобразует текст в последовательность последовательных слов [1,1,1,0,0]
6. NormalizeLpNorm Масштабирование входных данных по их lp-норме [ 0.577350529, 0.577350529, 0.577350529, 0, 0 ]