why_n-1_gradient_explanation
#library(ggplot2) #library(ggpmisc) rm(list=ls()) # rnorm 펑션을 변형한 펑션으로 # mean값과 sd값을 같는 n개의 샘플원소를 # 구한다. (샘플의 평균과 표준편차가 # 정확히 원하는 값이 되도록 함) rnorm2 <- function(n,mean,sd){ mean+sd*scale(rnorm(n)) } # set.seed(191) nx <- 1000 mx <- 50 sdx <- mx * 0.1 sdx # 5 x <- rnorm2(nx, mx, sdx) # x <- rnorm2(1000, 50, 5) 와 동일 mean(x) sd(x) length(x) hist(x) x.span <- seq(from = mean(x)-3*sd(x), to = mean(x)+3*sd(x), by = .1) residuals <- function(x, v) { return(x - v) } # sum of square residual 값을 # 구하는 펑션 ssr <- function(x, v) { residuals <- (x - v) return(sum(residuals^2)) } # mean square residual 값을 # 구하는 펑션 (mean square # residual = variance) msr <- function(x, v) { residuals <- (x - v) # return((sum(residuals^2))/(length(x)-1)) return((mean(residuals^2))) } ssrs <- c() # sum of square residuals msrs <- c() # mean square residuals = variance vs <- c() # the value of v in (x - v) x.span # x.span의 값들을 v값으로 삼아 # sum(x-x.span)^2 처럼 구하면 # SS값을 구한 것이 된다. # 우리가 배운 SS값은 x.span의 # 값으로 샘플의 평균을 사용했을 때의 # residual 값이다. # x.span은 샘플의 평균을 중심으로 # 여러가지 값을 사용하는 것을 # 가정한다. for (i in x.span) { res.x <- residuals(x,i) # srs.x <- sum(res.x) ssr.x <- ssr(x,i) msr.x <- msr(x,i) # srs <- append(srs, srs.x) ssrs <- append(ssrs, ssr.x) msrs <- append(msrs, msr.x) vs <- append(vs, i) } # 아래 plot은 SS값들이나 (두번째는) # MS값들을 v값이 변화함에 따라서 # (x.span의 범위에 따라서 변화) # 어떻게 변화하는지 구한 것 plot(ssrs) plot(msrs) # 아래는 위에서 계산한 msr 값들을 저장한 # msrs값들 중에서 최소값이 되는 것을 찾은 # 것. 우리는 이것이 샘플의 평균임을 안다. min(msrs) # 최소값일 때의 위치 (msrs에서 몇번째인지) min.pos.msrs <- which(msrs == min(msrs)) min.pos.msrs # 그 위치에 해당하는 (그 때 사용된) v값 print(vs[min.pos.msrs])
다시 설명하면 위의 코드는 [sum(x-mean(x)^2 / n]을 (= ms값 혹은 분산값임) 구하는 식에 mean(x)대신에 다양한 x값을 넣어 본 것이다. 그리고, 이 때 ms값 중에서 최소값이 되는 지점을 찾아서 이 때 사용된 v값을 (mean(x)대신에 사용된) 알아 본것이다. 이 v값이 mean(x)이 되는 것을 확인하여 mean(x)값으로 빼서 구한 SS값이 가장 작은 ms값을 (혹은 SS값을) 갖는다는 것을 보여준다.
위 방법의 단점은 x.span의 값을 길게 나열하여 한번씩 넣어서 msr값을 구하여 최소값을 보는데 리소스를 너무 사용한다는 것이다.
아래는 그 단점을 극복하는 방법이다.
# the above no gradient gradient <- function(x, v){ residuals = x - v # y = (sum(x-v)^2)/n 혹은 (mean(x-v)^2) # 의 식이 ms값을 구하는 식인데 # 이를 v에 대해서 미분하면 chain rule을 써야 한다 # 자세한 것은 http://commres.net/wiki/estimated_standard_deviation # 문서 중에 미분 부분 참조 # dy/dv = 2(x-v)*-1 chain rule # dy/dv = -2(x-v) dx = -2 * mean(residuals) # return(list("ds" = dx)) return(dx) } # function returns ds value
residuals <- function(x, v) { return(x - v) } ssr <- function(x, v) { residuals <- (x - v) return(sum(residuals^2)) } msr <- function(x, v) { residuals <- (x - v) return((sum(residuals^2))/(length(x)-1)) # return(mean(residuals^2)) } # pick one random v in (x-v) v <- rnorm(1) # Train the model with scaled features learning.rate = 1e-1 grads <- c() ssrs <- c() msrs <- c() mres <- c() vs <- c() steps <- c() # Record Loss for each epoch: zx <- (x-mean(x))/sd(x) nlen <- 75 for (epoch in 1:nlen) { residual <- residuals(zx, v) ssr.x <- ssr(zx, v) msr.x <- msr(zx, v) ssrs <- append(ssrs, ssr.x) msrs <- append(msrs, msr.x) grad <- gradient(zx, v) grads <- append(grads, grad) step.v <- grad * learning.rate steps <- append(steps, step.v) v <- v - step.v vs <- append(vs, v) } tail(grads) tail(msrs) tail(ssrs) tail(vs) plot(msrs) plot(ssrs) plot(vs) plot(grads) # scaled v # zx <- (x-mean(x))/sd(x) # v.표준화 <- (v.원래 - mean(x))/sd(x) v.orig <- (v*sd(x))+mean(x) v.orig steps vs.orig <- (vs*sd(x))+mean(x) vs.orig grads
why_n-1_gradient_explanation.txt · Last modified: 2025/09/04 13:04 by hkimscil