首页 > 解决方案 > 机器学习:R 中逻辑回归的随机梯度下降:计算 Eout 和平均时期数

问题描述

我正在尝试编写代码来解决以下问题(如加州理工学院课程学习数据中的 HW5 中所述):

在这个问题中,您将创建自己的目标函数 f(在这种情况下为概率)和数据集 D,以查看 Logistic 回归的工作原理。为简单起见,我们将 f 取为 0=1 的概率,因此 y 是 x 的确定性函数。取 d = 2 以便您可以可视化问题,并让 X = [-1; 1]×[-1; 1] 以均匀的概率选择每个 x 2 X 。选择平面中的一条线作为 f(x) = 1(其中 y 必须为 +1)和 f(x) = 0(其中 y 必须为 -1)之间的边界,方法是从X 并将穿过它们的线作为 y = ±1 之间的边界。从 X 中随机选择 N = 100 个训练点,并评估每个点 xn 的输出 yn。使用随机梯度下降运行逻辑回归以找到 g,并通过生成足够大的独立点集来估计 Eout(交叉熵误差)来评估误差。用不同的目标重复实验 100 次并取平均值。在每次运行中将 Logistic 回归的权重向量初始化为全零。当 |w(t-1) - w(t)| 时停止算法 < 0:01,其中 w(t) 表示 epoch t 结束时的权重向量。一个 epoch 是通过 N 个数据点的全通(使用 1;2;····N 的随机排列将数据点呈现给每个 epoch 内的算法,并为不同的 epoch 使用不同的排列)。使用 0.01 的学习率。在每次运行中将 Logistic 回归的权重向量初始化为全零。当 |w(t-1) - w(t)| 时停止算法 < 0:01,其中 w(t) 表示 epoch t 结束时的权重向量。一个 epoch 是通过 N 个数据点的全通(使用 1;2;····N 的随机排列将数据点呈现给每个 epoch 内的算法,并为不同的 epoch 使用不同的排列)。使用 0.01 的学习率。在每次运行中将 Logistic 回归的权重向量初始化为全零。当 |w(t-1) - w(t)| 时停止算法 < 0:01,其中 w(t) 表示 epoch t 结束时的权重向量。一个 epoch 是通过 N 个数据点的全通(使用 1;2;····N 的随机排列将数据点呈现给每个 epoch 内的算法,并为不同的 epoch 使用不同的排列)。使用 0.01 的学习率。

我需要计算 N=100 时最接近 Eout 的值,以及所需标准的平均时期数。

我编写并运行了代码,但没有得到正确的答案(如解决方案中所述,Eout 接近 0.1,epoch 数接近 350)。delta w 为 0.01 所需的 epoch 数太小(大约 10),导致误差太大(大约 2)。然后我尝试用 |w(t-1) - w(t)| 替换标准 < 0.001(而不是 0.01)。然后,平均所需的 epoch 数约为 250,样本外误差约为 0.35。

我的代码/解决方案是否有问题,或者提供的答案是否有问题?我添加了注释以表明我打算在每个步骤中执行的操作。提前致谢。

library(pracma)

h<- 0 # h will later be updated to number of required epochs

p<- 0 # p will later be updated to Eout

C <- matrix(ncol=10000, nrow=2) # Testing set, used to calculate out of sample error

d <- matrix(ncol=10000, nrow=1)

for(i in 1:10000){
  C[, i] <- c(runif(2, min = -1, max = 1)) # Sample data
  d[1, i] <- sign(C[2, i] - f(C[1, i])) 
}

for(g in 1:100){ # 100 runs of the experiment

  x <- runif(2, min = -1, max = 1)

  y <- runif(2, min = -1, max = 1)

  fit = (lm(y~x))

  t <- summary(fit)$coefficients[,1] 

  f <- function(x){   # Target function
    t[2]*x + t[1]
  }

  A <- matrix(ncol=100, nrow=2) # Sample data

  b <- matrix(ncol=100, nrow=1)

  norm_vec <- function(x) {sqrt(sum(x^2))} # vector norm calculator

  w <- c(0,0) # weights initialized to zero

  for(i in 1:100){

    A[, i] <- c(runif(2, min = -1, max = 1)) # Sample data

    b[1, i] <- sign(A[2, i] - f(A[1, i])) 
  }

  q <- matrix(nrow = 2, ncol = 1000) # q tracks the weight vector at the end of each epoch

  l= 1

  while(l < 1001){

    E <- function(z){ # cross entropy error function

      x = z[1]

      y = z[2]

      v = z[3]

      return(log(1 + exp(-v*t(w)%*%c(x, y))))
    }

    err <- function(xn1, xn2, yn){ #gradient of error function

      return(c(-yn*xn1, -yn*xn2)*(exp(-yn*t(w)*c(xn1,xn2))/(1+exp(-yn*t(w)*c(xn1,xn2)))))
    }

    e = matrix(nrow = 2, ncol = 100) # e will track the required gradient at each data point

    e[,1:100] = 0 

    perm = sample(100, 100, replace = FALSE, prob = NULL) # Random permutation of the data indices

    for(j in 1:100){ # One complete Epoch

      r = A[,perm[j]] # pick the perm[j]th entry in A

      s = b[perm[j]]  # pick the perm[j]th entry in b

      e[,perm[j]] = err(r[1], r[2], s) # Gradient of the error

      w = w - 0.01*e[,perm[j]] # update the weight vector accorng to the formula involving step size, gradient
    }

    q[,l] = w # the lth entry is the weight vector at the end of the lth epoch

    if(l > 1 & norm_vec(q[,l] - q[,l-1])<0.001){ # given criterion to terminate the algorithm

      break
    }
    l = l+1 # move to the next epoch
  }

  for(n in 1:10000){

    p[g] = mean(E(c(C[1,n], C[2, n], d[n]))) # average over 10000 data points, of the error function, in experiment no. g
  }

  h[g] = l #gth entry in the vector h, tracks the number of epochs in the gth iteration of the experiment

}

mean(h) # Mean number of epochs needed 

mean(p) # average Eout, over 100 experiments

标签: rmachine-learninglogistic-regressiongradient-descent

解决方案


推荐阅读