记录一个小实验,如何给卷积神经网络的特征值降维,在保证特征可判别性的同时减小特征值个数。
我们使用六组图片进行实验:
实验环境:
opencv-python 4.4.0.44
numpy 1.18.5
torch 1.0.1
1、首先,使用别人训练好的senet-101模型提取六张图片的特征值,得到6个2048维的特征向量。
2、用余弦相似度分别计算P1P2、D1D2、S1S2的相似度,分别是0.633、0.879、0.637。分别计算P1S1、D1P1、S1D1、P2S2、D2P2、S2D2的相似度,分别是0.136、0.105、0.138、0.224、0.163、0.178。可以看出,同类图片相似度大于0.5,异类图片相似度小于0.3。
3、使用opencv提供的pca接口实现降维算法,本次实验希望将2048维度的特征降到512。pca算法需要确保样本个数大于降维维度,所以我们额外从ImageNet数据集1000类图片中,每类随机选一张图片,共1000张组成训练数据。
4、使用opencv中的cv.PCACompute2函数,计算训练数据的特征值和特征向量。
5、使用六张图片的特征值 乘以 特征向量的转置([6*2048]x[2048*512]),得到降维后的六张图片特征([6*512])。
6、重复步骤2,P1P2、D1D2、S1S2的相似度分别为0.725、0.929、0.752。P1S1、D1P1、S1D1、P2S2、D2P2、S2D2的相似度分别是0.152、0.104、0.141、0.274、0.169、0.191。可以看出,同类图片相似度大于0.7,异类图片相似度小于0.3,特征依然保持可判别性。但是异类相似度的值都有不成程度的增长,说明特征判别性降低了。
def print_sim(data):
print(pw.cosine_similarity(data[0].reshape(1, -1), data[2].reshape(1, -1)))
print(pw.cosine_similarity(data[1].reshape(1, -1), data[3].reshape(1, -1)))
print(pw.cosine_similarity(data[4].reshape(1, -1), data[5].reshape(1, -1)))
print(pw.cosine_similarity(data[0].reshape(1, -1), data[1].reshape(1, -1)))
print(pw.cosine_similarity(data[1].reshape(1, -1), data[4].reshape(1, -1)))
print(pw.cosine_similarity(data[4].reshape(1, -1), data[0].reshape(1, -1)))
print(pw.cosine_similarity(data[2].reshape(1, -1), data[3].reshape(1, -1)))
print(pw.cosine_similarity(data[3].reshape(1, -1), data[5].reshape(1, -1)))
print(pw.cosine_similarity(data[5].reshape(1, -1), data[2].reshape(1, -1)))
if __name__ == '__main__':
#加载senet-101模型
model = se_resnet101()
param = torch.load('/home/dl/PycharmProjects/S2VT/extractor/se_resnet101-7e38fcc6.pth')
model.load_state_dict(param)
model.cuda()
model.eval()
#加载训练数据
feats = None
img_list = os.listdir('/home/dl/PycharmProjects/S2VT/Image')
for image in img_list:
img = cv.imread(os.path.join('/home/dl/PycharmProjects/S2VT/Image', image), 0)
feat = get_img_resnet_feature(model, img).cpu().numpy()#这个特征提取函数自己写
try:
feats = np.vstack((feats, feat))
except:
feats = feat
print(feats.shape[0])
#调用pca函数,返回均值、特征向量、特征值(从大到小)
mean, eigenvectors, eigenvalues = cv.PCACompute2(feats, np.array([]), maxComponents=512)
#加载6张测试图片
feats = None
img_list = os.listdir('/home/dl/PycharmProjects/S2VT/test_Image')
for image in img_list:
img = cv.imread(os.path.join('/home/dl/PycharmProjects/S2VT/test_Image', image), 0)
feat = get_img_resnet_feature(model, img).cpu().numpy()
try:
feats = np.vstack((feats, feat))
except:
feats = feat
#输出降维前和降维后的特征相似度
print_sim(feats)
pca_feats = np.matmul(feats, eigenvectors.T)#降维
print_sim(pca_feats)