起因:某一天下午,我在“玩”的时候,突然接到了老板的电话,说是要对图像做可视化降维。因此,我拿到了一批图像的数据。

数据的特点

  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降维算法对自建图像数据集进行二维可视化显示的更多相关文章

  1. 无线网络发射选址 2014年NOIP全国联赛提高组(二维前缀和)

    P2038 无线网络发射器选址 题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南 ...

  2. 你也可以手绘二维码(二)纠错码字算法:数论基础及伽罗瓦域GF(2^8)

    摘要:本文讲解二维码纠错码字生成使用到的数学数论基础知识,伽罗瓦域(Galois Field)GF(2^8),这是手绘二维码填格子理论基础,不想深究可以直接跳过.同时数论基础也是 Hash 算法,RS ...

  3. 【2048小游戏】——原生js爬坑之遍历算法显示二维数组内容

    引言:做2048小游戏会将横纵方向的数字内容,存储在一个二维数组中,要将这个二维数组中的内容显示在页面上,就一定要用遍历算法来实现了. 一.二维数组存储    首先考虑用二维数组存储所有行数,列数   ...

  4. NASNet学习笔记——   核心一:延续NAS论文的核心机制使得能够自动产生网络结构;    核心二:采用resnet和Inception重复使用block结构思想;    核心三:利用迁移学习将生成的网络迁移到大数据集上提出一个new search space。

    from:https://blog.csdn.net/xjz18298268521/article/details/79079008 NASNet总结 论文:<Learning Transfer ...

  5. PCA 降维算法详解 以及代码示例

    转载地址:http://blog.csdn.net/watkinsong/article/details/38536463 1. 前言 PCA : principal component analys ...

  6. [机器学习] t-SNE聚类算法实践指南

    ​  转载于比PCA降维更高级--(R/Python)t-SNE聚类算法实践指南-阿里云开发者社区 作者介绍:Saurabh.jaju2 Saurabh是一名数据科学家和软件工程师,熟练分析各种数据集 ...

  7. 详解ResNet 网络,如何让网络变得更“深”了

    摘要:残差网络(ResNet)的提出是为了解决深度神经网络的"退化"(优化)问题.ResNet 通过设计残差块结构,调整模型结构,让更深的模型能够有效训练更训练. 本文分享自华为云 ...

  8. 四大机器学习降维算法:PCA、LDA、LLE、Laplacian Eigenmaps

    四大机器学习降维算法:PCA.LDA.LLE.Laplacian Eigenmaps 机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中.降维的本质是学习一个映 ...

  9. 学习笔记-ResNet网络

    ResNet网络 ResNet原理和实现 总结 一.ResNet原理和实现 神经网络第一次出现在1998年,当时用5层的全连接网络LetNet实现了手写数字识别,现在这个模型已经是神经网络界的“hel ...

  10. 一步步教你轻松学奇异值分解SVD降维算法

    一步步教你轻松学奇异值分解SVD降维算法 (白宁超 2018年10月24日09:04:56 ) 摘要:奇异值分解(singular value decomposition)是线性代数中一种重要的矩阵分 ...

随机推荐

  1. 鸟类识别系统Python+Django+TensorFlow+卷积神经网络算法【完整代码】

    一.介绍 鸟类识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法.并通过对数据集进行训练,最后得到一个识别精度较高的模型.并基于Django框架,开 ...

  2. Java 数组及数组的优点与缺点

    1.java中的数组是一种引用数据类型.不属于基本数据类型.数组的父类是Object. 2.数组实际上是一个容器,可以同时容纳多个元素.(数组相当于是一个数据的集合.) 数组的字面意思是"一 ...

  3. Java正三角、倒三角

    正三角 public static void main(String[] args) { // 正三角 int num = 8; for(int i = 1;i<=num;i++) { for( ...

  4. String解析及其方法

    String解析及其方法 1.前言 2.什么是字符串(String) 3.字符串(String)的两种创建方式及其区别 4.字符串(String)的方法及其部分原码解析 5.字符串(String)的弊 ...

  5. SQL SERVER 查看表说明,字段属性

    查询表字段属性,说明等: 1 SELECT 2 表名=case when a.colorder=1 then d.name else '' end, 3 表说明=case when a.colorde ...

  6. 简约版八股文(day2)

    Redis(内存中->非关系型数据库) redis是什么,为什么要用redis redis是基于键值对的NoSQL数据库,经常用来做缓存用户直接读取数据库中的数据效率是相对比较慢的,如果把数据读 ...

  7. 通用权限系统-Spring-Boot-Starter

    Spring-Boot-Starter 自定义Starter 案例一:读取application.yml中的参数 1.创建 1.创建maven工程hello-spring-boot-starter 2 ...

  8. ubuntu发行版内核源码下载

    Ubuntu 发行版linux内核在哪里? 内核安装包:http://archive.ubuntu.com/ubuntu/pool/main/l/linux/ 内核源码:https://git.lau ...

  9. MySQL——GROUP BY详解与优化

    在 MySQL 中,GROUP BY用于将具有指定列中相同值的行分组在一起.这是在处理大量数据时非常有用的功能,允许对数据进行分类和聚合. 基本使用 语法 以下是GROUP BY子句的基本语法: &q ...

  10. asp.net core之配置

    简介 配置在asp.net core中可以说是我们必不可少一部分.ASP.NET Core 中的应用程序配置是使用一个或多个配置提供程序执行的. 配置提供程序使用各种配置源从键值对读取配置数据,普通最 ...