Scipy负距离?什么?

dis*_*dng 7 python scipy

我有一个输入文件,其中包含4位小数点的浮点数:

i.e. 13359    0.0000    0.0000    0.0001    0.0001    0.0002`    0.0003    0.0007    ... 
Run Code Online (Sandbox Code Playgroud)

(第一个是id).我的类使用的loadVectorsFromFile方法是将它乘以10000然后再乘以int()这些数字.最重要的是,我还遍历每个向量以确保内部没有负值.但是,当我表演时_hclustering,我不断看到错误,"LinkageZ contains negative values".

我认真地认为这是一个错误,因为:

  1. 我检查了我的价值观,
  2. 这些值不足够小或大到足以接近浮点数的极限
  3. 我用来导出文件中的值的公式使用绝对值(我的输入是DEFINITELY右).

有人能够告诉我为什么我会看到这个奇怪的错误吗?这是怎么回事造成这种负距离错误?

=====

def loadVectorsFromFile(self, limit, loc, assertAllPositive=True, inflate=True):
    """Inflate to prevent "negative" distance, we use 4 decimal points, so *10000
    """
    vectors = {}
    self.winfo("Each vector is set to have %d limit in length" % limit)
    with open( loc ) as inf:
        for line in filter(None, inf.read().split('\n')):
            l = line.split('\t')
            if limit:
                scores = map(float, l[1:limit+1])
            else:
                scores = map(float, l[1:])

            if inflate:        
                vectors[ l[0]] = map( lambda x: int(x*10000), scores)     #int might save space
            else:
                vectors[ l[0]] = scores                           

    if assertAllPositive:
        #Assert that it has no negative value
        for dirID, l in vectors.iteritems():
            if reduce(operator.or_, map( lambda x: x < 0, l)):
                self.werror( "Vector %s has negative values!" % dirID)
    return vectors

def main( self, inputDir, outputDir, limit=0,
        inFname="data.vectors.all", mappingFname='all.id.features.group.intermediate'):
    """
    Loads vector from a file and start clustering
    INPUT
        vectors is { featureID: tfidfVector (list), }
    """
    IDFeatureDic = loadIdFeatureGroupDicFromIntermediate( pjoin(self.configDir, mappingFname))
    if not os.path.exists(outputDir):
        os.makedirs(outputDir)

    vectors = self.loadVectorsFromFile( limit, pjoin( inputDir, inFname))
    for threshold in map( lambda x:float(x)/30, range(20,30)):
        clusters = self._hclustering(threshold, vectors)
        if clusters:
            outputLoc = pjoin(outputDir, "threshold.%s.result" % str(threshold))
            with open(outputLoc, 'w') as outf:
                for clusterNo, cluster in clusters.iteritems():
                    outf.write('%s\n' % str(clusterNo))
                    for featureID in cluster:
                        feature, group = IDFeatureDic[featureID]
                        outline = "%s\t%s\n" % (feature, group)
                        outf.write(outline.encode('utf-8'))
                    outf.write("\n")
        else:
            continue

def _hclustering(self, threshold, vectors):
    """function which you should call to vary the threshold
    vectors:    { featureID:    [ tfidf scores, tfidf score, .. ]
    """
    clusters = defaultdict(list)
    if len(vectors) > 1:
        try:
            results = hierarchy.fclusterdata( vectors.values(), threshold, metric='cosine')
        except ValueError, e:
            self.werror("_hclustering: %s" % str(e))
            return False

        for i, featureID in enumerate( vectors.keys()):
Run Code Online (Sandbox Code Playgroud)

dka*_*kar 7

这是因为浮点不准确,因此矢量之间的某些距离而不是0,例如-0.000000000000000002.使用scipy.clip()功能来纠正问题.如果您的距离矩阵是dmatr,使用numpy.clip(dmatr,0,1,dmatr),你应该没问题.


Jus*_*eel 5

我很确定这是因为你在调用fclusterdata时使用了余弦指标.尝试使用欧几里德,看看错误是否消失.

如果集合中两个向量的点积大于1,则余弦度量可能为负.由于您使用的是非常大的数字并将它们标准化,我很确定点积在很多时候都大于1在您的数据集中.如果要使用余弦指标,则需要对数据进行标准化,使得两个向量的点积不会大于1.请参阅此页面上的公式,以查看在Scipy中定义的余弦指标.

编辑:

好吧,从查看源代码我认为该页面上列出的公式实际上并不是Scipy使用的公式(这很好,因为源代码看起来像是使用正常和正确的余弦距离公式).然而,当它产生联系时,无论出于何种原因,联系中显然存在一些负面价值.尝试使用scipy.spatial.distance.pdist()和method ='cosine'找到矢量之间的距离,并检查负值.如果没有,那么它与如何使用距离值形成连接有关.