为自定义词汇表创建N-gram模型

时间:2018-12-12 20:58:48

标签: python nlp nltk prediction n-gram

我想创建一个N-Gram模型,该模型不适用于“英语单词”。我有一个如下的自定义词汇表:

  

vocabs = [[0.364,0.227,0.376],[0.875,0.785,0.376],........]

我要说的是,vocabs列表中的每个元素都需要被N-Gram模型视为一个“单词”。而且我的训练数据集将包含一些与词汇表完全相同的数字,如下所示:

  

training_data = [[0.344,0.219,0.374],[0.846,0.776,0.376],........]

注意:在该示例中,我想表明,训练的“单词”(列表由3个数字组成)与我词汇表中的“单词”并不完全相同,但它们将非常相似。关闭。

现在,我的问题是,我可以建立一个可以使用训练数据进行训练的N-Gram模型吗?然后,使用该模型预测新“单词”出现的可能性。

我正在使用python,并且可以使用“ nltk ”库找到很多N-Gram示例。但是问题是在大多数情况下使用“英语单词”。因为我对N-Grams不太熟悉,所以这些例子使我感到困惑。如果任何人都可以回答我的问题和/或指出一些教程来学习N语法(不专门针对NLP),我将感到非常高兴。

谢谢。

编辑:

为简化问题,我将尝试以不同的方式进行解释: 我的词汇如下:

  

vocabs = [v1,v2,v3,........ vn]

我也有两个序列发生器(SG)。他们两个都从我的词汇中产生了一系列单词。

我的目标是根据流数据进行预测:当前哪个生成器正在生成序列(字)。

现在,我想使用标记的训练数据(我已经从SG获得了一些标记数据)构建两个N-gram模型(每个SG一个)。最后,当我将流数据输入模型中并通过比较N-gram模型的预测来选择可能的SG时。只是要弄清楚,如果SG1的N-gram模型比SG2的N-gram模型具有更高的概率,我将决定当前的流数据是由SG1生成的。

希望说明有助于理解我的关注。我非常感谢您为回答这个问题所做的努力。

注意:如果您知道其他可以很好解决此问题的模型(比N-gram模型更好),请提及它们。

谢谢。

2 个答案:

答案 0 :(得分:1)

好的,我不确定您要确切地做什么。但是我们还是尝试一下。

首先,N-gram的工作方式: N-gram是序列概率的非常简单的预测因子。由于句子只是单词序列,而单词只是字符序列,因此通常适用于字符串:

问题:您有一个字母列表,想找出序列中的下一个字母。

letterSequence = ['a', 'b', None] 

如果序列中有一堆字母,您可以记下这些序列是什么:

training_data = ['a', 'b', 'c',
             'a', 'b', 'c',
             'a', 'b', 'd',
             'a', 'b', 'f',
             'b', 'c', 'd']

乍看之下,您会发现具有序列'a','b','c'的概率是具有'a','b','d'或'a的概率的两倍。 ','b','f'。 我们要做的是计算同一序列出现在training_data中的次数,然后选择出现频率更高的一个。

def makeNestedDict(aDict, listOfKeys):
    if len(listOfKeys) == 0: 
        if aDict != {}: return aDict
        return 0
    if listOfKeys[0] not in aDict:
        aDict[listOfKeys[0]] = {}
    aDict[listOfKeys[0]] = makeNestedDict(aDict[listOfKeys[0]], listOfKeys[1:])
    return aDict

def makeCoreferenceDict(ressource):
    #we'll use 3-grams but we could have chosen any n for n-grams
    ngramDict = {}
    index = 0
    #we make sure we won't go further than the length of the list
    while (index+2) < len(ressource):
        k1 = ressource[index]
        k2 = ressource[index+1]
        k3 = ressource[index+2]
        ngramDict = makeNestedDict(ngramDict, [k1, k2, k3])            
        ngramDict[k1][k2][k3] += 1 #counting
        index += 1
    return ngramDict

def predict(unkSequence, ngramDict):
    import operator
    corefDict = ngramDict[unkSequence[0]][unkSequence[1]]
    return max(corefDict.items(), key=operator.itemgetter(1))

############################################
ngramDict = makeCoreferenceDict(training_data)
#the most common letter that follows 'a', 'b' is... 
predict(letterSequence, ngramDict)
>>> ('c', 2) #... is 'c' and it appears twice in the data

您也可以通过替换行(在makeCoreferenceDict函数中)来获得预测得分,而不是获得最常用的元素:

ngramDict[k1][k2][k3] += 1 #counting

具有:

ngramDict[k1][k2][k3] += 1.0/float(len(ressource)) #add to the score

如此:

def showScore(unkSequence, ngramDict):
    return ngramDict[unkSequence[0]][unkSequence[1]]

############################################
ngramDict = makeCoreferenceDict(training_data)
#the most common letter that follows 'a', 'b' is... 
showScore(letterSequence, ngramDict)
>>> {'c': 0.13333333333333333, 'd': 0.06666666666666667, 'f': 0.06666666666666667}

现在,n-gram方法依赖于一组有限的元素(字符,单词,自然数等)。现在,在您的示例中,“ vocabs”和“ training_data”几乎没有任何共同点。而且我认为您真正需要的是获得单词之间的距离分数。我猜是因为您所说的:

  

在这个示例中,我想表明,训练的“单词”(3个数字的列表)与我词汇表中的“单词”并不完全相同,但是它们非常接近。

在这种情况下,它有点太复杂,无法在此处显示,但是您可能需要测量

之间的距离

“ vocabs”中每个元素的每个数量

“ training_data”中每个序列中每个元素的每个数量

然后比较它们并选择较小的分数。

如果这不是您的问题的答案,请重新制定或提供更多示例。 无论如何,祝你好运。

答案 1 :(得分:1)

在这种情况下,您肯定可以使用n-gram。

首先,请确保我了解:

您有一个词汇表:

  

vocabs = [v0,v1,v2,v3,........ vn]

和2个序列生成器,它们从您的vocab中提取元素并返回vocab序列列表:

  

sg1 = [v0,v1,v2,v1,v3]   sg2 = [v2,v4,v6,v2,v8]

现在,如果我理解正确,您想使用n-gram来人工复制和扩充sg1和sg2输出:

  

ngramSg1 = [v0,v1,v3,v0,v1,v2,v1,v2,...]   ngramSg2 = [v2,v4,v6,v2,v8,v2,v6,v2,...]

然后,您要使用ML模型来确定n-gram输出(SG1或SG2)的来源是什么。我对吗?我在盘旋吗?

如果就像我描述的那样,那么您应该能够使用我在上一个答案中编写的代码或所需的任何n-gram库。没什么,如果我理解正确的话,您的词汇表是由数字列表而不是单个对象组成的。如果真是这样,那么您可能会找不到任何可以处理该问题的库。太具体了。您可能必须编写自己的基于n元语法的序列生成器版本。

但是,您的案例看起来有点像单词嵌入(基本上是使用向量作为单词表示形式的语言处理算法)。如果您还不了解它们,则可能需要查看gensim的word2vecdoc2vecfastText并采用它们或对其进行改编。