I've plotted a scatter with custom colormap's normalization. Scatter appears right. After that, I've added a colorbar and I want the colors on this colorbar will be same as on the scatter. There is my code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
class SigmoidNormalize(mpl.colors.Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
if vcenter is None:
self.vcenter = (vmax+vmin) / 2
self.vcenter = vcenter
super().__init__(vmin, vmax, clip)
def __call__(self, value, clip=None):
threshold = self.vcenter
value = (value - threshold) * 10
norm = 1 / (1+np.exp(-value))
return norm
def inverse(self, value):
threshold = self.vcenter
nonzero = np.logical_and(value != 0, value != 1)
norm = np.empty_like(value)
norm[nonzero] = -np.log(1/value[nonzero] - 1)
norm[nonzero] = norm[nonzero] / 10 + threshold
norm[value==0] = self.vmin
norm[value==1] = self.vmax
return norm
class SigmoidNormalize_r(SigmoidNormalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
super().__init__(vmin, vmax, vcenter, clip)
def __call__(self, value, clip=None):
return super().inverse(value)
def inverse(self, value):
return super().__call__(value)
def plot_predictions(predictions,
actual,
threshold=0.5,
threshold_gap=0.1):
fig = plt.figure()
ax = fig.add_subplot()
normals = np.where(np.logical_and(actual == 0, predictions < threshold))[0]
abnormals = np.where(np.logical_and(actual == 1, predictions >= threshold))[0]
normals_wrong = np.where(np.logical_and(actual == 0, predictions > threshold))[0]
abnormals_wrong = np.where(np.logical_and(actual == 1, predictions <= threshold))[0]
cmap = mpl.cm.rainbow
norm = SigmoidNormalize(vmin=0, vmax=1, vcenter=threshold-threshold_gap)
norm_r = SigmoidNormalize_r(vmin=0, vmax=1, vcenter=threshold-threshold_gap)
# Artist's zorder is just a scalar and cannot be applied to
# each point in scatter, so we need to draw right and wrong
# predictions separately, to place wrong predictions on the top
# and make it's visibility more clean.
ax.scatter(predictions[normals], normals,
c=predictions[normals],
norm=norm,
cmap=cmap)
ax.scatter(predictions[abnormals], abnormals,
c=1-predictions[abnormals],
norm=norm,
cmap=cmap)
ax.scatter(predictions[normals_wrong], normals_wrong,
c=predictions[normals_wrong],
norm=norm,
cmap=cmap)
ax.scatter(predictions[abnormals_wrong], abnormals_wrong,
c=1-predictions[abnormals_wrong],
norm=norm,
cmap=cmap)
ax.axvline(threshold, color='red', linestyle='--', linewidth=1)
ax.set_xlim((0, 1))
fig.colorbar(mpl.cm.ScalarMappable(norm=norm_r, cmap=cmap), ax=ax,
orientation='horizontal')
if __name__ == '__main__':
predictions1 = np.abs(np.random.normal(0, 0.25, 1000))
predictions2 = 1-np.abs(np.random.normal(0, 0.25, 1000))
actual1 = np.full_like(predictions1, 0)
actual2 = np.full_like(predictions2, 1)
predictions = np.concatenate((predictions1, predictions2))
actual = np.concatenate((actual1, actual2))
gen = np.random.Generator(np.random.MT19937())
con = np.array([predictions, actual])
gen.shuffle(con, axis=1)
predictions, actual = con
plot_predictions(predictions, actual)
There is what I've got:
The greater the difference between predictions and actuals, the closer the color is to red. On the plot we can see that at the center of the graph the points are orange, while on the colorbar they are green. We need to adjust the colorbar so that it also has orange in the middle and red on the right side. The labels should be uniform, but if this is not possible, just remove them.
There is what I want:
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742294357a4416814.html
评论列表(0条)