记录一下热力图颜色映射建立的技巧

使用场景:我的需求,当我需要查看某个区间的值,并进行显著的标注,又不影响其他区域渐变的颜色。

导入一些库

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

绘制一个heatmap

以查看torch的dropout层对矩阵的效果为例

import torch
import torch.nn as nn
m = nn.Dropout(p=0.2)
input = torch.randn(8, 8)
output = m(input)
#我们获得了input,其值分布在0-1的[10,10]的矩阵
#output矩阵,有0.2的值被置为了0
# 绘制热力图
fig,(ax1, ax2) = plt.subplots(ncols=2,figsize=(10, 4))
sns.heatmap(input, annot=True, cmap="YlGnBu", ax=ax1)
# 设置标题和坐标轴标签
ax1.set_title("8x8 Matrix Heatmap")
ax1.set_xlabel("Column")
ax1.set_ylabel("Row")
sns.heatmap(output, annot=True, cmap="YlGnBu", ax=ax2)
ax2.set_title("8x8 Matrix Heatmap")
ax2.set_xlabel("Column")
ax2.set_ylabel("Row")
# 显示图像
# 调整子图之间的spacing
plt.subplots_adjust(wspace=0.4)
plt.show()
  • cmap:matplotlib的colormap名称或颜色对象;如果没有提供,默认为cubehelix map (数据集为连续数据集时) 或 RdBu_r (数据集为离散数据集时)

我们并不能很好的查看到0点的颜色。

image-20240611195114097

查看colormap

cmap = sns.color_palette("YlGnBu", as_cmap=True)

查看一下这个配色的colorbar

image-20240611195207151

#设置超过,低于的颜色
custom_cmap.set_over('r', 1.0)
#如果数据包含了无效值(如NaN或inf)
# 设置无效值颜色为灰色
cmap.set_bad(color='gray')

image-20240611195446010

有了显示这个特定的值的第一个方案,将我们希望标注的值设置为无效值,这损失了信息,但是可以起到可视化的效果。

#使用numpy实现
data = np.random.rand(5, 5)
# 定义条件
condition = (data > 0.5) & (data < 0.8)
# 应用条件得到布尔掩码数组
mask = np.where(condition)
data[mask] = np.nan
#torch
import torch
# 创建示例张量
data = torch.rand(5, 5)
# 定义条件
condition = (data > 0.5) & (data < 0.8)
# 使用掩码索引和赋值
data[condition] = float('nan')
#torch检查nan
#torch.isnan()
#tensor和numpy的转换
import torch
import numpy
A = X.numpy()
B = torch.tensor(A)

总体的解决方案1:

import torch
import torch.nn as nn
m = nn.Dropout(p=0.2)
input = torch.randn(8, 8)
output = m(input)
condition = (output > -0.0001) & (output < 0.0001)
output[condition] = float('nan')
# 获取颜色映射对象
custome_cmap = sns.color_palette("YlGnBu", as_cmap=True)
# 设置无效值颜色为红色,对于没有自带的nan的数据
custome_cmap.set_bad(color='red',alpha=1.0)

# 绘制热力图
fig,(ax1, ax2) = plt.subplots(ncols=2,figsize=(10, 4))

sns.heatmap(input, annot=True, cmap=custome_cmap, ax=ax1)
# 设置标题和坐标轴标签
ax1.set_title("8x8 Matrix Heatmap")
ax1.set_xlabel("Column")
ax1.set_ylabel("Row")

sns.heatmap(output, annot=True, cmap=custome_cmap, ax=ax2)
ax2.set_title("8x8 Matrix Heatmap")
ax2.set_xlabel("Column")
ax2.set_ylabel("Row")
# 显示图像
# 调整子图之间的spacing
plt.subplots_adjust(wspace=0.4)
plt.show()

image-20240611201455832

如何自定义color_map?

cmap是什么数据类型?

分开的色块

cmap = plt.cm.get_cmap('YlGnBu')
custome_cmap = sns.color_palette("YlGnBu", as_cmap=True)
type(cmap)
#matplotlib.colors.LinearSegmentedColormap

没什么有效信息

生成一个分割色块

colors = ['blue', 'green', 'yellow', 'red']
bounds = [0, 25, 50, 75, 100]
cmap = ListedColormap(colors)
cmap

image-20240611202324820

cmap.N:

一个整数,表示颜色映射(cmap)中包含的颜色数量。

cmap.colors:

对应的颜色

#这些颜色是一个一行多列的数组(列数取决于色彩的编码方式)
['blue', 'green', 'yellow', 'red']
norm = BoundaryNorm(bounds, cmap.N)

BoundaryNormmatplotlib中的一个类,用于根据给定的边界值(bounds)将数值映射到离散的颜色索引。它会将数值划分到不同的区间,并将每个区间映射到颜色映射中的一种颜色。

将这个norm对象与你的颜色映射cmap一起使用。在绘制条形图、热力图或其他可视化时。这样,不同的数值范围就会被映射到不同的颜色,使得可视化结果更加清晰和直观。

渐变色块

cmap = plt.cm.plasma  # 你可以使用其他渐变色,如 plt.cm.plasma, plt.cm.inferno, plt.cm.magma

数据的类型有所改变

matplotlib.colors.ListedColormap

对这个进行属性的plt.cm.plasma

cmap.colors

是一个[256,3]的数组

#等效
len(cmap.colors)
cmap.N
#256

渐变色和之前的分割差不多,只是使用的颜色更多、

生成一个渐变色块

colors = ["blue", "green", "yellow"]
#颜色的数量,按照区分的数量划分,没有bounds这个分割的界了
n_bins = 100  
#名字,可以随意设置
cmap_name = 'custom_cmap'
cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N=n_bins)

image-20240611205039949

#渐变色块的另一个声明方法
cmap_custom = LinearSegmentedColormap.from_list(
    "custom_cmap",
    [(0.0, "blue"), (0.40, "cyan"), (0.5, "green"), (0.60, "yellow"), (1.0, "red")],
    N=256
)

取一个颜色

对连续颜色块的取色

cmap是一个颜色的映射,相当于一个指示,我们真正把数值变到对应的颜色,需要使用norm。

norm是Normalize,百分比值

colors = ["blue", "green", "yellow"]
#颜色的数量,按照区分的数量划分,没有bounds这个分割的界了
n_bins = 100  
#名字,可以随意设置
cmap_name = 'custom_cmap'
cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N=n_bins)

#进行均匀的分割
norm = Normalize(vmin=0, vmax=100)
value = 50
normalized_value = norm(value) #0.5,百分比值
color_at_50 = cmap(normalized_value)
# 打印颜色值
print(f"The color at value {value} is: {color_at_50}")
fig, ax = plt.subplots(figsize=(6, 1))
# 使用矩形填充显示颜色
rect = plt.Rectangle((0, 0), 1, 1, fc=color_at_50)
ax.add_patch(rect)

# 移除坐标轴和边框
ax.set_xticks([])
ax.set_yticks([])
ax.set_frame_on(False)
plt.show()

对分段块的取色和显示

BoundaryNorm

colors = ['blue', 'green', 'yellow', 'red']
bounds = [0, 25, 50, 75, 100]
# 创建颜色映射和规范化对象
cmap = mcolors.ListedColormap(colors)
norm = mcolors.BoundaryNorm(bounds, cmap.N)
#按照设置的bounds=[0, 25, 50, 75, 100]来进行映射
bounds=[0, 25, 50, 75, 100]
norm = BoundaryNorm(bounds, cmap.N)

# 获取值为50对应的颜色
color_value = 100
color_rgb = cmap(norm([color_value]))[0]
#norm([color_value])
#映射为0,1,2,3,4.bounds 数组的索引
# 创建一个图像和轴域对象
fig, ax = plt.subplots(figsize=(6, 1))

# 使用矩形填充显示颜色
#起始点,行,列
rect = plt.Rectangle((0, 0), 1, 1, fc=color_rgb)
ax.add_patch(rect)

# 移除坐标轴和边框
ax.set_xticks([])
ax.set_yticks([])
ax.set_frame_on(False)

# 显示图像
plt.show()

设置渐变和离散色块合并

bounds = [0, 40, 50, 60, 100]
# 定义渐变颜色映射
colors_grad = ["cyan", "green", "yellow"]
cmap_grad = LinearSegmentedColormap.from_list("grad_cmap", colors_grad)
# 定义离散颜色映射
colors_disc = ["blue", "red"]
# 合并两个颜色映射
#通过人为构建一个从0到1的256个数量的序列
combined_colors = ["blue"] + [cmap_grad(i/256.0) for i in range(150)] + ["red"]*10+
[cmap_grad(i/256.0) for i in np.arange(160,256)]+["red"]
cmap_combined = LinearSegmentedColormap.from_list("combined_cmap", combined_colors)

image-20240611212947284

解决方案2:

import torch
import torch.nn as nn
m = nn.Dropout(p=0.2)
input = torch.randn(8, 8)
output = m(input)
#我们要确定0在最大值和最小值的区间范围
#先默认考虑最小值小于0,最大值大于0
output_min=torch.min(output)
output_max=torch.max(output)
ratio=-output_min/(output_max-output_min)
#256个色块,int直接向下取整
index=int(ratio*256)
print(index)
# 获取颜色映射对象
custome_cmap = sns.color_palette("YlGnBu", as_cmap=True)
#custome_cmap.N =256
custome_cmap = [custome_cmap(i/256.0) for i in range(index)] + ["red"]*1+[cmap_grad(i/256.0) for i in np.arange(index+1,256)]
cmap_combined = LinearSegmentedColormap.from_list("combined_cmap", custome_cmap)

接向下取整
index=int(ratio*256)
print(index)

获取颜色映射对象

custome_cmap = sns.color_palette("YlGnBu", as_cmap=True)
#custome_cmap.N =256
custome_cmap = [custome_cmap(i/256.0) for i in range(index)] + ["red"]*1+[cmap_grad(i/256.0) for i in np.arange(index+1,256)]
cmap_combined = LinearSegmentedColormap.from_list("combined_cmap", custome_cmap)

image-20240611214313711

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值