采用ResNet网络+TSNE降维算法对自建图像数据集进行二维可视化显示
起因:某一天下午,我在“玩”的时候,突然接到了老板的电话,说是要对图像做可视化降维。因此,我拿到了一批图像的数据。
数据的特点:
1、数据集的图像分为4类,并且每一种类的图像多少不均衡。
2、数据集图像是一个大文件夹,里面包含4个文件夹,而且里面命名非常不规范。
3、数据集图像大小也不一样。
任务:采用ResNet网络+TSNE降维算法对图像数据集进行二维可视化显示
大体步骤:
1、首先对图像进行重命名,这样在读入图像的时候,可以保持一个干净整洁的方式,写入。
2、对于重命名的数据,本来想着在ResNet算法中进行Resize,因为ResNet网络里面有一个方法是Transforms.Compose([transforms.Resize(256,256)]),也就是将图像转化为256像素*256像素的。但是后来一想,还是先把图像转换一下。
3、采用重命名+Resize的图片作为图像数据集,进行输入到ResNet网络中。使用训练集对模型进行训练,采用训练好的模型对测试集进行提取特征。特征+标签保存为npy文件。
4、使用TSNE降维算法对npy文件读取,并且降到二维,使用plt.show()展示降维后的结果。
步骤1的代码:图像进行重命名
import os
from PIL import Image
# 语言: Python
# 作用:批量对一个文件夹中的图片进行重命名,从0.1.2.3.4开始
# 一、首先定义图片重命名的函数
def IRename(folder_path):
Xin_folder_path = "{}/{}".format(total_folder_path,folder_path)
for i,filename in enumerate(os.listdir(Xin_folder_path)):
# 检查图片格式是否为PNG、JPG、JPEG 对于字母大小写不敏感
if(filename.endswith(".jpg") or filename.endswith(".png") or filename.endswith(".jpeg")):
# 1 打开图像文件
img = Image.open(os.path.join(Xin_folder_path,filename))
# 2 分割图像文件夹的名称,split("_")
print(filename)
hou_Word = folder_path.split('_')
print(hou_Word[1])
# 3 构建新的文件名称
new_filename = '{}_{}.{}'.format(hou_Word[1],i+1,img.format.lower()) # img.format.lower():获取图片格式
img.close()
# 3 重命名 图像名称
os.rename(os.path.join(Xin_folder_path,filename),os.path.join(Xin_folder_path,new_filename)) # 二、输入总的文件夹名称,包含4个图片的文件夹名称
total_folder_path = "../image"
for i,totalfilename in enumerate(os.listdir(total_folder_path)):
IRename(totalfilename)
上面展示了步骤1的代码,但是后来我在完成整个任务的时候,发现对于图像的重命名是没有必要的,因为给图像打标签完全可以使用包含每一种类别图像的文件夹名称进行打标签。
步骤2的代码:Resize 图像大小
import os
from PIL import Image
# 语言: Python
# 作用:批量对一个文件夹中的图片进行重设像素大小,width=值,height=值
import glob
def convertJPEG(jpgfile,outdir,width=64,height=64):
img = Image.open(jpgfile)
new_ing = img.resize((width,height),Image.BILINEAR)
new_ing.save(os.path.join(outdir,os.path.basename(jpgfile))) for jpgfile in glob.glob('images_all/*.jpeg'):
convertJPEG(jpgfile,"images_all_Resize")
步骤3的代码:采用ResNet网络进行重新训练,这里采用两个py文件,第一个py用来包装好测试集和训练集,完成所需工作。第二个py用来训练ResNet模型,并在最后保存测试集的特征为npy文件
import glob
import torch
# 语言: Python
# 作用:# 第一个py用来包装好测试集和训练集,完成所需工作
from torch.utils import data
from PIL import Image
import numpy as np
from torchvision import transforms
# 2 继承Dataset实现Mydataset子类
class Mydataset(data.Dataset):
# init() 初始化方法,传入数据文件夹路径
def __init__(self, root):
self.imgs_path = root # getitem() 切片方法,根据索引下标,获得相应的图片
def __getitem__(self, index):
img_path = self.imgs_path[index] # len() 计算长度方法,返回整个数据文件夹下所有文件的个数
def __len__(self):
return len(self.imgs_path) # 3、使用glob方法来获取数据图片的所有路径
all_imgs_path = glob.glob(r"../image/*/*.jpeg") # 数据文件夹路径 # 一 利用自定义的类来创建对象brake_dataset
brake_dataset = Mydataset(all_imgs_path)
brake_dataloader = torch.utils.data.DataLoader(brake_dataset, batch_size=4) # 每次迭代时返回4个数据 # 为所有的图片制造相对应的标签
species = ['haemorrhage','hardexudate','normal','softexudate'] species_to_id = dict((c,i) for i,c in enumerate(species)) id_to_species =dict((v,k) for k,v in species_to_id.items()) # 二 为对应的图片,打上标签 PS:这一部分很重要DDDDDDDanger
all_labels = []
for img in all_imgs_path:
# print(img)
for i,c in enumerate(species):
if c in img:
all_labels.append(i)
# print(len(all_labels)) # 三 将图片转化为Tensor,展示图片与标签对应的关系
# 对数据进行转换处理
transform = transforms.Compose([
transforms.Resize((256,256)),
transforms.ToTensor()
]) class Mydatasetpro(data.Dataset):
# 初始化
def __init__(self,img_paths,labels,transform):
self.imgs = img_paths
self.labels = labels
self.transforms = transform
# 切片处理
def __getitem__(self, index):
img = self.imgs[index]
label = self.labels[index]
pill_img = Image.open(img)
pill_img = pill_img.convert('RGB')
data = self.transforms(pill_img)
return data,label
# 返回长度
def __len__(self):
return len(self.imgs) BATCH_SIZE = 16
brake_dataset = Mydatasetpro(all_imgs_path,all_labels,transform)
brake_dataloader = data.DataLoader(
brake_dataset,
batch_size=BATCH_SIZE,
shuffle=True ) imgs_batch,labels_batch = next(iter(brake_dataloader))
# print(imgs_batch.shape) # 四 划分数据集和测试集
index = np.random.permutation(len(all_imgs_path)) all_imgs_path = np.array(all_imgs_path)[index]
all_labels = np.array(all_labels)[index] s = int(len(all_imgs_path) * 0.9)
train_imgs = all_imgs_path[:s]
train_labels = all_labels[:s]
test_imgs = all_imgs_path[s:]
test_labels = all_labels[s:] print(len(train_imgs),len(train_labels),len(test_imgs),len(test_labels)) # 将对应的数据,转化为对应的Tensor Data
train_ds = Mydatasetpro(train_imgs,train_labels,transform)
test_ds = Mydatasetpro(test_imgs,test_labels,transform)
print("@#$%^&^%$^&*&^%$&(*&^%$^")
train_loader = data.DataLoader(train_ds,batch_size=BATCH_SIZE,shuffle=True)
test_loader = data.DataLoader(test_ds,batch_size=BATCH_SIZE,shuffle=True)
第二个py用来训练ResNet模型,并在最后保存测试集的特征为npy文件
import torch
from torchvision import models
# 语言: Python
# 作用:# 第二个py用来训练ResNet模型,并在最后保存测试集的特征为npy文件
from tqdm import tqdm
from torch import nn
from torch import optim
from Doctor0913 import brake_dataloader
from Doctor0913 import train_loader, test_loader
import ssl
import numpy as np
from tqdm import tqdm
import torch.nn.functional as F
ssl._create_default_https_context = ssl._create_unverified_context # 1、查看一个Batch的图像+标注
train_images,train_labels = next(iter(train_loader))
print(train_images.shape) # torch.Size([4, 3, 256, 256])
print(train_labels.shape) # torch.Size([4])
# 2、将tensor转为array后即可使用plt调用
# 3、载入模型进行微调 DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") model_ft = models.resnet50(weights=models.ResNet50_Weights.DEFAULT) # 使用迁移学习,加载预训练权 in_features = model_ft.fc.in_features
model_ft.fc = nn.Sequential(nn.Linear(in_features,256),
nn.ReLU(),
nn.Linear(256,4),
nn.LogSoftmax(dim=1)
)
model_ft = model_ft.to(DEVICE) # 将模型迁移到gpu # 优化器
loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.to(DEVICE) # 将loss_fn迁移到GPU # Adam损失函数
optimizer = optim.Adam(model_ft.fc.parameters(), lr=0.0001)
epochs = 30 # 迭代次数
steps = 0
running_loss = 0
print_every = 10
train_losses, test_losses = [], []
lasds = []
tmp = []
acc = []
for epoch in range(epochs):
model_ft.train()
running_loss = 0
# 遍历训练集数据
for imgs, labels in tqdm(train_loader):
steps += 1
labels = torch.tensor(labels, dtype=torch.long)
imgs, labels = imgs.to(DEVICE), labels.to(DEVICE)
optimizer.zero_grad() # 梯度归零
outputs = model_ft(imgs)
loss = loss_fn(outputs, labels) loss.backward() # 反向传播计算梯度
optimizer.step() # 梯度优化
running_loss += loss.item()
print(f"Epoch {epoch + 1}/{epochs}"
f"...Train loss: {running_loss / len(train_loader):.3f} ")
with torch.no_grad():
test_loss = 0
accuracy = 0
# 遍历测试集数据
for imgs, labels in test_loader:
labels = torch.tensor(labels, dtype=torch.long)
imgs, labels = imgs.to(DEVICE), labels.to(DEVICE)
outputs = model_ft(imgs)
# 现将 特征放到cpu上面,再numpy
outputs = outputs.cpu().detach().numpy()
labels1 = np.array([int(i) for i in labels])
# 将对应的特征+标签进行抽取并保存
for i in labels1:
label1 = i
lasds.append(label1)
for i in outputs:
tmp.append(i)
labels = labels.to(DEVICE)
outputs = torch.tensor(outputs)
outputs = outputs.to(DEVICE) loss = loss_fn(outputs, labels) test_loss += loss.item()
ps = torch.exp(outputs)
top_p, top_class = ps.topk(1, dim=1)
equals = top_class == labels.view(*top_class.shape)
accuracy += torch.mean(equals.type(torch.FloatTensor)).item()
acc.append(accuracy / len(test_loader))
print(f"Test accuracy: {accuracy / len(test_loader):.3f}")
lapsds = torch.Tensor(lasds)
tmp = torch.Tensor(tmp)
print(acc)
# with open('ResNet_Test_FTLoss.txt', 'w') as f:
# for item in loss_FocalLoss:
# f.write("%s\n" % item)
np.save("Feature_ResNet_Test", tmp)
np.save("Label_ResNet_Test", lasds)b
步骤4的代码:将image_feature.npy文件+label.npy文件传到TSNE降维算法中,进行二维可视化展示
import numpy as np
from matplotlib import pyplot as plt
# # 语言: Python
# # 作用:# 将image_feature.npy文件+label.npy文件传到TSNE降维算法中,进行二维可视化展示
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE train = np.load('Feature_ResNet_Test_FTLoss.npy')
labels12 = np.load('Label_ResNet_Test_FTLoss.npy') # -===================================================================================
# 降到二维:平面图展示
asdasfa = 1
if asdasfa ==1:
labels_huitu_string = ['haemorrhage', 'hardexudate', 'normal', 'softexudate']
tsne = TSNE(n_components=2, learning_rate=150).fit_transform(train) plt.figure(figsize=(12, 6))
plt.scatter(tsne[:, 0], tsne[:, 1], c=labels12)
plt.show()
# -===================================================================================
if asdasfa == 2:
model_pca = PCA(n_components=2)
X_PCA = model_pca.fit_transform(train)
# # 绘图
labels_huitu = [0, 1, 2, 3]
Colors = ['red', 'orange', 'yellow', 'green']
labels_huitu_string = ['haemorrhage', 'hardexudate', 'normal', 'softexudate'] plt.figure(figsize=(8, 6), dpi=80) # figsize定义画布大小,dpi定义画布分辨率
plt.title('Transformed samples via sklearn.decomposition.PCA')
#分别确定x和y轴的含义及范围
plt.xlabel('x_values')
plt.ylabel('y_values')
for tlabel in labels_huitu:
# pca读取数据
x_pca_data=X_PCA[labels12==tlabel,0]
y_pca_data=X_PCA[labels12==tlabel,1]
plt.scatter(x=x_pca_data,y=y_pca_data,s=20,c=Colors[tlabel],label=labels_huitu_string[tlabel])
plt.legend(loc="upper right") #输出标签信息在右上角
plt.grid()
plt.show()
# -===================================================================================
经过TSNE降维之后的图像数据集的特征,进行二维可视化展示
到此,整个任务就结束了。撒花完结!!!!!!!!!!!!!!
题外话1:后来在写这一篇博客的时候,突然想到了还没有开始干活,就写了两个程序,头都大了。
题外话2:使用模型提取图像特征的时候,不要将训练集+测试集 一起打包放入模型中,会让你头疼的。图如下所示:
采用ResNet网络+TSNE降维算法对自建图像数据集进行二维可视化显示的更多相关文章
- 无线网络发射选址 2014年NOIP全国联赛提高组(二维前缀和)
P2038 无线网络发射器选址 题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南 ...
- 你也可以手绘二维码(二)纠错码字算法:数论基础及伽罗瓦域GF(2^8)
摘要:本文讲解二维码纠错码字生成使用到的数学数论基础知识,伽罗瓦域(Galois Field)GF(2^8),这是手绘二维码填格子理论基础,不想深究可以直接跳过.同时数论基础也是 Hash 算法,RS ...
- 【2048小游戏】——原生js爬坑之遍历算法显示二维数组内容
引言:做2048小游戏会将横纵方向的数字内容,存储在一个二维数组中,要将这个二维数组中的内容显示在页面上,就一定要用遍历算法来实现了. 一.二维数组存储 首先考虑用二维数组存储所有行数,列数 ...
- NASNet学习笔记—— 核心一:延续NAS论文的核心机制使得能够自动产生网络结构; 核心二:采用resnet和Inception重复使用block结构思想; 核心三:利用迁移学习将生成的网络迁移到大数据集上提出一个new search space。
from:https://blog.csdn.net/xjz18298268521/article/details/79079008 NASNet总结 论文:<Learning Transfer ...
- PCA 降维算法详解 以及代码示例
转载地址:http://blog.csdn.net/watkinsong/article/details/38536463 1. 前言 PCA : principal component analys ...
- [机器学习] t-SNE聚类算法实践指南
转载于比PCA降维更高级--(R/Python)t-SNE聚类算法实践指南-阿里云开发者社区 作者介绍:Saurabh.jaju2 Saurabh是一名数据科学家和软件工程师,熟练分析各种数据集 ...
- 详解ResNet 网络,如何让网络变得更“深”了
摘要:残差网络(ResNet)的提出是为了解决深度神经网络的"退化"(优化)问题.ResNet 通过设计残差块结构,调整模型结构,让更深的模型能够有效训练更训练. 本文分享自华为云 ...
- 四大机器学习降维算法:PCA、LDA、LLE、Laplacian Eigenmaps
四大机器学习降维算法:PCA.LDA.LLE.Laplacian Eigenmaps 机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中.降维的本质是学习一个映 ...
- 学习笔记-ResNet网络
ResNet网络 ResNet原理和实现 总结 一.ResNet原理和实现 神经网络第一次出现在1998年,当时用5层的全连接网络LetNet实现了手写数字识别,现在这个模型已经是神经网络界的“hel ...
- 一步步教你轻松学奇异值分解SVD降维算法
一步步教你轻松学奇异值分解SVD降维算法 (白宁超 2018年10月24日09:04:56 ) 摘要:奇异值分解(singular value decomposition)是线性代数中一种重要的矩阵分 ...
随机推荐
- C++面试八股文:std::vector了解吗?
某日二师兄参加XXX科技公司的C++工程师开发岗位第23面: 面试官:vector了解吗? 二师兄:嗯,用过. 面试官:那你知道vector底层是如何实现的吗? 二师兄:vector底层使用动态数组来 ...
- Android 巧用ImageView属性实现选中和未选中效果
原文地址: Android 巧用ImageView属性实现选中和未选中效果 - Stars-One的杂货小窝 选中和未选中状态变更是很常见需求,UI那边出的两个不同状态的图片,然后开发这边去实现 通常 ...
- 1.1 熟悉x64dbg调试器
x64dbg 是一款开源.免费.功能强大的动态反汇编调试器,它能够在Windows平台上进行应用程序的反汇编.调试和分析工作.与传统的调试器如Ollydbg相比,x64dbg调试器的出现填补了Olly ...
- pyinstaller打包程序后提示No module named ‘xxxx‘
解决方法1 1.检查 先在venv环境中安装xxx 报错的这个包 以我的举例 查看settings>project interpreter (存在对应的包) 解决方法2 2.在xxx.spec ...
- 图扑 AR 技术应用与管理:施工建造、机柜扫描、办公室导航解决方案
随着科技的不断革新和创新,越来越多的行业开始迎来数字化时代的变革.建筑行业作为人类历史上最重要的产业之一,在数字化转型方面同样也在不断推进.图扑软件结合 AR 技术的应用,为建筑行业带来了更加便捷高效 ...
- PTA 21级数据结构与算法实验4—字符串和数组
目录 7-1 字符串模式匹配(KMP) 7-2 [模板]KMP字符串匹配 7-3 统计子串 7-4 好中缀 7-5 病毒变种 7-6 判断对称矩阵 7-7 三元组顺序表表示的稀疏矩阵转置运算Ⅰ 7-8 ...
- 2023郑州轻工业大学校赛邀请赛wh
在这里,很感谢程立老师的帮助和选择我,我以后会跟着程老师,既然热爱,就要走下去! 2022年4月2号,我代表河南工业大学与郑州17所高校在郑州轻工业大学举办的"卓见杯"郑州轻工业大 ...
- 自学前端-HTML5+CSS-综合案例一-热词
综合案例一-热词 目录 综合案例一-热词 1.设计需求 2.设计所需标签和CSS样式 3.设计具体步骤 4.遇到的问题 设计图如下 1.设计需求 ①需要鼠标放上去有显示透明 ②需要点击后跳转到相应页面 ...
- 2021-7-30 MySql函数的使用归类整理
Mysql字符的使用 SELECT ASCII(user_password) as 阿斯克码 FROM users;#返回首字符的ascii码 SELECT CHAR_LENGTH(user_pass ...
- PLE-实践小结-2308-cnblogs
某场景介绍 前状:三模型,权重融合 解决问题:融合目标行为,充分利用样本信息,节省资源开销. 当前效果 主场景人均真实曝光+0.26%,不显著:子场景人均真实曝光+0.35%,不显著 千曝互动+2.6 ...