बैच सामान्यीकरण के साथ बैकप्रोपैजेशन का मैट्रिक्स रूप


12

बैच तंत्रिकाकरण को गहरे तंत्रिका जाल में पर्याप्त प्रदर्शन सुधार के साथ श्रेय दिया गया है। इंटरनेट पर बहुत सारी सामग्री यह बताती है कि इसे सक्रियण-दर-सक्रियण के आधार पर कैसे लागू किया जाए। मैंने पहले से ही मैट्रिक्स बीजगणित का उपयोग करके बैकप्रॉप लागू किया है, और यह देखते हुए कि मैं उच्च-स्तरीय भाषाओं में काम कर रहा हूं (जबकि Rcppघनी मैट्रिक्स गुणन के लिए (और अंततः GPU के) पर भरोसा करते हुए ), सब कुछ बाहर निकाल देना और for-loops का सहारा लेना शायद उनके कोड को धीमा कर देगा बहुत बड़ा दर्द होने के अलावा।

बैच सामान्यीकरण फ़ंक्शन जहां है

b(xp)=γ(xp−μxp)σxp−1+β
  • पीxp है से पहले ही सक्रिय हो जाता है, वें नोडp
  • बीटाγ और स्केलर पैरामीटर हैंβ
  • σ एक्स पी एक्स पीμxp और माध्य और SD का । (ध्यान दें कि विचरण के वर्गमूल के साथ-साथ एक ठगना कारक का आमतौर पर उपयोग किया जाता है - मान लें कि कॉम्पैक्ट के लिए गैर-एस्टेरो तत्व हैं)σxpxp

मैट्रिक्स के रूप में, एक पूरी परत के लिए बैच सामान्यीकरण जहां

b(X)=(γ⊗1p)⊙(X−μX)⊙σX−1+(β⊗1p)
  • X हैN×p
  • 1N एक कॉलम वेक्टर है
  • γ और अब प्रति-परत सामान्यीकरण मापदंडों के पंक्ति -vectors हैंपीβp
  • μX और हैं मैट्रिक्स, जहां प्रत्येक स्तंभ एक है -vector columnwise अर्थ है और मानक विचलन की एन × पी एनσXN×pN
  • ⊗ क्रोनकर उत्पाद है और एलिमेंटवाइज (हैडमार्ड) उत्पाद है⊙

एक बहुत ही सरल एक-परत तंत्रिका जाल जिसमें कोई बैच सामान्यीकरण नहीं है और एक निरंतर परिणाम है

y=a(XΓ1)Γ2+ϵ

कहाँ पे

  • Γ1 हैp1×p2
  • पी 2 × 1Γ2 हैp2×1
  • a(.) सक्रियण फ़ंक्शन है

यदि नुकसान , तो ग्रेडिएंट्स ∂ आरR=N−1∑(y−y^)2

∂R∂Γ1=−2VTϵ^∂R∂Γ2=XT(a′(XΓ1)⊙−2ϵ^Γ2T)

कहाँ पे

  • V=a(XΓ1)
  • ϵ^=y−y^

बैच के सामान्यीकरण के तहत, नेट या मुझे नहीं पता कि और क्रोनकर उत्पादों के डेरिवेटिव की गणना कैसे की जाती है। क्रोनकर उत्पादों के विषय पर, साहित्य को काफी रहस्यमय तरीके से प्राप्त होता है। y = एक ( ( गामा ⊗ 1 एन ) ⊙ ( एक्स Γ 1 - μ एक्स Γ 1

y=a(b(XΓ1))Γ2
y=a((γ⊗1N)⊙(XΓ1−μXΓ1)⊙σXΓ1−1+(β⊗1N))Γ2

क्या मैट्रिक्स फ्रेमवर्क के भीतर , , और की गणना करने का एक व्यावहारिक तरीका है ? नोड-दर-नोड संगणना का सहारा लिए बिना, एक सरल अभिव्यक्ति?∂ आर / ∂ बीटा ∂ आर / ∂ गामा 1∂R/∂γ∂R/∂β∂R/∂Γ1

अपडेट 1:

मुझे पता चला है कि - की तरह है। यह है: कुछ आर कोड दर्शाता है कि यह करने के लिए लूपिंग के बराबर है। पहले नकली डेटा सेट करें:1 टी एन (∂R/∂β

1NT(a′(XΓ1)⊙−2ϵ^Γ2T)
set.seed(1)
library(dplyr)
library(foreach)

#numbers of obs, variables, and hidden layers
N <- 10
p1 <- 7
p2 <- 4
a <- function (v) {
  v[v < 0] <- 0
  v
}
ap <- function (v) {
  v[v < 0] <- 0
  v[v >= 0] <- 1
  v
}

# parameters
G1 <- matrix(rnorm(p1*p2), nrow = p1)
G2 <- rnorm(p2)
gamma <- 1:p2+1
beta <- (1:p2+1)*-1
# error
u <- rnorm(10)

# matrix batch norm function
b <- function(x, bet = beta, gam = gamma){
  xs <- scale(x)
  gk <- t(matrix(gam)) %x% matrix(rep(1, N))
  bk <- t(matrix(bet)) %x% matrix(rep(1, N))
  gk*xs+bk
}
# activation-wise batch norm function
bi <- function(x, i){
  xs <- scale(x)
  gk <- t(matrix(gamma[i]))
  bk <- t(matrix(beta[i]))
  suppressWarnings(gk*xs[,i]+bk)
}

X <- round(runif(N*p1, -5, 5)) %>% matrix(nrow = N)
# the neural net
y <- a(b(X %*% G1)) %*% G2 + u

फिर डेरिवेटिव की गणना करें:

# drdbeta -- the matrix way
drdb <- matrix(rep(1, N*1), nrow = 1) %*% (-2*u %*% t(G2) * ap(b(X%*%G1)))
drdb
           [,1]      [,2]    [,3]        [,4]
[1,] -0.4460901 0.3899186 1.26758 -0.09589582
# the looping way
foreach(i = 1:4, .combine = c) %do%{
  sum(-2*u*matrix(ap(bi(X[,i, drop = FALSE]%*%G1[i,], i)))*G2[i])
}
[1] -0.44609015  0.38991862  1.26758024 -0.09589582

उनका मिलान होता है। लेकिन मैं अभी भी उलझन में हूं, क्योंकि मैं वास्तव में नहीं जानता कि यह क्यों काम करता है। @Mark L. स्टोन द्वारा संदर्भित MatCalc नोट का कहना है कि का व्युत्पन्न होना चाहिएβ⊗1N

∂A⊗B∂A=(Inq⊗Tmp)(In⊗vec(B)⊗Im)
जहां सदस्यता , , और , और के आयाम हैं । कम्यूटेशन मैट्रिक्स है, जो यहां सिर्फ 1 है क्योंकि दोनों इनपुट वैक्टर हैं। मैं यह कोशिश करता हूं और ऐसा परिणाम प्राप्त करता हूं जो सहायक नहीं लगता है:mnpqABT
# playing with the kroneker derivative rule
A <- t(matrix(beta)) 
B <- matrix(rep(1, N))
diag(rep(1, ncol(A) *ncol(B))) %*% diag(rep(1, ncol(A))) %x% (B) %x% diag(nrow(A))
     [,1] [,2] [,3] [,4]
 [1,]    1    0    0    0
 [2,]    1    0    0    0
 snip
[13,]    0    1    0    0
[14,]    0    1    0    0
snip
[28,]    0    0    1    0
[29,]    0    0    1    0
[snip
[39,]    0    0    0    1
[40,]    0    0    0    1

यह कंफर्टेबल नहीं है। स्पष्ट रूप से मैं उन क्रोनकर व्युत्पन्न नियमों को नहीं समझ रहा हूँ। उन लोगों के साथ मदद करना बहुत अच्छा होगा। मैं अभी भी पूरी तरह से अन्य डेरिवेटिव पर अटक कर रहा हूँ के लिए और - उन कड़ी मेहनत कर रहे हैं क्योंकि वे की तरह additively में प्रवेश नहीं करते करता है।γΓ1β⊗1

अपडेट २

पाठ्यपुस्तकें पढ़ना, मुझे पूरा यकीन है कि और को ऑपरेटर के उपयोग की आवश्यकता होगी । लेकिन मैं स्पष्ट रूप से व्युत्पत्तियों का पालन करने में असमर्थ हूं क्योंकि उन्हें कोड में अनुवाद करने में सक्षम होना चाहिए। उदाहरण के लिए, के व्युत्पन्न ले जा शामिल हो रहा है के संबंध में , जहां (जिसे हम इस समय के लिए एक स्थिर मैट्रिक्स के रूप में सकते हैं)। ∂R/∂Γ1∂R/∂γvec()∂R/∂Γ1w⊙XΓ1Γ1w≡(γ⊗1)⊙σXΓ1−1

मेरी वृत्ति केवल यह कहने के लिए है कि "उत्तर " है, लेकिन यह स्पष्ट रूप से काम नहीं करता है क्योंकि अनुरूप नहीं है ।w⊙XwX

मुझे पता है कि

∂(A⊙B)=∂A⊙B+A⊙∂B

और इस से , कि

∂vec(w⊙XΓ1)∂vec(Γ1)T=vec(XΓ1)I∂vec(w)∂vec(Γ1)T+vec(w)I∂vec(XΓ1)∂vec(Γ1)T
लेकिन मैं अनिश्चित हूं कि इसका मूल्यांकन कैसे किया जाए, अकेले इसे कोड करें।

अपडेट ३

यहां प्रगति हो रही है। मैं इस विचार के साथ कल रात 2 बजे उठा। मैथ नींद के लिए अच्छा नहीं है।

कुछ चीनी के बाद यहाँ :∂R/∂Γ1

  • w≡(γ⊗1)⊙σXΓ1−1
  • "stub"≡a′(b(XΓ1))⊙−2ϵ^Γ2T

श्रृंखला नियम के अंत में आने के बाद आपके पास यहां क्या है: यह लूपिंग तरीका करने से शुरू करें - और कॉलम को सब्स्क्रिप्ट करेंगे और एक कंफर्टेबल आइडेंटिटी मैट्रिक्स है:

∂R∂Γ1=∂w⊙XΓ1∂Γ1("stub")
ijI
∂R∂Γij=(wi⊙Xi)T("stub"j)
∂R∂Γij=(IwiXi)T("stub"j)
∂R∂Γij=XiTIwi("stub"j)
tl; dr आप मूल रूप से बल्लेबॉर्म स्केल कारकों द्वारा स्टब को पहले से गुणा कर रहे हैं। यह इसके बराबर होना चाहिए:
∂R∂Γ=XT("stub"⊙w)

और, वास्तव में यह है:

stub <- (-2*u %*% t(G2) * ap(b(X%*%G1)))
w <- t(matrix(gamma)) %x% matrix(rep(1, N)) * (apply(X%*%G1, 2, sd) %>% t %x% matrix(rep(1, N)))
drdG1 <- t(X) %*% (stub*w)

loop_drdG1 <- drdG1*NA
for (i in 1:7){
  for (j in 1:4){
    loop_drdG1[i,j] <- t(X[,i]) %*% diag(w[,j]) %*% (stub[,j])
  }
}

> loop_drdG1
           [,1]       [,2]       [,3]       [,4]
[1,] -61.531877  122.66157  360.08132 -51.666215
[2,]   7.047767  -14.04947  -41.24316   5.917769
[3,] 124.157678 -247.50384 -726.56422 104.250961
[4,]  44.151682  -88.01478 -258.37333  37.072659
[5,]  22.478082  -44.80924 -131.54056  18.874078
[6,]  22.098857  -44.05327 -129.32135  18.555655
[7,]  79.617345 -158.71430 -465.91653  66.851965
> drdG1
           [,1]       [,2]       [,3]       [,4]
[1,] -61.531877  122.66157  360.08132 -51.666215
[2,]   7.047767  -14.04947  -41.24316   5.917769
[3,] 124.157678 -247.50384 -726.56422 104.250961
[4,]  44.151682  -88.01478 -258.37333  37.072659
[5,]  22.478082  -44.80924 -131.54056  18.874078
[6,]  22.098857  -44.05327 -129.32135  18.555655
[7,]  79.617345 -158.71430 -465.91653  66.851965

अद्यतन ४

यहाँ, मुझे लगता है, । प्रथम∂R/∂γ

  • XΓ~≡(XΓ−μXΓ)⊙σXΓ−1
  • γ~≡γ⊗1N

पहले की तरह ही, चेन नियम आपको लूपिंग आपको जो पहले की तरह मूल रूप से स्टब को पहले से गुणा कर रहा है। इसलिए यह इसके बराबर होना चाहिए:

∂R∂γ~=∂γ~⊙XΓ~∂γ~("stub")
∂R∂γ~i=(XΓ~)iTIγ~i("stub"i)
∂R∂γ~=(XΓ~)T("stub"⊙γ~)

यह मेल खाता है:

drdg <- t(scale(X %*% G1)) %*% (stub * t(matrix(gamma)) %x% matrix(rep(1, N)))

loop_drdg <- foreach(i = 1:4, .combine = c) %do% {
  t(scale(X %*% G1)[,i]) %*% (stub[,i, drop = F] * gamma[i])  
}

> drdg
           [,1]      [,2]       [,3]       [,4]
[1,]  0.8580574 -1.125017  -4.876398  0.4611406
[2,] -4.5463304  5.960787  25.837103 -2.4433071
[3,]  2.0706860 -2.714919 -11.767849  1.1128364
[4,] -8.5641868 11.228681  48.670853 -4.6025996
> loop_drdg
[1]   0.8580574   5.9607870 -11.7678486  -4.6025996

पहले पर विकर्ण दूसरे पर वेक्टर के समान है। लेकिन वास्तव में चूंकि व्युत्पन्न एक मैट्रिक्स के संबंध में है - एक निश्चित संरचना के साथ एक के बावजूद, आउटपुट समान संरचना के साथ एक समान मैट्रिक्स होना चाहिए। क्या मुझे मैट्रिक्स एप्रोच का विकर्ण लेना चाहिए और बस इसे होना चाहिए ? मुझे यकीन नहीं है।γ

ऐसा लगता है कि मैंने अपने प्रश्न का उत्तर दिया है लेकिन मैं अनिश्चित हूं कि क्या मैं सही हूं। इस बिंदु पर मैं एक उत्तर को स्वीकार करूंगा कि कठोरता से साबित होता है (या नापसंद करता है) कि मैंने एक साथ हैक किया है।

while(not_answered){
  print("Bueller?")
  Sys.sleep(1)
}

2
मैग्नस और न्यूडकर द्वारा 3 डी "मैट्रिक्स डिफरेंशियल कैलकुलस इन एप्लीकेशंस विथ स्टैटिक्स एंड इकोनोमेट्रिक्स", सेक्शन 9 के सेक्शन 14 में मैग्नम प्रोडक्ट्स के डिफरेंशियल कवर के साथ क्रॉनिक क्रिमिनल प्रोडक्ट्स के डिफरेंसेस को शामिल किया गया है। पॉल एल। फैकलर www4.ncsu.edu/~pfackler/MatCalc.pdf द्वारा "मैट्रिक्स कैलकुलस पर नोट्स" में Kronceker उत्पादों को अलग करने पर बहुत सारी सामग्री है
— मार्क एल। स्टोन

संदर्भ के लिए धन्यवाद। मैंने पहले उन MatCalc नोटों को पाया है, लेकिन यह Hadamard को कवर नहीं करता है, और वैसे भी मुझे कभी भी निश्चित नहीं है कि क्या गैर-मैट्रिक्स कलन से कोई नियम लागू होता है या मैट्रिक्स केस पर लागू नहीं होता है। उत्पाद नियम, श्रृंखला नियम, आदि मैं पुस्तक में देखूंगा। मैं एक उत्तर को स्वीकार करता हूं जो मुझे उन सभी सामग्रियों की ओर
— इशारा करता है जिनकी

आप ऐसा क्यों कर रहे हो? क्यों नहीं कायर / TensorFlow जैसे framewroks का उपयोग करें? इन निम्न स्तर के एल्गोरिदम को लागू करने के लिए उत्पादक समय की बर्बादी है, जिसका उपयोग आप वास्तविक समस्याओं को हल करने में कर सकते हैं
— अक्सकाल

1
अधिक सटीक रूप से, मैं फिटिंग नेटवर्क हूं जो ज्ञात पैरामीट्रिक संरचना का शोषण करता है - दोनों इनपुट डेटा के रैखिक-इन-पैरामीटर मापदंडों के संदर्भ में, साथ ही अनुदैर्ध्य / पैनल संरचना। स्थापित रूपरेखाओं को इतनी भारी रूप से अनुकूलित किया जाता है कि मेरी हैकिंग / संशोधित करने की क्षमता से परे हो। साथ ही गणित आम तौर पर मददगार होता है। बहुत सारे कोडमोंकी को पता नहीं है कि वे क्या कर रहे हैं। इसी तरह Rcppइसे कुशलतापूर्वक लागू करने के लिए पर्याप्त सीखना उपयोगी है।
— जेनेरिक_युसर

1
@ MarkL.Stone न केवल यह सैद्धांतिक रूप से ध्वनि है, यह व्यावहारिक रूप से आसान है! अधिक या कम यांत्रिक प्रक्रिया! और% # $!
— जेनेरिक_युसर

जवाबों:


1

पूर्ण उत्तर नहीं है, लेकिन जो मैंने अपनी टिप्पणी में सुझाया है उसे प्रदर्शित करने के लिए यदि जहां , और एक सदिश राशि है, फिर श्रृंखला नियम कि और , हम देखते हैं कि

b(X)=(X−eNμXT)ΓΣX−1/2+eNβT
Γ=diag⁡(γ)ΣX−1/2=diag⁡(σX1−1,σX2−1,…)eN
∇βR=[−2ϵ^(Γ2T⊗I)JX(a)(I⊗eN)]T
−2ϵ^(Γ2T⊗I)=vec⁡(−2ϵ^Γ2T)TJX(a)=diag⁡(vec⁡(a′(b(XΓ1))))
∇βR=(I⊗eNT)vec⁡(a′(b(XΓ1))⊙−2ϵ^Γ2T)=eNT(a′(b(XΓ1))⊙−2ϵ^Γ2T)
पहचान । इसी प्रकार, जहां ("ठूंठ") और एकvec⁡(AXB)=(BT⊗A)vec⁡(X) डब्ल्यू=एक'(ख(एक्सΓ1))⊙-2 ε Γ टी 2
∇γR=[−2ϵ^(Γ2T⊗I)JX(a)(ΣXΓ1−1/2⊗(XΓ1−eNμXΓ1T))K]T=KTvec⁡((XΓ1−eNμXΓ1T)TWΣXΓ1−1/2)=diag⁡((XΓ1−eNμXΓ1T)TWΣXΓ1−1/2)
W=a′(b(XΓ1))⊙−2ϵ^Γ2TKNp×pबाइनरी मैट्रिक्स जो एक वर्ग मैट्रिक्स के विकर्ण तत्वों के अनुरूप क्रोनर उत्पाद के कॉलम का चयन करता है। यह इस तथ्य से निम्नानुसार है कि । पहले ढाल के विपरीत, यह अभिव्यक्ति आपके द्वारा प्राप्त की गई अभिव्यक्ति के बराबर नहीं है। यह हुए कि एक रैखिक फ़ंक्शन wrt , ग्रेडिएंट में का कारक नहीं होना चाहिए । मैं ओपी के लिए के ग्रेडिएंट को छोड़ देता हूं , लेकिन मैं निश्चित साथ व्युत्पत्ति के लिए कहूंगा कि "विस्फोट" बनाता है लेख के लेखक बचना चाहते हैं। अभ्यास में, आप भी की Jacobians खोजने की जरूरत होगी और wrtख γ मैं γ मैं Γ 1 डब्ल्यू Σ एक्स एक्सdΓi≠j=0bγiγiΓ1wΣXμXX और उत्पाद नियम का उपयोग करें।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.