基于深度学习实现SPECT放射性核素定量测量(四)-pix2pix网络结构搭建

(1)pix2pix网络结构

在本次工作中使用GAN网络的一种pix2pix网络模型,实现重建图像计数分布到放射性核素活度分布的计算。pix2pix网络实现的是有监督学习,需要输入成对的训练数据。pix2pix由一个生成器(Generator)和判别器(Discriminator)组成,如图1所示。使用x代表输入图像,G(x)代表生成器生成的图像。生成器生成图像G(x)后,将x和G(x)共同输入到判别器中,判别器会输出预测概率值用于判别输入的是否为一对真实图像。在训练pix2pix时,生成器的训练目标是希望生成的G(x)和x输入到判别器中时,判别器预测的概率值尽可能大,也就是希望尽可能的“欺骗”判别器。判别器的训练目标是在输入一对非真实图像时,输出概率尽可能小;当输入一对真实图像时,输出的概率尽可能大。

图1 pix2pix网络结构

(2)生成器结构-Unet

生成器使用的是Unet结构,在编码和解码过程中加入跳层连接(skip connection),使输入和输出共享部分底层信息。如图2所示。图2中所示网络由下采样和上采样两部分组成,下采样又被称为特征提取部分。下采样和上采样各四层,下采样每一层由两次卷积和一次最大池化(Max-Pooling)组成。下采样过程中自上而下,每一层卷积核数量分别为64、128、256、512、512,上采样过程中自下而上,每一层卷积核数量为512、256、128、64、64,输出层卷积核数量为1。网络中的卷积均为 3 × 3 3\times3 3×3卷积,步长为1,padding为1,使每一次卷积不改变图像大小只调整图像通道数,分别使用ReLu和LeakyReLu作为激活函数,使用Instance Normalization层对单样本进行归一化。BN层主要是对每个批量的样本进行归一化处理,忽略了单个样本的特征,IN层计算归一化时只考虑单个样本,在图片像素级的处理上,IN层比BN层会有更好的效果,可以更好的保留单个样本每个像素的信息。在每次卷积层(包括卷积操作、激活函数、IN层)后,进行Max-Pooling,通过设置参数,使Max-Pooling只改变图像大小而不改变通道数。为了防止过拟合、增强网络模型的泛化性能,在每一层的两次卷积后添加dropout随机丢弃神经元,在网络中设置dropout为0.5。网络输入数据分辨率为 128 × 128 128\times128 128×128,下采样过程中图像分辨率为 128 × 128 、 64 × 64 、 32 × 32 、 16 × 16 、 8 × 8 128\times128、64\times64、32\times32、16\times16、8\times8 128×128、64×64、32×32、16×16、8×8,上采样过程中图像分辨率自下而上为 8 × 8 、 16 × 16 、 32 × 32 、 64 × 64 、 128 × 128 8\times8、16\times16、32\times32、64\times64、128\times128 8×8、16×16、32×32、64×64、128×128。从图2中可以看到每上采样一次,就和下采样部分通道数相同的图像进行融合。

图2 Unet结构

(3)判别器结构-PatchGAN

判别器采用的是PatchGAN网络结构,如图3所示,将原始图像x和生成器生成的图像G(x)作为PatchGAN的输入,共经过5次卷积操作,每次卷积核大小为 4 × 4 4\times4 4×4,输出大小为 8 × 8 8\times8 8×8的Patch。对Patch中元素求均值可以得到输入图像为真的概率。PatchGAN和Unet网络均采用Adam优化算法。


关于该网络的详细信息可以阅读论文《Image-to-Image Translation with Conditional Adversarial Networks》

(4)网络代码

使用Pytorch进行网络结构的搭建
网络模型代码:

### models.py
import torch.nn as nn
import torch.nn.functional as F
import torchdef weights_init_normal(m):classname = m.__class__.__name__if classname.find("Conv") != -1:torch.nn.init.normal_(m.weight.data, 0.0, 0.02)elif classname.find("BatchNorm2d") != -1:torch.nn.init.normal_(m.weight.data, 1.0, 0.02)torch.nn.init.constant_(m.bias.data, 0.0)def initialize_weights(net):for m in net.modules():if isinstance(m, nn.Conv2d):m.weight.data.normal_(0, 0.02)# m.bias.data.zero_()
##############################
#           U-NET
##############################
#连续两次卷积操作模块
class DoubleConv(nn.Module):def __init__(self, in_channels, out_channels):super(DoubleConv, self).__init__()self.model = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, bias=False),nn.InstanceNorm2d(out_channels),nn.ReLU(inplace=True),     #True会覆盖输入数据,产生输出,节省内存nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, bias=False),nn.InstanceNorm2d(out_channels),nn.LeakyReLU(0.2, inplace=True))initialize_weights(self.model)def forward(self, x):return self.model(x)#下采样过程,使用最大池化maxpool, 加两次卷积
class Down(nn.Module):def __init__(self, in_channels, out_channels, dropout=0.0):super().__init__()if dropout:self.model = nn.Sequential(nn.MaxPool2d(2),DoubleConv(in_channels, out_channels),nn.Dropout(dropout))else:self.model = nn.Sequential(nn.MaxPool2d(2),DoubleConv(in_channels, out_channels))# 前向传播函数def forward(self, x):return self.model(x)#上采样模块
class Up(nn.Module):def __init__(self, in_channels, out_channels, bilinear=True, dropout=0.0):super().__init__()# if bilinear, use the normal convolutions to reduce the number of channelsself.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) if dropout:self.conv = nn.Sequential(DoubleConv(in_channels, out_channels),nn.Dropout(dropout))else:self.conv = DoubleConv(in_channels, out_channels)# torch.nn.Upsample(size=None, scale_factor=None, mode='nearest', align_corners=None)# size是要输出的尺寸,数据类型为tuple(元组):([optional D_out],[option H_out], W_out)# scale_factor在高度、宽度和深度上面的放大倍数。数据类型既可以是int-表明高度、宽度、深度都扩大同一倍数;# 亦或是tuple-指定高度、宽度、深度的扩大倍数# mode上采样的办法,包括最近邻(nearest),线性插值(linear),双线性插值(bilinear),三次线性插值(trilinear),默认是最近邻(nearest)# align_corners如果设为True,输入图像和输出图像角点的像素将会被对齐(aligned),这只在mode=linear,bilinear,or trilinear才有效,默认为False# 前向传播函数def forward(self, x1, x2):x1 = self.up(x1)             #接受上采样数据# input is CHW:channels, height, widthx = torch.cat([x2, x1], dim=1)           #进行特征融合后的,第一维为通道数return self.conv(x)                      #返回两次卷积后的#最后输出模块
class OutConv(nn.Module):def __init__(self, in_channels, out_channels):super(OutConv, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)initialize_weights(self.conv)def forward(self, x):return self.conv(x)class GeneratorUNet(nn.Module):def __init__(self, n_channels=1, n_classes=1, bilinear=True):super(GeneratorUNet, self).__init__()self.n_channels = n_channelsself.n_classes = n_classesself.bilinear = bilinearself.inc = DoubleConv(n_channels, 64)self.down1 = Down(64, 128)self.down2 = Down(128, 256, dropout=0.5)self.down3 = Down(256, 512, dropout=0.5)self.down4 = Down(512, 512, dropout=0.5)# Up函数是先进行上采样,再进行特征融合再进行卷积,前面两个操作不需要通道数,所以这里的输入通道数值特征融合后的通道数。# 因为特征融合通道数加倍,所以此处输出通道数为下一次输入通道数的一半。self.up1 = Up(1024, 256, bilinear, dropout=0.5)self.up2 = Up(512, 128, bilinear, dropout=0.5)self.up3 = Up(256, 64, bilinear, dropout=0.5)self.up4 = Up(128, 64, bilinear, dropout=0.5)self.outc = OutConv(64, n_classes)def forward(self, x):x1 = self.inc(x)x2 = self.down1(x1)x3 = self.down2(x2)x4 = self.down3(x3)x5 = self.down4(x4)x = self.up1(x5, x4)x = self.up2(x, x3)x = self.up3(x, x2)x = self.up4(x, x1)logits = self.outc(x)return logits##############################
#        Discriminator
##############################class Discriminator(nn.Module):def __init__(self, in_channels=1):super(Discriminator, self).__init__()def discriminator_block(in_filters, out_filters, normalization=True):"""Returns downsampling layers of each discriminator block"""layers = [nn.Conv2d(in_filters, out_filters, 4, stride=2, padding=1)]     # 图像大小变为原来的一半if normalization:layers.append(nn.InstanceNorm2d(out_filters))layers.append(nn.LeakyReLU(0.2, inplace=True))return layersself.model = nn.Sequential(*discriminator_block(in_channels * 2, 64, normalization=False),         #*discriminator_block(64, 128),*discriminator_block(128, 256),*discriminator_block(256, 512),nn.ZeroPad2d((1, 0, 1, 0)),                       # n+1nn.Conv2d(512, 1, 4, padding=1, bias=False)       # ((n+1)-4+2)/1+1= n)def forward(self, img_A, img_B):# Concatenate image and condition image by channels to produce inputimg_input = torch.cat((img_A, img_B), 1)return self.model(img_input)

数据加载模块:

### datasets.py
import torch
import cv2
from torch.utils.data import Dataset
import scipy.io as sio
import numpy as np
import os
import glob
import random# Dataset是一个抽象类,不能实例化,只能被其他子类继承
# DataLoader用于自动加载数据,实例化来帮助我们完成工作
class ImageDataset(Dataset):def __init__(self, data_path):# 初始化函数,读取所有data_path下的图片# self.test_data = 'C:/Users/汪煜晗/Desktop/breast_dataset/data/test_image'# self.test_label = 'C:/Users/汪煜晗/Desktop/breast_dataset/data/test_label'self.data_path = data_pathself.train_image = sorted(glob.glob(os.path.join(self.data_path, 'train_image/*')), key=os.path.getmtime)self.train_label = sorted(glob.glob(os.path.join(self.data_path, 'train_label/*')), key=os.path.getmtime)def augment_flip(self, Img, flipCode):# 使用cv2.flip进行数据增强,flipCode为1水平翻转,0垂直翻转,-1水平+垂直翻转flip = cv2.flip(Img, flipCode)return flipdef augment_rot(self, Img, degree):# degree=1:逆时针旋转90度, -1:顺时针旋转90度, 2:逆时针旋转180度,-2:顺时针旋转180度# rot = np.rot90(Img, degree)if degree == 90:rot = cv2.rotate(Img, cv2.ROTATE_90_CLOCKWISE)elif degree == 180:rot = cv2.rotate(Img, cv2.ROTATE_180)elif degree == 270:rot = cv2.rotate(Img, cv2.ROTATE_90_COUNTERCLOCKWISE)return rot# 数据获取函数# 使其支持下标索引操作def __getitem__(self, index):# 根据index读取数据# 获取训练图路径image_path = self.train_image[index]# 获取标签图路径label_path = self.train_label[index]# 读取训练图片img = sio.loadmat(image_path)['Q']/1.0# 读取训练标签lab = sio.loadmat(label_path)['Q']/1.0# 处理训练标签lab = lab/100660.224# 随机进行数据增强,为2时不处理flipCode = random.choice([-1, 0, 1, 2])if flipCode != 2:img = self.augment_flip(img, flipCode)lab = self.augment_flip(lab, flipCode)degree = random.choice([90, 180, 270, 0])# 随机进行数据增强,为0时不处理if degree != 0:img = self.augment_rot(img, degree)lab = self.augment_rot(lab, degree)image = img.reshape(1, img.shape[0], img.shape[1])label = lab.reshape(1, lab.shape[0], lab.shape[1])# 需要四个通道,原因不知,试错得到return {"A": image.copy(), "B": label}def __len__(self):# 返回训练集大小# len():Return the number of items in a container.return len(self.train_image)class val_ImageDataset(Dataset):def __init__(self, data_path):# 初始化函数,读取所有data_path下的图片self.data_path = data_pathself.test_image = sorted(glob.glob(os.path.join(self.data_path, 'test_image/*')), key=os.path.getmtime)self.test_label = sorted(glob.glob(os.path.join(self.data_path, 'test_label/*')), key=os.path.getmtime)# 数据获取函数# 使其支持下标索引操作def __getitem__(self, index):# 根据index读取数据# 获取测试图路径image_path = self.test_image[index]# 获取标签图路径label_path = self.test_label[index]# 读取测试图片img = sio.loadmat(image_path)['Q']/1.0# 读取测试标签lab = sio.loadmat(label_path)['Q']/1.0# 处理测试标签lab = lab / 100660.224image = img.reshape(1, img.shape[0], img.shape[1])label = lab.reshape(1, lab.shape[0], lab.shape[1])# 需要四个通道,原因不知,试错得到return {"A": image.copy(), "B": label}def __len__(self):# 返回训练集大小# len():Return the number of items in a container.return len(self.test_image)

训练和验证部分:

import argparse
from skimage.metrics import structural_similarity
import numpy as np
import os
import time
import datetime
import sys
import scipy.io as sio
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
from torch.autograd import Variable
from models import *
from datasets import *
import torchif __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument("--epoch", type=int, default=0, help="epoch to start training from")parser.add_argument("--data_path", type=str, default='breast_dataset/AC/data')parser.add_argument("--n_epochs", type=int, default=500, help="number of epochs of training")parser.add_argument("--batch_size", type=int, default=8, help="size of the batches")parser.add_argument("--lr", type=float, default=0.0001, help="adam: learning rate")parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient")parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")parser.add_argument("--img_height", type=int, default=128, help="size of image height")parser.add_argument("--img_width", type=int, default=128, help="size of image width")parser.add_argument("--channels", type=int, default=1, help="number of image channels")opt = parser.parse_args()print(opt)cuda = True if torch.cuda.is_available() else Falsedevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# Loss functionscriterion_GAN = torch.nn.MSELoss()criterion_pixelwise = torch.nn.L1Loss()    # L1  # loss# Loss weight of L1 pixel-wise loss between translated image and real imagelambda_pixel = 100# Calculate output of image discriminator (PatchGAN)patch = (1, opt.img_height // 2 ** 4, opt.img_width // 2 ** 4)# Initialize generator and discriminatorgenerator = GeneratorUNet()discriminator = Discriminator()if cuda:generator = generator.cuda()discriminator = discriminator.cuda()criterion_GAN.cuda()criterion_pixelwise.cuda()if opt.epoch != 0:# Load pretrained modelsgenerator.load_state_dict(torch.load("saved_models/generator_%d.pth" % 100*(opt.epoch+1) ))discriminator.load_state_dict(torch.load("saved_models/discriminator_%d.pth" % 100*(opt.epoch+1) ))else:# Initialize weights#generator.apply(weights_init_normal)discriminator.apply(weights_init_normal)# Optimizersoptimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))dataloader = DataLoader(ImageDataset(opt.data_path),batch_size=opt.batch_size,shuffle=True,num_workers=opt.n_cpu,)val_dataloader = DataLoader(val_ImageDataset(opt.data_path),batch_size=1,shuffle=False,num_workers=opt.n_cpu,)# Tensor typeTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensorpicture_path = 'breast_dataset/AC/picture/pred_img'pr_path = os.path.join(opt.data_path, 'pred_img')os.mkdir(pr_path)os.mkdir(picture_path)# 验证集def validation(epoch):generator.eval()discriminator.eval()img_path = os.path.join(pr_path, 'pred_%d_epoch' % (epoch + 1))pic_path = os.path.join(picture_path, 'pred_%d_epoch' % (epoch + 1))  # 存储每个epoch对应图片的路径os.mkdir(img_path)os.mkdir(pic_path)val_total_MSE = 0val_total_G_loss = 0ssim = 0for j, val_batch in enumerate(val_dataloader):test_A = Variable(val_batch["A"].type(Tensor))label_B = Variable(val_batch["B"].type(Tensor))val_fake_B = generator(test_A)val_valid = Variable(Tensor(np.ones((test_A.size(0), *patch))), requires_grad=False)val_fake = Variable(Tensor(np.zeros((test_A.size(0), *patch))), requires_grad=False)val_pred_fake = discriminator(val_fake_B, test_A)val_loss_GAN = criterion_GAN(val_pred_fake, val_valid)# pixel-wise lossval_loss_pixel = criterion_pixelwise(val_fake_B, label_B)val_G_loss = val_loss_GAN + lambda_pixel * val_loss_pixelval_total_G_loss += val_G_loss.item()val_loss_MSE = torch.nn.MSELoss()(val_fake_B, label_B)val_total_MSE += val_loss_MSE.item()file = open('pred_log/pred_log_MSE_%d_epoch.txt' % (epoch + 1), mode='a')file.write(str(val_loss_MSE.item()) + "\n")file.close()val_pred_B = np.array(val_fake_B.data.cpu()[0])[0]#求结构相似性#对生成的图像SSIM求和做平均Label_B = np.array(label_B.data.cpu())Label_B = Label_B.reshape(Label_B.shape[2], Label_B.shape[3])ssim = ssim + structural_similarity(np.array(val_pred_B), Label_B, full=False)sio.savemat(os.path.join(img_path, '%d.mat' % (j + 1)), {'Q': val_pred_B})# plt.figure(figsize=(5, 5), constrained_layout=True)# plt.imshow(val_pred_B, cmap='jet')# plt.axis('on')# plt.savefig(os.path.join(pic_path, '%d.png' % (j + 1)), dpi=600)# plt.close()#print('epoch:'+str(epoch+1)+'\t'+'batch:'+str(len(val_dataloader)))file = open('log/pred_log_MSE_epoch.txt', mode='a')file.write(str(val_total_MSE/len(val_dataloader)) + "\t")file.write(str(epoch+1) + "\n")file.close()File = open('log/SSIM_epoch.txt', mode='a')File.write(str(ssim/len(val_dataloader))+"\t")File.write(str(epoch+1) + '\n')File.close()fileG = open('log/G_loss_val.txt', mode='a')fileG.write(str(val_total_G_loss / len(val_dataloader)) + "\t")fileG.write(str(epoch + 1) + '\n')fileG.close()# ----------#  Training# ----------prev_time = time.time()for epoch in range(opt.epoch, opt.n_epochs):generator.train()discriminator.train()total_train_G_loss_epoch = 0total_train_D_loss_epoch = 0total_train_MSE_loss = 0for i, batch in enumerate(dataloader):# Model inputsreal_A = Variable(batch["A"].type(Tensor))real_B = Variable(batch["B"].type(Tensor))# Adversarial ground truthsvalid = Variable(Tensor(np.ones((real_A.size(0), *patch))), requires_grad=False)fake = Variable(Tensor(np.zeros((real_A.size(0), *patch))), requires_grad=False)# ------------------#  Train Generators# ------------------optimizer_G.zero_grad()# GAN lossfake_B = generator(real_A)         # 输入A,生成fake_B(虚假的B)pred_fake = discriminator(fake_B, real_A)   # 将输入A和fake_B同时输入到判别器中loss_GAN = criterion_GAN(pred_fake, valid)# Pixel-wise lossloss_pixel = criterion_pixelwise(fake_B, real_B)# MSE lossloss_MSE = torch.nn.MSELoss()(fake_B, real_B)# Total lossloss_G = loss_GAN + lambda_pixel * loss_pixelloss_G.backward()optimizer_G.step()# ---------------------#  Train Discriminator# ---------------------optimizer_D.zero_grad()# Real losspred_real = discriminator(real_B, real_A)loss_real = criterion_GAN(pred_real, valid)# Fake losspred_fake = discriminator(fake_B.detach(), real_A)loss_fake = criterion_GAN(pred_fake, fake)# Total lossloss_D = 0.5 * (loss_real + loss_fake)loss_D.backward()optimizer_D.step()# --------------#  Log Progress# --------------# Determine approximate time leftbatches_done = epoch * len(dataloader) + ibatches_left = opt.n_epochs * len(dataloader) - batches_donetime_left = datetime.timedelta(seconds=batches_left * (time.time() - prev_time))prev_time = time.time()# Print logsys.stdout.write("\r[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f, pixel: %f, adv: %f] ETA: %s"% (epoch,opt.n_epochs,i,len(dataloader),loss_D.item(),loss_G.item(),loss_pixel.item(),loss_GAN.item(),time_left,))total_train_G_loss_epoch += loss_G.item()total_train_D_loss_epoch += loss_D.item()total_train_MSE_loss += loss_MSE.item()# If at sample interval save image# if batches_done % opt.sample_interval == 0:#     sample_images(batches_done)with torch.no_grad():validation(epoch)file = open('log/log_generator.txt', mode='a')file.write(str(total_train_G_loss_epoch/len(dataloader))+"\t")file.write(str(epoch)+"\n")file.close()file = open('log/log_MSE.txt', mode='a')file.write(str(total_train_MSE_loss/len(dataloader))+"\t")file.write(str(epoch)+"\n")file.close()file = open('log/log_discriminator.txt', mode='a')file.write(str(total_train_D_loss_epoch/len(dataloader))+"\t")file.write(str(epoch)+"\n")file.close()# 只保存部分epoch下的模型if (epoch+1) % 50 == 0:torch.save(generator.state_dict(), "saved_models/generator_%s.pth" % (epoch+1))torch.save(discriminator.state_dict(), "saved_models/discriminator_%s.pth" % (epoch+1))

代码与数据集均为本人写的,可能会有一些错误。数据集为GATE模拟、图像重建和衰减修正后构建的。
源代码和数据下载链接:https://pan.baidu.com/s/1NU3WCCsHPzjnI3P4GO7n4A
提取码:7dc3

基于深度学习方法实现SPECT放射性核素定量测量(四)相关推荐

  1. 基于深度学习方法实现SPECT放射性核素定量测量(一)

    基于深度学习方法实现SPECT放射性核素定量测量(一)--课题介绍 放射治疗是目前癌症三大治疗手段之一,当前,世界上约有70%的癌症患者使用放射治疗.放射治疗技术包括普通X射线治疗.硼中子俘获治疗.质 ...

  2. 基于深度学习方法实现SPECT放射性核素定量测量(二)

    基于深度学习方法实现SPECT放射性核素定量测量(二)-GATE仿真 (1)GATE介绍 GATE(GEANT4 Application for Emission Tomography)由OpenGA ...

  3. 基于深度学习方法实现SPECT放射性核素定量测量(三)

    基于深度学习方法实现SPECT放射性核素定量测量(三)-图像重建及衰减校正 (1)图像重建 使用MLEM迭代重建算法进行图像重建,MLEM算法原理如图1所示. 图像重建可以借助重建软件进行,目前可以用 ...

  4. 基于深度学习方法的3D数据合成

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 3D 数据简介 人们普遍认为,从单一角度合成 3D 数据是人类视觉的基本功能.但这对计算机视觉算法来说 ...

  5. 基于深度学习方法的推荐系统(转载)

    原文:Deep Learning based Recommender System: A Survey and New Perspectives 作者:张帅, 新南威尔士大学 翻译:沈春旭,清华大学 ...

  6. nature | 基于深度学习方法的虚拟组织染色

    研究背景 组织病理学可以追溯到19世纪,它一直是病理学中使用的黄金标准诊断方法之一.如果在医学检查之后或在外科手术期间需要活组织检查,则需要从患者身上取出组织样本,然后将其切成微米薄片.这些病理学切片 ...

  7. WACV2020:开源基于深度学习方法DeOccNet用来去除透视光场中的前景遮挡

    作者信息 最近,国防科技大学的一个研究小组提出了一种利用阵列相机去除前景遮挡成像的新方法 作为国内外第一个基于深度学习的去遮挡成像工作,作者提出了掩模嵌入的方法来解决训练数据不足的问题,并建立了仿真和 ...

  8. 【SR汇总】基于深度学习方法

    1.SRCNN.FSRCNN (Learning a Deep Convolutional Network for Image Super-Resolution, ECCV2014) (Acceler ...

  9. 学习分享——基于深度学习的NILM负荷分解(四)深度学习实现,代码讲解

    QQ群1070535031 跟随上一篇的思路,本篇我们来实现整个流程. 实验需求 跟随本文进行学习和实验,需要前面博文中的环境,以及提取出来的UK数据.(学习分享--基于深度学习的NILM负荷分解(二 ...

最新文章

  1. 引用类型(一):Object类型
  2. 机器学习中的常见问题—损失函数
  3. 云上快报 | 分布式架构引领核心系统架构转型新趋势
  4. 1.2 private 关键字 面向对象封装
  5. c++语言 tcp例子,C++中TCP通信实现文件传输
  6. 【Java】List 按照字符串里的数值排序
  7. 我,第一次做项目经理,干赔了
  8. 《电磁学》学习笔记4——磁场高斯定理、安培环路定理、电动势
  9. 100m光纤测速多少正常_100m光纤测速多少正常 所以100M宽带最大下载速度
  10. python实现isPrime()函数
  11. 如何将eclipse项目和svn关联(从服务器取项目)
  12. 杂牌平板mt6797_联发科MT6797炸现跑分库 强得令人毛骨悚然
  13. 22-05-21 西安 javaweb(07) HttpServletRequest和HttpServletResponse、转发与重定向、web应用的路径问题、解决中文乱码问题
  14. 大一期末C语言大作业—结构体和链表框架
  15. unity倍镜瞄准镜
  16. 关于TAA SMAA
  17. Vultr新用户充值送50刀
  18. 基于android的记账APP大作业项目
  19. C# SQLite 数据库基本操作
  20. backslash-newline at end of file

热门文章

  1. android 时间间隔 calendar,android:在某些特定时间间隔内报警remian停止
  2. 实现全链路监控平台很难吗?Pinpoint、SkyWalking、Zipkin 选型对比
  3. Ubuntu16.04 装机必备软件
  4. 【投票】你心目中的Excel催化剂价值有多大(附主流国内外收费插件供参考)?...
  5. “小丑”(Joker)Android恶意窃听软件
  6. ElasticSearch~ES文档操作~对文档的增删改查
  7. webpack打包js/css/scss/less/styl等(可以打包图片)
  8. Python数据分析numpy入门(三)-------numpy100题练习
  9. 关于Apache shiro如何实现一个账户同一时刻只有一个人登录
  10. Solidity实现默克尔树 Merkle Tree