如何防止NAN问题?

时间:2017-03-29 18:01:17

标签: python numpy k-means

我收到Mean of empty slice运行时警告。 当我打印出我的变量(numpy数组)时,有几个 其中包含nan个值。运行时警告正在查看行 58作为问题。我可以改变什么才能使它发挥作用?

有时程序会运行没有问题。大部分时间都是如此 不。

这是一种从头开始的K-Means算法聚类 虹膜数据集。它首先提示用户的数量 他们想要的质心(簇)。然后它随机生成说 给定范围内的集群数量与已加载的集合中的数量相同 在文本文件中。

我在else语句中有break值以防止无限 循环。

是因为当我减去数字时,我的数字会低于零 来自文件中数据点的质心?

我跑的时候出错:

How Many Centrouds? 3
Dimensionality of Data:  (150, 4)
Starting Centroiuds:
 [[ 1.4  7.9  0.2  3.4]
 [ 7.8  0.2  4.3  1.4]
 [ 5.7  6.9  3.   6.6]]
t0 :
 [[[-3.7  4.4 -1.2  3.2]
  [ 2.7 -3.3  2.9  1.2]
  [ 0.6  3.4  1.6  6.4]]

 [[-3.5  4.9 -1.2  3.2]
  [ 2.9 -2.8  2.9  1.2]
  [ 0.8  3.9  1.6  6.4]]

 [[-3.3  4.7 -1.1  3.2]
  [ 3.1 -3.   3.   1.2]
  [ 1.   3.7  1.7  6.4]]

 ..., 
 [[-5.1  4.9 -5.   1.4]
  [ 1.3 -2.8 -0.9 -0.6]
  [-0.8  3.9 -2.2  4.6]]

 [[-4.8  4.5 -5.2  1.1]
  [ 1.6 -3.2 -1.1 -0.9]
  [-0.5  3.5 -2.4  4.3]]

 [[-4.5  4.9 -4.9  1.6]
  [ 1.9 -2.8 -0.8 -0.4]
  [-0.2  3.9 -2.1  4.8]]]

Warning (from warnings module):
  File "C:\Python27\lib\site-packages\numpy\core\_methods.py", line 59
    warnings.warn("Mean of empty slice.", RuntimeWarning)
RuntimeWarning: Mean of empty slice.

Warning (from warnings module):
  File "C:\Python27\lib\site-packages\numpy\core\_methods.py", line 68
    ret, rcount, out=ret, casting='unsafe', subok=False)
RuntimeWarning: invalid value encountered in true_divide
---------------
Starting Centroids:

[[ 1.4  7.9  0.2  3.4]
 [ 7.8  0.2  4.3  1.4]
 [ 5.7  6.9  3.   6.6]]


Starting NewMeans:

[[        nan         nan         nan         nan]
 [ 5.84333333  3.054       3.75866667  1.19866667]
 [        nan         nan         nan         nan]]
Starting Centroids Now:

[[        nan         nan         nan         nan]
 [ 5.84333333  3.054       3.75866667  1.19866667]
 [        nan         nan         nan         nan]]


NewMeans now:
[[        nan         nan         nan         nan]
 [ 5.84333333  3.054       3.75866667  1.19866667]
 [        nan         nan         nan         nan]]

Python代码:

import numpy as np
from pprint import pprint
import random
import sys
import warnings

arglist = sys.argv 

#UNCOMMENT BELOW IN FINAL PROGRAM
'''
NoOfCentroids = int(arglist[2])
dataPointsFromFile = np.array(np.loadtxt(sys.argv[1], delimiter = ','))
'''

dataPointsFromFile = np.array(np.loadtxt('iris.txt', delimiter = ','))

NoOfCentroids = input('How Many Centrouds? ')

dataRange = ([])

#UNCOMMENT BELOW IN FINAL PROGRAM
'''
with open(arglist[1]) as f:
    print 'Points in data set: ',sum(1 for _ in f)
'''
dataRange.append(round(np.amin(dataPointsFromFile),1))
dataRange.append(round(np.amax(dataPointsFromFile),1))
dataRange = np.asarray(dataRange)

dataPoints = np.array(dataPointsFromFile)
print 'Dimensionality of Data: ', dataPoints.shape

randomCentroids = []
data = ([])
templist = []
i = 0

while i<NoOfCentroids:
    for j in range(len(dataPointsFromFile[1,:])):
        cat = round(random.uniform(np.amin(dataPointsFromFile),np.amax(dataPointsFromFile)),1)
        templist.append(cat)
    randomCentroids.append(templist)
    templist = []
    i = i+1

centroids = np.asarray(randomCentroids)

def kMeans(array1, array2):
    ConvergenceCounter = 1
    keepGoing = True
    StartingCentroids = np.copy(centroids)
    print 'Starting Centroiuds:\n {}'.format(StartingCentroids)
    while keepGoing:      
        #--------------Find The new means---------#
        t0 = StartingCentroids[None, :, :] - dataPoints[:, None, :]
        print 't0 :\n {}'.format(t0)
        t1 = np.linalg.norm(t0, axis=-1)
        t2 = np.argmin(t1, axis=-1)
        #------Push the new means to a new array for comparison---------#
        CentroidMeans = []
        for x in range(len(StartingCentroids)):
            CentroidMeans.append(np.mean(dataPoints[t2 == [x]], axis=0))
        #--------Convert to a numpy array--------#
        NewMeans = np.asarray(CentroidMeans)
        #------Compare the New Means with the Starting Means------#
        if np.array_equal(NewMeans,StartingCentroids):
            print ('Convergence has been reached after {} moves'.format(ConvergenceCounter))
            print ('Starting Centroids:\n{}'.format(centroids))
            print ('Final Means:\n{}'.format(NewMeans))
            print ('Final Cluster assignments: {}'.format(t2))
            for x in xrange(len(StartingCentroids)):
                print ('Cluster {}:\n'.format(x)), dataPoints[t2 == [x]]
            for x in xrange(len(StartingCentroids)):
                print ('Size of Cluster {}:'.format(x)), len(dataPoints[t2 == [x]])
            keepGoing = False
        else:
            print 15*'-'
            ConvergenceCounter  = ConvergenceCounter +1
            print 'Starting Centroids:\n'
            print StartingCentroids
            print '\n'
            print 'Starting NewMeans:\n'
            print NewMeans
            StartingCentroids =np.copy(NewMeans)
            print 'Starting Centroids Now:\n'
            print StartingCentroids
            print '\n'
            print 'NewMeans now:'
            print NewMeans
            break


kMeans(centroids, dataPoints)

1 个答案:

答案 0 :(得分:0)

我认为警告出现在

np.mean(dataPoints[t2 == [x]], axis=0)

如果t2 == [x]全部为假(t2x之间不匹配),则dataPoints[...]将为空数组,从而产生mean警告。

我认为你需要对这个测试更加小心。如果蒙版数组为空,甚至可以跳过mean

具有浮动值的

==测试是不可预测的。您需要使用类似np.isclosenp.allclose的内容来测试容差的等效性。

第二个警告来自mean计算的后期,大概是在尝试除以0时,元素的数量。

可以在mean中找到完整的numpy.core._methods.py代码。

总而言之,请勿尝试获取空数组的mean