que tienen un archivo de entrada que contiene números de punto flotante a cabo el 4 decimales:Scipy Negative Distance? ¿Qué?
i.e. 13359 0.0000 0.0000 0.0001 0.0001 0.0002` 0.0003 0.0007 ...
(el primero es el id). Mi clase usa el método loadVectorsFromFile
que lo multiplica por 10000 y luego int()
estos números. Además de eso, también recorro cada vector para asegurarme de que no haya valores negativos en el interior. Sin embargo, cuando realizo _hclustering
, continuamente veo el error, "Linkage
Z contains negative values"
.
serio que esto es un error, porque:
- Revisé mis valores,
- los valores son en ninguna parte lo suficientemente pequeño o lo suficientemente grande como para acercarse a los límites de los números de punto flotante y
- la fórmula que usé para derivar los valores en el archivo usa valor absoluto (mi entrada es DEFINITIVAMENTE correcta).
¿Alguien me puede aclarar por qué estoy viendo este raro error? ¿Qué está pasando que está causando este error de distancia negativa?
=====
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()):
que tenía este problema en Scipy - valores negativos inesperados. El problema (para mí) era que no sabía que las funciones trigonométricas en Scipy esperan valores en radianes por defecto. – doug