python - 如何为k最近邻分类创建置信度估计的颜色图

标签 python algorithm numpy matplotlib

我想要的:
将我的简单分类算法(见下文)的结果显示为python中的color map(数据在2d中),在python中,每个类都被分配了一种颜色,2d地图上任何地方的预测可信度与与与类预测相关联的颜色的饱和度成正比。下面的图片说明了我对二进制(两类问题)的要求,其中红色部分可能表示对类1有很强的信心,而蓝色部分表示类2。中间的颜色暗示了两者的不确定性。显然,我希望颜色方案推广到多个类,因此我需要很多颜色,然后比例将从白色(不确定性)到与类关联的非常丰富的颜色。
illustration http://www.nicolacarlon.it/out.png
一些示例代码:
我的示例代码只是使用了一个简单的knn算法,其中最近的k个数据点被允许在地图上的一个新点的类上“投票”。预测的置信度简单地由得奖班级的相对频率给出,而得奖班级的相对频率则是投票的k。我还没有处理过关系,我知道这个方法有更好的概率版本,但我只想可视化我的数据,让观众看到一个类在二维平面的特定部分的机会。

import numpy as np
import matplotlib.pyplot as plt


# Generate some training data from three classes
n = 100 # Number of covariates (sample points) for each class in training set. 
mean1, mean2, mean3 = [-1.5,0], [1.5, 0], [0,1.5]
cov1, cov2, cov3 = [[1,0],[0,1]], [[1,0],[0,1]], [[1,0],[0,1]]
X1 = np.asarray(np.random.multivariate_normal(mean1,cov1,n))
X2 = np.asarray(np.random.multivariate_normal(mean2,cov2,n))
X3 = np.asarray(np.random.multivariate_normal(mean3,cov3,n))


plt.plot(X1[:,0], X1[:,1], 'ro', X2[:,0], X2[:,1], 'bo', X3[:,0], X3[:,1], 'go' )

plt.axis('equal'); plt.show() #Display training data


# Prepare the data set as a 3n*3 array where each row is a data point and its associated class
D = np.zeros((3*n,3))
D[0:n,0:2] = X1; D[0:n,2] = 1
D[n:2*n,0:2] = X2; D[n:2*n,2] = 2
D[2*n:3*n,0:2] = X3; D[2*n:3*n,2] = 3

def kNN(x, D, k=3):
    x = np.asarray(x)
    dist = np.linalg.norm(x-D[:,0:2], axis=1)
    i = dist.argsort()[:k] #Return k indices of smallest to highest entries
    counts = np.bincount(D[i,2].astype(int))
    predicted_class = np.argmax(counts) 
    confidence = float(np.max(counts))/k
    return predicted_class, confidence 

print(kNN([-2,0], D, 20))

最佳答案

因此,可以为二维平面中的每个点计算两个数字
置信度(0(一)
类(整数)
一种可能是计算自己的RGB图,并用imshow显示它这样地:

import numpy as np
import matplotlib.pyplot as plt

# color vector with N x 3 colors, where N is the maximum number of classes and the colors are in RGB
mycolors = np.array([
  [ 0, 0, 1],
  [ 0, 1, 0],
  [ 1, 0, 1],
  [ 1, 1, 0],
  [ 0, 1, 1],
  [ 0, 0, 0],
  [ 0, .5, 1]])

# negate the colors
mycolors = 1 - mycolors 

# extents of the area
x0 = -2
x1 = 2
y0 = -2
y1 = 2

# grid over the area
X, Y = np.meshgrid(np.linspace(x0, x1, 1000), np.linspace(y0, y1, 1000))

# calculate the classification and probabilities
classes = classify_func(X, Y)
probabilities = prob_func(X, Y)

# create the basic color map by the class
img = mycolors[classes]

# fade the color by the probability (black for zero prob)
img *= probabilities[:,:,None]

# reverse the negative image back
img = 1 - img

# draw it
plt.imshow(img, extent=[x0,x1,y0,y1], origin='lower')
plt.axis('equal')

# save it
plt.savefig("mymap.png")

制造负颜色的诀窍就是让数学更容易理解。当然,代码可以写得更密集。
我创建了两个非常简单的函数来模拟分类和概率:
def classify_func(X, Y):
    return np.round(abs(X+Y)).astype('int')

def prob_func(X,Y):
    return 1 - 2*abs(abs(X+Y)-classify_func(X,Y))

前者给出0到4之间的给定区域整数值,后者给出平滑变化的概率。
结果是:
如果你不喜欢颜色向零概率衰减的方式,你可能总是会创建一些非线性,这是与概率相乘时应用的。
这里给函数classify_funcprob_func两个数组作为参数,第一个数组是要计算值的X坐标,第二个数组是Y坐标如果底层计算完全矢量化,那么这很好。对于有问题的代码,情况并非如此,因为它只计算单个值。
在这种情况下,代码会稍微更改:
x = np.linspace(x0, x1, 1000)
y = np.linspace(y0, y1, 1000)
classes = np.empty((len(y), len(x)), dtype='int')
probabilities = np.empty((len(y), len(x)))
for yi, yv in enumerate(y):
    for xi, xv in enumerate(x):
    classes[yi, xi], probabilities[yi, xi] = kNN((xv, yv), D)

另外,由于您的置信度估计值不是0..1,因此需要对它们进行缩放:
probabilities -= np.amin(probabilities)
probabilities /= np.amax(probabilities)

完成此操作后,您的地图应如下所示,范围为-4,-4..4,4(根据颜色映射:绿色=1,洋红=2,黄色=3):
向量化或不向量化-这是个问题
这个问题不时出现。在web上有很多关于矢量化的信息,但是作为一个快速搜索没有显示任何简短的摘要,我将在这里给出一些想法。这是一个很主观的问题,所以一切都只是代表我的拙见。其他人可能有不同的意见。
有三个因素需要考虑:
性能
易读性
内存使用
通常(但并不总是)矢量化会使代码更快、更难理解,并消耗更多内存内存使用通常不是一个大问题,但对于大型阵列,这是需要考虑的问题(数百兆通常是可以的,千兆字节是麻烦的)。
撇开一些琐碎的例子不谈(元素级的简单操作,简单的矩阵操作),我的方法是:
编写不带矢量化的代码并检查它是否有效
剖析代码
如果需要和可能,对内部循环进行矢量化(1D矢量化)
如果简单,则创建二维矢量化
例如,逐像素图像处理操作可能导致这样的情况,即我最终(针对每一行)进行一维矢量化。然后内部循环(对于每个像素)很快,而外部循环(对于每一行)并不重要。如果代码不试图与所有可能的输入维度一起使用,那么代码看起来可能要简单得多。
我是一个糟糕的算法学家,在更复杂的情况下,我喜欢验证我的矢量代码与非矢量版本因此,我几乎总是先创建非矢量化代码,然后再对其进行优化。
有时矢量化不能提供任何性能优势。例如,handy函数numpy.vectorize可用于对几乎任何函数进行矢量化,但其文档说明:
提供矢量化功能主要是为了方便,而不是为了性能实现本质上是一个for循环。
(这个函数也可以在上面的代码中使用。为了便于不太熟悉numpy的人阅读,我选择了循环版本)
矢量化只有在底层矢量化函数更快的情况下才能提供更高的性能。它们有时是,有时不是。只有分析和经验才能说明问题。此外,并不总是需要将所有内容矢量化您可能有一个图像处理算法,它既有矢量化操作,也有逐像素操作。这里numpy.vectorize非常有用。
我会尝试将上面的knn搜索算法矢量化到至少一个维度。这里没有条件代码(它不会是一个show stopper,但它会使事情复杂化),而且算法相当直截了当。内存消耗会增加,但一维矢量化并不重要。
你可能会注意到,n维的推广并不复杂如果内存允许,那么就这样做。

关于python - 如何为k最近邻分类创建置信度估计的颜色图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24434485/

相关文章:

algorithm - 邻接表中的大 O - 删除顶点并删除边缘(对图执行各种操作的时间复杂度成本)

python - Linux 中的全局文本插入符位置

python - Numpy:使用矩阵切片体积

php - 为此使用什么算法?

c++ - 关于我在 C++ 中的排序算法的问题

python - 使用 StandardScaler 使用特定功能缩放具有不同形状的数组

python - 我在梯度下降中遇到问题,它给我的 thetas 没有

python - 为 pygame 混音器设置输出设备

python - 将 BeautifulSoup 用于 2 因素身份验证背后的页面

python - 无法对我的数据应用 scipy.signal lfilter