本文主要是介绍基于互信息最大化的无监督学习图像特征表示------P02114198田园,P02114018刘颖,P02114050刘欣让,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在概率论和信息论中,两个随机变量的互信息衡量了两个变量之间相互依赖的程度。通俗来说可以理解为两个变量交叠的信息,对于两个随机变量,互信息衡量了一个随机变量平均传达了多少关于另一个的信息。
正式地,两个离散随机变量X和Y的互信息可以定义为:
其中是和的联合概率分布函数,而和分别是和的边缘概率函数分布。
在连续随机变量的情形下,求和被替换成了二重定积分:
其中是和的联合概率密度函数,而和分别是和的边缘概率密度函数。
互信息量在联合概率空间中的统计平均值。平均互信息克服了互信息量的随机性,成为一个确定的量。如果对数以2为基底,互信息的单位是bit。
许多表示学习算法使用像素级的训练目标,当只有一小部分信号在语义层面上起作用时是不利的。Bengio 等研究者假设应该更直接地根据信息内容和统计或架构约束来学习表示,据此提出了Deep INFOMAX(DIM)。该方法可用于学习期望特征的表示,并且在分类任务上优于许多流行的无监督学习方法。他们认为,这是学习更好的和更条理的表示的一个重要方向,有利于未来的人工智能研究。
用表示原始图像的集合,用表示某一原始图像,表示编码向量的集合,表示某个编码向量,表示所产生的编码向量的分布,我们设它为高斯分布,或者简单理解它就是我们想要寻找的编码器。那么可以用互信息来表示的相关性。
这里的原始数据的分布,是在给定之后整个的分布,即:
那么一个好的特征编辑器,应该要使得互信息尽量的大,即:
互信息越大意味着(大部分的)应当尽量大,这意味着应当远大于,即对于每个,编码器能找出专属于的那个,使得的概率远大于随机的概率。这样一来,就有能力只通过就从中分辨出原始样本来。
接下来进行最大化互信息,互信息的定义式稍微变换后如下:
这个形式揭示了互信息的本质含义:描述了两个变量的联合分布,则是随机抽取一个和一个时的分布(假设它们两个不相关时),而互信息则是这两个分布的散度。而所谓最大化互信息,就是要拉大与之间的距离。
全局互信息
全局互信息是指两个随机变量之间的互信息,它是一个大于等于0的实数,且满足以下条件:当两个随机变量独立时,它们的全局互信息为1;当两个随机变量不独立时,它们的全局互信息的取值范围为[0, 1/2]。
计算全局互信息的方法有很多种,其中一种常用的方法是使用贝叶斯公式。具体来说,对于两个离散随机变量X和Y,它们的全局互信息可以表示为:
其中表示在给定的情况下发生的概率,表示在给定的情况下发生条件概率对数。
局部互信息
由于图片的相关性更多体现在局部中。换言之,图片的识别、分类等应该是一个从局部到整体的过程。因此,有必要把“局部互信息”也考虑进来。
通过 CNN 进行编码的过程一般是:
已经考虑了和的关联,那么中间层特征(feature map)和的关联呢?我们记中间层特征为 也就是视为个向量的集合,我们也去算这个向量跟的互信息,称为“局部互信息”。
估算方法跟全局是一样的,将每一个与拼接起来得到,相当于得到了一个更大的 feature map,然后对这个 feature map 用多个1x1的卷积层来作为局部互信息的估算网络 Tlocal。
下面的代码使用Python实现,可以计算和两个向量的最大互信息。具体地,代码将和的值分成若干个区间(bin),并使用numpy.histogram2d()函数计算这些区间中和同时出现的次数。接着,使用 shan_entropy()函数计算、和与的熵,最后使用这些熵值计算最大互信息。
import numpy as np
from sklearn.metrics import mutual_info_scoredef max_mutual_information(X, y):"""计算最大互信息:param X: 特征矩阵,形状为 (n_samples, n_features):param y: 标签向量,形状为 (n_samples,):return: 最大互信息值"""mi = mutual_info_score(y, X)max_mi = mifor i in range(X.shape[1]):for j in range(i+1, X.shape[1]):new_mi = mutual_info_score(y, X[:, [i, j]])if new_mi > max_mi:max_mi = new_mireturn max_mi# 示例
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
y = np.array([0, 1, 0, 1])
result = max_mutual_information(X, y)
print("最大互信息值:", result)
下面这段代码是基于Deep InfoMax模型的,用于无监督学习图像特征表示。它首先定义了一些参数,如隐变量维度、全局互信息和局部互信息的比重等。然后,它使用卷积神经网络(CNN)对输入图像进行编码,并使用重参数技巧生成潜在空间中的样本。接下来,它定义了全局判别器和局部判别器,分别用于计算全局和局部信息损失。最后,它训练了一个模型来学习这些信息损失,并输出了编码器的特征。此外,它还提供了一个采样函数,可以从潜在空间中随机选择一张图片,并输出与这张图片最相近的图片。
import numpy as np
import glob
import imageio
from scipy import misc
from keras.models import Model
from keras.layers import *
from keras import backend as K
from keras.optimizers import Adam
from tqdm import tqdm
import tensorflow as tfimgs = glob.glob('tiny-imagenet-200/train/*/images/*')
np.random.shuffle(imgs)def imread(f):x = misc.imread(f, mode='RGB')return x.astype(np.float32) / 255 * 2 - 1x_train = np.array([imread(f) for f in tqdm(iter(imgs))])
img_dim = x_train.shape[1]z_dim = 256 # 隐变量维度
alpha = 0.5 # 全局互信息的loss比重
beta = 1.5 # 局部互信息的loss比重
gamma = 0.01 # 先验分布的loss比重# 编码器(卷积与最大池化)
x_in = Input(shape=(img_dim, img_dim, 3))
x = x_infor i in range(4):x = Conv2D(z_dim // 2**(3-i),kernel_size=(3,3),padding='SAME')(x)x = BatchNormalization()(x)x = LeakyReLU(0.2)(x)x = MaxPooling2D((2, 2))(x)feature_map = x # 截断到这里,认为到这里是feature_map(局部特征)
feature_map_encoder = Model(x_in, x)for i in range(2):x = Conv2D(z_dim,kernel_size=(3,3),padding='SAME')(x)x = BatchNormalization()(x)x = LeakyReLU(0.2)(x)x = GlobalMaxPooling2D()(x) # 全局特征z_mean = Dense(z_dim)(x) # 均值,也就是最终输出的编码
z_log_var = Dense(z_dim)(x) # 方差,这里都是模仿VAE的encoder = Model(x_in, z_mean) # 总的编码器就是输出z_mean# 重参数技巧
def sampling(args):z_mean, z_log_var = argsu = K.random_normal(shape=K.shape(z_mean))return z_mean + K.exp(z_log_var / 2) * u# 重参数层,相当于给输入加入噪声
z_samples = Lambda(sampling)([z_mean, z_log_var])
prior_kl_loss = - 0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var))# shuffle层,打乱第一个轴
def shuffling(x):idxs = K.arange(0, K.shape(x)[0])idxs = tf.random_shuffle(idxs)return K.gather(x, idxs)# 与随机采样的特征拼接(全局)
z_shuffle = Lambda(shuffling)(z_samples)
z_z_1 = Concatenate()([z_samples, z_samples])
z_z_2 = Concatenate()([z_samples, z_shuffle])# 与随机采样的特征拼接(局部)
feature_map_shuffle = Lambda(shuffling)(feature_map)
z_samples_repeat = RepeatVector(4 * 4)(z_samples)
z_samples_map = Reshape((4, 4, z_dim))(z_samples_repeat)
z_f_1 = Concatenate()([z_samples_map, feature_map])
z_f_2 = Concatenate()([z_samples_map, feature_map_shuffle])# 全局判别器
z_in = Input(shape=(z_dim*2,))
z = z_in
z = Dense(z_dim, activation='relu')(z)
z = Dense(z_dim, activation='relu')(z)
z = Dense(z_dim, activation='relu')(z)
z = Dense(1, activation='sigmoid')(z)GlobalDiscriminator = Model(z_in, z)z_z_1_scores = GlobalDiscriminator(z_z_1)
z_z_2_scores = GlobalDiscriminator(z_z_2)global_info_loss = - K.mean(K.log(z_z_1_scores + 1e-6) + K.log(1 - z_z_2_scores + 1e-6))# 局部判别器
z_in = Input(shape=(None, None, z_dim*2))
z = z_in
z = Dense(z_dim, activation='relu')(z)
z = Dense(z_dim, activation='relu')(z)
z = Dense(z_dim, activation='relu')(z)
z = Dense(1, activation='sigmoid')(z)LocalDiscriminator = Model(z_in, z)z_f_1_scores = LocalDiscriminator(z_f_1)
z_f_2_scores = LocalDiscriminator(z_f_2)
local_info_loss = - K.mean(K.log(z_f_1_scores + 1e-6) + K.log(1 - z_f_2_scores + 1e-6))# 用来训练的模型
model_train = Model(x_in, [z_z_1_scores, z_z_2_scores, z_f_1_scores, z_f_2_scores])
model_train.add_loss(alpha * global_info_loss + beta * local_info_loss + gamma * prior_kl_loss)
model_train.compile(optimizer=Adam(1e-3))model_train.fit(x_train, epochs=100, batch_size=100)
model_train.save_weights('total_model.tiny.imagenet.weights')# 输出编码器的特征
zs = encoder.predict(x_train, verbose=True)
zs.mean() # 查看均值(简单观察先验分布有没有达到效果)
zs.std() # 查看方差(简单观察先验分布有没有达到效果)# 随机选一张图片,输出最相近的图片
# 可以选用欧氏距离或者cos值
def sample_knn(path):n = 10topn = 10figure1 = np.zeros((img_dim*n, img_dim*topn, 3))figure2 = np.zeros((img_dim*n, img_dim*topn, 3))zs_ = zs / (zs**2).sum(1, keepdims=True)**0.5for i in range(n):one = np.random.choice(len(x_train))idxs = ((zs**2).sum(1) + (zs[one]**2).sum() - 2 * np.dot(zs, zs[one])).argsort()[:topn]for j,k in enumerate(idxs):digit = x_train[k]figure1[i*img_dim: (i+1)*img_dim,j*img_dim: (j+1)*img_dim] = digitidxs = np.dot(zs_, zs_[one]).argsort()[-n:][::-1]for j,k in enumerate(idxs):digit = x_train[k]figure2[i*img_dim: (i+1)*img_dim,j*img_dim: (j+1)*img_dim] = digitfigure1 = (figure1 + 1) / 2 * 255figure1 = np.clip(figure1, 0, 255)figure2 = (figure2 + 1) / 2 * 255figure2 = np.clip(figure2, 0, 255)imageio.imwrite(path+'_l2.png', figure1)imageio.imwrite(path+'_cos.png', figure2)sample_knn('test')
这篇关于基于互信息最大化的无监督学习图像特征表示------P02114198田园,P02114018刘颖,P02114050刘欣让的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!