Pytorch autoencoder降維

1. 我們一般面對的數據是numpy array的格式,如何轉變爲支持batch_size,shuffle等功能的數據集呢,pytorch 採用 DataLoader類來實現,參考源碼

# DataLoader 類的構造函數

def __init__(self, dataset, batch_size=1, shuffle=False, sampler=None,
                 batch_sampler=None, num_workers=0, collate_fn=None,
                 pin_memory=False, drop_last=False, timeout=0,
                 worker_init_fn=None, multiprocessing_context=None):
    torch._C._log_api_usage_once("python.data_loader")
    
# TensorDataset 類,繼承了Dataset
class TensorDataset(Dataset)

我們採用如下步驟:1. numpy array -> tensor    2.tensor -> dataset  3.通過dataloader加載dataset;具體實現demo如下:

import torch
from torch.utils.data import DataLoader,Dataset,TensorDataset
from sklearn.datasets import load_iris

iris=load_iris()
data=iris.data

tensor_x=torch.from_numpy(data)
my_dataset=TensorDataset(tensor_x)
my_dataset_loader=DataLoader(my_dataset,batch_size=10,shuffle=False)
print(isinstance(my_dataset,Dataset))  # 返回是true

 

  • 一些基本概念
    • batch,一般來說會採用梯度下降的方法進行迭代,估計參數;深度學習中一般採用sgd,batch就是每次迭代參數用到的樣本量
    • epoch,輪訓的次數;1個epoch等於使用訓練集中全部樣本訓練一次

 

  • autoencoder原理和作用

 

image.png

 

針對iris數據集,構建了一個autoencoder模型

 

class autoencode(nn.Module):                    
    def __init__(self):                         
        super(autoencode,self).__init__()       
        self.encoder=nn.Sequential(             
            nn.Linear(4, 3),                    
            nn.Tanh(),                          
            nn.Linear(3, 2),                    
        )                                       
        self.decoder=nn.Sequential(             
            nn.Linear(2, 3),                    
            nn.Tanh(),                          
            nn.Linear(3, 4),                    
            nn.Sigmoid()                        
        )                                       
                                                
    def forward(self, x):                       
        encoder=self.encoder(x)                 
        decoder=self.decoder(encoder)           
        return encoder,decoder                                                        

 

  • 降維

上圖中 Encoded Data 就是降維後的向量,針對sklearn裏面的iris數據集,訓練一個autoencoder模型,進行降維,最終壓縮到2維

 

import matplotlib.pyplot as plt           
                                          
x_=[]                                     
y_=[]                                     
for i, (x, y) in enumerate(my_dataset):   
    _, pred = model(V(x))            # 這裏的model爲訓練好的autoencoder模型               
    #loss = criterion(pred, x)            
    dimension=_.data.numpy()              
    x_.append(dimension[0])               
    y_.append(dimension[1])               
                                          
plt.scatter(numpy.array(x_),numpy.array(y_),c=Y)        
                                          
for i in range(len(numpy.array(x_))):     
    plt.annotate(i,(x_[i],y_[i]))         
                                          
plt.show()                                
                                          

 

image.png

 

維度降低到2維的時候,還是能比較明顯的把類別區分開來。

 

完整的代碼:

import torch.nn as nn
from torch.autograd import Variable as V
import torch
from torch.utils.data import DataLoader,Dataset,TensorDataset
from sklearn.datasets import load_iris
from  sklearn.preprocessing import MinMaxScaler
import numpy
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest


###### 讀入數據
iris=load_iris()
x=iris.data
y=iris.target
Y=y # 在畫圖中備用

###### 對輸入進行歸一化,因爲autoencoder只用到了input
MMScaler=MinMaxScaler()
x=MMScaler.fit_transform(x)
iforestX=x

###### 輸入數據轉換成神經網絡接受的dataset類型,batch設定爲10
tensor_x=torch.from_numpy(x.astype(numpy.float32))
tensor_y=torch.from_numpy(y.astype(numpy.float32))
my_dataset=TensorDataset(tensor_x,tensor_y)
my_dataset_loader=DataLoader(my_dataset,batch_size=10,shuffle=False)
#print(isinstance(my_dataset,Dataset))


###### 定義一個autoencoder模型
class autoencoder(nn.Module):
    def __init__(self):
        super(autoencoder,self).__init__()
        self.encoder=nn.Sequential(
            nn.Linear(4, 3),
            nn.Tanh(),
            nn.Linear(3, 2),
        )
        self.decoder=nn.Sequential(
            nn.Linear(2, 3),
            nn.Tanh(),
            nn.Linear(3, 4),
            nn.Sigmoid()
        )

    def forward(self, x):
        encoder=self.encoder(x)
        decoder=self.decoder(encoder)
        return encoder,decoder

model=autoencoder()

####### 定義損失函數

criterion=nn.MSELoss()

####### 定義優化函數
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)  # 如果採用SGD的話,收斂不下降

####### epoch 設定爲300

for epoch in range(300):
    total_loss = 0
    for i ,(x,y) in enumerate(my_dataset_loader):
       _,pred=model(V(x))
       loss=criterion(pred,x)
       optimizer.zero_grad()
       loss.backward()
       optimizer.step()
       total_loss+=loss
    if epoch % 100==0:
        print(total_loss.data.numpy())


###### 基於訓練好的model做降維並可視化

x_=[]
y_=[]
for i, (x, y) in enumerate(my_dataset):
    _, pred = model(V(x))
    #loss = criterion(pred, x)
    dimension=_.data.numpy()
    x_.append(dimension[0])
    y_.append(dimension[1])

plt.scatter(numpy.array(x_),numpy.array(y_),c=Y)

for i in range(len(numpy.array(x_))):
    plt.annotate(i,(x_[i],y_[i]))

plt.show()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章