深度学习--Pytorch构建栈式自编码器实现以图搜图任务(以cifar10数据集为例)

本文涉及的产品
图像搜索,7款服务类型 1个月
简介: 本文旨在使用CIFAR-10数据集,构建与训练栈式自编码器,提取数据集中图像的特征;基于所提取的特征完成CIFAR-10中任意图像的检索任务并展示效果。

搞清楚pytorch与tensorflow区别


pytorch


学习文档

pytorch是一种python科学计算框架

作用:


无缝替换numpy,通过GPU实现神经网络的加速

通过自动微分机制,让神经网络实现更容易(即自动求导机制)

张量:类似于数组和矩阵,是一种特殊的数据结构。在pytorch中,神经网络的输入、输出以及网络的参数等数据,都是使用张量来进行描述的。

张量的基本方法,持续更新


每个变量中都有两个标志:requires_grad volatile

requires_grad:

如果有一个单一的输入操作需要梯度,它的输出就需要梯度。只有所有输入都不需要梯度时,输出才不需要。

volatile:

只需要一个volatile的输入就会得到一个volatile输出。


tensorflow


学习文档

TensorFlow 是由 Google Brain 团队为深度神经网络(DNN)开发的功能强大的开源软件库

TensorFlow 则还有更多的特点,如下:


支持所有流行语言,如 Python、C++、Java、R和Go。

可以在多种平台上工作,甚至是移动平台和分布式平台。

它受到所有云服务(AWS、Google和Azure)的支持。

Keras——高级神经网络 API,已经与 TensorFlow 整合。

与Torch/Theano 比较,TensorFlow 拥有更好的计算图表可视化。 允

许模型部署到工业生产中,并且容易使用。

有非常好的社区支持。 TensorFlow 不仅仅是一个软件库,它是一套包括 TensorFlow,TensorBoard 和TensorServing 的软件。


搞清楚栈式自编码器的内部原理


1.jpg

 我们构建栈式编码器,用编码器再解码出来的结果和原标签对比进行训练模型,然后用中间编码提取到的特征直接和原图的特征进行对比,得到相似度,实现以图搜图。

整个网络的训练不是一蹴而就的,而是逐层进行的。

2.png

3.png

4.png


效果图


随机取测试集的五张图片,进行以图搜图(TOP8)


提取的分布式特征聚集图像:第一张为原图散点图,第二张以检索的TOP8的TOP1的提取特征散点图为例

5.png

6.png


代码及效果图


欠完备编码器


# -*- coding: utf-8 -*-
"""
Created on Sat Apr 24 18:37:55 2021
@author: ASUS
"""
import torch
import torchvision
import torch.utils.data
import torch.nn as nn
import matplotlib.pyplot as plt
import random #随机取测试集的图片
import time
starttime = time.time()
torch.manual_seed(1)
EPOCH = 10
BATCH_SIZE = 64
LR = 0.005
trainset = torchvision.datasets.CIFAR10(
    root='./data',
    train=True,
    transform=torchvision.transforms.ToTensor(),
    download=False)
testset = torchvision.datasets.CIFAR10(
    root='./data',
    train=False,
    transform=torchvision.transforms.ToTensor(),
    download=False)
# dataloaders
trainloader = torch.utils.data.DataLoader(trainset, batch_size=BATCH_SIZE,
                                        shuffle=True)
testloader = torch.utils.data.DataLoader(testset, batch_size=BATCH_SIZE,
                                        shuffle=True)
train_data = torchvision.datasets.MNIST(
    root='./data',
    train=True,
    transform=torchvision.transforms.ToTensor(),
    download=False
)
loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
class Stack_AutoEncoder(nn.Module):
    def __init__(self):
        super(Stack_AutoEncoder,self).__init__()
        self.encoder  =  nn.Sequential(
            nn.Linear(32*32,256),
            nn.Tanh(),
            nn.Linear(256, 128),
            nn.Tanh(),
            nn.Linear(128, 32),
            nn.Tanh(),
            nn.Linear(32, 16),
            nn.Tanh(),
            nn.Linear(16, 8)
        )
        self.decoder = nn.Sequential(
            nn.Linear(8, 16),
            nn.Tanh(),
            nn.Linear(16, 32),
            nn.Tanh(),
            nn.Linear(32, 128),
            nn.Tanh(),
            nn.Linear(128, 256),
            nn.Tanh(),
            nn.Linear(256, 32*32),
            nn.Sigmoid()
        )
    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded,decoded
Coder = Stack_AutoEncoder()
print(Coder)
optimizer = torch.optim.Adam(Coder.parameters(),lr=LR)
loss_func = nn.MSELoss()
for epoch in range(EPOCH):
    for step,(x,y) in enumerate(trainloader):
        b_x = x.view(-1,32*32)
        b_y = x.view(-1,32*32)
        b_label = y
        encoded , decoded = Coder(b_x)
#         print(encoded)
        loss = loss_func(decoded,b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
#         if step%5 == 0:
    print('Epoch :', epoch,'|','train_loss:%.4f'%loss.data)
torch.save(Coder,'Stack_AutoEncoder.pkl')
print('________________________________________')
print('finish training')
endtime = time.time()
print('训练耗时:',(endtime - starttime))
#以图搜图函数  
Coder = Stack_AutoEncoder()
Coder = torch.load('Stack_AutoEncoder.pkl')
def search_by_image(x,inputImage,K):
    c = ['b','g','r'] #画特征散点图
    loss_func = nn.MSELoss()
    x_ = inputImage.view(-1,32*32)
    encoded , decoded = Coder(x_)
#    print(encoded)
    lossList=[]
    for step,(test_x,y) in enumerate(testset):
        if(step == x):  #去掉原图
            lossList.append((x,1))
            continue
        b_x = test_x.view(-1,32*32)
        b_y = test_x.view(-1,32*32)
        b_label = y
        test_encoded , test_decoded = Coder(b_x)
        loss = loss_func(encoded,test_encoded)
#         loss = round(loss, 4) #保留小数
        lossList.append((step,loss.item()))
    lossList=sorted(lossList,key=lambda x:x[1],reverse=False)[:K]
    print(lossList)
    plt.figure(1)
#    plt.figure(figsize=(10, 10)) 
    trueImage = inputImage.reshape((3, 32, 32)).transpose(0,2)
    plt.imshow(trueImage)
    plt.title('true')
    plt.show()
    for j in range(K):
        showImage = testset[lossList[j][0]][0] #遍历相似度最高列表里的图
        showImage = showImage.reshape((3, 32, 32)).transpose(0,2)
        plt.subplots_adjust(left=4, right=5) #好像没起作用
        plt.subplots(figsize=(8, 8)) 
        plt.subplot(2,4,j+1)
        plt.title("img" + str(lossList[j][0])+"loss:"+str(round(lossList[j][1],5)))
        plt.imshow(showImage)
    plt.show()
    #特征散点图 只显示第一个相似度最高的特征散点图聚集关系
    y_li = encoded.detach()
    x_li = [x for x in range(8)]
    for i in range(len(encoded)):
        plt.scatter(x_li, y_li[i],c = c[i])
    plt.show()
    sim = testset[lossList[j][0]][0].view(-1,32*32)
    sim_encoded , _d = Coder(sim)
#    print(sim_encoded)
    sim_li = sim_encoded.detach() #将torch转为numpy画图要加上detach
    x_li = [x for x in range(8)]
    for i in range(len(encoded)):
        plt.scatter(x_li, sim_li[i],c = c[i])
    plt.show()
for i in range(5):
    x = random.randint(0, len(testset))
    print(x)
    im,_ = testset[x]
    search_by_image(x,inputImage = im,K = 8)
#    break

Epoch : 0 | train_loss:0.0536

Epoch : 1 | train_loss:0.0411

Epoch : 2 | train_loss:0.0293

Epoch : 3 | train_loss:0.0274

Epoch : 4 | train_loss:0.0339

Epoch : 5 | train_loss:0.0337

Epoch : 6 | train_loss:0.0313

Epoch : 7 | train_loss:0.0338

Epoch : 8 | train_loss:0.0279

Epoch : 9 | train_loss:0.0289


finish training

训练耗时: 395.6197159290314

7.png

8.png

9.png

10.png

11.png

12.png


卷积栈式编码器


import numpy as np
import torch
import torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
import torch.optim as optim
import os
class layer1(nn.Module):
    def __init__(self):
        super(layer1,self).__init__()
        self.encoder=nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=5),  # 16*28*28
            nn.BatchNorm2d(16),
            nn.ReLU(inplace=True),
            # nn.MaxPool2d(kernel_size=2,stride=2)#16*15*15
        )
        self.decoder=nn.Sequential(
            nn.ConvTranspose2d(16,3,kernel_size=5,stride=1),
            nn.BatchNorm2d(3),
            nn.ReLU(inplace=True)
        )
    def forward(self,x):
        encode=self.encoder(x)
        decode=self.decoder(encode)
        return encode,decode
class layer2(nn.Module):
    def __init__(self,layer1):
        super(layer2,self).__init__()
        self.layer1=layer1
        self.encoder=nn.Sequential(
            nn.Conv2d(16, 10, kernel_size=5),  # 10*24*24
            nn.BatchNorm2d(10),
            nn.ReLU(inplace=True),
            # nn.MaxPool2d(kernel_size=2,stride=2)#10*6*6
        )
        self.decoder=nn.Sequential(
            nn.ConvTranspose2d(10,3,kernel_size=9,stride=1),
            nn.BatchNorm2d(3),
            nn.ReLU(inplace=True)
        )
    def forward(self,x):
        self.layer1.eval()
        x,_=self.layer1(x)
        encode=self.encoder(x)
        decode=self.decoder(encode)
        return encode,decode
class layer3(nn.Module):
    def __init__(self,layer2):
        super(layer3,self).__init__()
        self.layer2=layer2
        self.encoder=nn.Sequential(
            nn.Conv2d(10, 5, kernel_size=5),  # 5*20*20
            nn.BatchNorm2d(5),
            nn.ReLU(inplace=True)
        )
        self.decoder=nn.Sequential(
            nn.ConvTranspose2d(5,3,kernel_size=13,stride=1),
            nn.BatchNorm2d(3),
            nn.ReLU(inplace=True)
        )
    def forward(self,x):
        self.layer2.eval()
        x,_=self.layer2(x)
        encode=self.encoder(x)
        decode=self.decoder(encode)
        return encode,decode
def train_layer(layer,k):
    loss_fn = torch.nn.MSELoss().to(device)
    optimizer = optim.Adam(layer.parameters(), lr=0.01)
    for epoch in range(10):
        i = 0
        for data, target in trainloader:
            data,target=data.to(device),target.to(device)
            encoded, decoded = layer(data)
            loss = loss_fn(decoded, data)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
            if i % 50 == 0:
                print(loss)
            i += 1
        print("epoch:%d,loss:%f"%(epoch,loss))
        torch.save(layer.state_dict(), '卷积model/layer%d.pkl'%k)
def search_pic(test_dataset,input_img,input_label,K=8):
    model=layer3
    loss_fn = nn.MSELoss()
    input_img=input_img.to(device)
    input_img=input_img.unsqueeze(0)
    inputEncode,inputDecoder = model(input_img)
    lossList = []
    for (i, (testImage,_)) in enumerate(test_dataset):
        testImage=testImage.to(device)
        testImage=testImage.unsqueeze(0)
        testEncode,testDecoder = model(testImage)
        enLoss = loss_fn(inputEncode, testEncode)
        lossList.append((i, np.sqrt(enLoss.item())))
    lossList = sorted(lossList, key=lambda x: x[1], reverse=False)[:K]
    input_img=input_img.squeeze(0)
    input_img=input_img.to(torch.device("cpu"))
    npimg = input_img.numpy()
    npimg = npimg /2 +0.5
    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # transpose()
    plt.show()
    search_labels=[]
    search_dises=[]
    k=0
    for i,dis in lossList:
        search_dises.append(dis)
        plt.subplot(1, 8, k + 1)
        img=test_dataset[i][0].numpy()
        search_labels.append(test_dataset[i][1])
        plt.imshow(np.transpose(img, (1, 2, 0)))
        k+=1
    plt.show()
    print("input label:",input_label)
    print("search labels:",search_labels)
    print("search distence:",search_dises)
if __name__ == '__main__':
#    device=torch.device("cuda:0")
    device = torch.device("cuda"if torch.cuda.is_available() else "cpu")
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    train_dataset = torchvision.datasets.CIFAR10(root='data/',
                                                 train=True,
                                                 transform=transform,
                                                 download=False)
    test_dataset = torchvision.datasets.CIFAR10(root='data/',
                                                train=False,
                                                transform=transform,
                                                download=False)
    trainloader = DataLoader(train_dataset, batch_size=256, shuffle=True)
    layer1 = layer1().to(device)
    if os.path.exists('卷积model/layer1.pkl'):
        layer1.load_state_dict(torch.load("卷积model/layer1.pkl"))
    else:
        train_layer(layer1, 1)
    layer2 = layer2(layer1).to(device)
    if os.path.exists('卷积model/layer2.pkl'):
        layer2.load_state_dict(torch.load("卷积model/layer2.pkl"))
    else:
        train_layer(layer2, 2)
    layer3 = layer3(layer2).to(device)
    if os.path.exists('卷积model/layer3.pkl'):
        layer3.load_state_dict(torch.load("卷积model/layer3.pkl"))
    else:
        train_layer(layer3, 3)
    search_pic(test_dataset,train_dataset[0][0],train_dataset[0][1])

13.png

我把生成和模型和代码会放到资源上,方便大家下载


栈式编码器

import numpy as np
import torch
import torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
import torch.optim as optim
import os
class Layer1(nn.Module):
    def __init__(self,hidden_size):
        super(Layer1, self).__init__()
        self.hidden_size=hidden_size
        self.encoder = nn.Linear(3 * 32 * 32, hidden_size)
        self.decoder = nn.Linear(hidden_size, 3 * 32 * 32)
    def forward(self, x):
        x = x.view(-1, 3 * 32 * 32)
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded
class Layer2(nn.Module):
    def __init__(self,layer1,hidden_size):
        super(Layer2, self).__init__()
        self.layer1=layer1
        self.hidden_size=hidden_size
        self.encoder = nn.Linear(layer1.hidden_size, hidden_size)
        self.decoder = nn.Sequential(
            nn.Linear(hidden_size, self.layer1.hidden_size),
            nn.Linear(self.layer1.hidden_size,3*32*32)
        )
    def forward(self, x):
        #保证前一层参数不变
        self.layer1.eval()
        x = x.view(-1, 3 * 32 * 32)
        x,_=layer1(x)
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded
class Layer3(nn.Module):
    def __init__(self,layer2,hidden_size):
        super(Layer3, self).__init__()
        self.layer2=layer2
        self.hidden_size=hidden_size
        self.encoder = nn.Linear(layer2.hidden_size, hidden_size)
        self.decoder = nn.Sequential(
            nn.Linear(hidden_size, self.layer2.hidden_size),
            nn.Linear(self.layer2.hidden_size,self.layer2.layer1.hidden_size),
            nn.Linear(self.layer2.layer1.hidden_size,3*32*32)
        )
    def forward(self, x):
        #保证前一层参数不变
        self.layer2.eval()
        x = x.view(-1, 3 * 32 * 32)
        x,_=self.layer2(x)
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded
def train_layer(layer,k):
    loss_fn = torch.nn.MSELoss().to(device)
    optimizer1 = optim.Adam(layer.parameters(), lr=0.01)
    for epoch in range(20):
        i = 0
        for data, target in trainloader:
            data,target=data.to(device),target.to(device)
            encoded, decoded = layer(data)
            label = data.view(-1, 3072)
            loss = loss_fn(decoded, label)
            loss.backward()
            optimizer1.step()
            optimizer1.zero_grad()
            if i % 50 == 0:
                print(loss)
            i += 1
        print("epoch:%d,loss:%f"%(epoch,loss))
        torch.save(layer.state_dict(), '全连接model/layer%d.pkl'%k)
def search_pic(test_dataset,input_img,input_label,K=8):
    model=layer3
    loss_fn = nn.MSELoss()
    input_img=input_img.to(device)
    input_img=input_img.unsqueeze(0)
    inputEncode,inputDecoder = model(input_img)
    lossList = []
    for (i, (testImage,_)) in enumerate(test_dataset):
        testImage=testImage.to(device)
        testEncode,testDecoder = model(testImage)
        enLoss = loss_fn(inputEncode, testEncode)
        lossList.append((i, np.sqrt(enLoss.item())))
    lossList = sorted(lossList, key=lambda x: x[1], reverse=False)[:K]
    input_img=input_img.squeeze(0)
    input_img=input_img.to(torch.device("cpu"))
    npimg = input_img.numpy()
    npimg = npimg / 2 + 0.5
    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # transpose()
    plt.show()
    search_labels=[]
    search_dises=[]
    k=0
    for i,dis in lossList:
        search_dises.append(dis)
        plt.subplot(1, 8, k + 1)
        img=test_dataset[i][0].numpy()
        search_labels.append(test_dataset[i][1])
        plt.imshow(np.transpose(img, (1, 2, 0)))
        k+=1
    plt.show()
    print("input label:",input_label)
    print("search labels:",search_labels)
    print("search distence:",search_dises)
if __name__ == '__main__':
#    device=torch.device("cuda:0")
    device = torch.device("cuda"if torch.cuda.is_available() else "cpu")
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    train_dataset = torchvision.datasets.CIFAR10(root='data/',
                                                 train=True,
                                                 transform=transform,
                                                 download=False)
    trainloader = DataLoader(train_dataset, batch_size=256, shuffle=True)
    test_dataset = torchvision.datasets.CIFAR10(root='data/',
                                                 train=False,
                                                 transform=transform,
                                                 download=False)
    layer1=Layer1(2048).to(device)
    if os.path.exists('全连接model/layer1.pkl'):
        layer1.load_state_dict(torch.load("全连接model/layer1.pkl"))
    else:
        train_layer(layer1,1)
    layer2=Layer2(layer1,1024).to(device)
    if os.path.exists('全连接model/layer2.pkl'):
        layer2.load_state_dict(torch.load("全连接model/layer2.pkl"))
    else:
        train_layer(layer2,2)
    layer3 = Layer3(layer2, 512).to(device)
    if os.path.exists('全连接model/layer3.pkl'):
        layer3.load_state_dict(torch.load("全连接model/layer3.pkl"))
    else:
        train_layer(layer3, 3)
    search_pic(test_dataset,train_dataset[8][0],train_dataset[8][1])
相关文章
|
2月前
|
机器学习/深度学习 人工智能 运维
深度学习中的自编码器:从理论到实践
在深度学习的众多模型中,自编码器以其独特的数据压缩和特征学习功能脱颖而出。本文将深入浅出地介绍自编码器的工作原理、变体及其在实际问题中的应用,旨在为初学者和从业者提供一份实用的指南。通过简洁明了的语言和直观的例子,我们将一起探索这一强大工具如何帮助解决现实世界的问题。
|
2月前
|
机器学习/深度学习 算法 TensorFlow
深度学习中的自编码器:从理论到实践
【8月更文挑战第29天】本文旨在揭示自编码器的神秘面纱,带领读者领略其在数据表示学习中的独特魅力。我们将从其数学原理出发,逐步深入到网络架构的搭建,最后通过代码示例实现一个简易的自编码器模型。无论是深度学习新手还是经验丰富的研究者,这篇文章都将为你提供新的视角和实用知识。
|
7天前
|
并行计算 PyTorch 算法框架/工具
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
文章介绍了如何在CUDA 12.1、CUDNN 8.9和PyTorch 2.3.1环境下实现自定义数据集的训练,包括环境配置、预览结果和核心步骤,以及遇到问题的解决方法和参考链接。
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
|
4天前
|
机器学习/深度学习 存储 自然语言处理
深度学习之任务序列中的快速适应
基于深度学习的任务序列中的快速适应是指模型在接连处理不同任务时,能够迅速调整和优化自身以适应新任务的能力。这种能力在动态环境和多任务学习中尤为重要,旨在减少训练时间和资源需求。
15 3
|
25天前
|
机器学习/深度学习 人工智能 算法
操作系统的未来:从多任务到深度学习的演变之路
本文将探讨操作系统如何从处理简单多任务发展到支持复杂的深度学习任务。我们将分析现代操作系统面临的新挑战,以及它们如何适应人工智能和大数据时代的要求。文章不仅回顾过去,也展望未来,思考操作系统在技术演进中的角色和方向。
35 3
|
27天前
|
机器学习/深度学习 数据采集 数据可视化
深度学习实践:构建并训练卷积神经网络(CNN)对CIFAR-10数据集进行分类
本文详细介绍如何使用PyTorch构建并训练卷积神经网络(CNN)对CIFAR-10数据集进行图像分类。从数据预处理、模型定义到训练过程及结果可视化,文章全面展示了深度学习项目的全流程。通过实际操作,读者可以深入了解CNN在图像分类任务中的应用,并掌握PyTorch的基本使用方法。希望本文为您的深度学习项目提供有价值的参考与启示。
|
1月前
|
存储 缓存 PyTorch
使用PyTorch从零构建Llama 3
本文将详细指导如何从零开始构建完整的Llama 3模型架构,并在自定义数据集上执行训练和推理。
47 1
|
25天前
|
机器学习/深度学习 算法
深度学习中的自编码器:探索无监督学习的秘密
在深度学习的浩瀚海洋中,自编码器犹如一座神秘的灯塔,指引着无监督学习的方向。本文将带你航行于自编码器的构造与原理之间,探索它们如何通过编码输入数据、重构输出来捕捉数据的内在特征。我们将一起见证自编码器在降维、去噪、生成模型等方面的应用奇迹,并思考其在深度学习未来中的角色与挑战。准备好了吗?让我们启航,揭开自编码器的神秘面纱。
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:使用Python和TensorFlow构建你的第一个神经网络
【8月更文挑战第31天】 本文是一篇面向初学者的深度学习指南,旨在通过简洁明了的语言引导读者了解并实现他们的第一个神经网络。我们将一起探索深度学习的基本概念,并逐步构建一个能够识别手写数字的简单模型。文章将展示如何使用Python语言和TensorFlow框架来训练我们的网络,并通过直观的例子使抽象的概念具体化。无论你是编程新手还是深度学习领域的新兵,这篇文章都将成为你探索这个激动人心领域的垫脚石。
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习之旅:构建你的第一个神经网络
【8月更文挑战第31天】在人工智能的浪潮下,深度学习技术正以前所未有的速度改变世界。本文将带你走进深度学习的大门,通过构建一个简单的神经网络模型,探索其背后的原理与实践。我们将从基础概念入手,逐步实现一个能够识别手写数字的神经网络,并在此过程中揭示深度学习的魅力和力量。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往深度学习世界的新窗户。

热门文章

最新文章

下一篇
无影云桌面