r - 机器学习: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
解决方案
推荐阅读
- typescript - 在推断泛型类型时避免扩大
- r - 列表中的向量 - 如何从其中一个向量中提取元素
- css - 为什么在笔记本电脑和移动设备上显示相同元素的颜色不同
- c++ - 多态 C++:基指针的字段不使用派生类构造函数给出的值
- azure - 在 Kusto 中使用 union 组合 2 个结果集
- typescript - 我的 if 语句无法识别 string.indexOf(letter) == -1
- c# - 如何在所有测试类之间共享一个夹具?
- node.js - 我如何以编程方式使用 tor
- javascript - 有没有办法将原始 Sequelize 查询的字段转换为驼峰式?
- html - css 背景 url 中不会显示本地图像路径