使用降噪自编码器【DAE】对车流量数据进行降维

一.自动编码器

时序数据常常表现为高维度的特点,过多的冗余属性不仅徒增训练负担,还会对模型的预测效果带来负面影响。通过使用时序数据降维的方法对训练数据进行预处理,可以大幅减少冗余维度的数据,从而提高训练速度和预测性能。Bengio等人受多层受限玻尔兹曼机堆叠而成的深度信念网络启发,由此提出了一种具有多层隐藏层的深度神经网络结构,这种结构中包含自动编码器( Auto- Encoder,AE) [60。深度自动编码器的结构如图2.1所示,输入x经过- -层-层隐藏层的编码,得到压缩后的编码h,,然后经过层层解码后得到输出x'。

图一 自动编码器结构示意图 

深度自动编码器以输入对输出之间的误差作为损失函数,使用反向传播算法不断迭代整个网络的参数,得到最终的编码器模型。自动编码器以无监督的方式学习时序数据不同属性间的相关性,从而尽可能保留原始数据的特征。若输入的样本数量为N个,损失函数L(x,x)的表示为:

L(x,x') = \frac{1}{N} \sum_{i = 1}^{N}(\frac{1}{2}\left \| x'-x\right \|^{2})

二.降噪自动编码器

Vincent在一篇论文中提出了一种基于自动编码器改良的降噪自动编码器(Denoising Auto Encoder, DAE) , 这种编码器相比于原始的自动编码器具有更好从原始数据中提取出关键特征的能力162]。首先以一定概率将原始数据x矩阵中的部分数据置0,得到丢失数据的残缺输入矩阵x,然后以x为输入,一层一层编码得到压缩后的矩阵y,再通过一层一层编码得到输出x,根据x'和x之间的误差进行网络参数学习和迭代,这样就得到想要的压缩后的编码y。这种原理类似于深度神经网络中的Dropout,通过看似不全的训练过程,实际上能够得到泛化能力和鲁棒性更好的模型。降噪自动编码器结构如图。

图二 降噪自动编码器结构

 

三.数据集介绍

点这里下载数据集

该数据集包括每小时的天气特征和假日对交通量的影响。

 四.模型介绍

        编码维数小于输入维数时的欠完备自编码器可以学习到数据分布的最显著的特征。我们已经知道如果赋予这类自编码器过大的容量,它就不能学到一个任何有用的信息。

        理想情况下,根据要剑魔的数据分布的复杂性,选择合适的编码维数和编码器、解码器容量就可以成功训练任意架构的自编码器。降噪自编码器提供这样的能力。

import torch
import torch.nn as nn



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

        # Encoder
        self.encoder = nn.Sequential(
            nn.Linear(64, 128),
            nn.ReLU(),
            nn.Linear(128, 256),
            nn.ReLU(),
            nn.Linear(256, 512),
            nn.ReLU(),
            nn.Linear(512, 1024),
        )

        # Decoder
        self.decoder = nn.Sequential(
            nn.Linear(1024, 512),
            nn.ReLU(),
            nn.Linear(512, 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 64),

            nn.Sigmoid()
        )

    def forward(self, inputs):
        z = self.encoder(inputs)
        outputs = self.decoder(z)

        return z, outputs

 五.训练文件

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader,Dataset
import numpy as np
from model import DenoisingAutoencoder
from sklearn import preprocessing
import pandas as pd
import matplotlib.pyplot as plt

# global constants全局参数
BATCH_SIZE = 32
N_INP = 64
N_EPOCHS = 100
NOISE = 0.15

#  data loading数据加载
def custom_ts_multi_data_prep(dataset, start, window): #数据折叠
    X = []
    end = len(dataset)
    start = start + window
    for i in range(start, end):
        if i % window == 0:
            indices = range(i - window, i)
            X.append(dataset[indices].T)

    return np.array(X)

class noisedDataset(Dataset):

    def __init__(self, datasetclean):

        self.clean = datasetclean
        # self.transform = transform

    def __len__(self):
        return len(self.clean)

    def __getitem__(self, idx): #参数idx表示图片和标签在总数据集中的Index。

        xClean = self.clean[idx]

        return  xClean



df = pd.read_csv(r'E:\mine_python\GRU\Metro-Interstate-Traffic-Volume-Encoded.csv')
x_scaler = preprocessing.MinMaxScaler()
dataX_temp = x_scaler.fit_transform(df[['traffic_volume']])
hist_window = 64
dataX = custom_ts_multi_data_prep(dataX_temp, 0, hist_window)
train_set=noisedDataset(dataX)#tsfms) #datasetnoised, datasetclean, labels, transform


train_loader = DataLoader(
        dataset=train_set,
        batch_size=BATCH_SIZE,
        shuffle=False,drop_last=True)

running_loss = 0
epochloss = 0

l = len(train_loader)
auto_encoder = DenoisingAutoencoder()
optimizer = optim.Adam(auto_encoder.parameters(), lr=1e-3)
losslist = list()
criterion = nn.MSELoss()
#开始训练
for epoch in range(N_EPOCHS):
    for (x,z) in enumerate(train_loader):
        y = z.view(z.size()[0], -1)
        noise = np.random.choice([1, 0], size=(BATCH_SIZE, N_INP), p=[NOISE, 1 - NOISE])
        inp = y * torch.FloatTensor(noise)
        inp = inp.float()
        y = y.float()
        mid,decoded = auto_encoder(inp)
        loss = criterion(decoded,y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        epochloss += loss.item()
    losslist.append(running_loss / l)
    running_loss = 0
    print("======> epoch: {}/{}, Loss:{}".format(epoch, N_EPOCHS, loss.item()))


t_new_sum =np.empty((1,0))
with torch.no_grad():
    for (x, z) in enumerate(train_loader ):
        y = z.view(z.size()[0], -1)
        # noise = np.random.choice([1, 0], size=(BATCH_SIZE, N_INP), p=[NOISE, 1 - NOISE])
        # inp = z * torch.FloatTensor(noise)
        inp = y.float()
        mid,decoded = auto_encoder(inp)
        decoded  = decoded .view(1, -1)
        output = decoded.detach().cpu().numpy()
        t_new_sum = np.hstack((t_new_sum, output))

plt.plot(range(len(losslist)),losslist)
plt.show()
loss下降图像

 


版权声明:本文为m0_71452661原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。