1.自编码介绍
- 自编码是一种数据压缩算法,类似于主成分分析法
- 特性
- 自编码与数据相关,你的自编器是通过训练才能使用的,如果你使用手写数字作为训练集,那么编码器在压缩手写数字是非常好的,对于其他数据是非常不好的。
- 自动编码器是有损的,即输入和输出的数据是有一些不同的
- 自动编码器是从数据样本中自动学习的
2.实战压缩手写数字
2.1 导入我们的库
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt
import numpy as np
# 随机种子
torch.manual_seed(1)
2.2 定义超参数
# Hyper Parameters
EPOCH = 2
BATCH_SIZE = 64
LR = 0.01
DOWNLOAD_MNIST = True
N_TEST_IMG = 5
2.3 加载数据集,并展示其中一个数据
# 导入数据
train_data = torchvision.datasets.MNIST(
root='./mnist/',
train=True,
transform=torchvision.transforms.ToTensor(),
download=DOWNLOAD_MNIST,
)
# plot one example
print(train_data.train_data.size()) # (60000, 28, 28)
print(train_data.train_labels.size()) # (60000)
plt.imshow(train_data.train_data[3].numpy(),cmap='gray')
plt.title('%i' % train_data.train_labels[3])
plt.show()
# 打包数据
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE,shuffle=True)
2.4 定义我们的AutoEncoder
class AutoEncoder(nn.Module):
def __init__(self):
super(AutoEncoder,self).__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() # 映射到0-1范围内
)
˽˽˽˽
def forward(self,x):
encoded = self.encoder(x)
decoded = self.decoder(encoded)
return encoded, decoded
autoencoder = AutoEncoder()
optimizer = torch.optim.Adam(autoencoder.parameters(),lr=LR)
loss_func = nn.MSELoss()
2.5 初始化图片
# 初始化照片
f ,a = plt.subplots(2,N_TEST_IMG,figsize=(15,12))
plt.ion() # 开启动图
# 画初始的5个图
view_data = train_data.train_data[:N_TEST_IMG].view(-1, 28*28).type(torch.FloatTensor)/255
for i in range(N_TEST_IMG):
a[0][i].imshow(np.reshape(view_data.numpy()[i],(28,28)),cmap='gray')
a[0][i].set_xticks(())
2.6 训练我们的AutoEncoder
for epoch in range(EPOCH):
for step, (x, b_label) in enumerate (train_loader):
b_x = x.view(-1,28*28) # batch x,shape (batch,28*28)
b_y = x.view(-1,28*28) # batch x,shape (batch,28*28)
encoded, decoded = autoencoder(b_x)
loss = loss_func(decoded,b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if step % 100 == 0:
print('Epoch:',epoch,'| train loss: %.4f' % loss.data.numpy())
# 看看测试的情况 解码后的图片
_, decoded_data = autoencoder(view_data)
for i in range(N_TEST_IMG):
a[1][i].clear()
a[1][i].imshow(np.reshape(decoded_data.data.numpy()[i],(28,28)),cmap='gray') # 展示我们压缩在解码的图片
a[1][i].set_xticks(())
plt.draw();plt.pause(0.05)
plt.ioff()
plt.show()
2.7 展示我们的压缩后的数据
# 画一个3D的图,来展示 压缩后的精髓数据
view_data = train_data.train_data[:200].view(-1, 28*28).type(torch.FloatTensor)/255.
encoded_data, _ = autoencoder(view_data)
# 3D图的初始化
fig = plt.figure(2); ax = Axes3D(fig)
# 提取X,Y,Z
X, Y, Z = encoded_data.data[:, 0].numpy(), encoded_data.data[:, 1].numpy(), encoded_data.data[:, 2].numpy()
# 制定标签
values = train_data.train_labels[:200].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()
可以使Arch的neovim使用系统剪切版
sudo pacman -S xsel