我需要解决一个问题,即需要比较具有相同列数的两个矩阵。其中一个被操纵,直到获得最佳匹配。我对两个矩阵之间的差异进行评分的方式非常复杂,我仍然需要最终确定它。我现在真正感兴趣的是找到一个仅使用正整数的搜索/优化算法。我创建了一个简单的示例,其中包含一个最大化的简单函数。假设我有一个数据集D.
D <- data.frame(rbind(c(1,1,1),
c(1,1,0),c(1,1,0),c(1,1,0),c(1,0,0),
c(0,0,0),c(1,0,0),c(1,0,0),c(1,1,0),
c(1,0,0),c(1,1,1),c(1,1,0),c(1,0,0),
c(1,0,0),c(1,0,1)))
我想找到Dx的哪个重新排列给我最低的绝对差异。
Dx<-data.frame(rbind(c(1,1,0),c(1,0,0),c(0,0,0),c(1,1,0)))
所以我可以使用下面的函数来完成所有可能的排列
library(combinat)
SPACE <- t(as.data.frame(list(permn(1:3))))
f <- function(x){
if(anyDuplicated(x)>0){return(0)}
Dist<-NA
for (i in 1:nrow(D)){
Dist[i]<-sum(abs(Dx[,x]-t(D[i,])))}
return(sum(Dist))}
apply(SPACE,1,f)
并得到正确的结果。然而,这对我实际使用的数据有两个缺点:
apply
会检查每个可能的排列并计算我的错误分数。 随着矩阵中列数的增加,A和B都变得难以计算。我认为即使在一个R会话中保留数字1到14的所有可能排列在大多数计算机上也是不可能的。
我发现的优化算法是网格搜索。这开始解决A.这意味着我不必指定SPACE(即所有可能的permuatation),所以它是正确方向的一步,因为我想查看更大的数据集。
library(NMOF)
gridSearch(f, rep(list(seq(1,ncol(D))),ncol(D)))
但显然这并没有解决B,因为它经历了每次可能的迭代。如果我的数据集非常大,假设有15个甚至更多的列,该怎么办?
请记住我的参数只能是正整数(即它们是列号),是否有一个R算法可以让我在合理的量内找到最佳的列顺序(或至少是一个很好的近似值)时间(例如1-2天),当我处理更大的数据集时?这可能看起来像一个愚蠢的例子,但它很好地模仿了我试图解决的问题。我已经optim()
与method="SANN"
一起尝试过,但无处可去。不幸的是,我的经验很少,如果您认为这是一个不可行的问题,请告诉我。只是从一个更容易的数据集(几行但很多列)问题开始,您是否认为通过使用某种聪明的优化可以找到如上所示的D2的最佳列顺序?
#D2
D<-cbind(D,D,D,D,D)
ncol(D)
Dx<-cbind(Dx,Dx,Dx,Dx,Dx)
#examples
f(c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
f(c(13,2,4,3,5,6,7,8,9,10,11,12,1,14,15))
编辑: 我的主要兴趣是理解如何使用在搜索过程中使用一系列独特正积分(基本上是排名)的优化算法,而不是解决这个特定问题。我在这种情况下使用了一个简单的例子,因此它很容易复制,但我比较的两个数据集的行数和其他方面往往不同,我在这里没有详细说明......距离函数I' m building很好地处理这个问题,因此理解如何使用D2将优化算法(例如下面建议的遗传算法)用于上面的函数f是我目前的主要问题。
答案 0 :(得分:3)
如果您的目标函数f
必须真正被视为黑盒子,那么我们需要采用近似方法,例如遗传算法。以下是使用gaoptim
包的解决方案,该解决方案在f(p)
列的所有排列p
中最大化Dx
:
library(gaoptim)
myGA = GAPerm(f, ncol(Dx), popSize=10)
myGA$evolve(10)
myGA
# Results for 10 Generations:
# Mean Fitness:
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 95.0 107.4 115.6 112.4 118.3 120.6
#
# Best Fitness:
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 125 125 125 125 125 125
#
# Best individual:
# [1] 3 1 2
#
# Best fitness value:
# [1] 125
在这种情况下,它找到了最好的解决方案,目标值为125,但通常不保证遗传算法将返回的解决方案的质量。
答案 1 :(得分:2)
据我了解,您正在搜索从一组候选列到一组目标列的最佳分配,并且将候选列与目标列匹配会产生一些成本。您正在搜索最小化总体成本的一对一匹配。
这称为赋值问题,这是运筹学中的经典问题。您的网格搜索方法将具有指数运行时(您需要搜索所有可能的分配),但有更有效的方法来解决此问题,其中许多方法依赖于线性编程。
您可以使用lp.assign
包中的lpSolve
函数在R中解决您的问题,提供矩阵列之间的成对距离:
# Build cost matrix
costs <- as.matrix(dist(t(D), method="manhattan"))
costs
# X1 X2 X3
# X1 0 7 11
# X2 7 0 6
# X3 11 6 0
# Solve assignment problem
library(lpSolve)
solution <- lp.assign(costs)$solution
apply(solution > 0.999, 2, which)
# [1] 1 2 3
这意味着我们选择排列1,2,3作为最有希望的。