GAN Mnist code doesn't go well

i start to learn GAN, and try to write a code. but after 10000 step, it doesn’t work well.
i wanna know what goes wrong, and i think the the transform of uint to float type may be have a influence of accurate.
and loss function from this:

import torch
import numpy as np
import torch.nn as nn
import torchvision
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt

batch_size = 1
LR_G = 0.00001
LR_D = 0.00001

train_dataset = dsets.MNIST(root='../../data_sets/mnist',  # 选择数据的根目录
                            train=True,  # 选择训练集
                            transform=transforms.ToTensor(),  # 转换成tensor变量
                            download=False)  # 不从网络上download图片
# plot one example
""" python
print("e")
print(train_dataset.train_data[0].numpy())
plt.imshow(train_dataset.train_data[0].numpy(), cmap='gray')
plt.show()
"""
def paint(output):
    output = output.detach().numpy()
    output = output + 1
    output = output / 2
    output = output * 255
    output.shape = -1, 28
    plt.imshow(output, cmap='gray')
    plt.show()

class View(nn.Module):
    def __init__(self, size):
        super(View, self).__init__()
        self.size = size

    def forward(self, x):
        x = x.view(self.size)
        return x


G = nn.Sequential(
    nn.Linear(100, 7 * 7 * batch_size),  # 线性层
    nn.ReLU(),
    View((batch_size, 1, 7, 7)),  # 类似于reshape
    nn.Upsample(size=14),  # 上采样层 使size 改变
    nn.Conv2d(in_channels=1, out_channels=12, kernel_size=5, padding=2),
    nn.ReLU(),
    nn.Upsample(28),
    nn.Conv2d(in_channels=12, out_channels=32, kernel_size=5, padding=2),
    nn.ReLU(),
    nn.Conv2d(in_channels=32, out_channels=1, kernel_size=5, padding=2),
    nn.Tanh()
)


# input shape [1,1,28,28]
# outpout shape[1,1]
D = nn.Sequential(
    nn.Conv2d(in_channels=1, out_channels=12, kernel_size=5, padding=2),
    nn.ReLU(),
    nn.Conv2d(in_channels=12, out_channels=32, kernel_size=5, padding=2),
    nn.ReLU(),
    nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
    nn.ReLU(),
    nn.Conv2d(in_channels=64, out_channels=128, kernel_size=5, padding=2),
    nn.ReLU(),
    View((batch_size, 128 * 28 * 28)),
    nn.Linear(128 * 28 * 28, 1),
    nn.Sigmoid()
)
if torch.cuda.is_available():
    D = D.cuda()
    G = G.cuda()
opt_D = torch.optim.Adam(D.parameters(), lr=LR_D)
opt_G = torch.optim.Adam(G.parameters(), lr=LR_G)


def get(x):
    x = x.unsqueeze(0)
    x = x.unsqueeze(0)
    x = x.float()
    x = x / 255
    x = x - 0.5
    x = x * 2
    x = x.float()
    return x


for i in range(10000):
    real = train_dataset.train_data[i%100]
    real = get(real)
    x = torch.randn(1, 100)
    if torch.cuda.is_available():
        real = real.cuda()
        x = x.cuda()
    output = G(x)

    p0 = D(output)
    p1 = D(real)

    D_loss = - torch.mean(torch.log(p1) + torch.log(1 - p0))

    opt_D.zero_grad()
    D_loss.backward(retain_graph=True)  # reusing computational graph
    opt_D.step()

    G_loss = torch.mean(torch.log(p0))
    opt_G.zero_grad()
    G_loss.backward()
    opt_G.step()
    print(i, ':', D_loss, " ", G_loss)
x = torch.randn(1, 100)
x = x.cuda()
output = G(x)
print(output)

#paint(output)