Матрична форма зворотного розмноження з партійною нормалізацією


12

Нормалізація партії пояснюється значним покращенням продуктивності глибоких нейронних сіток. Багато матеріалів в Інтернеті показує, як реалізувати його на основі активації за допомогою активації. Я вже реалізував backprop, використовуючи матричну алгебру, і враховуючи, що я працюю на мовах високого рівня (покладаючись на Rcpp(а згодом і на GPU) для щільного множення матриці), видобування всього і вдавання до for-loops, ймовірно, уповільнить мій код по суті, крім того, що це великий біль.

Функція пакетної нормалізації - де

b(xp)=γ(xpμxp)σxp1+β
  • pxp - й вузол, перш ніж він активуєтьсяp
  • βγ та - скалярні параметриβ
  • σ x p x pμxp і - це середнє значення та SD з . (Зверніть увагу, що зазвичай використовується квадратний корінь дисперсії плюс коефіцієнт витіснення. Припустимо, не компактні елементи для компактності)σxpxp

У матричній формі пакетна нормалізація для цілого шару буде де

b(X)=(γ1p)(XμX)σX1+(β1p)
  • X -N×p
  • 1N - вектор стовпців
  • γ та тепер рядкові вектори параметрів нормалізації шарурβp
  • μX і - матриць, де кожен стовпець є вектором значень стовпців і стандартних відхилень N × p NσXN×pN
  • є продуктом а - продуктом елементів (Адамард)

Дуже проста одношарова нейронна сітка без пакетної нормалізації та безперервного результату -

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

де

  • Γ1 -p1×p2
  • p 2 × 1Γ2 -p2×1
  • a(.) - функція активації

Якщо втрата , то градієнти RR=N1(yy^)2

RΓ1=2VTϵ^RΓ2=XT(a(XΓ1)2ϵ^Γ2T)

де

  • V=a(XΓ1)
  • ϵ^=yy^

Під час пакетної нормалізації сітка стає або Я не маю уявлення, як обчислити похідні продуктів Hadamard і Kronecker. Що стосується продуктів Kronecker, то література стає досить затхлою. y = a ( ( γ 1 N )( X Γ 1 - μ X Γ 1 )σ - 1 X Γ 1 + ( β 1 N ) ) Γ 2

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

Чи існує практичний спосіб обчислення , , і в рамках матриці? Простий вираз, не вдаючись до обчислення вузлів за вузлом?R/γR/βR/Γ1

Оновлення 1:

Я з'ясував - на зразок. Це: Деякі код R демонструє, що це еквівалентно петельному способу зробити це. Спочатку налаштуйте підроблені дані: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

Вони відповідають. Але я все ще розгублений, бо не знаю, чому це працює. Зауваження MatCalc, на які посилається @Mark L. Stone, кажуть, що похідна повинна бутиβ1N

ABA=(InqTmp)(Invec(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

Це не відповідає. Ясно, що я не розумію цих похідних правил Kronecker. Допомога з цим була б чудовою. Я все ще повністю застряг в інших похідних, для та - вони складніші, оскільки вони не вводять додатково, як .γΓ1β1

Оновлення 2

Читаючи підручники, я цілком впевнений, що та потребують використання оператора. Але я, мабуть, не в змозі слідкувати за виведеннями достатньо, щоб можна було перевести їх у код. Наприклад, передбачає взяття похідної стосовно , де (що ми можемо розглядати як постійну матрицю на даний момент). R/Γ1R/γvec()R/Γ1wXΓ1Γ1w(γ1)σXΓ11

Мій інстинкт полягає в тому, щоб просто сказати "відповідь є ", але це, очевидно, не працює, тому що не сумісний з .wXwX

Я знаю, що

(AB)=AB+AB

і з цього , що

vec(wXΓ1)vec(Γ1)T=vec(XΓ1)Ivec(w)vec(Γ1)T+vec(w)Ivec(XΓ1)vec(Γ1)T
Але я не впевнений, як це оцінити, не кажучи вже про кодування.

Оновлення 3

Прогрес тут. Я прокинувся о 2 годині ночі з цією ідеєю. Математика не корисна для сну.

Ось , після деякого нотаційного цукру:R/Γ1

  • w(γ1)σXΓ11
  • "stub"a(b(XΓ1))2ϵ^Γ2T

Ось що ви маєте після того, як дійшли до кінця ланцюгового правила: Почніть з цього циклу - та буде підписувати стовпці, а - це сумісна матриця ідентичності:

RΓ1=wXΓ1Γ1("stub")
ijI
RΓij=(wiXi)T("stub"j)
RΓij=(IwiXi)T("stub"j)
RΓij=XiTIwi("stub"j)
tl; dr, ви в основному попередньо помножили заглушку на коефіцієнти шкали batchnorm. Це має бути еквівалентно:
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

Оновлення 4

Тут, я думаю, є . Перший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
Розділ 14 розділу 14 "Матричне диференціальне обчислення із застосуванням у статистиці та економетрії" Магнуса та Недекера, 3-е видання janmagnus.nl/misc/mdc2007-3rdedition охоплює різні продукти Kronecker та завершує вправу на диференціювання продукту Адамара. "Зауваження щодо матричного обчислення" Пола Л. Факлера www4.ncsu.edu/~pfackler/MatCalc.pdf є багато матеріалу про розмежування продуктів Kronceker
Марк Л. Стоун

Дякую за довідку. Я раніше знаходив ці нотатки MatCalc, але він не охоплює Адамара, і все одно я ніколи не впевнений, застосовується чи не застосовується до матричного випадку правило з нематричного обчислення. Правила щодо продуктів, правила ланцюжка тощо. Я перегляну книгу. Я прийняв би відповідь, яка вказує мені на всі інгредієнти, які мені потрібні для того, щоб оформити це самостійно ...
generic_user

чому ви це робите? чому б не скористатися рамками, такими як Keras / TensorFlow? Марно витрачати продуктивний час на реалізацію цих алгоритмів низького рівня, які можна використати для вирішення актуальних проблем
Аксакал,

1
Точніше, я підходить до мереж, які використовують відому параметричну структуру - як з точки зору лінійних представлень параметрів вхідних даних, так і з поздовжньої / панельної структури. Створені рамки настільки сильно оптимізовані, що виходять за рамки моїх можливостей зламати / змінювати. Плюс математика загалом корисна. Дуже багато кодемокей не мають уявлення, що вони роблять. Так само Rcppкорисне навчання, щоб ефективно його втілити.
generic_user

1
@ MarkL.Stone не тільки теоретично звучить, це практично просто! Більш-менш механічний процес! &% # $!
generic_user

Відповіді:


1

Не повна відповідь, але щоб продемонструвати те, що я запропонував у своєму коментарі, якщо де , і - вектор одиниць, то за ланцюговим правилом Зауваживши, що і , ми бачимо, що

b(X)=(XeNμXT)ΓΣX1/2+eNβT
Γ=diag(γ)ΣX1/2=diag(σX11,σX21,)eN
βR=[2ϵ^(Γ2TI)JX(a)(IeN)]T
2ϵ^(Γ2TI)=vec(2ϵ^Γ2T)TJX(a)=diag(vec(a(b(XΓ1))))
βR=(IeNT)vec(a(b(XΓ1))2ϵ^Γ2T)=eNT(a(b(XΓ1))2ϵ^Γ2T)
через ідентичність . Аналогічно where ("заглушка") і -vec(AXB)=(BTA)vec(X) W='(Ь(ХГ1))-2 & epsi ; Г Т 2
γR=[2ϵ^(Γ2TI)JX(a)(ΣXΓ11/2(XΓ1eNμXΓ1T))K]T=KTvec((XΓ1eNμXΓ1T)TWΣXΓ11/2)=diag((XΓ1eNμXΓ1T)TWΣXΓ11/2)
W=a(b(XΓ1))2ϵ^Γ2TN p × p d Γ i j = 0 b γ i γ i Γ 1 w Σ X μ X XKNp×pдвійкова матриця, яка вибирає стовпці продукту Kronecker, відповідні діагональним елементам квадратної матриці. Це випливає з того, що . На відміну від першого градієнта, цей вираз не еквівалентний виведеному вами виразом. Враховуючи, що є лінійною функцією wrt , в градієнті не повинно бути коефіцієнта . Я залишаю градієнт до ОП, але скажу, що для деривації з фіксованим створюється "вибух", який письменники статті прагнуть уникнути. На практиці вам також знадобиться знайти та wrtdΓij=0bγiγiΓ1wΣXμXX і використовувати правило про товар.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.