我无法正确区分权重的变化,因为分布在正负权重之间是不对称的;应该识别空权重,因为这意味着不使用给定的变量。
有关如何处理此事的任何想法吗?
答案 0 :(得分:5)
matplotlib中的颜色条将0到1之间的数字映射到一种颜色。要将其他数字映射到颜色,您需要首先对范围[0,1]
进行标准化。这通常是根据最小和最大数据自动完成的,或者使用相应绘图功能的vmin
和vmax
参数。在内部,规范化实例matplotlib.colors.Normalize
用于执行规范化,默认情况下,假设vmin
和vmax
之间的线性比例。
在这里你需要一个非线性比例,它(a)将中间点移动到某个指定值,(b)挤压该值周围的颜色。
现在的想法可以是matplotlib.colors.Normalize
的子类,让它返回一个满足标准(a)和(b)的映射。
选项可能是两个根函数的组合,如下所示。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
class SqueezedNorm(matplotlib.colors.Normalize):
def __init__(self, vmin=None, vmax=None, mid=0, s1=2, s2=2, clip=False):
self.vmin = vmin # minimum value
self.mid = mid # middle value
self.vmax = vmax # maximum value
self.s1=s1; self.s2=s2
f = lambda x, zero,vmax,s: np.abs((x-zero)/(vmax-zero))**(1./s)*0.5
self.g = lambda x, zero,vmin,vmax, s1,s2: f(x,zero,vmax,s1)*(x>=zero) - \
f(x,zero,vmin,s2)*(x<zero)+0.5
matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
r = self.g(value, self.mid,self.vmin,self.vmax, self.s1,self.s2)
return np.ma.masked_array(r)
fig, (ax, ax2, ax3) = plt.subplots(nrows=3,
gridspec_kw={"height_ratios":[3,2,1], "hspace":0.25})
x = np.linspace(-13,4, 110)
norm=SqueezedNorm(vmin=-13, vmax=4, mid=0, s1=1.7, s2=4)
line, = ax.plot(x, norm(x))
ax.margins(0)
ax.set_ylim(0,1)
im = ax2.imshow(np.atleast_2d(x).T, cmap="Spectral_r", norm=norm, aspect="auto")
cbar = fig.colorbar(im ,cax=ax3,ax=ax2, orientation="horizontal")
选择函数使其独立于其参数,将任何范围映射到范围[0,1]
,以便可以使用色彩映射。参数mid
确定应将哪个值映射到色彩映射的中间。在这种情况下,这将是0
。参数s1
和s2
决定了色彩图在两个方向上的挤压方式。
设置mid = np.mean(vmin, vmax), s1=1, s2=1
将恢复原始缩放。
为了选择好的参数,可以使用一些滑块来查看实时更新的图。
from matplotlib.widgets import Slider
midax = plt.axes([0.1, 0.04, 0.2, 0.03], facecolor="lightblue")
s1ax = plt.axes([0.4, 0.04, 0.2, 0.03], facecolor="lightblue")
s2ax = plt.axes([0.7, 0.04, 0.2, 0.03], facecolor="lightblue")
mid = Slider(midax, 'Midpoint', x[0], x[-1], valinit=0)
s1 = Slider(s1ax, 'S1', 0.5, 6, valinit=1.7)
s2 = Slider(s2ax, 'S2', 0.5, 6, valinit=4)
def update(val):
norm=SqueezedNorm(vmin=-13, vmax=4, mid=mid.val, s1=s1.val, s2=s2.val)
im.set_norm(norm)
cbar.update_bruteforce(im)
line.set_ydata(norm(x))
fig.canvas.draw_idle()
mid.on_changed(update)
s1.on_changed(update)
s2.on_changed(update)
fig.subplots_adjust(bottom=0.15)
答案 1 :(得分:1)
您可以使用自定义normalizer
。方便的是,文档中的示例已经是“替代中点”规范化器。这个例子是由Joe Kington制作的,所以所有的归功于他。
请参阅本页底部: https://matplotlib.org/users/colormapnorms.html
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
自定义规范化类:
class MidpointNormalize(mpl.colors.Normalize):
## class from the mpl docs:
# https://matplotlib.org/users/colormapnorms.html
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
super().__init__(vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
结果:
data = np.linspace(-5,1,100)[None,:]
fig, axs = plt.subplots(2,1, figsize=(5,2), facecolor='w', subplot_kw=dict(xticks=[], yticks=[]))
props = dict(aspect=15, cmap=plt.cm.coolwarm)
axs[0].imshow(data, **props)
axs[1].imshow(data, norm=MidpointNormalize(midpoint=0), **props)
这是一个相对简单的例子,但在类似的事情中可以实现更复杂的缩放。