昇思25天学习打卡营第7天|Pix2Pix实现图像转换

文章目录

      • 昇思MindSpore应用实践
        • 基于MindSpore的Pix2Pix图像转换
          • 1、Pix2Pix 概述
          • 2、U-Net架构
            • 定义UNet Skip Connection Block
          • 2、生成器部分
          • 3、基于PatchGAN的判别器
          • 4、Pix2Pix的生成器和判别器初始化
          • 5、模型训练
          • 6、模型推理
      • Reference

昇思MindSpore应用实践

本系列文章主要用于记录昇思25天学习打卡营的学习心得。

基于MindSpore的Pix2Pix图像转换
1、Pix2Pix 概述

Pix2Pix 是一个专门为图像到图像的转换任务设计的网络,可以实现语义/标签到真实图片、灰度图到彩色图、航空图到地图、白天到黑夜、线稿图到实物图的转换。Pix2Pix是将条件GAN(CGAN)应用于有监督(需要成对的输入素描图像Sketch和真实图像GT,来训练网络)的图像到图像翻译的经典之作,和所有的GANs一样,模型同样包括:生成器判别器两个部分。

CGAN:CGAN(条件GAN) 的目标是生成与给定条件匹配的数据样本。这些条件可以是标签、部分实例标注数据或任何其他形式的多模态辅助信息。CGAN 通过将条件并入网络的生成器和判别器中来指导数据生成过程。
在这里插入图片描述
相比普通的生成对抗损失:
L G A N ( G , D ) = E y [ l o g ( D ( y ) ) ] + E ( x , z ) [ l o g ( 1 − D ( x , z ) ) ] L_{GAN}(G,D)=\mathbb{E}_{y}[log(D(y))]+\mathbb{E}_{(x,z)}[log(1-D(x,z))] LGAN(G,D)=Ey[log(D(y))]+E(x,z)[log(1D(x,z))]

  • x x x:代表观测图像的数据。
  • z z z:代表随机噪声的数据。
  • y = G ( x , z ) y=G(x,z) y=G(x,z):生成器网络,给出由观测图像 x x x与随机噪声 z z z生成的“假”图片,其中 x x x来自于训练数据而非生成器。
  • D ( x , G ( x , z ) ) D(x,G(x,z)) D(x,G(x,z)):判别器网络,给出图像判定为真实图像的概率,其中 x x x来自于训练数据, G ( x , z ) G(x,z) G(x,z)来自于生成器。

CGAN多了来自于观测图像的条件 x x x(因此Pix2Pix训练时采用有监督的方式,需要标注好的语义数据,如下图中的
Map2Aerial数据集、Anime Sketch Colorization Pair 素描生成动漫数据集),
在这里插入图片描述
在这里插入图片描述

CGAN的目标可以表示为:

L C G A N ( G , D ) = E ( x , y ) [ l o g ( D ( x , y ) ) ] + E ( x , z ) [ l o g ( 1 − D ( x , G ( x , z ) ) ) ] L_{CGAN}(G,D)=\mathbb{E}_{(x,y)}[log(D(x,y))]+\mathbb{E}_{(x,z)}[log(1-D(x,G(x,z)))] LCGAN(G,D)=E(x,y)[log(D(x,y))]+E(x,z)[log(1D(x,G(x,z)))]

Pix2Pix 还包括 L1 损失,帮助生成器产生结构上接近真实图像的结果,这一点在图像翻译任务中尤为重要:
L L 1 ( G ) = E ( x , y , z ) [ ∣ ∣ y − G ( x , z ) ∣ ∣ 1 ] L_{L1}(G)=\mathbb{E}_{(x,y,z)}[||y-G(x,z)||_{1}] LL1(G)=E(x,y,z)[∣∣yG(x,z)1]

进而得到最终目标:

a r g min ⁡ G max ⁡ D L C G A N ( G , D ) + λ L L 1 ( G ) arg\min_{G}\max_{D}L_{CGAN}(G,D)+\lambda L_{L1}(G) argGminDmaxLCGAN(G,D)+λLL1(G)

图像转换问题本质上其实就是像素到像素的映射问题,Pix2Pix使用完全一样的网络结构和目标函数,仅更换不同的训练数据集就能分别实现以上的任务。

2、U-Net架构

U-Net架构:Pix2Pix 使用 U-Net 架构作为其生成器,在传统的编解码网络结构基础上加入了跳跃连接的方式,可以更好地捕捉图像的细节和上下文信息,适合于图像到图像的翻译任务。相比于普通的编解码结构(Encoder-Decoder),U-Net在编码器和解码器之间引入了跳跃连接,极大地改善了梯度流:
在这里插入图片描述

定义UNet Skip Connection Block
import mindspore
import mindspore.nn as nn
import mindspore.ops as opsclass UNetSkipConnectionBlock(nn.Cell):def __init__(self, outer_nc, inner_nc, in_planes=None, dropout=False,submodule=None, outermost=False, innermost=False, alpha=0.2, norm_mode='batch'):super(UNetSkipConnectionBlock, self).__init__()down_norm = nn.BatchNorm2d(inner_nc)up_norm = nn.BatchNorm2d(outer_nc)use_bias = Falseif norm_mode == 'instance':down_norm = nn.BatchNorm2d(inner_nc, affine=False)up_norm = nn.BatchNorm2d(outer_nc, affine=False)use_bias = Trueif in_planes is None:in_planes = outer_ncdown_conv = nn.Conv2d(in_planes, inner_nc, kernel_size=4,stride=2, padding=1, has_bias=use_bias, pad_mode='pad')down_relu = nn.LeakyReLU(alpha)up_relu = nn.ReLU()if outermost:up_conv = nn.Conv2dTranspose(inner_nc * 2, outer_nc,kernel_size=4, stride=2,padding=1, pad_mode='pad')down = [down_conv]up = [up_relu, up_conv, nn.Tanh()]model = down + [submodule] + upelif innermost:up_conv = nn.Conv2dTranspose(inner_nc, outer_nc,kernel_size=4, stride=2,padding=1, has_bias=use_bias, pad_mode='pad')down = [down_relu, down_conv]up = [up_relu, up_conv, up_norm]model = down + upelse:up_conv = nn.Conv2dTranspose(inner_nc * 2, outer_nc,kernel_size=4, stride=2,padding=1, has_bias=use_bias, pad_mode='pad')down = [down_relu, down_conv, down_norm]up = [up_relu, up_conv, up_norm]model = down + [submodule] + upif dropout:model.append(nn.Dropout(p=0.5))self.model = nn.SequentialCell(model)self.skip_connections = not outermostdef construct(self, x):out = self.model(x)if self.skip_connections:out = ops.concat((out, x), axis=1)return out
2、生成器部分

原始CGAN的输入是条件x和噪声z两种信息,这里的生成器只使用了条件信息,因此不能生成多样性的结果。因此Pix2Pix在训练和测试时都使用了dropout,这样可以生成多样性的结果。

通过MindSpore实现基于U-Net的生成器:

class UNetGenerator(nn.Cell):def __init__(self, in_planes, out_planes, ngf=64, n_layers=8, norm_mode='bn', dropout=False):super(UNetGenerator, self).__init__()unet_block = UNetSkipConnectionBlock(ngf * 8, ngf * 8, in_planes=None, submodule=None,norm_mode=norm_mode, innermost=True)for _ in range(n_layers - 5):unet_block = UNetSkipConnectionBlock(ngf * 8, ngf * 8, in_planes=None, submodule=unet_block,norm_mode=norm_mode, dropout=dropout)unet_block = UNetSkipConnectionBlock(ngf * 4, ngf * 8, in_planes=None, submodule=unet_block,norm_mode=norm_mode)unet_block = UNetSkipConnectionBlock(ngf * 2, ngf * 4, in_planes=None, submodule=unet_block,norm_mode=norm_mode)unet_block = UNetSkipConnectionBlock(ngf, ngf * 2, in_planes=None, submodule=unet_block,norm_mode=norm_mode)self.model = UNetSkipConnectionBlock(out_planes, ngf, in_planes=in_planes, submodule=unet_block,outermost=True, norm_mode=norm_mode)def construct(self, x):return self.model(x)
3、基于PatchGAN的判别器

判别器使用的PatchGAN结构,可看做卷积。
生成的矩阵中的每个点代表原图的一小块区域(patch)。通过矩阵中的各个值来判断原图中对应每个Patch的真假。

import mindspore.nn as nnclass ConvNormRelu(nn.Cell):def __init__(self,in_planes,out_planes,kernel_size=4,stride=2,alpha=0.2,norm_mode='batch',pad_mode='CONSTANT',use_relu=True,padding=None):super(ConvNormRelu, self).__init__()norm = nn.BatchNorm2d(out_planes)if norm_mode == 'instance':norm = nn.BatchNorm2d(out_planes, affine=False)has_bias = (norm_mode == 'instance')if not padding:padding = (kernel_size - 1) // 2if pad_mode == 'CONSTANT':conv = nn.Conv2d(in_planes, out_planes, kernel_size, stride, pad_mode='pad',has_bias=has_bias, padding=padding)layers = [conv, norm]else:paddings = ((0, 0), (0, 0), (padding, padding), (padding, padding))pad = nn.Pad(paddings=paddings, mode=pad_mode)conv = nn.Conv2d(in_planes, out_planes, kernel_size, stride, pad_mode='pad', has_bias=has_bias)layers = [pad, conv, norm]if use_relu:relu = nn.ReLU()if alpha > 0:relu = nn.LeakyReLU(alpha)layers.append(relu)self.features = nn.SequentialCell(layers)def construct(self, x):output = self.features(x)return outputclass Discriminator(nn.Cell):def __init__(self, in_planes=3, ndf=64, n_layers=3, alpha=0.2, norm_mode='batch'):super(Discriminator, self).__init__()kernel_size = 4layers = [nn.Conv2d(in_planes, ndf, kernel_size, 2, pad_mode='pad', padding=1),nn.LeakyReLU(alpha)]nf_mult = ndffor i in range(1, n_layers):nf_mult_prev = nf_multnf_mult = min(2 ** i, 8) * ndflayers.append(ConvNormRelu(nf_mult_prev, nf_mult, kernel_size, 2, alpha, norm_mode, padding=1))nf_mult_prev = nf_multnf_mult = min(2 ** n_layers, 8) * ndflayers.append(ConvNormRelu(nf_mult_prev, nf_mult, kernel_size, 1, alpha, norm_mode, padding=1))layers.append(nn.Conv2d(nf_mult, 1, kernel_size, 1, pad_mode='pad', padding=1))self.features = nn.SequentialCell(layers)def construct(self, x, y):x_y = ops.concat((x, y), axis=1)output = self.features(x_y)return output
4、Pix2Pix的生成器和判别器初始化

实例化Pix2Pix生成器和判别器:

import mindspore.nn as nn
from mindspore.common import initializer as initg_in_planes = 3
g_out_planes = 3
g_ngf = 64
g_layers = 8
d_in_planes = 6
d_ndf = 64
d_layers = 3
alpha = 0.2
init_gain = 0.02
init_type = 'normal'net_generator = UNetGenerator(in_planes=g_in_planes, out_planes=g_out_planes,ngf=g_ngf, n_layers=g_layers)
for _, cell in net_generator.cells_and_names():if isinstance(cell, (nn.Conv2d, nn.Conv2dTranspose)):if init_type == 'normal':cell.weight.set_data(init.initializer(init.Normal(init_gain), cell.weight.shape))elif init_type == 'xavier':cell.weight.set_data(init.initializer(init.XavierUniform(init_gain), cell.weight.shape))elif init_type == 'constant':cell.weight.set_data(init.initializer(0.001, cell.weight.shape))else:raise NotImplementedError('initialization method [%s] is not implemented' % init_type)elif isinstance(cell, nn.BatchNorm2d):cell.gamma.set_data(init.initializer('ones', cell.gamma.shape))cell.beta.set_data(init.initializer('zeros', cell.beta.shape))net_discriminator = Discriminator(in_planes=d_in_planes, ndf=d_ndf,alpha=alpha, n_layers=d_layers)
for _, cell in net_discriminator.cells_and_names():if isinstance(cell, (nn.Conv2d, nn.Conv2dTranspose)):if init_type == 'normal':cell.weight.set_data(init.initializer(init.Normal(init_gain), cell.weight.shape))elif init_type == 'xavier':cell.weight.set_data(init.initializer(init.XavierUniform(init_gain), cell.weight.shape))elif init_type == 'constant':cell.weight.set_data(init.initializer(0.001, cell.weight.shape))else:raise NotImplementedError('initialization method [%s] is not implemented' % init_type)elif isinstance(cell, nn.BatchNorm2d):cell.gamma.set_data(init.initializer('ones', cell.gamma.shape))cell.beta.set_data(init.initializer('zeros', cell.beta.shape))class Pix2Pix(nn.Cell):"""Pix2Pix模型网络"""def __init__(self, discriminator, generator):super(Pix2Pix, self).__init__(auto_prefix=True)self.net_discriminator = discriminatorself.net_generator = generatordef construct(self, reala):fakeb = self.net_generator(reala)return fakeb
5、模型训练

训练分为两个主要部分:训练判别器和训练生成器;
训练判别器的目的是最大程度地提高判别图像真伪的概率;
训练生成器是希望能产生更好的虚假图像;
在这两个部分中,分别获取训练过程中的损失,并在每个周期结束时进行统计。

通过MindSpore进行训练:

import numpy as np
import os
import datetime
from mindspore import value_and_grad, Tensorepoch_num = 3
ckpt_dir = "results/ckpt"
dataset_size = 400
val_pic_size = 256
lr = 0.0002
n_epochs = 100
n_epochs_decay = 100def get_lr():lrs = [lr] * dataset_size * n_epochslr_epoch = 0for epoch in range(n_epochs_decay):lr_epoch = lr * (n_epochs_decay - epoch) / n_epochs_decaylrs += [lr_epoch] * dataset_sizelrs += [lr_epoch] * dataset_size * (epoch_num - n_epochs_decay - n_epochs)return Tensor(np.array(lrs).astype(np.float32))dataset = ds.MindDataset("./dataset/dataset_pix2pix/train.mindrecord", columns_list=["input_images", "target_images"], shuffle=True, num_parallel_workers=1)
steps_per_epoch = dataset.get_dataset_size()
loss_f = nn.BCEWithLogitsLoss()
l1_loss = nn.L1Loss()def forword_dis(reala, realb):lambda_dis = 0.5fakeb = net_generator(reala)pred0 = net_discriminator(reala, fakeb)pred1 = net_discriminator(reala, realb)loss_d = loss_f(pred1, ops.ones_like(pred1)) + loss_f(pred0, ops.zeros_like(pred0))loss_dis = loss_d * lambda_disreturn loss_disdef forword_gan(reala, realb):lambda_gan = 0.5lambda_l1 = 100fakeb = net_generator(reala)pred0 = net_discriminator(reala, fakeb)loss_1 = loss_f(pred0, ops.ones_like(pred0))loss_2 = l1_loss(fakeb, realb)loss_gan = loss_1 * lambda_gan + loss_2 * lambda_l1return loss_gand_opt = nn.Adam(net_discriminator.trainable_params(), learning_rate=get_lr(),beta1=0.5, beta2=0.999, loss_scale=1)
g_opt = nn.Adam(net_generator.trainable_params(), learning_rate=get_lr(),beta1=0.5, beta2=0.999, loss_scale=1)grad_d = value_and_grad(forword_dis, None, net_discriminator.trainable_params())
grad_g = value_and_grad(forword_gan, None, net_generator.trainable_params())def train_step(reala, realb):loss_dis, d_grads = grad_d(reala, realb)loss_gan, g_grads = grad_g(reala, realb)d_opt(d_grads)g_opt(g_grads)return loss_dis, loss_ganif not os.path.isdir(ckpt_dir):os.makedirs(ckpt_dir)g_losses = []
d_losses = []
data_loader = dataset.create_dict_iterator(output_numpy=True, num_epochs=epoch_num)for epoch in range(epoch_num):for i, data in enumerate(data_loader):start_time = datetime.datetime.now()input_image = Tensor(data["input_images"])target_image = Tensor(data["target_images"])dis_loss, gen_loss = train_step(input_image, target_image)end_time = datetime.datetime.now()delta = (end_time - start_time).microsecondsif i % 2 == 0:print("ms per step:{:.2f}  epoch:{}/{}  step:{}/{}  Dloss:{:.4f}  Gloss:{:.4f} ".format((delta / 1000), (epoch + 1), (epoch_num), i, steps_per_epoch, float(dis_loss), float(gen_loss)))d_losses.append(dis_loss.asnumpy())g_losses.append(gen_loss.asnumpy())if (epoch + 1) == epoch_num:mindspore.save_checkpoint(net_generator, ckpt_dir + "Generator.ckpt")

在这里插入图片描述

6、模型推理

导入模型训练保存的权重:

from mindspore import load_checkpoint, load_param_into_netparam_g = load_checkpoint(ckpt_dir + "Generator.ckpt")
load_param_into_net(net_generator, param_g)
dataset = ds.MindDataset("./dataset/dataset_pix2pix/train.mindrecord", columns_list=["input_images", "target_images"], shuffle=True)
data_iter = next(dataset.create_dict_iterator())
predict_show = net_generator(data_iter["input_images"])
plt.figure(figsize=(10, 3), dpi=140)
for i in range(10):plt.subplot(2, 10, i + 1)plt.imshow((data_iter["input_images"][i].asnumpy().transpose(1, 2, 0) + 1) / 2)plt.axis("off")plt.subplots_adjust(wspace=0.05, hspace=0.02)plt.subplot(2, 10, i + 11)plt.imshow((predict_show[i].asnumpy().transpose(1, 2, 0) + 1) / 2)plt.axis("off")plt.subplots_adjust(wspace=0.05, hspace=0.02)
plt.show()

图像翻译效果如下:
在这里插入图片描述

Reference

昇思官方文档-Pix2Pix实现图像转换
昇思大模型平台
AI 助你无码看片,生成对抗网络(GAN)大显身手

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据面试题之Flink(3)

如何确定Flink任务的合理并行度? Flink任务如何实现端到端一致? Flink如何处理背(反)压? Flink解决数据延迟的问题 Flink消费kafka分区的数据时flink件务并行度之间的关系 使用flink-client消费kafka数据还是使用flink-connector消费 如何动态修改Flink的配置&a…

实战:基于Java的大数据处理与分析平台

实战:基于Java的大数据处理与分析平台 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何利用Java构建高效的大数据处理与分析平台。…

Python基础003

Python流程控制基础 1.条件语句 内置函数input a input("请输入一段内容:") print(a) print(type(a))代码执行的时候遇到input函数,就会等键盘输入结果,已回车为结束标志,也就时说输入回车后代码才会执行 2.顺序执行…

pandas数据分析(5)

pandas使用Numpy的np.nan代表缺失数据,显示为NaN。NaN是浮点数标准中地Not-a-Number。对于时间戳,则使用pd.NaT,而文本使用的是None。 首先构造一组数据: 使用None或者np.nan来表示缺失的值: 清理DataFrame时&#xf…

深度学习之交叉验证

交叉验证(Cross-Validation)是一种用于评估和验证机器学习模型性能的技术,尤其是在数据量有限的情况下。它通过将数据集分成多个子集,反复训练和测试模型,以更稳定和可靠地估计模型的泛化能力。常见的交叉验证方法有以…

java设计模式(四)——抽象工厂模式

一、模式介绍 改善在工厂方法模式中,扩展时新增产品类、工厂类,导致项目中类巨多的场面,减少系统的维护成本,且一个工厂可以生成多种产品,而不是同一种的产品,比如一个工厂既可以生产鞋子又可以衣服&#…

解决数据库PGSQL,在Mybatis中创建临时表报错TODO IDENTIFIER,连接池用的Druid。更换最新版本Druid仍然报错解决

Druid版本1.1.9报错Caused by: java.sql.SQLException: sql injection violation, syntax error: TODO IDENTIFIER : CREATE TEMPORARY TABLE temp_ball_classify (id int8 NOT NULL,create_time TIMESTAMP,create_by VARCHAR,classify_name VARCHAR) 代码如下: 测…

四川蔚澜时代电子商务有限公司打造抖音电商服务新高地

在数字化浪潮汹涌澎湃的今天,电商行业以其独特的魅力和强大的市场潜力,成为了推动经济增长的新引擎。四川蔚澜时代电子商务有限公司,作为这个领域的佼佼者,正以其专业的服务、创新的理念和卓越的实力,引领抖音电商服务…

用AI,每天创作200+优质内容,2分钟教会你操作!

前段时间发布了这篇“寻找爆款文案及标题的9大渠道,直接搬运都能搞流量!”,里面我讲到如何寻找爆款标题。最近不少朋友问我,如何创作这个标题相关的内容。 多数平台都有风控规则,有些平台内容也会有字数要求。为了让大…

SpringBoot 项目整合 MyBatis 框架,附带测试示例

文章目录 一、创建 SpringBoot 项目二、添加 MyBatis 依赖三、项目结构和数据库表结构四、项目代码1、application.yml2、TestController3、TbUser4、TbUserMapper5、TestServiceImpl6、TestService7、TestApplication8、TbUserMapper.xml9、MyBatisTest 五、浏览器测试结果六、…

JavaScript实现时钟计时

会动的时钟 1.目标 2.分析 1.最开始页面不显示时间,有两个按钮 开始 暂停。开始按钮是可以点击的,暂停按钮不能点击 2.当点击开始按钮后,设置开始按钮不可用,暂停按钮可用。然后将当前系统时间放到按钮上面。每隔1秒中更新一下…

TransMIL:基于Transformer的多实例学习

MIL是弱监督分类问题的有力工具。然而,目前的MIL方法通常基于iid假设,忽略了不同实例之间的相关性。为了解决这个问题,作者提出了一个新的框架,称为相关性MIL,并提供了收敛性的证明。基于此框架,还设计了一…

3.js - 反射率(reflectivity) 、折射率(ior)

没啥太大的感觉 反射率 reflectivity 概念 反射率:指的是,材质表面反射光线的能力反射率,用于控制材质对环境光,或光源的反射程度反射率越高,材质表面反射的光线越多,看起来就越光亮使用 适用于&#xff0…

【OCPP】ocpp1.6协议第5.1章节Cancel Reservation的介绍及翻译

目录 5.1 取消预约Cancel Reservation-概述 Cancel Reservation CancelReservation.req 请求消息 CancelReservation.conf 确认消息 取消预定的流程 应用场景 示例消息 CancelReservation.req 示例 CancelReservation.conf 示例 总结 5.1 取消预约Cancel Reservation…

VScode 常用插件

基础开发插件 Chinese (Simplified)(简体中文语言包):这是适用于VS Code的中文(简体)语言包,适用于英语不太流利的用户。Auto Rename Tag:这个插件可以同步修改HTML/XML标签,当用户修…

【PYG】Cora数据集分类任务计算损失,cross_entropy为什么不能直接替换成mse_loss

cross_entropy计算误差方式,输入向量z为[1,2,3],预测y为[1],选择数为2,计算出一大坨e的式子为3.405,再用-23.405计算得到1.405MSE计算误差方式,输入z为[1,2,3],预测向量应该是[1,0,0]&#xff0…

Dify入门指南

一.Dify介绍 生成式 AI 应用创新引擎,开源的 LLM 应用开发平台。提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力,轻松构建和运营生成式 AI 原生应用,比 LangChain 更易用。一个平台,接入全球大型语言模型。不同…

CesiumJS【Basic】- #050 绘制扫描线(Primitive方式)

文章目录 绘制扫描线(Primitive方式)- 需要自定义着色器1 目标2 代码2.1 main.ts绘制扫描线(Primitive方式)- 需要自定义着色器 1 目标 使用Primitive方式绘制扫描线 2 代码 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium.Viewer(cesiumConta…

自我反思与暑假及大三上学期规划

又要放暑假了,依稀记得上个暑假一边练车,一边试图拿捏C语言,第一次感觉暑假也可以如此忙碌。但是开学以后,我并没有把重心放在期望自己应该做的事情上,更多的时间花费在了处理学院的相关事务。现在看来,大二…

《昇思 25 天学习打卡营第 9 天 | FCN 图像语义分割 》

活动地址:https://xihe.mindspore.cn/events/mindspore-training-camp 签名:Sam9029 这一章节 出现了一个 深度学习 中经常出现的概念 全卷积网络(Fully Convolutional Networks) : 官话:FCN 主要用于图像分割领域&…