R neuralnet - вычислить, дать постоянный ответ

11

Я пытаюсь использовать neuralnetпакет R (документация здесь ) для прогноза.

Вот что я пытаюсь сделать:

library(neuralnet)
x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] * x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = c(5, 5), threshold=0.01)
print(net)

all: neuralnet(formula = f, data = train, hidden = c(5, 5), threshold = 0.01)

1 repetition was calculated.

    Error Reached Threshold Steps
1 66136930789    0.004658283648 97938

test <- cbind(runif(10, min=1, max=500), runif(10, min=1, max=500))
res <- compute(net, test)
res$net.result
         [,1]
[1,] 58749.01798
[2,] 58749.01798
[3,] 58749.01798
[4,] 58749.01798
[5,] 58749.01798
[6,] 58749.01798
[7,] 58749.01798
[8,] 58749.01798
[9,] 58749.01798
[10,] 58749.01798

Может кто-нибудь объяснить мне, почему ошибки такие большие и почему все прогнозируемые значения почти постоянны?

luckyi
источник

Ответы:

6

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

1 Большие ошибки: почему ваш пример не сработал

почему ошибки такие большие и почему все прогнозируемые значения почти постоянны?

Это связано с тем, что нейронная сеть не смогла вычислить функцию умножения, которую вы ей дали, и вывести постоянное число в середине диапазона y, независимо от того x, было лучшим способом минимизировать ошибки во время обучения. (Обратите внимание, что 58749 довольно близко к среднему значению умножения двух чисел между 1 и 500).

-11

2 Локальные минимумы: почему теоретически обоснованный пример может не сработать

Однако даже при попытке сложения вы столкнетесь с проблемами в своем примере: сеть не работает успешно. Я считаю, что это из-за второй проблемы: получение локальных минимумов во время обучения. На самом деле, для сложения использовать два слоя из 5 скрытых юнитов слишком сложно, чтобы вычислить сложение. Сеть без скрытых единиц работает отлично:

x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] + x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = 0, threshold=0.01)
print(net) # Error 0.00000001893602844

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

3 Количество примеров обучения по сравнению с количеством параметров для оценки

ИксК>сКзнак равно(1,2,3,4,5)сзнак равно3750

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

library(neuralnet)
set.seed(1) # make results reproducible
N=500
x <- cbind(runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500))
y <- ifelse(x[,1] + 2*x[,1] + 3*x[,1] + 4*x[,1] + 5*x[,1] > 3750, 1, 0)
trainSMALL <- data.frame(x[1:(N/10),], y=y[1:(N/10)])
trainALL <- data.frame(x, y)
n <- names(trainSMALL)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
netSMALL <- neuralnet(f, trainSMALL, hidden = c(5,5), threshold = 0.01)
netALL <- neuralnet(f, trainALL, hidden = c(5,5), threshold = 0.01)
print(netSMALL) # error 4.117671763
print(netALL) # error 0.009598461875

# get a sense of accuracy w.r.t small training set (in-sample)
cbind(y, compute(netSMALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  0.587903899825
 [2,] 0  0.001158500142
 [3,] 1  0.587903899825
 [4,] 0  0.001158500281
 [5,] 0 -0.003770868805
 [6,] 0  0.587903899825
 [7,] 1  0.587903899825
 [8,] 0  0.001158500142
 [9,] 0  0.587903899825
[10,] 1  0.587903899825

# get a sense of accuracy w.r.t full training set (in-sample)
cbind(y, compute(netALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  1.0003618092051
 [2,] 0 -0.0025677656844
 [3,] 1  0.9999590121059
 [4,] 0 -0.0003835722682
 [5,] 0 -0.0003835722682
 [6,] 0 -0.0003835722199
 [7,] 1  1.0003618092051
 [8,] 0 -0.0025677656844
 [9,] 0 -0.0003835722682
[10,] 1  1.0003618092051

Очевидно, что netALLэто намного лучше! Почему это? Посмотрите, что вы получаете с помощью plot(netALL)команды:

введите описание изображения здесь

Я делаю это 66 параметров, которые оцениваются во время обучения (5 входов и 1 вход смещения для каждого из 11 узлов). Вы не можете достоверно оценить 66 параметров с 50 примерами обучения. Я подозреваю, что в этом случае вы могли бы сократить количество параметров для оценки, сократив количество единиц. И вы можете увидеть из построения нейронной сети для того, чтобы сделать дополнение, что более простая нейронная сеть может с меньшей вероятностью столкнуться с проблемами во время обучения.

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

TooTone
источник
1
Большое количество информации для размышления, спасибо! Ты абсолютно прав! Если переменные были нормализованы, количество обучающих примеров было бы больше, а количество нейронов на одном скрытом слое равно единице, это будет выглядеть намного лучше. Конечно, не функция умножения, а нечто подобное. Ах, если бы я получил такой замечательный ответ 2 недели назад, все было бы проще. Тем не менее, очень благодарен за ваш ответ, спасибо!
luckyi