Algorithm 序列平滑

Algorithm 序列平滑,algorithm,Algorithm,我认为应该有一个算法来解决这个问题——可能是在生物信息学这样的领域(这个问题让我想起了一点序列比对),所以我希望有人能在这里帮助我 问题如下:假设我将一些数据分为两个不同的类X和Y。其结果可能如下:…XXX Y XXX。。进一步假设我们对这些类有一些领域知识,并且知道一行中的实例不可能少于一定数量(即序列中不可能少于4个Xs或Ys-最好每个类使用不同的阈值,但这不是必须的)。因此,如果我们使用这个领域知识,它是“显而易见”的,我们想用X.替换中间的单个Y。 因此,算法应该获取一系列分类实例和类的

我认为应该有一个算法来解决这个问题——可能是在生物信息学这样的领域(这个问题让我想起了一点序列比对),所以我希望有人能在这里帮助我

问题如下:假设我将一些数据分为两个不同的类X和Y。其结果可能如下:…XXX Y XXX。。进一步假设我们对这些类有一些领域知识,并且知道一行中的实例不可能少于一定数量(即序列中不可能少于4个Xs或Ys-最好每个类使用不同的阈值,但这不是必须的)。因此,如果我们使用这个领域知识,它是“显而易见”的,我们想用X.

替换中间的单个Y。 因此,算法应该获取一系列分类实例和类的阈值(如果简化了问题,则为所有类设置一个阈值),并尝试找到满足该属性的序列(没有比给定阈值短的类序列)。显然,可能存在大量正确的解决方案(例如,在上面的示例中,我们也可以用Y替换所有X),因此我认为一个合理的优化标准是最小化替换的数量


这里我不需要特别有效的算法,因为实例的数量非常少(比如<4k),而且我们只有两个类。此外,由于这显然只是一个启发式问题,如果它们极大地简化了算法,我对一些不准确的地方没有意见。

与此非常相似的问题可以作为经典的动态规划最短路径问题来解决。我们希望找到使成本概念最小化的序列。惩罚序列中与原始序列中相应字符不同的每个字符。惩罚序列中字符的每一个变化,因此惩罚从X到Y的每一个变化,反之亦然

这并不完全是您想要的,因为YYYXYYY的惩罚与yxxxxy的惩罚相同-一个是YX,一个是XY-但是这可能是一个很好的近似值,因为例如,如果基序列表示YYY…YXY…YY,那么将中心X更改为Y将比支付XY和YX的成本更便宜-并且您可以很明显,为了得到一些看似合理的东西,需要调整不同的成本惩罚

现在把序列中的每个位置想象成两个点,一个在另一个上面,一个点代表“X到这里”,另一个点代表“Y到这里”。根据原始序列中对应的字符是X还是Y,以及该线是将X与X还是将X与Y连接,依此类推,可以将点与成本行链接。然后使用动态程序计算出从左到右的最短路径,该程序计算出在位置i+1处终止于X和Y的最佳路径,已知在位置i处终止于X和Y的最佳路径的成本


如果您真的想对短期更改的惩罚比长期更改更严厉,您可能可以通过增加路径查找表示中的点数来做到这一点-您的点数对应于“这里的X,最近的Y是3个字符之前”。但是,根据您对惩罚的要求,您可能会在每个字符处得到大量的点数。

您可以使用动态编程,如下面的伪代码草图所示(为简单起见,此代码假定阈值为一行3个X或Y,而不是4个):

上述代码基本上计算了创建平滑序列的最低成本,直至第i个字符,该序列存储了一行中所有相关数量的连续X或Y(一行中的1、2或3)的最佳值。更正式

  • opt[i][0][k]
    存储最小的 转换字符串的成本
    s[0…k]
    进入平滑序列,然后以
    i
    连续的Xs。运行3次或以上 在
    opt[3][0][k]
    中核算
  • opt[0][j][k]
    存储最小的 转换字符串的成本
    s[0…k]
    进入平滑序列,然后以
    j
    连续的Y。运行3次或以上 在
    opt[0][3][k]
    中核算
将其转换为返回序列和最佳成本的算法非常简单


请注意,上述代码中的某些情况可能是不必要的,这只是从约束中派生出来的简单重复。

将腐蚀运算符与自定义过滤器内核一起使用。@ypnos我已经阅读了一些关于腐蚀的简短解释(此处)[我不知道该如何在这里应用它。特别是因为如果外部类是足够大的块的一部分,我不想去掉它们。例如yyy XXXXX(假设两者的阈值均为4)不应该改变。也许我误解了你-你能详细说明一下吗?侵蚀和膨胀是同时发生的。看看打开操作。你可能会想以更定制的方式应用这些。听起来像是维特比算法的工作,维特比算法是一种根据马尔可夫模型推断最可能输入的动态规划方法。目前的两个答案可能都是这样描述的;我没有仔细阅读它们来说明。这是一个有趣的想法。所以我对序列比对问题的思考是正确的——听起来有点(好的,有点)类似。我真的应该更多地研究动态规划——实现动态规划听起来是一个很好的方法。因为目前我的阈值足够小,这应该与一些有用的成本函数和附加点一起很好地工作。这不是完美的,但简单的解决方案意味着检查所有排列好吧,我已经试着理解了代码,但我仍然不完全确定代码是如何工作的,所以对我来说绝对不简单;)
min_switch(s):
  n = len(s)
  optx = array(4, n, infinity) // initialize all values to infinity
  opty = array(4, n, infinity) // initialize all values to infinity
  if s[0] == 'X':
    optx[1][0] = 0
    opty[1][0] = 1
  else:
    optx[1][0] = 1
    opty[1][0] = 0
  for i in {1, n - 1}:
    x = s[i]
    if x == 'X':
      optx[1][i] = opty[3][i - 1]
      optx[2][i] = optx[1][i - 1]
      optx[3][i] = min(optx[2][i - 1], optx[3][i - 1])
      opty[1][i] = 1 + min(optx[1][i - 1], optx[2][i - 1], optx[3][i - 1])
      opty[2][i] = 1 + opty[1][i - 1]
      opty[3][i] = 1 + min(opty[2][i - 1], opty[3][i - 1])
    else:
      optx[1][i] = 1 + min(opty[1][i - 1], opty[2][i - 1], opty[3][i - 1])
      optx[2][i] = 1 + opty[1][i - 1]
      optx[3][i] = 1 + min(opty[2][i - 1], opty[3][i - 1])
      opty[1][i] = optx[3][i - 1]
      opty[2][i] = opty[1][i - 1]
      opty[3][i] = min(opty[2][i - 1], opty[3][i - 1])
  return min(optx[3][n - 1], opty[3][n - 1])