суббота, 28 мая 2016 г.

Понижение размерности: PCA, MDS, t-SNE



В качестве примера рассматривается набор данных Colon из пакета plsgenomics. Он содержит 2000 переменных, характеризующих уровень экспрессии генов в 62 образцах тканей (40 опухолевых и 22 нормальных); решить нужно задачу двухклассовой классификации. Здесь n<<p - переменных гораздо больше, чем наблюдений. Попробуем понизить размерность данных разными методами и сравнить результаты.
library(plsgenomics)
library(Rtsne)
library(caret)
data(Colon)
df <- Colon$X # предикторы
Y <- as.factor(Colon$Y) # метки классов
preProcValues <- preProcess(df, method = c("center", "scale")) # стандартизация
df <- predict(preProcValues, df) 
head(df[, 1:5])
##            1          2           3            4          5
## 1  0.5087761  0.2290114  0.09277894  0.038208566 -0.6921737
## 2  0.6946290  0.8006657  0.43382052 -0.133540752 -0.6794033
## 3 -1.0313974  0.9152589  0.70142142  0.355537305 -1.3048343
## 4 -0.2487376  1.3050329  1.02366571 -0.006054709 -0.6886951
## 5 -1.2238907 -0.5813493 -0.38171451 -0.259624082 -0.5569221
## 6 -1.4566778 -1.3734381 -1.39070424 -0.453161864 -0.8304916

PCA

Применим метод главных компонент, используя предварительно стандартизированные данные. Всего будет создано n-1 ненулевых главных компонент, в данном случае 61 в соответствии с фактическй размерностью данных (см. 1, 2, 3).
df.pca <- prcomp(df, center = FALSE, scale = FALSE)
plot(df.pca$x[,1], df.pca$x[, 2], col = Y)

На графике в пространстве первух двух главных компонент классы выглядят неразделимыми. Это довольно предсказуемо, ведь направления наибольшей вариабельности данных вовсе не обязательно будут тесно связаны с переменной отклика.

MDS

Многомерное шкалирование ищет проекцию данных в пространство меньшей размерности таким образом, чтобы как можно точнее сохранить расстояния между объектами. Двухмерная проекция, полученная данным методом, выглядит следующим образом:
df.mds <- cmdscale(dist(df), eig = TRUE, k = 2) 
plot(df.mds$points[, 1], df.mds$points[, 2], col = Y)

Классы по-прежнему выглядят плохо разделимыми.

t-SNE

Суть метода подробно объясняется в публикации на хабре. Воспользуемся эффективной реализацией алгоритма на C++ при помощи пакета Rstne (есть также реализация непосредственно на R):
set.seed(100)
df.rtsne <- Rtsne(Colon$X, dims = 2, perplexity = 20)
plot(df.rtsne$Y, col = Y)

В полученном пространстве классы можно достаточно хорошо разделить с использованием простейших методов, таких как одиночное решающее дерево. Недостаток метода состоит в том, что решаемая им задача оптимизации не имеет единственного решения, а полученные переменные, в координатах которых строится график, не выражаются через исходные переменные. Если на обучающей выборке построить модель, то она окажется бесполезной, поскольку нельзя определить координаты новых точек в пространстве пониженной размерности. Иными словами, мы получили информацию о разделимости классов, но по-прежнему не знаем, как именно их разделить.
Очевидным выходом из ситуации является предложенный ниже алгоритм:
  1. Для обучающей выборки понизить размерность (например, до 2) при помощи t-SNE.
  2. Подобрать оптимальную модель с использованием кросс-валидации.
  3. Новые данные, для которых неизвестны значения целевой переменной, объединить с обучающей выборкой. Получившаяся выборка будет содержать размеченную и неразмеченную часть.
  4. Аналогичным образом понизить размерность для новой выборки, включающей в себя обучающую.
  5. На размеченной части выборки построить модель с подобранной в п.2 спецификацией.
  6. Использовать модель для предсказания значений целевой переменной на неразмеченной части выборки.
Иллюстрация на примере k ближайших соседей:
set.seed(100)
df.rtsne <- Rtsne(Colon$X, dims = 2, perplexity = 20)$Y
df.rtsne <- cbind(df.rtsne, Colon$Y)
df.rtsne <- as.data.frame(df.rtsne)
df.rtsne[, 3] <- factor(df.rtsne[, 3], levels = c(1, 2), 
                        labels = c("normal", "tumor"))
colnames(df.rtsne) <- c("X1", "X2", "Y")
trainIndex <- createDataPartition(df.rtsne$Y, p = 0.8, list = FALSE, times = 1)
train <- df.rtsne[trainIndex, ]
test <- df.rtsne[-trainIndex, ]

set.seed(100)
fitControl <- trainControl(method = "cv",
                           number = 5,
                           classProbs = TRUE,
                           summaryFunction = twoClassSummary)
set.seed(100)
fit1 <- train(Y ~ X1 + X2,
              data = train,
              method = "knn", 
              trControl = fitControl,
              metric = "ROC")
fit1
## k-Nearest Neighbors 
## 
## 50 samples
##  2 predictor
##  2 classes: 'normal', 'tumor' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 41, 40, 40, 39, 40 
## Resampling results across tuning parameters:
## 
##   k  ROC        Sens  Spec     
##   5  0.8279762  0.65  0.9047619
##   7  0.8263889  0.65  0.8761905
##   9  0.7416667  0.55  0.8761905
## 
## ROC was used to select the optimal model using  the largest value.
## The final value used for the model was k = 5.
pred <- predict(fit1, newdata = test)
confusionMatrix(pred, test$Y, positive = "tumor")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction normal tumor
##     normal      3     0
##     tumor       1     8
##                                           
##                Accuracy : 0.9167          
##                  95% CI : (0.6152, 0.9979)
##     No Information Rate : 0.6667          
##     P-Value [Acc > NIR] : 0.05395         
##                                           
##                   Kappa : 0.8             
##  Mcnemar's Test P-Value : 1.00000         
##                                           
##             Sensitivity : 1.0000          
##             Specificity : 0.7500          
##          Pos Pred Value : 0.8889          
##          Neg Pred Value : 1.0000          
##              Prevalence : 0.6667          
##          Detection Rate : 0.6667          
##    Detection Prevalence : 0.7500          
##       Balanced Accuracy : 0.8750          
##                                           
##        'Positive' Class : tumor           
## 
P.S. Stochastic k-Neighborhood Selection for Supervised and Unsupervised Learning

Комментариев нет:

Отправить комментарий