R нейроннет - обчислення дають постійну відповідь


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

Хтось може мені пояснити, чому помилки такі великі і чому всі прогнозовані значення майже постійні?

Відповіді:


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 Кількість навчальних прикладів порівняно з кількістю параметрів для оцінки

хк>cк=(1,2,3,4,5)c=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 прикладів тренувань. Я підозрюю, що в цьому випадку ви, можливо, зможете зменшити кількість параметрів для оцінки, зменшивши кількість одиниць. І ви можете бачити, як створити нейронну мережу, щоб додати, що простіша нейронна мережа може менше стикатися під час тренувань.

Але, як правило, у будь-якому машинному навчанні (включаючи лінійну регресію) ви хочете мати набагато більше прикладів навчання, ніж параметри для оцінки.


1
Дуже багато інформації, щоб подумати, дякую! Ти абсолютно правий! Якщо змінні були нормалізовані, кількість прикладів тренувань була більшою, а кількість нейронів на одному прихованому шарі дорівнює одиниці, це буде виглядати набагато краще. Звичайно, не функція множення, але щось подібне. Ах, якби я отримав таку чудову відповідь 2 тижні тому, все було б простіше. Однак дуже вдячний за вашу відповідь, дякую!
luckyi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.