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

บางคนสามารถอธิบายได้ว่าทำไมข้อผิดพลาดจึงใหญ่และทำไมค่าที่คาดการณ์ทั้งหมดเกือบจะคงที่?

คำตอบ:


6

ฉันไม่ใช่ผู้เชี่ยวชาญด้านอวนประสาท แต่ฉันคิดว่าประเด็นต่อไปนี้อาจเป็นประโยชน์กับคุณ นอกจากนี้ยังมีบางโพสต์ที่ดีเช่นนี้ในหน่วยที่ซ่อนอยู่ซึ่งคุณสามารถค้นหาบนเว็บไซต์นี้เกี่ยวกับสิ่งที่มุ้งประสาทที่คุณอาจพบว่ามีประโยชน์

1 ข้อผิดพลาดขนาดใหญ่: ทำไมตัวอย่างของคุณจึงไม่ทำงานเลย

ทำไมข้อผิดพลาดมีขนาดใหญ่มากและทำไมค่าที่คาดการณ์ทั้งหมดเกือบจะคงที่?

นี่เป็นเพราะเครือข่ายประสาทไม่สามารถคำนวณฟังก์ชันการคูณที่คุณให้และส่งออกตัวเลขคงที่ในช่วงกลางของช่วงyโดยไม่คำนึงถึงxเป็นวิธีที่ดีที่สุดเพื่อลดข้อผิดพลาดในระหว่างการฝึกอบรม (สังเกตว่า 58749 นั้นใกล้เคียงกับค่าเฉลี่ยของการคูณสองตัวเลขระหว่าง 1 ถึง 500 ด้วยกันอย่างไร)

มันยากมากที่จะเห็นว่าเครือข่ายประสาทเทียมสามารถคำนวณฟังก์ชันการคูณได้อย่างสมเหตุสมผล ลองคิดดูว่าแต่ละโหนดในเครือข่ายรวมผลลัพธ์ที่คำนวณไว้ก่อนหน้านี้อย่างไร: คุณรับผลรวมถ่วงน้ำหนักของผลลัพธ์จากโหนดก่อนหน้า (จากนั้นใช้ฟังก์ชัน sigmoidal กับมันดูตัวอย่างเช่นIntroduction to Neural Networksเพื่อแยกสัญญาณออกระหว่างและ ) คุณจะได้รับผลรวมถ่วงน้ำหนักอย่างไรเพื่อให้การคูณสองอินพุต (ฉันคิดว่าอาจเป็นไปได้ที่จะใช้เลเยอร์ที่ซ่อนอยู่จำนวนมากเพื่อให้การคูณทวีคูณในลักษณะที่ถูกต้องมาก)-11

2 Local minima: ทำไมตัวอย่างที่สมเหตุสมผลในทางทฤษฎีอาจไม่ทำงาน

อย่างไรก็ตามแม้พยายามที่จะเพิ่มนอกจากนี้คุณพบปัญหาในตัวอย่างของคุณ: เครือข่ายไม่สำเร็จ ฉันเชื่อว่านี่เป็นเพราะปัญหาที่สอง: รับminima ท้องถิ่นในระหว่างการฝึกอบรม ในความเป็นจริงสำหรับการเพิ่มการใช้สองชั้นของ 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 จำนวนตัวอย่างการฝึกอบรมเปรียบเทียบกับจำนวนพารามิเตอร์ที่จะประมาณ

xk>k=(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 ตัวอย่าง ฉันสงสัยว่าในกรณีนี้คุณอาจจะสามารถลดจำนวนของพารามิเตอร์ที่จะประมาณโดยการลดจำนวนของหน่วย และคุณสามารถเห็นได้จากการสร้างโครงข่ายประสาทเทียมเพื่อทำเพิ่มเติมว่าเครือข่ายประสาทที่เรียบง่ายอาจมีปัญหาในการฝึกซ้อมน้อยลง

แต่ตามกฎทั่วไปในการเรียนรู้ของเครื่อง (รวมถึงการถดถอยเชิงเส้น) คุณต้องมีตัวอย่างการฝึกอบรมมากกว่าพารามิเตอร์ที่จะประมาณ


1
มีข้อมูลมากมายให้คิดขอบคุณ! คุณพูดถูก! หากตัวแปรถูกทำให้เป็นมาตรฐานจำนวนตัวอย่างการฝึกอบรมจะมีขนาดใหญ่ขึ้นและจำนวนของเซลล์ประสาทในเลเยอร์ที่ซ่อนอยู่หนึ่งชั้นจะเท่ากับหนึ่งมันจะดูดีขึ้นมาก แน่นอนไม่ใช่ฟังก์ชั่นการคูณ แต่สิ่งที่คล้ายกัน อ๊ะถ้าฉันได้รับการตอบรับที่ดีมากเมื่อ 2 สัปดาห์ก่อนสิ่งต่างๆจะง่ายขึ้น อย่างไรก็ตามขอบคุณมากสำหรับคำตอบของคุณขอบคุณ!
luckyi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.