www.machinelearningmastery.ru

Машинное обучение, нейронные сети, искусственный интеллект
Header decor

Home

Является ли LDA методом уменьшения размерности или алгоритмом классификатора?

Дата публикации Mar 28, 2017

Введение

В моем последнем посте я начал обсуждение уменьшения размерности, которое имело реальное влияние на результаты с использованием анализа главных компонентов (PCA), прежде чем выполнить задачу классификации (https://meigarom.github.io/blog/pca.html). В этом посте я собираюсь продолжить обсуждение этой темы, но теперь поговорим об алгоритме линейного дискриминантного анализа (LDA). LDA определяется как метод уменьшения размерности авторами, однако некоторые источники объясняют, что LDA фактически работает как линейный классификатор.

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

Немного о LDA

Идея, лежащая в основе LDA, проста. Говоря математически, нам нужно найти новое пространство функций для проецирования данных, чтобы максимизировать разделимость классов. Ну, очевидно, первый шаг - найти способ измерить эту способность разделения каждого нового кандидата пространственных объектов. Расстояние между прогнозируемыми средними для каждого класса может быть одной из мер, однако только это расстояние не будет очень хорошим показателем, поскольку оно не учитывает разброс данных. В 1988 году статистик по имени Рональд Фишер предложил следующее решение: максимизировать функцию, которая представляет собой разницу между средними, нормированную мерой изменчивости внутри класса. Предложение Фишера состоит в том, чтобы максимизировать расстояние между средними значениями каждого класса и минимизировать распространение внутри самого класса. Таким образом, мы придумали две меры: внутри класса и между классом. Однако такая формулировка возможна только в том случае, если мы предположим, что набор данных имеет нормальное распределение. Это предположение может иметь недостаток, потому что, если распределение ваших данных значительно негауссово, LDA может работать не очень хорошо. В следующих статьях я углублюсь в код алгоритма LDA, показывающий его реализацию, и здесь я заинтересован в том, чтобы найти ответ на первоначальный вопрос. Является ли LDA линейным классификатором или техникой уменьшения размерности?

Подробности об эксперименте

Эксперимент, предложенный в этом посте, состоит из задачи классификации по общедоступному набору данных. В основном, набор данных содержит 846 наблюдений и 18 признаков от 3 различных типов транспортных средств. Характеристики соответствуют физическим показателям формы этих транспортных средств, таким как компактность, округлость и радиус, например. Вы можете проверить набор данных здесь:https://archive.ics.uci.edu/ml/datasets/Statlog+(Vehicle+Silhouettes, Исходный набор данных содержит наблюдения из 4 типов транспортных средств, я собираюсь собрать примеры только из 3 классов, чтобы иметь возможность построить новое пространство признаков.

LDA как алгоритм классификатора

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

В языке R LDA в качестве классификатора выглядит следующим образом:

library( dplyr )# Load dataset
data_raw = read.csv( "../dataset/vehicle.csv", stringsAsFactor = FALSE )data = data_raw %>% filter( class == "bus" | class == "opel" | class == "van" )# Scale dataset
maxs = apply( data[,1:18], 2, max )
mins = apply( data[,1:18], 2, min )
dataset = as.data.frame( scale( data[,1:18], center = mins, scale = maxs - mins ) )
dataset = cbind( dataset, "class" = data$class )# Split dataset
index = sample( 1:nrow( dataset ), round( nrow( dataset )*0.6 ), replace = FALSE )
X_train = dataset[ index, ]
test = dataset[ -index, ]

Прежде всего, я загрузил набор данных и отфильтровал только строки из классов bus, open и van. Позже я масштабировал набор данных, используя стандартную технику, а затем я разделял набор данных в обучающем и тестовом наборе с 60% и 40% примеров каждого, соответственно. С готовыми наборами данных мы можем применить LDA к обучающему набору данных.

# Model Discriminant Analysis
library( MASS )
model = lda( class ~ ., data = X_train )# Ploting LDA Model
projected_data = as.matrix( X_train[, 1:18] ) %*% model$scaling
plot( projected_data, col = X_train[,19], pch = 19 )

LDA моделируется с использованием библиотеки MASS R, она содержит несколько параметров модели, таких как априорные вероятности групп, средние значения групп и коэффициенты линейного дискриминанта. Наиболее важным результатом здесь являются коэффициенты, они представляют собой значения, которые описывают новое пространство объектов, в которое будут проецироваться данные. LDA уменьшает размерность от исходного количества объектов до объектов C - 1, где C - количество классов. В этом случае у нас есть 3 класса, поэтому в новом пространстве объектов будет только 2 объекта. Приведенное выше изображение представляет собой график пространства новых объектов с двумя объектами, мы можем видеть новую позицию данных, между тремя классами перекрываются несколько точек, но в целом набор данных довольно разделим. После этапа обучения нам необходимо измерить точность полученной модели.

# Model Testing
X_test = test[, !( names( test ) %in% c( "class" ) ) ]
model.results = predict( model, X_test )# Results - Confusion Matrix
library( caret )
t = table( model.results$class, test$class )
print( confusionMatrix( t ) )## Confusion Matrix and Statistics
##
##
## bus opel van
## bus 87 5 0
## opel 2 75 0
## van 0 5 78
##
## Overall Statistics
##
## Accuracy : 0.952381
## 95% CI : (0.9182971, 0.9751557)
## No Information Rate : 0.3531746
## P-Value [Acc > NIR] : < 0.00000000000000022204
##
## Kappa : 0.9285056
## Mcnemar's Test P-Value : NA
##
## Statistics by Class:
##
## Class: bus Class: opel Class: van
## Sensitivity 0.9775281 0.8823529 1.0000000
## Specificity 0.9693252 0.9880240 0.9712644
## Pos Pred Value 0.9456522 0.9740260 0.9397590
## Neg Pred Value 0.9875000 0.9428571 1.0000000
## Prevalence 0.3531746 0.3373016 0.3095238
## Detection Rate 0.3452381 0.2976190 0.3095238
## Detection Prevalence 0.3650794 0.3055556 0.3293651
## Balanced Accuracy 0.9734266 0.9351884 0.9856322

Последняя часть этого первого подхода заключается в применении тестового набора данных в модели и измерении его результатов. Как мы видим, LDA достиг около 95% точности в качестве классификатора, что является довольно хорошим результатом. LDA в основном проецирует данные в новое линейное пространство признаков, очевидно, классификатор достигнет высокой точности, если данные будут линейно разделимыми. Теперь, когда мы помним о точности LDA, работающей как классификатор, давайте проверим второй подход.

LDA как алгоритм уменьшения размерности

Линейный Дискриминантный Анализ также работает как алгоритм уменьшения размерности, это означает, что он уменьшает число измерений от оригинала до C - 1 число признаков, где C - количество классов. В этом примере у нас есть 3 класса и 18 функций, LDA сократится с 18 функций до 2 функций. После сокращения модель нейронной сети будет применена к задаче классификации. Процедура здесь почти такая же, как и предыдущая. Посмотрите на это.

# New Dataset
new_X_train = as.matrix( X_train[,1:18] ) %*% model$scaling
new_X_train = as.data.frame( new_X_train )
new_X_train$class = X_train$class

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

# Multi-Class -> Transforming The Labels
new_X_train = cbind( new_X_train, opel = new_X_train$class == "opel" )
new_X_train = cbind( new_X_train, van = new_X_train$class == "van" )
new_X_train = cbind( new_X_train, bus = new_X_train$class == "bus" )
new_X_train = new_X_train[, !( names( new_X_train ) %in% c( "class" ) ) ]

Прежде чем приступить к моделированию, нам нужно преобразовать набор данных, чтобы можно было использовать модель нейронной сети в качестве задачи классификации нескольких классов. Модификация состоит в создании новых столбцов для каждой метки со значениями «True» или «False». Например, все примеры из «opel» получат значение «True» ниже столбца «opel» и «False» в других столбцах метки. Следовательно, набор данных готов для мультиклассовой модели.

# Model Neural Network
library( neuralnet )
n = names( new_X_train )
f = as.formula( "opel+van+bus ~ LD1+LD2" )
nn = neuralnet( f, new_X_train, hidden = 3, linear.output = FALSE, lifesign = "full",
threshold = 0.02, stepmax = 1e6 )## hidden: 3 thresh: 0.02 rep: 1/1 steps: 1000 min thresh: 0.7307363799
## 2000 min thresh: 0.7307363799
## 3000 min thresh: 0.7307363799
## 4000 min thresh: 0.6448965006
## 5000 min thresh: 0.4485495524
## 6000 min thresh: 0.3650681285
## 7000 min thresh: 0.2756491212
## 8000 min thresh: 0.2137706548
## 9000 min thresh: 0.1995287711
## 10000 min thresh: 0.173313487
## 11000 min thresh: 0.173313487
## 12000 min thresh: 0.173313487
## 13000 min thresh: 0.173313487
## 14000 min thresh: 0.1420902136
## 15000 min thresh: 0.08689029484
## 16000 min thresh: 0.08255271673
## 17000 min thresh: 0.0690402594
## 18000 min thresh: 0.04721150014
## 19000 min thresh: 0.02719626607
## 19149 error: 11.92918 time: 4.03 secs

Модель нейронной сети начинается очень просто с 3 скрытых слоев, с квадратным средним порогом ошибки 0,02 и 1e6 максимальных эпох. Идея здесь в том, чтобы применить нейронную сеть к новому набору данных и проверить, можем ли мы достичь лучших результатов. Тестовый набор данных будет таким же, как и в предыдущем подходе.

# Testing
X_test = as.matrix( test[,1:18] ) %*% model$scaling
nn.results = compute( nn, X_test )# Results
print( "... resulting ..." )## [1] "... resulting ..."idx = apply( nn.results$net.result, c(1), function( x ){ which( x == max( x ) ) } )
predictions = c( "opel", "van", "bus")[idx]# Confusion Matrix
library( caret )
t = table( predictions, test$class )
print( confusionMatrix( t ) )## Confusion Matrix and Statistics
##
##
## predictions bus opel van
## bus 84 3 1
## opel 4 81 3
## van 1 1 74
##
## Overall Statistics
##
## Accuracy : 0.9484127
## 95% CI : (0.9133996, 0.9722494)
## No Information Rate : 0.3531746
## P-Value [Acc > NIR] : < 0.00000000000000022
##
## Kappa : 0.9224872
## Mcnemar's Test P-Value : 0.7667396
##
## Statistics by Class:
##
## Class: bus Class: opel Class: van
## Sensitivity 0.9438202 0.9529412 0.9487179
## Specificity 0.9754601 0.9580838 0.9885057
## Pos Pred Value 0.9545455 0.9204545 0.9736842
## Neg Pred Value 0.9695122 0.9756098 0.9772727
## Prevalence 0.3531746 0.3373016 0.3095238
## Detection Rate 0.3333333 0.3214286 0.2936508
## Detection Prevalence 0.3492063 0.3492063 0.3015873
## Balanced Accuracy 0.9596402 0.9555125 0.9686118

Модель нейронной сети достигла около 93% точности, примененной к набору данных с уменьшенным размером. Этот результат очень очень близок к результату первого подхода. Это импортная подсказка о лучшем режиме работы для LDA.

Результаты обоих подходов

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

Вывод

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

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

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

Я видел несколько работ в этой области, где авторы объединяют PCA и LDA, оба для уменьшения размерности. Во-первых, PCA действует, уменьшая характеристики по своей дисперсии, затем LDA применяет линейное уменьшение размерности, и, наконец, модель классификатора выполняется над этим модифицированным набором данных. Это определенно дорожная карта, которой нужно следовать, чтобы улучшить результаты в задачах классификации.

Благодарность!

Полный код доступен в моем репозитории git hub, а также в наборе данных.

Спасибо за ваше время, читая этот пост. Я очень ценю, отзывы всегда приветствуются.

Поговорим с вами, ребята, в ближайшее время.

Оригинальная статья

Footer decor

© www.machinelearningmastery.ru | Ссылки на оригиналы и авторов сохранены. | map