10

小数点以下 4 桁までの浮動小数点数を含む入力ファイルがあります。

i.e. 13359    0.0000    0.0000    0.0001    0.0001    0.0002`    0.0003    0.0007    ... 

(最初は ID です)。私のクラスでは、 loadVectorsFromFile10000 を掛けてからint()これらの数値を掛ける方法を使用しています。さらに、各ベクトルをループして、内部に負の値がないようにします。ただし、 を実行する_hclusteringと、継続的にエラー"LinkageZが表示されますcontains negative values"

次の理由から、これはバグだと真剣に考えています。

  1. 自分の価値観を調べてみた
  2. 値は、浮動小数点数の限界に近づくのに十分小さいか、または十分大きい場所ではありません。
  3. ファイル内の値を導出するために使用した式は、絶対値を使用します (私の入力は間違いなく正しいです)。

この奇妙なエラーが表示される理由を教えてもらえますか? この負の距離誤差の原因は何ですか?

=====

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()):
4

5 に答える 5

9

これは浮動小数点の不正確さが原因で、0 ではなくベクトル間の距離が -0.000000000000000002 のようになります。scipy.clip()関数を使用して問題を修正してください。距離行列が の場合はdmatr、使用numpy.clip(dmatr,0,1,dmatr)して問題ありません。

于 2012-06-05T16:58:17.610 に答える
5

これは、fclusterdata を呼び出すときにコサイン メトリックを使用しているためだと確信しています。ユークリッドを使用してみて、エラーが解消されるかどうかを確認してください。

セット内の 2 つのベクトルのドット積が 1 より大きい場合、コサイン メトリックは負になる可能性があります。非常に大きな数を使用してそれらを正規化しているため、多くの場合、ドット積が 1 より大きいと確信しています。あなたのデータセットで。コサイン メトリックを使用する場合は、2 つのベクトルの内積が 1 を超えないようにデータを正規化する必要があります。このページの式を参照して、コサイン メトリックが Scipy で定義されているものを確認してください。

編集:

ソースコードを見ると、そのページにリストされている式は実際には Scipy が使用する式ではないと思います (ソースコードは通常の正しいコサイン距離式を使用しているように見えるため、これは良いことです)。ただし、リンケージを作成するまでには、何らかの理由で明らかにリンケージに負の値が含まれています。method='cosine' を指定して scipy.spatial.distance.pdist() を使用してベクトル間の距離を見つけ、負の値を確認してください。何もない場合は、距離値を使用してリンケージがどのように形成されるかに関係しています。

于 2010-04-07T05:18:54.663 に答える
1

「リンケージ Z には負の値が含まれています」。このエラーは、リンケージ マトリックスのリンケージ クラスタ インデックスに -1 が割り当てられている場合にも、scipy 階層クラスタリング プロセスで発生します。

私の観察によると、結合プロセス中に、結合するクラスターまたはポイントのすべてのペア間の距離がマイナス無限大になると、結合クラスターインデックスに-1が割り当てられます。そのため、リンケージ関数は、クラスター間のリンケージ距離が -infinite であってもクラスターを結合します。そして、クラスターまたはポイントの負のインデックスのいずれかを割り当てます

要約ポイントは、コサイン距離をメトリックとして使用し、データポイントのノルムまたはマグニチュードがゼロの場合、このエラーが発生することです

于 2015-06-27T14:05:33.580 に答える
0

ジャスティンの回答を改善することはできませんが、もう1つの注意点はデータ処理です​​。

int( float("0.0003") * 10000 )あなたは、データを読み取るようなことをすると言います。しかし、それを行うと32.9999999999999996. これは、浮動小数点の不正確さが乗算されるためです。

より良い、または少なくともより正確です。方法は、文字列で乗算を行うことです。つまり、文字列操作を使用して0.0003to3.0などを取得します。

おそらく、変換前に乗算を実行できる精度を失うことなくこの種のデータを読み取ることができるPythonデータ型拡張機能がどこかにあるかもしれません。私は SciPy/numerics に慣れていないのでわかりません。

編集

Justin は、Python 内に 10 進型のビルドがあるとコメントしました。そして、それは文字列を解釈し、整数で乗算し、浮動小数点数に変換できます(私はそれをテストしました)。その場合、次のようにロジックを更新することをお勧めします。

factor = 1
if inflate:
  factor = 10000
scores = map(lambda x: float(decimal.Decimal(x) * factor), l[1:])

これにより、丸めの問題が少し軽減されます。

于 2010-04-07T06:16:05.900 に答える