# 大话 - 自编码(Autoencoder)和变分自编码(Variational Autoencoder)

### 自编码 (Autoencoder)

1. 网络结构
2. 前向数据流 (forward)
3. 损失函数 (loss function) & 优化器 (optimizer)
4. 训练 & 梯度下降

#### 网络结构

class AutoEncoder(nn.Module):
"""
"""
def __init__(self, latent_num=16):
"""
TODO: doconvolution
"""
super(AutoEncoder, self).__init__()

self.fc1 = nn.Linear(IMG_SIZE, 256)
self.fc1.weight.data.normal_(0.0, 0.05)

self.fc2 = nn.Linear(256, 64)
self.fc2.weight.data.normal_(0.0, 0.05)

self.fc3 = nn.Linear(64, 256)
self.fc3.weight.data.normal_(0.0, 0.05)

self.fc4 = nn.Linear(256, IMG_SIZE)
self.fc4.weight.data.normal_(0.0, 0.05)

#### 前向数据流 (forward)

    def forward(self, x):
h1 = F.relu(self.fc1(x))  # IMG_SIZE -> 518
h2 = F.relu(self.fc2(h1)) # 518 -> 256
h3 = F.relu(self.fc3(h2)) # 256 -> 128
h4 = F.relu(self.fc4(h3)) # 128 -> 256
output = h4
# output = F.sigmoid(h6)
return output

#### 损失函数 (Loss Function) & 优化器 (optimizer)

def loss_function(output, x):
"""
"""
mse = encoder_loss(output, x)
return mse

optimizer = optim.Adam(model.parameters(), lr=1e-3)

### 训练 & 梯度下降

for epoch in range(num_epochs):
train_loss = 0
img = data.view(data.size(0), -1)
img = Variable(img.float())
output = model(img)
# backward
loss = loss_function(output, img)
loss.backward()
train_loss += loss.data[0]
optimizer.step()
if batch_idx % 100 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch,
batch_idx * len(img),
loss.data[0] / len(img)))
print('====> Epoch: {} Average loss: {:.4f}'.format(
epoch, train_loss / len(dataloader.dataset)))

### 代码部分

#### 网络配置

class VAE(nn.Module):
"""
"""
def __init__(self, latent_num=2):
"""
TODO: doconvolution
"""
super(VAE, self).__init__()

self.fc1 = nn.Linear(IMG_SIZE, 256)
self.fc21 = nn.Linear(256,  16)
self.fc22 = nn.Linear(256, 16)
self.fc3 = nn.Linear(16, 256)
self.fc4 = nn.Linear(256, 784)

#### 前向数据流 (forward)

    def encoder(self, x):
h1 = F.relu(self.fc1(x))
mu, std = self.fc21(h1), self.fc22(h1)
return mu, std
def decoder(self, x):
h2 = F.relu(self.fc3(x))
return self.fc4(h2)

def forward(self, x):
mu, var = self.encoder(x)
z = self.reparametrize(mu, var)
return self.decoder(z), mu, var

#### 损失函数 （Loss Function）

def loss_function(output, x, mu, var):
"""
"""
mse = encoder_loss(output, x)
#   0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
KLD = torch.sum(latent_loss)
return mse - KLD

#### 训练 & 梯度下降

for epoch in range(num_epochs):
train_loss = 0
img = data.view(data.size(0), -1)
img = Variable(img.float())
output, mu, var = model(img)
# backward
loss = loss_function(output, img, mu, var)
loss.backward()
train_loss += loss.data[0]
optimizer.step()
if batch_idx % 100 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch,
batch_idx * len(img),
loss.data[0] / len(img)))