昇思25天学习打卡营第20天|ShuffleNet 图像分类案例:模块、训练与评估

news2024/11/17 7:43:59

目录

基于 MindSpore 的分组卷积类定义与实现

基于 MindSpore 的 ShuffleV1Block 类定义与数据处理

基于 MindSpore 的 ShuffleNetV1 网络定义与构建

Cifar-10 数据集的获取、预处理与分批操作

基于 ShuffleNetV1 模型在 CPU 上的训练配置与执行

ShuffleNetV1 模型在 CPU 上的测试与评估

ShuffleNetV1 模型对 Cifar10 数据集的推理效果展示


基于 MindSpore 的分组卷积类定义与实现


        定义了一个名为 GroupConv 的类,用于实现分组卷积操作。首先,通过 pip 命令确保安装了特定版本的 mindspore 库。在 GroupConv 类中,初始化方法接收多个参数,包括输入通道数、输出通道数、卷积核大小、步长、填充模式、填充值、分组数和是否有偏置等。通过创建一个 nn.CellList 来存储每个分组的卷积层。在构造方法中,将输入特征按分组数进行分割,然后分别通过每个分组的卷积层进行处理,最后将处理结果拼接起来返回。

        代码如下:

%%capture captured_output
# 实验环境已经预装了mindspore==2.3.0rc1,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.3.0rc1
# 查看当前 mindspore 版本
!pip show mindspore
from mindspore import nn
import mindspore.ops as ops
from mindspore import Tensor

class GroupConv(nn.Cell):
    def __init__(self, in_channels, out_channels, kernel_size,
                 stride, pad_mode="pad", pad=0, groups=1, has_bias=False):
        super(GroupConv, self).__init__()
        self.groups = groups
        self.convs = nn.CellList()
        for _ in range(groups):
            self.convs.append(nn.Conv2d(in_channels // groups, out_channels // groups,
                                        kernel_size=kernel_size, stride=stride, has_bias=has_bias,
                                        padding=pad, pad_mode=pad_mode, group=1, weight_init='xavier_uniform'))

    def construct(self, x):
        features = ops.split(x, split_size_or_sections=int(len(x[0]) // self.groups), axis=1)
        outputs = ()
        for i in range(self.groups):
            outputs = outputs + (self.convs[i](features[i].astype("float32")),)
        out = ops.cat(outputs, axis=1)
        return out

基于 MindSpore 的 ShuffleV1Block 类定义与数据处理


        定义了一个名为 ShuffleV1Block 的类,它继承自 nn.Cell 类。在初始化方法 __init__ 中,接收了多个参数,包括输入通道数 inp 、输出通道数 oup 、分组数 group 等,并根据步长 stride 的情况计算输出的通道数。还定义了一些激活函数和卷积、批归一化等操作的配置。通过构建两个顺序结构 branch_main_1 和 branch_main_2 来定义主要的分支操作。在构造方法 construct 中,根据步长的不同处理输入数据,对右侧分支进行一系列操作,并在适当的情况下进行通道打乱和元素相加或拼接,最后通过激活函数输出结果。channel_shuffle 方法用于实现通道打乱的操作。

        代码如下:

class ShuffleV1Block(nn.Cell):
    def __init__(self, inp, oup, group, first_group, mid_channels, ksize, stride):
        super(ShuffleV1Block, self).__init__()
        self.stride = stride
        pad = ksize // 2
        self.group = group
        if stride == 2:
            outputs = oup - inp
        else:
            outputs = oup
        self.relu = nn.ReLU()
        branch_main_1 = [
            GroupConv(in_channels=inp, out_channels=mid_channels,
                      kernel_size=1, stride=1, pad_mode="pad", pad=0,
                      groups=1 if first_group else group),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(),
        ]
        branch_main_2 = [
            nn.Conv2d(mid_channels, mid_channels, kernel_size=ksize, stride=stride,
                      pad_mode='pad', padding=pad, group=mid_channels,
                      weight_init='xavier_uniform', has_bias=False),
            nn.BatchNorm2d(mid_channels),
            GroupConv(in_channels=mid_channels, out_channels=outputs,
                      kernel_size=1, stride=1, pad_mode="pad", pad=0,
                      groups=group),
            nn.BatchNorm2d(outputs),
        ]
        self.branch_main_1 = nn.SequentialCell(branch_main_1)
        self.branch_main_2 = nn.SequentialCell(branch_main_2)
        if stride == 2:
            self.branch_proj = nn.AvgPool2d(kernel_size=3, stride=2, pad_mode='same')

    def construct(self, old_x):
        left = old_x
        right = old_x
        out = old_x
        right = self.branch_main_1(right)
        if self.group > 1:
            right = self.channel_shuffle(right)
        right = self.branch_main_2(right)
        if self.stride == 1:
            out = self.relu(left + right)
        elif self.stride == 2:
            left = self.branch_proj(left)
            out = ops.cat((left, right), 1)
            out = self.relu(out)
        return out

    def channel_shuffle(self, x):
        batchsize, num_channels, height, width = ops.shape(x)
        group_channels = num_channels // self.group
        x = ops.reshape(x, (batchsize, group_channels, self.group, height, width))
        x = ops.transpose(x, (0, 2, 1, 3, 4))
        x = ops.reshape(x, (batchsize, num_channels, height, width))
        return x

基于 MindSpore 的 ShuffleNetV1 网络定义与构建


        定义了一个名为 ShuffleNetV1 的类,它继承自 nn.Cell 类。在初始化方法中,根据指定的模型大小 model_size 和分组数 group 来设置不同阶段的输出通道数。定义了一些初始的卷积、池化操作和特征提取模块。通过循环构建多个 ShuffleV1Block 来组成特征提取部分,并根据不同阶段和重复次数设置相应的参数。最后定义了全局平均池化和全连接分类器。在构造方法中,按照顺序对输入数据进行初始卷积、最大池化、特征提取、全局池化、形状调整和分类操作,最终输出分类结果。

        代码如下:

class ShuffleNetV1(nn.Cell):
    def __init__(self, n_class=1000, model_size='2.0x', group=3):
        super(ShuffleNetV1, self).__init__()
        print('model size is ', model_size)
        self.stage_repeats = [4, 8, 4]
        self.model_size = model_size
        if group == 3:
            if model_size == '0.5x':
                self.stage_out_channels = [-1, 12, 120, 240, 480]
            elif model_size == '1.0x':
                self.stage_out_channels = [-1, 24, 240, 480, 960]
            elif model_size == '1.5x':
                self.stage_out_channels = [-1, 24, 360, 720, 1440]
            elif model_size == '2.0x':
                self.stage_out_channels = [-1, 48, 480, 960, 1920]
            else:
                raise NotImplementedError
        elif group == 8:
            if model_size == '0.5x':
                self.stage_out_channels = [-1, 16, 192, 384, 768]
            elif model_size == '1.0x':
                self.stage_out_channels = [-1, 24, 384, 768, 1536]
            elif model_size == '1.5x':
                self.stage_out_channels = [-1, 24, 576, 1152, 2304]
            elif model_size == '2.0x':
                self.stage_out_channels = [-1, 48, 768, 1536, 3072]
            else:
                raise NotImplementedError
        input_channel = self.stage_out_channels[1]
        self.first_conv = nn.SequentialCell(
            nn.Conv2d(3, input_channel, 3, 2, 'pad', 1, weight_init='xavier_uniform', has_bias=False),
            nn.BatchNorm2d(input_channel),
            nn.ReLU(),
        )
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')
        features = []
        for idxstage in range(len(self.stage_repeats)):
            numrepeat = self.stage_repeats[idxstage]
            output_channel = self.stage_out_channels[idxstage + 2]
            for i in range(numrepeat):
                stride = 2 if i == 0 else 1
                first_group = idxstage == 0 and i == 0
                features.append(ShuffleV1Block(input_channel, output_channel,
                                               group=group, first_group=first_group,
                                               mid_channels=output_channel // 4, ksize=3, stride=stride))
                input_channel = output_channel
        self.features = nn.SequentialCell(features)
        self.globalpool = nn.AvgPool2d(7)
        self.classifier = nn.Dense(self.stage_out_channels[-1], n_class)

    def construct(self, x):
        x = self.first_conv(x)
        x = self.maxpool(x)
        x = self.features(x)
        x = self.globalpool(x)
        x = ops.reshape(x, (-1, self.stage_out_channels[-1]))
        x = self.classifier(x)
        return x

Cifar-10 数据集的获取、预处理与分批操作


        首先从指定的 URL 下载了一个数据集压缩文件。然后定义了一个函数 get_dataset ,用于获取 Cifar10 数据集。根据数据集的使用场景(训练或测试),为图像数据定义了不同的预处理操作,包括随机裁剪、水平翻转、调整大小、缩放、归一化和格式转换等,对标签数据进行类型转换。接着,使用 Cifar10Dataset 类加载数据集,并对图像和标签进行相应的映射操作,最后将数据集按照指定的批大小进行分批处理。最后,通过调用 get_dataset 函数获取训练数据集,并计算了每个 epoch 包含的批次数。

        代码如下:

from download import download

url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"

download(url, "./dataset", kind="tar.gz", replace=True)
import mindspore as ms
from mindspore.dataset import Cifar10Dataset
from mindspore.dataset import vision, transforms

def get_dataset(train_dataset_path, batch_size, usage):
    image_trans = []
    if usage == "train":
        image_trans = [
            vision.RandomCrop((32, 32), (4, 4, 4, 4)),
            vision.RandomHorizontalFlip(prob=0.5),
            vision.Resize((224, 224)),
            vision.Rescale(1.0 / 255.0, 0.0),
            vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
            vision.HWC2CHW()
        ]
    elif usage == "test":
        image_trans = [
            vision.Resize((224, 224)),
            vision.Rescale(1.0 / 255.0, 0.0),
            vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
            vision.HWC2CHW()
        ]
    label_trans = transforms.TypeCast(ms.int32)
    dataset = Cifar10Dataset(train_dataset_path, usage=usage, shuffle=True, num_samples=2000)
    dataset = dataset.map(image_trans, 'image')
    dataset = dataset.map(label_trans, 'label')
    dataset = dataset.batch(batch_size, drop_remainder=True)
    return dataset

dataset = get_dataset("./dataset/cifar-10-batches-bin", 4, "train")
batches_per_epoch = dataset.get_dataset_size()

        运行结果:

基于 ShuffleNetV1 模型在 CPU 上的训练配置与执行


        定义了一个名为 train 的函数,用于训练一个 ShuffleNetV1 模型。首先设置了运行环境为 PYNATIVE_MODE 并指定在 CPU 上运行。定义了交叉熵损失函数,设置了学习率调度器、优化器和损失缩放管理器。构建了 Model 对象,配置了一些回调函数,包括时间监控、损失监控和模型检查点保存等。最后打印训练开始信息,进行模型训练,并计算和打印训练所用的总时间。

        代码如下:

import time
import mindspore
import numpy as np
from mindspore import Tensor, nn
from mindspore.train import ModelCheckpoint, CheckpointConfig, TimeMonitor, LossMonitor, Model, Top1CategoricalAccuracy, Top5CategoricalAccuracy

def train():
    mindspore.set_context(mode=mindspore.PYNATIVE_MODE, device_target="CPU")
    net = ShuffleNetV1(model_size="2.0x", n_class=10)
    loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)
    min_lr = 0.0005
    base_lr = 0.05
    lr_scheduler = mindspore.nn.cosine_decay_lr(min_lr,
                                                base_lr,
                                                batches_per_epoch*2,
                                                batches_per_epoch,
                                                decay_epoch=2)
    lr = Tensor(lr_scheduler[-1])
    optimizer = nn.Momentum(params=net.trainable_params(), learning_rate=lr, momentum=0.9, weight_decay=0.00004, loss_scale=1024)
    loss_scale_manager = ms.amp.FixedLossScaleManager(1024, drop_overflow_update=False)
    model = Model(net, loss_fn=loss, optimizer=optimizer, amp_level="O3", loss_scale_manager=loss_scale_manager)
    callback = [TimeMonitor(), LossMonitor()]
    save_ckpt_path = "./"
    config_ckpt = CheckpointConfig(save_checkpoint_steps=batches_per_epoch, keep_checkpoint_max=5)
    ckpt_callback = ModelCheckpoint("shufflenetv1", directory=save_ckpt_path, config=config_ckpt)
    callback += [ckpt_callback]

    print("============== Starting Training ==============")
    start_time = time.time()
    model.train(1, dataset, callbacks=callback)
    use_time = time.time() - start_time
    hour = str(int(use_time // 60 // 60))
    minute = str(int(use_time // 60 % 60))
    second = str(int(use_time % 60))
    print("total time:" + hour + "h " + minute + "m " + second + "s")
    print("============== Train Success ==============")

if __name__ == '__main__':
train()

        运行结果:

ShuffleNetV1 模型在 CPU 上的测试与评估


        定义了一个名为 test 的函数。首先设置了运行环境为 PYNATIVE_MODE 并指定在 CPU 上运行,获取了测试数据集。然后加载了之前训练保存的模型参数到 ShuffleNetV1 模型中,并设置模型为评估模式。定义了交叉熵损失函数和评估指标,构建了 Model 对象用于评估。计算了模型在测试数据集上评估所用的时间,并将评估结果、模型检查点路径和时间信息整理成日志字符串,打印出来并保存到指定的文件中。

        代码如下:

from mindspore import load_checkpoint, load_param_into_net

def test():
    mindspore.set_context(mode=mindspore.PYNATIVE_MODE, device_target="CPU")
    dataset = get_dataset("./dataset/cifar-10-batches-bin", 2, "test")
    net = ShuffleNetV1(model_size="2.0x", n_class=10)
    param_dict = load_checkpoint("shufflenetv1-1_500.ckpt")
    load_param_into_net(net, param_dict)
    net.set_train(False)
    loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)
    eval_metrics = {'Loss': nn.Loss(), 'Top_1_Acc': Top1CategoricalAccuracy(),
                    'Top_5_Acc': Top5CategoricalAccuracy()}
    model = Model(net, loss_fn=loss, metrics=eval_metrics)
    start_time = time.time()
    res = model.eval(dataset, dataset_sink_mode=False)
    use_time = time.time() - start_time
    hour = str(int(use_time // 60 // 60))
    minute = str(int(use_time // 60 % 60))
    second = str(int(use_time % 60))
    log = "result:" + str(res) + ", ckpt:'" + "./shufflenetv1-1_500.ckpt" \
        + "', time: " + hour + "h " + minute + "m " + second + "s"
    print(log)
    filename = './eval_log.txt'
    with open(filename, 'a') as file_object:
        file_object.write(log + '\n')

if __name__ == '__main__':
test()

        运行结果:

model size is  2.0x

result:{'Loss': 2.2262978378534317, 'Top_1_Acc': 0.211, 'Top_5_Acc': 0.758}, ckpt:'./shufflenetv1-1_500.ckpt', time: 0h 3m 17s

ShuffleNetV1 模型对 Cifar10 数据集的推理效果展示


        首先加载了训练好的 ShuffleNetV1 模型参数。然后,从指定路径获取了 Cifar10 数据集的训练数据,并对用于预测和展示的数据进行了预处理和分批操作。定义了类别字典,用于将预测的类别索引转换为具体的类别名称。通过模型对预测数据进行推理,得到预测结果,并将预测结果对应的类别名称作为标题,与原始图像一起在图形中展示。

        代码如下:

import mindspore
import matplotlib.pyplot as plt
import mindspore.dataset as ds

net = ShuffleNetV1(model_size="2.0x", n_class=10)
show_lst = []
param_dict = load_checkpoint("shufflenetv1-1_500.ckpt")
load_param_into_net(net, param_dict)
model = Model(net)
dataset_predict = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = dataset_show.batch(16)
show_images_lst = next(dataset_show.create_dict_iterator())["image"].asnumpy()
image_trans = [
    vision.RandomCrop((32, 32), (4, 4, 4, 4)),
    vision.RandomHorizontalFlip(prob=0.5),
    vision.Resize((224, 224)),
    vision.Rescale(1.0 / 255.0, 0.0),
    vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),
    vision.HWC2CHW()
        ]
dataset_predict = dataset_predict.map(image_trans, 'image')
dataset_predict = dataset_predict.batch(16)
class_dict = {0:"airplane", 1:"automobile", 2:"bird", 3:"cat", 4:"deer", 5:"dog", 6:"frog", 7:"horse", 8:"ship", 9:"truck"}
# 推理效果展示(上方为预测的结果,下方为推理效果图片)
plt.figure(figsize=(16, 5))
predict_data = next(dataset_predict.create_dict_iterator())
output = model.predict(ms.Tensor(predict_data['image']))
pred = np.argmax(output.asnumpy(), axis=1)
index = 0
for image in show_images_lst:
    plt.subplot(2, 8, index+1)
    plt.title('{}'.format(class_dict[pred[index]]))
    index += 1
    plt.imshow(image)
    plt.axis("off")
plt.show()

        运行结果:

        打印时间:

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

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

相关文章

【神器分享】自从用了这个神器,大规模RNA-seq数据挖掘我也可以

咱不来虚的,只分享干货,不谈枯燥的理论,只来通俗易懂的操作。先来看一张图: 通过这张图展示的是 GEO数据库中的 RNA-seq数据与芯片数据积累随时间的变化,很显然测序数据从2015年开始就已经超过了芯片数据的累积 &#…

EtherCAT运动控制器上位机之Python+Qt(一):链接与单轴运动

ZMC408CE硬件介绍 ZMC408CE是正运动推出的一款多轴高性能EtherCAT总线运动控制器,具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口,ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC408CE支持8轴运动控制,最多可扩展至32轴…

AI初学者必看: 什么是大型语言模型 (LLM)?

介绍 “人工智能(AI)”一词于 1956 年问世,如今已为大家所熟知。然而,在 ChatGPT 迅速流行之前,AI 的使用和讨论大多局限于科学研究或虚构电影。如今,AI 尤其是生成式 AI 已成为大家热议的话题。 初学者生…

使用Process Explorer和Dependency Walker排查dll动态库加载失败的问题

目录 1、问题描述 2、如何调试Release版本的代码? 3、使用Process Explorer查看exe主程序加载的dll库列表,发现mediaplay.dll没有加载起来 4、使用Dependency Walker查看rtcmpdll.dll的库依赖关系和接口调用情况,定位问题 4.1、使用Depe…

html+css+js 实现3D透视倾斜按钮,javascript库之vanilla-tilt.js详解

前言:哈喽,大家好,今天给大家分享htmlcss 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 文…

常用游戏运行库 v4 官方版下载与安装教程 (游戏DLL补全包)

前言 游戏运行库包含了VC运行库合集,.NET2.0到.NET4.8合集,DirectX9.0 Rapture3D 等游戏必备的系统组件,如果你的游戏安装后无法运行,那么安装这些组件基本上就可以解决。本必备运行库安装包集成32位和64位运行库,是目…

(自用)MyLog 简单日志 .net6.0 等

appsettings.json {"LogOnOff": true //true 开启日志&#xff1b;false 关闭日志 } MyLog.cs using System.ComponentModel;namespace Namespace {/// <summary>/// 日志类型 枚举/// </summary>public enum LogType{[Description("调试日志&q…

Android经典面试题之实战经验分享:如何简单实现App的前后台监听判断

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 在Android中判断一个应用是否处于前台或后台&#xff0c;可以使用ActivityLifecycleCallbacks 和 ProcessLifecycleOwner。在Kotlin中&#xff…

实验2-5-3 求平方根序列前N项和

//实验2-5-3 求平方根序列前N项和/*本题要求编写程序&#xff0c; 计算平方根序列123⋯的前N项之和。 可包含头文件math.h&#xff0c;并调用sqrt函数求平方根。*/#include<stdio.h> #include<math.h> int main(){int n0;scanf("%d",&n);//输入Nint …

【Canvas与艺术】三环莫比乌斯圈

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>三环莫比乌斯圈</title><style type"text/css"&g…

测桃花运(算姻缘)的网站系统源码

简介&#xff1a; 站长安装本源码后只要有人在线测算&#xff0c;就可以获得收入哦。是目前市面上最火的变现利器。 本版本无后台&#xff0c;无数据。本版本为开发的逗号联盟接口版本。直接对接逗号联盟&#xff0c;修改ID就可以直接运营收费赚钱。 安装环境&#xff1a;PH…

可以个性化的网盘与相册服务 PDS

可以个性化的网盘与相册服务 PDS 什么是PDS企业版企业网盘团队管理用户管理安全策略企业设置文件设置及其他设置专属登录配置 使用建议企业网盘用户端开发者版体验感受 什么是PDS 在正式开始测评PDS之前&#xff0c;首先来了解一下什么是PDS。PDS 网盘与相册服务&#xff08;D…

Pythonic 的从远程列表中提取分支名称方法

1、问题背景 在 Git 版本控制系统中&#xff0c;我们需要经常使用 git ls-remote 命令来获取远程仓库的分支列表。 这个命令的输出通常包含分支的哈希值和分支名称&#xff0c;就像这样&#xff1a; db6ad7246abf74cb845baa60e6fe45dacf897612 HEAD 1fc347b17201054d8b5b9…

YOLOv8 基于BN层的通道剪枝

YOLOv8 基于BN层的通道剪枝 1. 稀疏约束训练 在损失项中增加对BN层的缩放系数 γ \gamma γ和偏置项 β \beta β的稀疏约束&#xff0c; λ \lambda λ系数越大&#xff0c;稀疏约束越严重 L ∑ ( x , y ) l ( f ( x ) , y ) λ 1 ∑ γ g ( γ ) λ 2 ∑ β g ( β ) L…

华杉研发九学习日记18 集合 泛型

华杉研发九学习日记18 一&#xff0c;集合框架 1.1 集合和数组的区别 集合就是在java中用来保存多个对象的容器 集合是数组的升级版&#xff0c;集合中只能放置对象[object]. 数组: 在java中用来保存多个具有相同数据类型数据的容器 数组弊端&#xff1a; 1.数组只能保存…

2024AICoding公司全景图及评分

AI Coding背景 AI coding 领域的产品和公司在 2024 年开始爆发了&#xff0c;主要涉及技术进步、市场需求和开发者生态系统的变化。 本文会从技术背景&#xff0c;市场需求&#xff0c;生态以及相关评分为大家完整梳理一下相关内容。 底层技术 大规模预训练模型 技术背景&#…

C#使用OPC组件方式和AB的PLC通信

目录 一、PLC硬件配置 1、创建PLC程序 &#xff08;1&#xff09;程序工程选择 &#xff08;2&#xff09;变量和程序 2、配置程序在模拟器中运行 &#xff08;1&#xff09;打开RSLkin Classic &#xff08;2&#xff09;仿真器配置 &#xff08;3&#xff09;PLC程序…

我终于搭建完成了我的个人网站!(仅分享,非教程)

先看看我的个人网站~ https://yaoqx.pages.devhttps://yaoqx.pages.dev 来看看我搭建的过程吧&#xff01; &#xff08;仅分享&#xff0c;非教程&#xff09; 网站技术 前端框架&#xff1a;Astro主题&#xff1a;Frosti代码托管&#xff1a;Github网页部署&#xff1a;Cl…

Vscode ssh Could not establish connection to

错误表现 上午还能正常用vs code连接服务器看代码&#xff0c;中午吃个饭关闭vscode再重新打开输入密码后就提示 Could not establish connection to 然后我用终端敲ssh的命令连接&#xff0c;结果是能正常连接。 解决方法 踩坑1 网上直接搜Could not establish connectio…

浮点数如何存储

一、浮点数存储格式 符号&#xff08;sign&#xff09; s是符号位&#xff0c;1表示负&#xff0c;0表示正阶码&#xff08;exponent&#xff09; E的作用是对浮点数加权&#xff0c;这个权重是2的E次幂尾数&#xff08;significand&#xff09; M是一个二进制小数 二、举例说…