pt第8章 基于线性层的自编码网络

pt第8章 基于线性层的自编码网络

导入库


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from sklearn.manifold import TSNE
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.metrics import classification_report, accuracy_score
import torch
from torch import nn
import torch.nn.functional as F
import torch.utils.data as Data
import torch.optim as optim

from torchvision import transforms
from torchvision.datasets import MNIST  
from torchvision.utils import make_grid

数据准备

# 使用手写体数据,准备训练数据集
train_data = MNIST(root="./data/MNIST",
                    train=True,
                    transform=transforms.ToTensor(),
                    download=True
                  )

# 将图像数据转化为向量数据
train_data_x = train_data.data.type(torch.FloatTensor) / 255.0
train_data_x = train_data_x.reshape(train_data_x.shape[0], -1)
train_data_y = train_data.targets

# 定义一个数据加载器
train_loader = Data.DataLoader(dataset=train_data_x,
                                batch_size=64,
                                shuffle=True,
                                num_workers=2
                              )

# 对测试数据集进行导入
test_data = MNIST(root="./data/MNIST",  
                   train=False,
                   transform=transforms.ToTensor(),
                   download=True
                 )

# 为测试数据添加一个通道纬度,获取测试数据的X和Y
test_data_x = test_data.data.type(torch.FloatTensor) / 255.0
test_data_x = test_data_x.reshape(test_data_x.shape[0], -1)  # 将图像数据展平成向量
test_data_y = test_data.targets

# 打印数据集的形状信息
print("训练数据集:", train_data_x.shape)
print("测试数据集 :", test_data_x.shape)
训练数据集: torch.Size([60000, 784])
测试数据集 : torch.Size([10000, 784])
for step, b_x in enumerate(train_loader):
    if step > 0:
        break
im = make_grid(b_x.reshape((-1,1,28,28)))
im = im.data.numpy().transpose((1,2,0))
# 显示图像
plt.figure()
plt.imshow(im) 
plt.axis("off")
plt.show()


在这里插入图片描述

模型定义

自编码器

class EnDecoder(nn.Module):
    def __init__(self):
        super(EnDecoder, self).__init__()

        self.Encoder = nn.Sequential(
            nn.Linear(784, 512),
            nn.Tanh(),
            nn.Linear(512, 256),
            nn.Tanh(),
            nn.Linear(256, 128),
            nn.Tanh(),
            nn.Linear(128, 3),
            nn.Tanh()
        )
        # 定义 Decoder
        self.Decoder = nn.Sequential(
            nn.Linear(3, 128),
            nn.Tanh(),
            nn.Linear(128, 256),
            nn.Tanh(),
            nn.Linear(256, 512),
            nn.Tanh(),
            nn.Linear(512, 784),
            nn.Sigmoid()
        )

    def forward(self, x):
        encoder = self.Encoder(x)
        decoder = self.Decoder(encoder)
        return encoder, decoder
edmodel = EnDecoder()
edmodel
EnDecoder(
  (Encoder): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): Tanh()
    (2): Linear(in_features=512, out_features=256, bias=True)
    (3): Tanh()
    (4): Linear(in_features=256, out_features=128, bias=True)
    (5): Tanh()
    (6): Linear(in_features=128, out_features=3, bias=True)
    (7): Tanh()
  )
  (Decoder): Sequential(
    (0): Linear(in_features=3, out_features=128, bias=True)
    (1): Tanh()
    (2): Linear(in_features=128, out_features=256, bias=True)
    (3): Tanh()
    (4): Linear(in_features=256, out_features=512, bias=True)
    (5): Tanh()
    (6): Linear(in_features=512, out_features=784, bias=True)
    (7): Sigmoid()
  )
)

训练过程

import hiddenlayer as hl
optimizer = torch.optim.Adam(edmodel.parameters(), lr=0.003)
loss_func = nn.MSELoss()
# 记录
history1 = hl.History()
# 使用 Canvas 进行可视化
canvas = hl.Canvas()
train_num = 0
val_num = 0
# 对模型进行迭代训练
for epoch in range(10):
    train_loss_epoch = 0
    # 对训练数据的加载器进行迭代计算
    for step, b_x in enumerate(train_loader):
        _,output = edmodel(b_x)
        loss = loss_func(output, b_x)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        train_loss_epoch += loss.item() * b_x.size(0)
        train_num += b_x.size(0)
    # 计算一个epoch 的损失
    train_loss = train_loss_epoch / train_num
    # 保存每个 epoch 上的输出 loss
    history1.log(epoch, train_loss=train_loss)

    # 可视网络训练的过程
    with canvas:
        canvas.draw_plot(history1["train_loss"])


在这里插入图片描述

可视化一个批次的图像

edmodel.eval()  # 将模型设置为评估模式
_, test_decoder_output = edmodel(test_data_x[0:100, :]) ##预测前一百章
# 可视化原始的图像
plt.figure(figsize=(6, 6))
for ii in range(test_decoder_output.shape[0]):
    plt.subplot(10, 10, ii + 1)
    im = test_data_x[ii, :]  #使用原始图像数据
    im = im.numpy().reshape(28, 28)  #将图像数据转换为 numpy 数组并重塑为 28x28
    plt.imshow(im)
    plt.axis("off")  #不显示坐标轴
plt.show()
#可视化编码后的图像
plt.figure(figsize=(6, 6))
for ii in range(test_decoder_output.shape[0]):
    plt.subplot(10, 10, ii + 1)
    im = test_decoder_output[ii, :]  #使用编码后的图像数据
    im = im.data.numpy().reshape(28, 28)
    plt.imshow(im)
    plt.axis("off")
plt.show()

在这里插入图片描述

在这里插入图片描述

edmodel.eval()  # 将模型设置为评估模式
# 获取前500个样本的自编码后的特征
TEST_num = 500
test_encoder, _ = edmodel(test_data_x[0:TEST_num, :])

# 打印编码后的特征的形状
print("test_encoder_output.shape:", test_encoder.shape)
test_encoder_output.shape: torch.Size([500, 3])

3D可视化自编码特征

from mpl_toolkits.mplot3d import Axes3D
## 将 3 个维度的特征进行可视化
test_encoder_arr = test_encoder.data.numpy()
print(test_encoder_arr)
# 创建图形和轴对象用于3D可视化
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_axes(Axes3D(fig))
# 从编码的特征中提取每个维度的数据
X = test_encoder_arr[:, 0]
Y = test_encoder_arr[:, 1]
Z = test_encoder_arr[:, 2]
# 设置坐标轴的范围
ax1.set_xlim([min(X), max(X)])
ax1.set_ylim([min(Y), max(Y)])
ax1.set_zlim([min(Z), max(Z)])
# 在每个点的位置上添加标签文本
for ii in range(test_encoder.shape[0]):
    text = test_data_y.data.numpy()[ii]
    ax1.text(X[ii], Y[ii], Z[ii], str(text), 
            fontsize=10,
            bbox=dict(boxstyle="round", 
                      facecolor=plt.cm.Set1(text), 
                      alpha=0.7)
            )
plt.show()
[[ 0.31008023  0.49149397 -0.95673186]
 [-0.9799462  -0.10318345  0.78829974]
 [-0.79156405  0.91067296 -0.41046414]
 ...
 [ 0.37451348 -0.18652499 -0.5412912 ]
 [ 0.71749717 -0.57455105  0.60234135]
 [ 0.7848706  -0.30445015  0.17963228]]

在这里插入图片描述

使用自编码特征

# 自编码后的特征训练集和测试集
train_ed_x,_ = edmodel(train_data_x)
train_ed_x = train_ed_x.data.numpy()
train_y = train_data_y.data.numpy()

test_ed_x,_ = edmodel(test_data_x)
test_ed_x = test_ed_x.data.numpy()
test_y = test_data_y.data.numpy()

使用PCA降维特征

# PCA 降维获得的训练集和测试集前 3 个主成分
pcamodel = PCA(n_components=3, random_state=10)
train_pca_x = pcamodel.fit_transform(train_data_x.data.numpy())
test_pca_x = pcamodel.transform(test_data_x.data.numpy())
print(train_pca_x.shape)
(60000, 3)
# 使用自编码数据建立分类器,训练和预测
encodersvc = SVC(kernel="rbf", random_state=123)
encodersvc.fit(train_ed_x, train_y)

edsvc_pred = encodersvc.predict(test_ed_x)
print(classification_report(test_y, edsvc_pred))
print("模型精度", accuracy_score(test_y, edsvc_pred))
              precision    recall  f1-score   support

           0       0.93      0.97      0.95       980
           1       0.98      0.98      0.98      1135
           2       0.95      0.90      0.92      1032
           3       0.89      0.86      0.87      1010
           4       0.79      0.74      0.77       982
           5       0.81      0.89      0.85       892
           6       0.94      0.94      0.94       958
           7       0.93      0.90      0.91      1028
           8       0.84      0.83      0.83       974
           9       0.70      0.76      0.73      1009

    accuracy                           0.88     10000
   macro avg       0.88      0.88      0.88     10000
weighted avg       0.88      0.88      0.88     10000

模型精度 0.8772
# 使用 PCA 降维数据建立分类器,训练和预测
pcasvc = SVC(kernel="rbf", random_state=123)
pcasvc.fit(train_pca_x, train_y)

# 进行预测
pcasvc_pred = pcasvc.predict(test_pca_x)
# 打印分类报告和模型精度
print(classification_report(test_y, pcasvc_pred))
print("模型精度", accuracy_score(test_y, pcasvc_pred))
              precision    recall  f1-score   support

           0       0.68      0.74      0.71       980
           1       0.93      0.95      0.94      1135
           2       0.51      0.49      0.50      1032
           3       0.65      0.64      0.64      1010
           4       0.41      0.55      0.47       982
           5       0.42      0.31      0.36       892
           6       0.38      0.60      0.47       958
           7       0.52      0.51      0.52      1028
           8       0.41      0.26      0.32       974
           9       0.44      0.30      0.36      1009

    accuracy                           0.54     10000
   macro avg       0.54      0.54      0.53     10000
weighted avg       0.54      0.54      0.54     10000

模型精度 0.5427



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值