Python 确定字符串位置的算法?

Python 确定字符串位置的算法?,python,string,algorithm,Python,String,Algorithm,我有两组字符串-每组大约5000个字符串-(更具体地说,序列仅由ACTG组成),它们根据一些其他数据分为两组。每个字符串的长度都是相等的,效率并不重要。给定一个特定的序列,我希望能够确定该字符串将属于哪个类别*。我应该使用什么算法来实现这一点 *仅基于组中以前的数据 一个小例子: 第1组:AATTGG 第2组:ATCCGC 然后,如果我有字符串CCGTCC,它将转到第2组,因为第2组的序列中有更多的C,而第1组更喜欢A、T和G的双倍。这个问题还没有确定。没有好的答案。但你还是被要求这么做。那是真

我有两组字符串-每组大约5000个字符串-(更具体地说,序列仅由ACTG组成),它们根据一些其他数据分为两组。每个字符串的长度都是相等的,效率并不重要。给定一个特定的序列,我希望能够确定该字符串将属于哪个类别*。我应该使用什么算法来实现这一点

*仅基于组中以前的数据

一个小例子:

第1组:AATTGG
第2组:ATCCGC


然后,如果我有字符串CCGTCC,它将转到第2组,因为第2组的序列中有更多的C,而第1组更喜欢A、T和G的双倍。这个问题还没有确定。没有好的答案。但你还是被要求这么做。那是真实的生活

所以你有一个选择。学习很多关于机器学习的知识。那会让你做一些聪明的事情。或者做最愚蠢的事情,然后看看你是否喜欢结果

根据对您问题的描述,我建议采用以下方法。从当前数据中构造“预测器”,预测下一个角色应该出现。就拿那些预测结果最好的人来说吧

那么什么样的预测因素呢?我建议使用拉普拉斯平滑(添加一个看不见的答案)。这很容易实现,在实践中,它可以很好地处理DNA数据。然后你可以做一些事情,比如0克(只是字母频率),1克(基于前一个字母),2克(前两个字母)和3克

对于每个预测值,以及每个可以预测的字母,您可以构建该预测值给出该字母的可能性的日志。添加日志,最后一个可能性最大的日志就是赢家。(添加日志在数学上等同于乘以概率,但避免超出浮点范围。)

您的示例太小,无法显示该技术的真正威力。没有足够的数据来训练1克、2克和3克。(对于1克,没有XY序列出现两次,因此,由于拉普拉斯平滑,在任何观察到的X之后,所有答案被认为是同等可能的。对于2克和3克,用XY和XYZ替换X。)

然而,0-gram将给A、G和T组1 2/7的可能性,但只给C组1/7的可能性(第7个字符是
C
的假观察值,它实际上没有出现在字符串中-这是拉普拉斯平滑)。对于测试字符串,这将给出
2*log(2/7)+4*log(1/7)=-10.289166533212
。相比之下,第2组A、G和T的可能性为1/6,而C的可能性为1/2。这使得
2*log(1/6)+4*log(1/2)=-6.3561076069589
因为第2组的预测因子做得更好,所以将其分配给第2组

请注意,这项技术得到了您希望应用的推理的预期结果。第2组有更多的Cs,因此将包含大量Cs的新字符串分配给第2组。如果你有更多的数据,并且你所描述的模式继续保持不变,第一组会得到A,G和T的两倍

还请注意,给定大量字符串,此技术将采用可由单个字母频率和短跑频率描述的模式。但它不会学习可能存在的其他类型的模式。例如,如果第一组和第二组的起始字符是一个非常强的信号,你不会注意到。其他技术也可以

以下是此技术的代码:

import math
n_limit = 4

def make_predictor (strings):
    freq_dict = {}
    for string in strings:
        for i in range(len(string)):
            for j in range(n_limit): # 0..3
                if j <= i:
                    substr = string[i-j:i]
                    if substr not in freq_dict:
                        freq_dict[substr] = {}
                    freq = freq_dict[substr]
                    char = string[i]
                    if char not in freq:
                        freq[char] = 1.0
                    else:
                        freq[char] = freq[char] + 1.0

    # Smoothing and precalculation of logs.
    predict_dict = {}
    for substr, freq in freq_dict.iteritems():
        for char in 'ACGT':
            if char not in freq:
                freq[char] = 1.0
        total = sum(freq.values())
        predict = {}
        for char, f in freq.iteritems():
            predict[char] = math.log(f / total)
        predict_dict[substr] = predict

    return predict_dict

def run_predictor (predict_dict, string):
    answer = 0.0
    empty_predict = math.log(0.25) # 4 values, equally likely.
    for i in range(len(string)):
        for j in range(n_limit):
            if j <= i:
                substr = string[i-j:i]
                if substr not in predict_dict:
                    answer = answer + empty_predict
                else:
                    answer = answer + predict_dict[substr][string[i]]
    return answer

def classify (p1, p2, string):
    if run_predictor(p1, string) < run_predictor(p2, string):
        return 2
    else:
        return 1

predictor1 = make_predictor(['AATTGG'])
predictor2 = make_predictor(['ATCCGC'])

print(classify(predictor1, predictor2, 'CCGTCC'))
导入数学
n_极限=4
def make_预测器(字符串):
freq_dict={}
对于字符串中的字符串:
对于范围内的i(len(string)):
对于范围内的j(n#U限制):#0..3

如果j提出的问题过于模糊,无法回答。(虽然这可能是相关的::)举一些例子怎么样?听起来你在寻找一个机器学习分类问题。但我无法从所写的内容中分辨出来。我尝试使用感知器,但我甚至不确定如何对数据进行排序。因为字符串->数字是我被卡住的地方。如何根据字符串计算数字?你不需要数字,你需要一个数字向量,它可以是a=0,C=1,t=2和G=3@JerryQian我添加了代码,澄清了我的解释,解释了它的缺点,并就如何测试这种技术是否能够很好地处理您的数据提供了建议。谢谢!我只是想知道你是在哪里发现这个算法的?我认为了解更多的算法将是有益的(不仅仅是在这个领域)。@JerryQian老实说,他已经知道ngrams,并且认为你对这个问题的想法听起来很合适。我提醒自己它们是如何工作的,并说,“这应该足够好。”n_限制有什么作用?很抱歉问了这么多问题(另外,p1和p2可以是我所有序列的列表,对吗?