Нейронная сеть с автоматическим кодированием — это алгоритм обучения без учителя, цель которого — сделать выходное значение как можно более похожим на входное значение.
1. Структура сети
Простая модель автоэнкодера представляет собой трехслойную модель нейронной сети, которая включает в себя входной слой, скрытый слой и выходной слой реконструкции.
На практике мы часто проектируем двухслойную модель.
- уровень кодирования
- уровень декодирования
Уровень кодирования отвечает за считывание данных и выполнение серии линейных преобразований для сжатия входных выборок в скрытый слой.
Слой декодирования должен восстановить сложную сетевую структуру и сделать восстановленное значение максимально похожим на входное значение.
2. Функция
Цель нейронной сети с автоматическим кодированием — добиться максимально похожих на входные результаты выходных результатов, и очень важным шагом является «сжатие» входных данных, то есть сопоставление входных признаков со скрытым слоем, и скрыть Размер слоя на самом деле намного меньше размера входного образца, который является первой функцией автоэнкодераРеализовать уменьшение размерности признаков:Он всегда изучает наиболее важные признаки, чтобы подготовить почву для последующих операций декодирования, поэтому мы можем получить вектор основных признаков входных данных после слоя кодирования.
Вторая функция заключается в его первоначальном намерении добиться приблизительного результата. После того, как модель научилась кодировать и декодировать, мы можем сначала закодировать, чтобы получить основные характеристики входных данных, а затем декодировать, чтобы получить выходные данные, которые приближаются к исходным входным данным. Затем мы также можем сами установить некоторые закодированные функции, а затем использовать декодер для декодирования, мы можем получить некоторые «удивительные» результаты. Говоря об этом, на самом деле его можно связать со следующей генеративно-состязательной сетью.Когда мы обучаем GAN, мы можем использовать генеративную модель для генерации изображений из входного случайного шума; особенно в styleGAN мы вводим скрытые факторы, промежуточный скрытое пространство получается через сеть сопоставления, и благодаря сети сопоставления и AdaIN мы можем даже не заботиться о начальном вводе, и нам нужно только добавить некоторый случайный шум перед сверткой и AdaIN, чтобы контролировать характеристики сгенерированного изображения.
3. Раздел кода
Демонстрационный код на этот раз написан на основе pytorch, а версия tensorflow в будущем будет заполнена пустым пространством.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch
from torch import nn,optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets,transforms
from torchvision.utils import save_image
import seaborn as sns
import os
import warnings
plt.rcParams['font.sans-serif']='SimHei'
plt.rcParams['axes.unicode_minus']=False
warnings.filterwarnings('ignore')
%matplotlib inline
# 设置参数
batch_size = 100
learning_rate=1e-2
num_epoches=3
# 导入数据集
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor())
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=False)
# 定义网络
class autoencoder(nn.Module):
def __init__(self):
super().__init__()
# 编码器
self.encoder = nn.Sequential(
nn.Linear(28*28, 128),
nn.Tanh(),
nn.Linear(128, 64),
nn.Tanh(),
nn.Linear(64, 12),
nn.Tanh(),
nn.Linear(12, 3),
)
# 解码器
self.decoder = nn.Sequential(
nn.Linear(3, 12),
nn.Tanh(),
nn.Linear(12, 64),
nn.Tanh(),
nn.Linear(64, 128),
nn.Tanh(),
nn.Linear(128, 28*28),
nn.Sigmoid(),
)
def forward(self, x):
encode = self.encoder(x)
decode = self.decoder(encode)
return encode, decode
# 实例化
net = autoencoder().cuda()
# 损失函数以及优化函数
loss_func = nn.MSELoss().cuda()
optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)
# 训练过程可视化
def list_img(i, img, title):
img = img.reshape(28, 28)
plt.subplot(2, 5, i+1)
plt.imshow(img)
plt.title('%s' % (title))
def generate_test(inputs, title=''):
plt.figure(figsize=(15, 6))
for i in range(len(inputs)):
img = inputs[i].view(-1, 28*28).cuda()
hidden, outputs = net(img)
list_img(i, outputs.cpu().detach().numpy(), title)
plt.show()
# 训练部分
result = []
test_inputs = []
hiddens=[]
plt.figure(figsize=(15, 6))
for i, (img, _) in enumerate(test_loader):
if i > 4 : break
test_inputs.append(img)
list_img(i, img.numpy(), 'truth')
plt.show()
for e in range(num_epoches):
for i, (inputs, _) in enumerate(train_loader):
inputs = inputs.view(-1, 28*28).cuda()
optimizer.zero_grad()
hidden, outputs = net(inputs)
hiddens.append(hidden)
loss = loss_func(outputs, inputs)
loss.backward()
optimizer.step()
if i % 100 == 0:
result.append(float(loss))
if i % 500 == 0:
generate_test(test_inputs, 'generation')
В конце видно, что изображения, сгенерированные при обучении модели, и реальные изображения на входе очень близки.Ошибка всего 0,03
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
# 可视化结果
view_data = Variable((train_dataset.train_data[:500].type(torch.FloatTensor).view(-1, 28*28) / 255. - 0.5) / 0.5).cuda()
encode, _ = net(view_data) # 提取压缩的特征值
fig = plt.figure(2)
ax = Axes3D(fig) # 3D 图
# x, y, z 的数据值
X = encode.data[:, 0].cpu().numpy()
Y = encode.data[:, 1].cpu().numpy()
Z = encode.data[:, 2].cpu().numpy()
values = train_dataset.train_labels[:500].numpy() # 标签值
for x, y, z, s in zip(X, Y, Z, values):
c = cm.rainbow(int(255*s/9)) # 上色
ax.text(x, y, z, s, backgroundcolor=c) # 标位子
ax.set_xlim(X.min(), X.max())
ax.set_ylim(Y.min(), Y.max())
ax.set_zlim(Z.min(), Z.max())
plt.show()
В трехмерном пространстве распределение отдельных чисел выглядит следующим образом
Наконец, в соответствии с положением на карте, запишите несколько случайных входных признаков в декодер, чтобы посмотреть, сможет ли он получить изображение, которое мы хотим.
# 看图上4的位置大概在0附近,-0.5附近,-0.5-0之间
code = Variable(torch.FloatTensor([[0.02,-0.543,-0.012]])).cuda()
decode = net.decoder(code)
decode_img = decode.data.reshape(28,28).cpu().numpy() * 255
plt.imshow(decode_img.astype('uint8')) # 生成图片
plt.show()
Входные данные, которые я задал случайным образом, очень хорошо оправдали мои ожидания, что, если я задам какие-то данные, которых нет на графике?
В итоге знак вопроса, что очень интересно