DCGAN的原理(附代码解读)

学习DCGAN之前需要了解一下转置卷积 可以参考学DCGAN对抗网络之前--转置卷积(附代码解读)-CSDN博客

1.DCGAN对于GAN的改进之处

  1. 网络架构的优化
    • DCGAN在生成器和判别器中明确使用了卷积层和卷积转置层(也称为反卷积层或分数阶卷积层)。这一改变使得网络能够更好地捕捉图像的空间特征,从而生成更高质量的图像。
    • 生成器中使用转置卷积层进行上采样,而判别器中使用标准的卷积层进行下采样。这种设计有助于保持图像的空间结构,减少模糊和伪影。
  2. 训练稳定性的提升
    • DCGAN在每一层之后都使用了Batch Normalization(BN)层,这有助于处理初始化不良导致的训练问题,加速模型训练,并提升训练的稳定性。
    • 在生成器中,除输出层使用Tanh或Sigmoid激活函数外,其余层全部使用ReLU激活函数。而在判别器中,所有层都使用LeakyReLU激活函数,以防止梯度消失的问题。
  3. 生成图像质量的改善
    • 通过使用深度卷积结构和优化的训练策略,DCGAN能够生成更高分辨率、更清晰和更逼真的图像。这得益于其改进的网络架构和训练稳定性。

2.网络模型

        1.生成器网络模型

使用到了转置卷积 将一个100个长度的正态分布噪声经过转置卷积之后生成一张3*64*64的图片

        2.判别器网络模型

使用到了卷积 将3*64*64大小的图片经过多次卷积之后变成一个1*1*1大小的概率值

3.DCGAN的设计细节

1. 取消所有pooling层,G网络中使用转置卷积(transposed convolutional layer)进行上采样,D网络中加入stride的卷积(为防止梯度稀疏)代替pooling。

2. 去掉FC层(全连接),使网络变成全卷积网络。

3. G网络中使用Relu作为激活函数,最后一层用Tanh。

4. D网络中使用LeakyRelu激活函数。

5. 在generator和discriminator上都使用batchnorm,解决初始化差的问题,帮助梯度传播到每一层,防止generator把所有的样本都收敛到同一点。直接将BN应用到所有层会导致样本震荡和模型不稳定,因此在生成器的输出层和判别器的输入层不使用BN层,可以防止这种现象。

6. 使用Adam优化器。

4.代码解读

DCGAN和GAN代码的区别主要体现在生成器和判别器的定义中 训练什么的都大差不差

1.数据加载

数据加载的代码和GAN的代码一样可参考:GAN对抗网络(代码详细解读)_gan 生成对抗网络-CSDN博客

代码如下

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
import  matplotlib.pyplot as plt
import torchvision
from torchvision import transforms#对数据做归一化处理 -1 - 1 之间 这和Gan训练最后要用tanh函数有关 tanh函数取值范围就是-1 - 1之间
transforms =  transforms.Compose([#0-1归一化:将图像中的像素值从原范围(通常是 [0, 255] 或者具体的设备特定范围)转换到 [0, 1]的范围内,方便神经网络模型训练,加速收敛。#通道顺序调整:图像通常以 HWC(Height, Width, Channel)的形式存在#ToTensor() 函数会将通道(color channels)移动到最前面,变成标准的 CHW(Channel, Height, Width)格式,这是PyTorch张量的标准格式。transforms.ToTensor(),# mean:均值 std:方差  可以将数据转换成-1 - 1之间的数据transforms.Normalize(0.5,0.5)
])#加载内置数据集
train_ds = torchvision.datasets.MNIST(root='E:\Pc项目\pythonProjectlw\数据集',train=True,transform=transforms,download=True)dataloader = torch.utils.data.DataLoader(train_ds,batch_size=64,shuffle=True)

2.生成器模型代码

定义生成器(使用转置卷积进行传播)

#定义生成器
class Generator(nn.Module):def __init__(self):super(Generator,self).__init__()self.linear1 = nn.Linear(100, 7*7*256)self.bn1 = nn.BatchNorm1d(7*7*256)self.deconv1 = nn.ConvTranspose2d(256,128,kernel_size=(3,3),stride=1,padding=1)self.bn2 = nn.BatchNorm2d(128)self.deconv2 = nn.ConvTranspose2d(128,64,kernel_size=(4,4),stride=2,padding=1)self.bn3 = nn.BatchNorm2d(64)self.deconv3 = nn.ConvTranspose2d(64,1,kernel_size=(4,4),stride=2,padding=1)

1.self.linear1 = nn.Linear(100, 256 * 7 * 7):

定义了一个全连接层(也称为线性层),输入特征数为100,输出特征数为256 * 7 * 7。这通常是将一个随机噪声向量(大小为100)映射到一个更大的空间,以便后续的反卷积层可以将其转换为图像。

2.self.bn1 = nn.BatchNorm1d(256 * 7 * 7):

定义了一个一维批量归一化层,用于对linear1层的输出进行归一化,以加速训练过程并提高模型的稳定性。

3.self.decon1 = nn.ConvTranspose2d(in_channels=256, out_channels=128, kernel_size=(3, 3), stride=1, padding=1) # (128, 7, 7):

定义了一个反卷积层(也称为转置卷积层),用于将特征图的大小上采样(放大)。输入通道数为256,输出通道数为128,卷积核大小为3x3,步长为1,填充为1。注释中的(128, 7, 7)表示该层输出特征图的通道数和空间维度(假设输入特征图的空间维度也是7x7)。

定义生成器的前向传播

def forward(self,x):x = F.relu(self.linear1(x))x = self.bn1(x)#维度维7*7*256的唯一向量 拉成长和宽都为7*7 通道数为256的图像 torch.size([64,256,7,7])x = x.view(-1,256,7,7)x = F.relu(self.deconv1(x))x =self.bn2(x)x = F.relu(self.deconv2(x))x = self.bn3(x)x = torch.tanh(self.deconv3(x))return x

1.x = F.relu(self.linear1(x)):

通过linear1层传递输入x,并应用ReLU激活函数。

2.x = self.bn1(x):

linear1层的输出进行批量归一化。

3.x = x.view(-1, 256, 7, 7):

bn1层的输出重塑为四维张量,以便可以传递给反卷积层。-1表示自动计算该维度的大小。

4.x = torch.tanh(self.decon3(x)):

通过decon3层传递归一化后的x,并应用tanh激活函数。tanh函数将输出值限制在-1到1之间,这对于生成图像数据是有用的。

为什么要对linear层的输出进行归一化?

对于linear层(一个全连接层),其输出可能会因为权重和偏置的随机初始化以及输入数据的分布差异而具有较大的方差。这种较大的方差可能会导致后续层的输入分布发生显著变化,从而影响模型的训练效果。通过对linear1层的输出进行归一化,可以使其输出保持在一个相对稳定的分布范围内,有助于后续层更好地学习和泛化。

具体来说,批量归一化层会对每个小批量(batch)的数据进行以下操作:

  1. 计算该小批量数据的均值和方差。
  2. 使用这些均值和方差对该小批量数据进行归一化,使其具有零均值和单位方差。
  3. 引入两个可学习的参数(缩放因子和偏移量),以便在归一化的基础上进行微调,以保持模型的表示能力。

3.判别器模型代码

定义判别器(使用卷积进行传播)

#定义判别器
class Discriminator(nn.Module):def __init__(self):super(Discriminator,self).__init__()self.conv1 = nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, stride=2)self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=2)self.bn = nn.BatchNorm2d(128)self.fc = nn.Linear(128*6*6,1)

1.self.conv1 = nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, stride=2):

  • 这行代码定义了一个二维卷积层conv1nn.Conv2d是PyTorch中用于二维卷积的类。
    • in_channels=1:表示输入图像的通道数为1,这通常用于灰度图像。
    • out_channels=64:表示输出特征图的通道数为64。
    • kernel_size=3:表示卷积核的大小为3x3。
    • stride=2:表示卷积时的步长为2,这会导致输出特征图的尺寸减半。

2.self.bn = nn.BatchNorm2d(128):

  • 这行代码定义了一个二维批归一化层bnnn.BatchNorm2d是PyTorch中用于二维数据的批归一化类。
    • 128:表示归一化的特征图通道数为128,这与conv2的输出通道数相同。

3.self.fc = nn.Linear(128*6*6,1):

  • 这行代码定义了一个全连接层fcnn.Linear是PyTorch中用于全连接的类。
    • 128*6*6:这是输入特征的数量。由于conv2的输出特征图在经过步长为2的两次卷积后,其高度和宽度都会减半(假设输入图像的高度和宽度均为28,则conv2的输出特征图尺寸为6x6),且通道数为128,因此输入特征的数量为12866。
    • 1:表示输出特征的数量,即判别器的输出是一个标量,用于表示输入图像是真实图像的概率(在GAN的上下文中)。

定义判别器的前向传播

    def forward(self,x):x = F.dropout2d(F.leaky_relu(self.conv1(x)),p = 0.3)x = F.dropout2d(F.leaky_relu(self.conv2(x)),p = 0.3)x = self.bn(x)x = x.view(-1,128*6*6)x = torch.sigmoid(self.fc(x))return x

1.x = F.dropout2d(F.leaky_relu(self.conv1(x)), p=0.3):

  • 这行代码执行了几个操作:
    • self.conv1(x):首先,数据x通过第一个卷积层conv1
    • F.leaky_relu(...):然后,卷积层的输出通过Leaky ReLU激活函数。Leaky ReLU是ReLU激活函数的一个变体,它在负输入值上有一个小的非零梯度,这有助于缓解ReLU的“死亡神经元”问题。
    • F.dropout2d(..., p=0.3):最后,Leaky ReLU的输出通过二维Dropout层。Dropout是一种正则化技术,用于减少神经网络过拟合。p=0.3表示在每个训练步骤中,每个元素有30%的概率被随机置零。

2.x = self.bn(x):

  • 这行代码将Dropout层的输出通过批归一化层bn

3.x = x.view(-1, 128*6*6):

  • 这行代码使用view方法重新塑形数据x-1表示自动计算该维度的大小,以保持数据的总元素数量不变。128*6*6是期望的输出形状,其中128是通道数,6x6是特征图的高度和宽度(假设输入图像经过两次步长为2的卷积后尺寸减半两次,且输入图像大小适合此假设)。这一步是为了准备数据以便输入到全连接层fc

4.x = torch.sigmoid(self.fc(x)):

  • 这行代码首先将数据x通过全连接层fc,然后通过sigmoid激活函数。Sigmoid函数将输出压缩到0和1之间,这在二分类问题中很有用,例如,在GAN中,判别器需要输出一个概率值来表示输入图像是真实图像的概率。

4.代码总览

剩下的代码还有分别初始化判别器和生成器的优化器,损失计算函数,绘图函数,GAN的训练

代码和GAN的代码一样 具体代码请参考GAN对抗网络(代码详细解读)_gan 生成对抗网络-CSDN博客

对代码有详细的解读

以下是完整的代码:

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
import torchvision
from torch import le
from torchvision import transforms
from torch.utils.data import DataLoader# 对数据做归一化处理 -1 - 1 之间 这和Gan训练最后要用tanh函数有关 tanh函数取值范围就是-1 - 1之间
transforms = transforms.Compose([# 0-1归一化:将图像中的像素值从原范围(通常是 [0, 255] 或者具体的设备特定范围)转换到 [0, 1] 的范围内,方便神经网络模型训练,加速收敛。# 通道顺序调整:图像通常以 HWC(Height, Width, Channel)的形式存在# ToTensor() 函数会将通道(color channels)移动到最前面,变成标准的 CHW(Channel, Height, Width)格式,这是PyTorch张量的标准格式。transforms.ToTensor(),# mean:均值 std:方差  可以将数据转换成-1 - 1之间的数据transforms.Normalize(0.5, 0.5)
])# 加载内置数据集
train_ds = torchvision.datasets.MNIST(root='E:\Pc项目\pythonProjectlw\数据集',train=True,transform=transforms,download=True)train_dl = torch.utils.data.DataLoader(train_ds, batch_size=64, shuffle=True)#定义生成器
class Generator(nn.Module):def __init__(self):super(Generator,self).__init__()self.linear1 = nn.Linear(100, 7*7*256)self.bn1 = nn.BatchNorm1d(7*7*256)self.deconv1 = nn.ConvTranspose2d(256,128,kernel_size=(3,3),stride=1,padding=1)self.bn2 = nn.BatchNorm2d(128)self.deconv2 = nn.ConvTranspose2d(128,64,kernel_size=(4,4),stride=2,padding=1)self.bn3 = nn.BatchNorm2d(64)self.deconv3 = nn.ConvTranspose2d(64,1,kernel_size=(4,4),stride=2,padding=1)def forward(self,x):x = F.relu(self.linear1(x))x = self.bn1(x)#维度维7*7*256的唯一向量 拉成长和宽都为7*7 通道数为256的图像 torch.size([64,256,7,7])x = x.view(-1,256,7,7)x = F.relu(self.deconv1(x))x =self.bn2(x)x = F.relu(self.deconv2(x))x = self.bn3(x)x = torch.tanh(self.deconv3(x))return x#定义判别器
class Discriminator(nn.Module):def __init__(self):super(Discriminator,self).__init__()self.conv1 = nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, stride=2)self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=2)self.bn = nn.BatchNorm2d(128)self.fc = nn.Linear(128*6*6,1)def forward(self,x):x = F.dropout2d(F.leaky_relu(self.conv1(x)),p = 0.3)x = F.dropout2d(F.leaky_relu(self.conv2(x)),p = 0.3)x = self.bn(x)x = x.view(-1,128*6*6)x = torch.sigmoid(self.fc(x))return x# 初始化模型 优化器及损失计算函数
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 初始化生成器
gen = Generator().to(device)
# 初始化判别器
dis = Discriminator().to(device)
# 判别器优化器
d_optim = torch.optim.Adam(dis.parameters(), lr=0.0001)
# 生成器优化器
g_optim = torch.optim.Adam(gen.parameters(), lr=0.0001)
# 损失计算函数 二分类计算交叉熵损失的loss函数为BCELoss
loss_fn = torch.nn.BCELoss()# 定义绘图函数
# model:输入的模型 比如gen或者dis
# test_input:生成器生成模型的时候需要输入一个正态分布随机数
def gen_img_plot(model, test_input):# 预测结果# squeeze将维度为1的去掉prediction = np.squeeze(model(test_input).detach().cpu().numpy())# 初始化画布 画16张图片fig = plt.figure(figsize=(4, 4))for i in range(16):# 4行4列 i从0开始 所以i+1plt.subplot(4, 4, i + 1)# 预测输出结果 生成器最后使用的是tanh函数 范围是-1 - 1 无法绘图 需要转换成0-1之间的 所以( +1)/2plt.imshow((prediction[i] + 1) / 2,cmap="gray")plt.axis('off')plt.show()# 因为要绘制16张 所以要绘制16*100的张量
test_input = torch.randn(16, 100, device=device)# GAN训练
# 记录每次epoch产生的loss值
D_loss = []
G_loss = []# 训练循环 100个epoch
for epoch in range(100):# 初始化损失值为0 将每一个批次产生的损失累加到d_epoch_loss中# 最后除以总的批次数 能够计算出每一个epoch的平均lossd_epoch_loss = 0g_epoch_loss = 0# len(dataloader):返回批次数   len(dataset):返回样本数count = len(train_dl)# 对dataloader进行迭代会返回一个批次的图片 根据这个图片的数量创建同样数量的noise 作为genertator的输入for step, (img, _) in enumerate(train_dl):img = img.to(device)# 获取批次的大小size = img.size(0)random_noise = torch.rand(size, 100, device=device)# 判别器训练# 判别器训练过程 有两部分损失 一部分是判断为真的损失 一部分是判断为假的损失d_optim.zero_grad()# 1.真实的损失# 判别器输入真实的图片 real_output就是对真实图片的预测结果real_output = dis(img)# 得到判别器在真实图像上的损失# 希望判别器对真实数据的输出real_output的值为1# 这个函数是用来衡量真实输出(real_output)与预期值torch.ones_like(real_output)# (在这里是与 real_output 形状相同的全1张量)之间的差异d_real_loss = loss_fn(real_output,torch.ones_like(real_output))# 反向传播求梯度d_real_loss.backward()# 2.假的损失# 先将噪声传入生成器生成图片gen_img = gen(random_noise)# 判别器输入生成的图片 fake_output就是对生成图片的预测结果# 对于生成器产生的损失 优化的目标是判别器 生成器的参数是不需要进行优化的# 当训练判别器时,我们希望仅根据判别器自身的参数和输入(真实图像或生成图像)来计算梯度并更新参数# 如果生成图像的梯度传递到生成器,那么生成器的参数也会在判别器的训练过程中被更新,这不是我们想要的结果# 因此,我们使用.detach()方法来截断梯度,确保它们不会传播回生成器 .detach()会得到一个没有批次的tensorfake_output = dis(gen_img.detach())d_fake_loss = loss_fn(fake_output,torch.zeros_like(fake_output))# 反向传播求梯度d_fake_loss.backward()# 损失求和d_loss = d_real_loss + d_fake_loss# 优化并更新参数d_optim.step()# 生成器的损失优化 只包含一部分# 将生成器所有的梯度归零g_optim.zero_grad()# 将生成器的图片传入到判别器中 没有做梯度的截断fake_output = dis(gen_img)# 生成器的损失 .ones 因为是对生成器进行优化 生成器想判别为1g_loss = loss_fn(fake_output,torch.ones_like(fake_output))g_loss.backward()g_optim.step()# 计算在一个epoch当中总共的g_loss和d_losswith torch.no_grad():d_epoch_loss += d_lossg_epoch_loss += g_loss# 计算平均loss值with torch.no_grad():d_epoch_loss /= countg_epoch_loss /= count# 传入到列表当中D_loss.append(d_epoch_loss)G_loss.append(g_epoch_loss)# 打印信息print('Epoch:', epoch, 'D Loss:', d_epoch_loss, 'G Loss:', g_epoch_loss)
gen_img_plot(gen, test_input)

5.结果图

DCGAN:

GAN:

以上都是训练了5次的结果 可以明显地看到DCGAN的训练结果比GAN好太多了

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

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

相关文章

『 Linux 』HTTPS

文章目录 HTTPS协议密钥加密的原因加密方式数据指纹网络通信加密方案及短板CA认证CA证书的细节以及如何保证服务端公钥的安全性和数据完整性 CA认证后对称加密与非对称加密配合使用的安全性中间人的攻击方式 HTTPS协议 HTTPS协议并不是一个独立的协议,其是一种以HTTP协议为基础…

基于SSM的洗浴中心管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 方案设计(研究的基本内容,拟解决的基本问题,研究步骤、方法及措施): 研究的基本内容:根据当今社会市场所需,通过对比多家洗浴中心进行深入细致的…

第二十九篇:图解TCP三次握手,看过不会忘,从底层说清楚,TCP系列四

⼀开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝,处于 LISTEN 状态。 接下来这部分内容的介绍将影响你能不能彻底理解了TCP的三次握手。 一、划重点:只有服务端启动了端口监听,客户端TCP握手才能建立连接&…

ubuntu系统库和Anaconda库冲突问题

之前安装opencv时没出现过这种问题,自从安装Anaconda后就总遇到问题。记录下自己的解决过程。 目录 第一步 第二步 第三步 安装opencv时出现以下问题: /usr/bin/ld: /lib/x86_64-linux-gnu/libwayland-client.so.0: undefined reference to `ffi_prep_cif@LIBFFI_BASE_7.…

若依框架篇-若依集成 X-File-Storage 框架(实现图片上传阿里云 OSS 服务器)、EasyExcel 框架(实现 Excel 数据批量导入功能)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 实现使用 Excel 文件批量导入 1.1 导入功能的前端具体实现 1.2 导入功能的后端具体实现 1.3 使用 EasyExcel 框架实现 Excel 读、写功能 1.4 将 Easy Excel 集成到…

路径跟踪之导航向量场(二)——三维导航向量场

上一期文章介绍了二维平面下的导航向量场计算方法,本期文章将介绍三维空间中,导航向量场及扩展。 本文主要介绍论文[1]中提出的一种基于导航向量场的航迹跟踪算法。此外,虽然本文以三维航迹为例进行介绍,但该方法可非常方便的拓展…

智能优化算法-生物地理学算法(BBO)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 生物地理学优化算法 (Biogeography-Based Optimization, BBO) 是一种基于生物地理学原理的元启发式优化算法,由Dan Simon于2008年提出。BBO通过模拟物种在不同栖息地之间的迁移过程来搜索最优解&…

【JavaEE】——四次挥手,TCP状态转换,滑动窗口,流量控制

阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:断开连接的本质 二:四次挥手 1:FIN 2:过程梳理 …

新时代AI桌宠:XGO Rider让你的办公室瞬间高大上

​ XGO Rider Luwu 智能打造了桌面双轮足式机器人 XGO Rider,这款全球首创的轮腿式桌面AI机器人,正在悄然改变我们的办公环境。它不仅是一个高科技玩具,更是一个能大幅提升工作效率和办公室科技感的智能助手。 XGO Rider 新时代“桌宠” micr…

基于java+springboot的宇宙动漫网站

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图 前言 文章底部名片,获取项目的完整演示视频,免费解答技术疑问 项目介绍 本系统为用户而设计制作宇宙动漫网站,旨在实现宇宙动漫智能化、现代化管理。本宇宙动漫管理自…

爬虫——scrapy的基本使用

一,scrapy的概念和流程 1. scrapy的概念 Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。 框架就是把之前简单的操作抽象成一套系统,这样我们在使用框架的时候,它会自动的帮我们完成很…

【数据结构与算法】之有序链表去重(保留重复元素)

目录 1.问题描述 2.思路讲解 3.Java 代码实现 4.代码解释 5.复杂度分析 6.其它方法 6.1 递归实现 6.2 双指针 7.总结 相关教程: 有序链表去重(不保留重复元素) 数据结构之链表详解 递归详解 1.问题描述 给定一个已排序的单链表…

Java可以做人工智能吗-回答是当然可以

Java在人工智能应用开发中的角色与优势 人工智能主要分为两个部分:一个是做底层的大语言模型的训练,另一个是基于大模型进行业务应用。Java最适合做的就是第二个方面,即基于大模型构建业务应用。由于过去大量的企业级应用都是使用Java开发的…

网络服务请求流程简单理解

网络流程: DNS负责将域名解析为IP地址,ALB可以在多个服务实例之间分配流量,APISIX作为API网关处理更细粒度的流量管理,Service在Kubernetes中为Pod提供稳定的访问入口,而Kubernetes则负责整个应用的部署、扩展和运维。…

Java项目-基于springboot框架的逍遥大药房管理系统项目实战(附源码+文档)

作者:计算机学长阿伟 开发技术:SpringBoot、SSM、Vue、MySQL、ElementUI等,“文末源码”。 开发运行环境 开发语言:Java数据库:MySQL技术:SpringBoot、Vue、Mybaits Plus、ELementUI工具:IDEA/…

【UML】一个UML学习的还不错的几个帖子

https://segmentfault.com/a/1190000042775634 寂然解读设计模式 - UML类图&类的六大关系-阿里云开发者社区

最佳简历--JAVA程序员的项目经验如何写

小熊学Java全能学习+面试指南:https://www.javaxiaobear.cn 首先你要明确,你能干什么,包括你自己编写的专业技能,到底会不会,怎么运用到技术上的? 1、你能干什么? 你能干什么,其实就展现你的能力,这是简历中最重要的部分,你需要证明前面说的你会的东东; 这就有点…

【前端】如何制作一个自己的网页(14)

当我们还需要对网页中的内容进行局部样式的修改。这时候,就需要用到HTML中的重要元素:span。 span是一个行内元素,可以对HTML文档中的内容进行局部布局。 如图,我们给标题和段落元素的部分内容设置了各种样式。 接下来&#xff0…

rk3588 opencv 的使用

-------------------------------------------------------------------------------------------------------- 目前是 3588 上无法 直接编译出 C程序。 报错如下: -----------------------------------------------------------------------------------------…