Excel R 中带有 1 个参数的求解器
Excel Solver in R with 1 parameter
我想在数据集中找到用于 ELO 计算的最佳 K 参数。
我的例子:
#load SciViews for ln function
library("SciViews")
ELO1 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000,
1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1475.898, 1500.000, 1475.000, 1486.617, 1512.516)
ELO2 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1499.550, 1500.450, 1499.550, 1512.950, 1487.050, 1512.950, 1524.102, 1500.000)
dataset <- data.frame("ELO1" = ELO1, "ELO2" = ELO2)
#Lets set if the Player1 was the winner:
dataset$HomeWinner <- c(1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0)
根据 ELO,玩家 1 的获胜概率计算如下:
dataset$P1ExpWin <- 1/(1 + 10^((dataset$ELO2 - dataset$ELO1)/400))
dataset$P2ExpWin <- 1 - dataset$P1ExpWin
日志错误计算方式如下:
dataset$LogError <- dataset$HomeWinner * ln(dataset$P1ExpWin) + (1-dataset$HomeWinner) * ln(1-dataset$P1ExpWin)
K 参数设置 ELO 变化率,可以在 4 到 32 之间变化。让我们将其设置为 20:
Kparameter = 20
并且 ELO 变化是根据结果以这种方式计算的:
for (row in 1:nrow(dataset)) {
if (dataset[row,"HomeWinner"] == 1) {
dataset$NewELO1[row] <- dataset$ELO1 + Kparameter * (1 - dataset$P1ExpWin)
dataset$NewELO2[row] <- dataset$ELO2 - Kparameter * dataset$P2ExpWin
}
else{
dataset$NewELO1[row] <- dataset$ELO1[row] - Kparameter * dataset$P1ExpWin
dataset$NewELO2[row] <- dataset$ELO2[row] + Kparameter * (1 - dataset$P2ExpWin)
}
}
最后,log loss 计算为每个 LogError 的总和除以计数:
LogLossELO = sum(dataset$LogError) * -1/nrow(dataset)
我的问题是如何使用 Kparameter 的 optim 或优化函数来找到最小的 LogLossELO(类似于 Excel 中的 Solver)?
我已经更改了一些没有意义的公式,但这可能是也可能不是您想要的。请查看此内容并在必要时进行更正。请注意,SciViews 中的 ln
与基础 R 中的 log
相同,因此我们也替换了它。 for
循环可以矢量化,但我们将其保留为循环以便于与问题中的代码进行比较。
ELO1 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000,
1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1475.898, 1500.000, 1475.000, 1486.617, 1512.516)
ELO2 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1499.550, 1500.450, 1499.550, 1512.950, 1487.050, 1512.950, 1524.102, 1500.000)
HomeWinner <- c(1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0)
n <- length(HomeWinner)
lloss <- function(K) {
P1ExpWin <- 1/(1 + 10^((ELO2 - ELO1)/400))
P2ExpWin <- 1 - P1ExpWin
for (r in 1:n) {
if (HomeWinner[r] == 1) {
ELO1[r] <- ELO1[r] + K * (1 - P1ExpWin[r])
ELO2[r] <- ELO2[r] - K * P2ExpWin[r]
}
else{
ELO1[r] <- ELO1[r] - K * P1ExpWin[r]
ELO2[r] <- ELO2[r] + K * (1 - P2ExpWin[r])
}
}
P1ExpWin <- 1/(1 + 10^((ELO2 - ELO1)/400))
P2ExpWin <- 1 - P1ExpWin
LogError <- HomeWinner * log(P1ExpWin) + (1-HomeWinner) * log(P1ExpWin)
-mean(LogError) # LogLossELO
}
rng <- c(0, 100)
opt <- optimize(lloss, rng); opt
## $minimum
## [1] 76.05614
##
## $objective
## [1] 0.6833352
下面我们绘制结果。
curve(Vectorize(lloss)(K), rng[1], rng[2], xname = "K", ylab = "LogLossELO")
with(opt, abline(h = objective, v = minimum))
我想在数据集中找到用于 ELO 计算的最佳 K 参数。 我的例子:
#load SciViews for ln function
library("SciViews")
ELO1 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000,
1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1475.898, 1500.000, 1475.000, 1486.617, 1512.516)
ELO2 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1499.550, 1500.450, 1499.550, 1512.950, 1487.050, 1512.950, 1524.102, 1500.000)
dataset <- data.frame("ELO1" = ELO1, "ELO2" = ELO2)
#Lets set if the Player1 was the winner:
dataset$HomeWinner <- c(1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0)
根据 ELO,玩家 1 的获胜概率计算如下:
dataset$P1ExpWin <- 1/(1 + 10^((dataset$ELO2 - dataset$ELO1)/400))
dataset$P2ExpWin <- 1 - dataset$P1ExpWin
日志错误计算方式如下:
dataset$LogError <- dataset$HomeWinner * ln(dataset$P1ExpWin) + (1-dataset$HomeWinner) * ln(1-dataset$P1ExpWin)
K 参数设置 ELO 变化率,可以在 4 到 32 之间变化。让我们将其设置为 20:
Kparameter = 20
并且 ELO 变化是根据结果以这种方式计算的:
for (row in 1:nrow(dataset)) {
if (dataset[row,"HomeWinner"] == 1) {
dataset$NewELO1[row] <- dataset$ELO1 + Kparameter * (1 - dataset$P1ExpWin)
dataset$NewELO2[row] <- dataset$ELO2 - Kparameter * dataset$P2ExpWin
}
else{
dataset$NewELO1[row] <- dataset$ELO1[row] - Kparameter * dataset$P1ExpWin
dataset$NewELO2[row] <- dataset$ELO2[row] + Kparameter * (1 - dataset$P2ExpWin)
}
}
最后,log loss 计算为每个 LogError 的总和除以计数:
LogLossELO = sum(dataset$LogError) * -1/nrow(dataset)
我的问题是如何使用 Kparameter 的 optim 或优化函数来找到最小的 LogLossELO(类似于 Excel 中的 Solver)?
我已经更改了一些没有意义的公式,但这可能是也可能不是您想要的。请查看此内容并在必要时进行更正。请注意,SciViews 中的 ln
与基础 R 中的 log
相同,因此我们也替换了它。 for
循环可以矢量化,但我们将其保留为循环以便于与问题中的代码进行比较。
ELO1 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000,
1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1475.898, 1500.000, 1475.000, 1486.617, 1512.516)
ELO2 <- c(1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1500.000, 1512.500, 1487.500, 1512.500, 1487.500, 1487.500, 1512.500, 1499.550, 1500.450, 1499.550, 1512.950, 1487.050, 1512.950, 1524.102, 1500.000)
HomeWinner <- c(1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0)
n <- length(HomeWinner)
lloss <- function(K) {
P1ExpWin <- 1/(1 + 10^((ELO2 - ELO1)/400))
P2ExpWin <- 1 - P1ExpWin
for (r in 1:n) {
if (HomeWinner[r] == 1) {
ELO1[r] <- ELO1[r] + K * (1 - P1ExpWin[r])
ELO2[r] <- ELO2[r] - K * P2ExpWin[r]
}
else{
ELO1[r] <- ELO1[r] - K * P1ExpWin[r]
ELO2[r] <- ELO2[r] + K * (1 - P2ExpWin[r])
}
}
P1ExpWin <- 1/(1 + 10^((ELO2 - ELO1)/400))
P2ExpWin <- 1 - P1ExpWin
LogError <- HomeWinner * log(P1ExpWin) + (1-HomeWinner) * log(P1ExpWin)
-mean(LogError) # LogLossELO
}
rng <- c(0, 100)
opt <- optimize(lloss, rng); opt
## $minimum
## [1] 76.05614
##
## $objective
## [1] 0.6833352
下面我们绘制结果。
curve(Vectorize(lloss)(K), rng[1], rng[2], xname = "K", ylab = "LogLossELO")
with(opt, abline(h = objective, v = minimum))