Рубрики
Без рубрики

Логистическая регрессия в Java

Изучите основную идею логистической регрессии и некоторые из доступных инструментов Java.

Автор оригинала: Andrew Shcherbakov.

1. введение

Логистическая регрессия является важным инструментом в инструментарии практикующего специалиста по машинному обучению (ML).

В этом уроке мы рассмотрим основную идею логистической регрессии .

Во-первых, давайте начнем с краткого обзора парадигм и алгоритмов ML.

2. Обзор

ML позволяет нам решать проблемы, которые мы можем сформулировать в удобных для человека терминах. Однако этот факт может представлять проблему для американских разработчиков программного обеспечения. Мы привыкли решать проблемы, которые можем сформулировать в удобных для компьютера терминах. Например, будучи людьми, мы можем легко обнаружить объекты на фотографии или установить настроение фразы. Как мы могли бы сформулировать такую задачу для компьютера?

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

Обучение является частью итеративного рабочего процесса ML:

Мы начинаем с сбора данных. Часто данные поступают из разных источников. Поэтому мы должны сделать его в том же формате. Мы также должны контролировать, чтобы набор данных справедливо представлял область исследования. Если модель никогда не была обучена на красных яблоках, она вряд ли может предсказать это.

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

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

3. Парадигмы МЛ

В ML, основываясь на том, какими входными данными мы располагаем, мы можем выделить три основные парадигмы:

  • контролируемое обучение (классификация изображений, распознавание объектов, анализ настроений)
  • неконтролируемое обучение (обнаружение аномалий)
  • обучение с подкреплением (игровые стратегии)

Случай, который мы собираемся описать в этом уроке, относится к контролируемому обучению.

4. Набор инструментов ML

В ML существует набор инструментов, которые мы можем применить при построении модели. Давайте упомянем некоторые из них:

  • Линейная регрессия
  • Логистическая регрессия
  • Нейронные сети
  • метод опорных векторов
  • k-Ближайшие Соседи

Мы можем объединить несколько инструментов при построении модели, обладающей высокой прогностической способностью. На самом деле, для этого урока наша модель будет использовать логистическую регрессию и нейронные сети.

5. Библиотеки ML

Несмотря на то, что Java не является самым популярным языком для прототипирования моделей ML, он имеет репутацию надежного инструмента для создания надежного программного обеспечения во многих областях, включая ML. Поэтому мы можем найти библиотеки ML, написанные на Java.

В этом контексте мы можем упомянуть де-факто стандартную библиотеку Tensorflow , которая также имеет версию Java. Еще стоит упомянуть библиотеку глубокого обучения под названием Deeplearning4j . Это очень мощный инструмент, и мы собираемся использовать его и в этом уроке.

6. Логистическая регрессия при распознавании цифр

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

Мы тренируем модель до тех пор, пока так называемая функция потерь или целевая функция не достигнет некоторого минимального значения. Функция потерь зависит от фактических и ожидаемых прогнозов модели (меток входных данных). Наша цель состоит в том, чтобы свести к минимуму расхождение фактических прогнозов модели и ожидаемых.

Если нас не устраивает это минимальное значение, мы должны построить другую модель и снова провести обучение.

Чтобы увидеть логистическую регрессию в действии, мы проиллюстрируем ее на распознавании рукописных цифр. Эта проблема уже стала классической. Библиотека Deeplearning4j имеет ряд реалистичных примеров , которые показывают, как использовать ее API. Часть этого руководства, связанная с кодом, в значительной степени основана на классификаторе MNIST .

6.1. Входные данные

В качестве входных данных мы используем хорошо известную базу данных MNIST рукописных цифр. В качестве входных данных у нас есть изображения в сером масштабе размером 28×28 пикселей. Каждое изображение имеет естественную метку, которая является цифрой, которую представляет изображение:

Чтобы оценить эффективность модели, которую мы собираемся построить, мы разделяем входные данные на обучающие и тестовые наборы:

DataSetIterator train = new RecordReaderDataSetIterator(...);
DataSetIterator test = new RecordReaderDataSetIterator(...);

Как только у нас есть входные изображения, помеченные и разделенные на два набора, этап “обработки данных” завершен, и мы можем перейти к “построению модели”.

6.2. Построение модели

Как мы уже упоминали, нет моделей, которые хорошо работают в каждой ситуации. Тем не менее, после многих лет исследований в области ML ученые нашли модели, которые очень хорошо справляются с распознаванием рукописных цифр. Здесь мы используем так называемую модель LeNet-5 .

LeNet-5-это нейронная сеть, состоящая из серии слоев, которые преобразуют изображение размером 28×28 пикселей в десятимерный вектор:

Десятимерный выходной вектор содержит вероятности того, что метка входного изображения равна либо 0, либо 1, либо 2, и так далее.

Например, если выходной вектор имеет следующий вид:

{0.1, 0.0, 0.3, 0.2, 0.1, 0.1, 0.0, 0.1, 0.1, 0.0}

это означает, что вероятность того, что входное изображение будет равно нулю, равна 0,1, единице-0, двум-0,3 и т. Д. Мы видим, что максимальная вероятность (0.3) соответствует метке 3.

Давайте погрузимся в детали построения модели. Мы опускаем детали, относящиеся к Java,и концентрируемся на концепциях ML.

Мы настраиваем модель, создавая Многослойную сеть объект:

MultiLayerNetwork model = new MultiLayerNetwork(config);

В его конструкторе мы должны передать многослойную конфигурацию объекта. Это тот самый объект, который описывает геометрию нейронной сети. Чтобы определить геометрию сети, мы должны определить каждый слой.

Давайте покажем, как мы это делаем с первым и вторым:

ConvolutionLayer layer1 = new ConvolutionLayer
    .Builder(5, 5).nIn(channels)
    .stride(1, 1)
    .nOut(20)
    .activation(Activation.IDENTITY)
    .build();
SubsamplingLayer layer2 = new SubsamplingLayer
    .Builder(SubsamplingLayer.PoolingType.MAX)
    .kernelSize(2, 2)
    .stride(2, 2)
    .build();

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

Теперь мы готовы построить Многослойную конфигурацию объект:

MultiLayerConfiguration config = new NeuralNetConfiguration.Builder()
    // preparation steps
    .list()
    .layer(layer1)
    .layer(layer2)
    // other layers and final steps
    .build();

это мы передаем в Многослойную сеть конструктор.

6.3. Обучение

Построенная нами модель содержит 431080 параметров или весов. Мы не собираемся приводить здесь точный расчет этого числа, но мы должны знать, что только первый слой имеет больше весов.

Этап обучения так же прост, как:

model.fit(train);

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

Evaluation eval = model.evaluate(test);
logger.info(eval.stats());

Модель LeNet-5 достигает довольно высокой точности почти 99% даже за одну обучающую итерацию (эпоху). Если мы хотим достичь более высокой точности, мы должны сделать больше итераций, используя простой for-loop :

for (int i = 0; i < epochs; i++) {
    model.fit(train);
    train.reset();
    test.reset();
}

6.4. Прогнозирование

Теперь, когда мы обучили модель и довольны ее предсказаниями по тестовым данным, мы можем попробовать модель на некоторых абсолютно новых входных данных. С этой целью давайте создадим новый класс MnistPrediction , в котором мы загрузим изображение из файла, выбранного из файловой системы:

INDArray image = new NativeImageLoader(height, width, channels).asMatrix(file);
new ImagePreProcessingScaler(0, 1).transform(image);

Переменная image содержит наше изображение, уменьшенное до 28×28 оттенков серого. Мы можем скормить его нашей модели:

INDArray output = model.output(image);

Переменная output будет содержать вероятности того, что изображение будет равно нулю, единице, двум и т. Д.

Давайте теперь немного поиграем и напишем цифру 2, оцифруем это изображение и скормим ему модель. Мы можем получить что-то вроде этого:

Как мы видим, компонент с максимальным значением 0.99 имеет индекс два. Это означает, что модель правильно распознала нашу рукописную цифру.

7. Заключение

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

Как всегда, мы можем найти соответствующие фрагменты кода в нашем репозитории GitHub .