pytorch09:可视化工具-TensorBoard,实现卷积核和特征图可视化

在这里插入图片描述

目录

  • 一、TensorBoard简介
  • 二、TensorBoard安装
  • 三、TensorBoard运行可视化
  • 四、TensorBoard详细使用
    • 4.1 SummaryWriter
    • 4.2 add_scalar()
    • 4.3 add_scalars()
    • 4.4 add_histogram()
      • 4.4.1实际项目开发使用
    • 4.5 add_image()
    • 4.6 torchvision.utils.make_grid
    • 4.7 卷积核和特征图可视化
      • 4.7.1 AlexNet卷积核可视化
      • 4.7.2 特征图可视化
    • 4.8 add_graph()
  • 五、summary网络查看工具

一、TensorBoard简介

当我们在模型训练过程中想要将部分参数进行可视化,例如:精确度、损失等参数,想通过一个可视化工具实时观察,可以使用tensorboard工具。
在这里插入图片描述
在使用pytorch进行一些深度学习测试的过程中,首先将生成的数据使用Python脚本进行保存,将数据保存到电脑硬盘当中,然后使用tensorboard将硬盘中的数据绘制成图,在浏览器端展示出来。

二、TensorBoard安装

打开终端,进入到项目所在的虚拟环境当中输入以下安装命令。
安装命令:

pip install tensorboard -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

三、TensorBoard运行可视化

代码案例:

import numpy as np
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter(comment='test_tensorboard')  # 使用SummaryWriter记录我们想要可视化的数据

for x in range(100):
    writer.add_scalar('y=2x', x * 2, x)
    writer.add_scalar('y=pow(2, x)', 2 ** x, x)

    writer.add_scalars('data/scalar_group', {"xsinx": x * np.sin(x),
                                             "xcosx": x * np.cos(x),
                                             "arctanx": np.arctan(x)}, x)
writer.close()

执行该代码会在当前代码文件夹目录下生成一个runs文件夹,该文件夹目录下保存的就是使用tensorboard中方法保存的可视化文件。
在这里插入图片描述
打开pycharm自带的终端,输入以下命令 tensorboard --logdir=./05-02-代码-TensorBoard简介与安装/lesson-20/runs
注意:logdir后面的文件夹路径一定要输入正确,然后会在终端显示一个本地端口号
在这里插入图片描述
点击端口号就能跳转到浏览器,观看到可视化界面,我们代码中的三个函数都进行可绘图可视化。
在这里插入图片描述

四、TensorBoard详细使用

4.1 SummaryWriter

在这里插入图片描述
功能:提供创建event file的高级接口
主要属性:
• log_dir:event file输出文件夹
• comment:不指定log_dir时,文件夹后缀
• filename_suffix:event file文件名后缀
代码实现

flag = 1
if flag:
    log_dir = "./train_log/test_log_dir"  # 指定可视化文件保存路径
    writer = SummaryWriter(log_dir=log_dir, comment='_scalars', filename_suffix="12345678")
    # writer = SummaryWriter(comment='_scalars', filename_suffix="12345678")
    for x in range(100):
        writer.add_scalar('y=pow_2_x', 2 ** x, x)
    writer.close()

文件创建结果
文件指定路径train_log/test_log_dir,生成的event 文件后缀名为12345678,_scalars并没有出现在路径当中,因为我们设置log_dir 指定路径。
在这里插入图片描述


不使用log_dir代码实现

flag = 1
if flag:
    log_dir = "./train_log/test_log_dir"  # 指定可视化文件保存路径
    # writer = SummaryWriter(log_dir=log_dir, comment='_scalars', filename_suffix="12345678")
    writer = SummaryWriter(comment='_scalars', filename_suffix="12345678")
    for x in range(100):
        writer.add_scalar('y=pow_2_x', 2 ** x, x)
    writer.close()

文件创建结果:
创建的文件夹带有comment指定后缀名_scalars。
在这里插入图片描述

4.2 add_scalar()

在这里插入图片描述
功能:记录标量
• tag:图像的标签名,图的唯一标识
• scalar_value:要记录的标量
• global_step:x轴
该方法有一定局限性,只能记录一条曲线,所以一般我们不使用该方法

4.3 add_scalars()

在这里插入图片描述
功能:记录多个标量,可以绘制多条曲线。
• main_tag:该图的标签。
• tag_scalar_dict:key是变量的tag,value是变量的值,使用字典的形式去记录多条曲线。

scalar 和 scalars代码实现

flag = 1
if flag:
    max_epoch = 100
    writer = SummaryWriter(comment='test_comment', filename_suffix="test_suffix")
    for x in range(max_epoch):
        writer.add_scalar('y=2x', x * 2, x)
        writer.add_scalar('y=pow_2_x', 2 ** x, x)
        writer.add_scalars('data/scalar_group', {"xsinx": x * np.sin(x),
                                                 "xcosx": x * np.cos(x)}, x) #字典存储的两个函数
    writer.close()

可视化结果:
在这里插入图片描述

4.4 add_histogram()

在这里插入图片描述
功能:统计参数直方图与多分位数折线图
• tag:图像的标签名,图的唯一标识。
• values:要统计的参数,可以是权重、偏执或者是梯度。
• global_step:y轴。
• bins:取直方图的bins。
代码实现1:

flag = 1
if flag:
    writer = SummaryWriter(comment='test_comment', filename_suffix="test_suffix")
    for x in range(2):
        np.random.seed(x)
        data_union = np.arange(100)
        data_normal = np.random.normal(size=1000)  #1000个数据正态分布
        writer.add_histogram('distribution union', data_union, x)  # 使用tensorboard绘制直方图
        writer.add_histogram('distribution normal', data_normal, x)
        plt.subplot(121).hist(data_union, label="union")  # 使用plt绘制直方图
        plt.subplot(122).hist(data_normal, label="normal")
        plt.legend()
        plt.show()
    writer.close()

plt直方图两次绘制结果:
在这里插入图片描述
在这里插入图片描述

tensorboard两次绘制结果:
在这里插入图片描述

4.4.1实际项目开发使用

代码实现:

将训练、验证过程中的损失已经精度都使用add_scalars写入进去,同时将每一个epoch的梯度都使用add_histogram方法添加。

# -*- coding:utf-8 -*-

import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from torch.utils.tensorboard import SummaryWriter
import torch.optim as optim
from matplotlib import pyplot as plt
from lenet import LeNet
from my_dataset import RMBDataset
from common_tools import set_seed

set_seed()  # 设置随机种子
rmb_label = {"1": 0, "100": 1}

# 参数设置
MAX_EPOCH = 10
BATCH_SIZE = 16
LR = 0.01
log_interval = 10
val_interval = 1

# ============================ step 1/5 数据 ============================

split_dir = os.path.join("rmb_split")
train_dir = os.path.join(split_dir, "train")
valid_dir = os.path.join(split_dir, "valid")

norm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

train_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomCrop(32, padding=4),
    transforms.RandomGrayscale(p=0.8),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

valid_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

# 构建MyDataset实例
train_data = RMBDataset(data_dir=train_dir, transform=train_transform)
valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform)

# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)

# ============================ step 2/5 模型 ============================

net = LeNet(classes=2)
net.initialize_weights()

# ============================ step 3/5 损失函数 ============================
criterion = nn.CrossEntropyLoss()  # 选择损失函数

# ============================ step 4/5 优化器 ============================
optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9)  # 选择优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)  # 设置学习率下降策略

# ============================ step 5/5 训练 ============================
train_curve = list()
valid_curve = list()

iter_count = 0

# 构建 SummaryWriter
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

for epoch in range(MAX_EPOCH):

    loss_mean = 0.
    correct = 0.
    total = 0.

    net.train()
    for i, data in enumerate(train_loader):

        iter_count += 1

        # forward
        inputs, labels = data
        outputs = net(inputs)

        # backward
        optimizer.zero_grad()
        loss = criterion(outputs, labels)
        loss.backward()

        # update weights
        optimizer.step()

        # 统计分类情况
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).squeeze().sum().numpy()

        # 打印训练信息
        loss_mean += loss.item()
        train_curve.append(loss.item())
        if (i + 1) % log_interval == 0:
            loss_mean = loss_mean / log_interval
            print("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, i + 1, len(train_loader), loss_mean, correct / total))
            loss_mean = 0.

        # 记录数据,保存于event file
        writer.add_scalars("Loss", {"Train": loss.item()}, iter_count)
        writer.add_scalars("Accuracy", {"Train": correct / total}, iter_count)

    # 每个epoch,记录梯度,权值
    # net.named_parameters() 返回我们的参数以及对应的名字
    for name, param in net.named_parameters():
        writer.add_histogram(name + '_grad', param.grad, epoch)
        writer.add_histogram(name + '_data', param, epoch)

    scheduler.step()  # 更新学习率

    # validate the model
    if (epoch + 1) % val_interval == 0:

        correct_val = 0.
        total_val = 0.
        loss_val = 0.
        net.eval()
        with torch.no_grad():
            for j, data in enumerate(valid_loader):
                inputs, labels = data
                outputs = net(inputs)
                loss = criterion(outputs, labels)

                _, predicted = torch.max(outputs.data, 1)
                total_val += labels.size(0)
                correct_val += (predicted == labels).squeeze().sum().numpy()

                loss_val += loss.item()

            valid_curve.append(loss.item())
            print("Valid:\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, j + 1, len(valid_loader), loss_val, correct / total))

            # 记录数据,保存于event file
            writer.add_scalars("Loss", {"Valid": np.mean(valid_curve)}, iter_count)
            writer.add_scalars("Accuracy", {"Valid": correct / total}, iter_count)

train_x = range(len(train_curve))
train_y = train_curve

train_iters = len(train_loader)
valid_x = np.arange(1, len(valid_curve) + 1) * train_iters * val_interval  # 由于valid中记录的是epochloss,需要对记录点进行转换到iterations
valid_y = valid_curve

plt.plot(train_x, train_y, label='Train')
plt.plot(valid_x, valid_y, label='Valid')

plt.legend(loc='upper right')
plt.ylabel('loss value')
plt.xlabel('Iteration')
plt.show()

训练精度和验证集精度(图1),以及训练损失和验证集损失(图2)
在这里插入图片描述
训练过程中的参数分布
在这里插入图片描述

直方图分布情况
会发现越往下,梯度值越小,因为梯度是loss的导数,loss随着epoch的增加减少,所以越往后梯度也就越小。
在这里插入图片描述

4.5 add_image()

功能:记录图像
在这里插入图片描述
• tag:图像的标签名,图的唯一标识
• img_tensor:图像数据,注意尺度
• global_step:x轴
• dataformats:数据形式,CHW,HWC,HW
代码实现:

flag = 1
if flag:
    writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")
    # img 1     random
    fake_img = torch.randn(3, 512, 512)
    writer.add_image("fake_img", fake_img, 1)
    time.sleep(1)
    # img 2     ones
    fake_img = torch.ones(3, 512, 512)
    time.sleep(1)
    writer.add_image("fake_img", fake_img, 2)
    # img 3     1.1
    fake_img = torch.ones(3, 512, 512) * 1.1
    time.sleep(1)
    writer.add_image("fake_img", fake_img, 3)
    # img 4     HW
    fake_img = torch.rand(512, 512)  # 灰度图
    writer.add_image("fake_img", fake_img, 4, dataformats="HW")
    # img 5     HWC
    fake_img = torch.rand(512, 512, 3)
    writer.add_image("fake_img", fake_img, 5, dataformats="HWC")
    writer.close()

展示结果:
在这里插入图片描述

4.6 torchvision.utils.make_grid

功能:制作网格图像在这里插入图片描述
• tensor:图像数据, BCH*W形式,pytorch训练图像格式
• nrow:行数(列数自动计算)
• padding:图像间距(像素单位),也就是网格线的宽度
• normalize:是否将像素值标准化,0~225之间
• range:标准化范围
• scale_each:是否单张图维度标准化
• pad_value:padding的像素值,也就是网格线的颜色

代码实现:

flag = 1
if flag:
    writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

    split_dir = os.path.join("rmb_split")
    train_dir = os.path.join(split_dir, "train")

    transform_compose = transforms.Compose([transforms.Resize((32, 64)), transforms.ToTensor()])
    
    train_data = RMBDataset(data_dir=train_dir, transform=transform_compose)
    train_loader = DataLoader(dataset=train_data, batch_size=16, shuffle=True)
    data_batch, label_batch = next(iter(train_loader))  # 取出一个batch数据,data_batch图片数据以及数据标签

    img_grid = vutils.make_grid(data_batch, nrow=4, normalize=True, scale_each=True)
    writer.add_image("input img", img_grid, 0)
    writer.close()

展示结果:
在这里插入图片描述

4.7 卷积核和特征图可视化

4.7.1 AlexNet卷积核可视化

代码实现:
对单个卷积核的三个通道图展示,以及对64个卷积核直接进行可视化。

flag = 1
if flag:
    writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")
    alexnet = models.alexnet(pretrained=True)  # 获取一个预训练好的alexnet
    kernel_num = -1  # 当前第几个卷积核层
    vis_max = 1  # 最大可视化卷积层
    for sub_module in alexnet.modules():  # 递归当前网络下的所有网络层
        if isinstance(sub_module, nn.Conv2d):  # 判断当前递归的网络层是否是卷积层
            kernel_num += 1
            if kernel_num > vis_max:  # 只展示前两个卷积层
                break
            kernels = sub_module.weight  # 获取当前卷积核的权重
            c_out, c_int, k_w, k_h = tuple(kernels.shape)
            # 对c_out单独可视化
            for o_idx in range(c_out):
                kernel_idx = kernels[o_idx, :, :, :].unsqueeze(1)  # make_grid需要 BCHW,这里拓展C维度
                kernel_grid = vutils.make_grid(kernel_idx, normalize=True, scale_each=True, nrow=c_int)
                writer.add_image('{}_Convlayer_split_in_channel'.format(kernel_num), kernel_grid, global_step=o_idx)

            # 对64个卷积核直接进行可视化
            kernel_all = kernels.view(-1, 3, k_h, k_w)  # b,3, h, w
            kernel_grid = vutils.make_grid(kernel_all, normalize=True, scale_each=True, nrow=8)  # c, h, w
            writer.add_image('{}_all'.format(kernel_num), kernel_grid, global_step=322)
            print("{}_convlayer shape:{}".format(kernel_num, tuple(kernels.shape)))
    writer.close()

展示结果:
在这里插入图片描述

4.7.2 特征图可视化

代码实现:
将经过第一层卷积之后的特征图展示出来;

# ----------------------------------- 特征图可视化 -----------------------------------
# flag = 0
flag = 1
if flag:
    writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

    # 数据
    path_img = "3.jpg"  # your path to image
    normMean = [0.49139968, 0.48215827, 0.44653124]
    normStd = [0.24703233, 0.24348505, 0.26158768]

    # 图片预处理
    img_transforms = transforms.Compose([
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize(normMean, normStd)
    ])

    # 将图片转换成RGB格式
    img_pil = Image.open(path_img).convert('RGB')
    if img_transforms is not None:
        img_tensor = img_transforms(img_pil)

    # 增加一个维度
    img_tensor.unsqueeze_(0)  # chw --> bchw

    # 模型
    alexnet = models.alexnet(pretrained=True)

    # forward
    convlayer1 = alexnet.features[0]  # 获取第一个卷积层
    fmap_1 = convlayer1(img_tensor)  # 将图片交给第一个卷积层进行处理

    # 预处理 希望batch能够大一些
    fmap_1.transpose_(0, 1)  # bchw=(1, 64, 55, 55) --> (64, 1, 55, 55)
    fmap_1_grid = vutils.make_grid(fmap_1, normalize=True, scale_each=True, nrow=8)

    writer.add_image('feature map in conv1', fmap_1_grid, global_step=322)
    writer.close()

展示结果:在这里插入图片描述

4.8 add_graph()

功能:可视化模型计算图
在这里插入图片描述
• model:模型,必须是 nn.Module
• input_to_model:输出给模型的数据
• verbose:是否打印计算图结构信息
代码实现:

flag = 1
if flag:
    writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")
    # 模型
    fake_img = torch.randn(1, 3, 32, 32)
    lenet = LeNet(classes=2)
    writer.add_graph(lenet, fake_img)
    writer.close()

展示结果:
在这里插入图片描述

五、summary网络查看工具

功能:查看模型信息,便于调试,用于观察网络结构很好的工具。
在这里插入图片描述
• model:pytorch模型
• input_size:模型输入size
• batch_size:batch size
• device:“cuda” or “cpu”

代码实现:

    from torchsummary import summary
    lenet = LeNet(classes=2)
    print(summary(lenet, (3, 32, 32), device="cpu"))

输出结果:
在这里插入图片描述

第一层456个参数是如何计算的?
LeNet网络结构如下,可以看出第一层网络input通道数为3,output输出通道数为6,卷积核大小为5x5,所以参数量为6x3x5x5=450,因为加了6个bias,所以总参数量为456.
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android开发Flutter使用SharedPreferences示例

文章目录 SharedPreferences具体使用 SharedPreferences Android原生开发经常会用SharedPreferences来保存一些设置,Flutter用什么来保存这些设置呢? 在Flutter中,你可以使用shared_preferences插件来实现类似Android原生开发中的SharedPref…

低抖动可编程SPXO SG-8200CG, SG-8201CG -高稳定性和低抖动特性

描述 SG-8200CG和SG-8201CG (sg -8201系列)利用爱普生新的低噪声分n锁相环技术&#xff0c;与上一代爱普生可编程晶体振荡器相比&#xff0c;稳定性提高了约2x&#xff0c;相位抖动降低了<1/25。sg -8201系列可编程为1.2MHz至170MHz的任何频率&#xff0c;工作温度范围可达…

tcp/ip协议2实现的插图,数据结构6 (24 - 章)

(142) 142 二四1 TCP传输控制协议 tcpstat统计量与tcp 函数调用链 (143) 143 二四2 TCP传输控制协议 宏定义与常量值–上 (144) 144 二四3 TCP传输控制协议 宏定义与常量值–下 (145) 145 二四4 TCP传输控制协议 结构tcphdr,tcpiphdr (146) 146 二四5 TCP传输控制协议 结构 tcp…

【MATLAB】ICEEMDAN_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 ICEEMDAN-LSTM神经网络时序预测算法是一种结合了改进的完全扩展经验模态分解&#xff08;ICEEMDAN&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 …

x-cmd pkg | raku - 渐进类型的、多范式的编程语言

目录 简介首次用户技术特点相关的术语进一步阅读 简介 Raku 是 Perl 家族中的一种编程语言&#xff0c;原名 Perl 6&#xff0c;主要设计者为 Larry Wall&#xff0c;从2000年开始开发&#xff0c;2019年10月更名为 Raku&#xff0c;是一种通用的、渐进类型的、多范式的编程语…

C++常用库函数大小写转换

在我们在编写代码时大小写转换是基础知识&#xff0c;这篇博客将通过介绍C常用库函数来回顾和学习一种不一样的大小写转换 目录 一、islower/isupper函数二、tolower/toupper函数三、ASCLL码 一、islower/isupper函数 islower和isupper函数是C标准库中的字符分类函数&#xff…

什么是检索增强生成 (RAG)

什么是 RAG RAG&#xff0c;即检索增强生成&#xff0c;是一种将预训练的大型语言模型的功能与外部数据源相结合的技术。这种方法将 GPT-3 或 GPT-4 等 LLM 的生成能力与专用数据搜索机制的精确性相结合&#xff0c;从而形成一个可以提供细微响应的系统。 本文更详细地探讨了…

搭建Eureka服务注册中心

前言 我们在别的章节中已经详细讲解过eureka注册中心的作用&#xff0c;本节会简单讲解eureka作用&#xff0c;侧重注册中心的搭建。 Eureka作为服务注册中心可以进行服务注册和服务发现&#xff0c;注册在上面的服务可以到Eureka上进行服务实例的拉取&#xff0c;主要作用就是…

加载符号文件

1、加载符号文件 当程序突发崩溃时&#xff0c;当我们尝试通过core文件分析原因时&#xff0c;通常会遇到以下问题&#xff0c;那么这种情况该怎么解决呢&#xff1f; 适用场景 二进制文件与符号文件分离的情况。 # 将test中的调试信息以外的数据剥离&#xff0c;生成符号文…

性能分析与调优: Linux 文件系统观测工具

目录 一、实验 1.环境 2.mount 3.free 4.top 5.vmstat 6.sar 7.slabtop 8.strace 9.opensnoop 10.filetop 11.cachestat 二、问题 1.Ftrace实例如何实现 2.Function trace 如何跟踪实例 3.function_graph Trace 如何跟踪实例 4.trace event 如何跟踪实例 5.未…

C语言入门教程,C语言学习教程(第一部分:编程基础 )二

九、进制详解&#xff1a;二进制、八进制和十六进制 我们平时使用的数字都是由 0~9 共十个数字组成的&#xff0c;例如 1、9、10、297、952 等&#xff0c;一个数字最多能表示九&#xff0c;如果要表示十、十一、二十九、一百等&#xff0c;就需要多个数字组合起来。 例如表示…

SpringIOC之support模块GenericApplicationContext

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

外贸企业建站步骤有哪些?海洋建站怎么做?

外贸企业建站平台推荐&#xff1f;做外贸如何搭建贸易网站&#xff1f; 外贸企业要想在激烈的市场竞争中立于不败之地&#xff0c;建立一个专业而吸引人的网站是至关重要的一环。海洋建站将深入探讨外贸企业建站的关键步骤&#xff0c;为您提供一个清晰的指南&#xff0c;助您…

自行车商城网站网页设计与制作web前端设计html+css+js成品。电脑网站制作代开发。vscodeDrea

【自行车商城网站网页设计与制作web前端设计htmlcssjs成品。电脑网站制作代开发。vscodeDrea】 https://www.bilibili.com/video/BV1wT4y1p7jq/?share_sourcecopy_web&vd_sourced43766e8ddfffd1f1a1165a3e72d7605

xilinix 7系列器件生成已加密文件和已经过身份验证的文件

注释 &#xff1a;如需了解更多信息&#xff0c;请参阅《使用加密确保 7 系列 FPGA 比特流的安全》(XAPP1239)。 要生成加密比特流&#xff0c;请在 Vivado IDE 中打开已实现的设计。在主工具栏中&#xff0c;依次选择“Flow” → “Bitstream Settings”&#xff08;流程 >…

ARCGIS PRO SDK 设置UI控件状态:启用/禁用

举例&#xff1a; 第一步&#xff1a;添加两个 Button 分别命名为Connect、Disconnect 第二步&#xff1a;nfig.daml添加状态和条件&#xff1a;在 DAML 中定义条件。请记住&#xff0c;条件存在于模块标记<modules>之外&#xff0c;下代码定义&#xff1a;Disconnected_…

前端八股文(网络篇)一

目录 1.Get和Post的请求的区别 2.常见的HTTP请求头和响应头 3.常见的HTTP请求方法 4.HTTP与HTTPS协议的区别 5.对keep-alive的理解 6.页面有多张图片&#xff0c;HTTP是怎样的加载表现&#xff1f; 7.HTTP请求报文是什么样的&#xff1f; 8.HTTP响应报文是什么样&#x…

基于SSM+BootStrap的学生宿舍管理系统(带文档、Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

速卖通跨境智星:解决IP及环境问题,实现批量注册轻松搞定

如果想要注册大批量的速卖通买家号&#xff0c;关键问题之一就是IP及浏览环境的管理。为了确保每个账号都能独立运行&#xff0c;使用独立的IP是必不可少的。近期&#xff0c;速卖通跨境智星备受关注&#xff0c;支持绑定代理IP&#xff0c;并内置反指纹技术&#xff0c;为用户…

阿里云99元赠送云·原生建站(电商版)是什么?

购买阿里云99元服务器赠送云原生建站&#xff08;电商版&#xff09;&#xff0c;什么是云原生建站&#xff1f;类似模板建站&#xff0c;云原生建站预置响应式模板CMS内容管理系统&#xff0c;用户可以按需随意切换模板样式&#xff0c;通过模板可视化在线编辑轻松完成网站搭建…