Я не эксперт по нейронным сетям, но я думаю, что следующие пункты могут быть полезны для вас. Есть также несколько хороших постов, например, о скрытых юнитах , которые вы можете найти на этом сайте о том, что делают нейронные сети, которые могут оказаться полезными.
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 Количество примеров обучения по сравнению с количеством параметров для оценки
x ⋅ k >ck =(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 примерами обучения. Я подозреваю, что в этом случае вы могли бы сократить количество параметров для оценки, сократив количество единиц. И вы можете увидеть из построения нейронной сети для того, чтобы сделать дополнение, что более простая нейронная сеть может с меньшей вероятностью столкнуться с проблемами во время обучения.
Но, как правило, в любом машинном обучении (включая линейную регрессию) вы хотите иметь гораздо больше обучающих примеров, чем параметров для оценки.