在这篇文章中我们详细的讨论了随机熵、时间无关熵和真实熵,但是他们都是针对单一变量的时间序列进行的处理,无法反映多变量时间序列之间的关系。那么要如何反映两个变量之间是否存在内在联系呢,这里就不得不提到条件熵:
信息熵反映的是随机变量的所有可能取值,即所有可能发生事件所带来的信息量的期望。那么信息熵指的是定义为X给定条件下,Y的条件概率分布的熵对X的数学期望。话不多说直接上代码:
# 计算信息熵
def calc_ent(x):
"""
calculate shanno ent of x
"""
x_value_list = set([x[i] for i in range(x.shape[0])])
ent = 0.0
for x_value in x_value_list:
p = float(x[x == x_value].shape[0]) / x.shape[0]
logp = np.log2(p)
ent -= p * logp
return ent
# 计算条件熵
def calc_condition_ent(x, y):
"""
calculate ent H(y|x)
"""
# calc ent(y|x)
x_value_list = set([x[i] for i in range(x.shape[0])])
ent = 0.0
for x_value in x_value_list:
sub_y = y[x == x_value]
temp_ent = calc_ent(sub_y)
ent += (float(sub_y.shape[0]) / y.shape[0]) * temp_ent
return ent
一个特征往往会使一个随机变量Y的信息量减少,减少的部分就是信息增益。如果信息增益的值越大,说明引入的特征使得随机变量Y的信息量减少的越多,随机变量Y的不确定性降低了,那么引入的这个特征就越好,它和随机变量Y的相关越高。
代码展示如下:
# 计算信息增益
def calc_ent_grap(x,y):
"""
calculate ent grap
"""
base_ent = calc_ent(y)
condition_ent = calc_condition_ent(x, y)
ent_grap = base_ent - condition_ent
return ent_grap
最终我们在我们随机生成的数据集上进行结果展示。该数据集展示了10个节点随时间的流量变化,为了便于后续时间序列的处理,我们对数据集进行了切分,(X,Y,Z)其对应的Y为节点数10,Z为所选的时间序列的长度,X为切分出来的(Y,Z)的数量。代码如下:
cond_list = []
for i in range(node.shape[1]):
cond = []
for j in range(node.shape[1]):
x = node[0, i, :]
y = node[0, j, :]
cond.append(calc_ent_grap(x, y))
cond_list.append(cond)
print(np.array(cond_list).shape)
cond_array=np.array(cond_list)-np.diag(cond_list)*np.eye(10)
print(cond_list)
最终我们选择使用heatmap对结果进行展示,展示结果为一个10×10的矩阵,代表相应节点(i,j)之间的信息增益。
sns.set_theme(font='Times New Roman', font_scale=1.2)
fig, ax = plt.subplots(constrained_layout=True, figsize=(6, 5))
node = sns.heatmap(cond_list, xticklabels=False, yticklabels=False, cbar=True, annot=True)
node = node.set_title('conditional entropy')
plt.show()
输出结果图展示如下: