昇思25天学习打卡营第19天|ResNet50 图像分类案例:数据集、训练与预测可视化

目录

环境配置

数据集加载

数据集可视化

Building Block

Bottleneck

构建ResNet50网络

模型训练与评估

可视化模型预测


环境配置


        首先指出实验环境预装的 mindspore 版本以及更换版本的方法。然后,它卸载了已安装的 mindspore 并重新安装指定的 2.3.0rc1 版本,并查看了当前安装的 mindspore 版本。接着,通过自定义的 download 函数从给定的 url 下载一个压缩文件(cifar-10-binary.tar.gz)到指定的本地路径(./datasets-cifar10-bin),同时设置了覆盖已存在文件的选项。

        代码如下:

%%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 download import downloadurl = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"download(url, "./datasets-cifar10-bin", kind="tar.gz", replace=True)

数据集加载


        首先,定义了一些常量,如数据集根目录、批量大小、图像大小、并行线程个数和分类数量。

        然后,定义了一个名为 create_dataset_cifar10 的函数,用于根据指定的参数创建 Cifar10Dataset 。在函数内部,根据数据的使用类型(训练或测试)添加不同的数据增强操作,如随机裁剪、水平翻转、调整大小、缩放、归一化等,并对标签进行类型转换。然后进行数据映射和批量处理操作。

        最后,使用上述函数分别创建了训练数据集 dataset_train 和测试数据集 dataset_val ,并获取了它们各自的批量数量。

        代码如下:

import mindspore as ms
import mindspore.dataset as ds
import mindspore.dataset.vision as vision
import mindspore.dataset.transforms as transforms
from mindspore import dtype as mstypedata_dir = "./datasets-cifar10-bin/cifar-10-batches-bin"  # 数据集根目录
batch_size = 64  # 批量大小
image_size = 32  # 训练图像空间大小
workers = 1  # 并行线程个数
num_classes = 10  # 分类数量def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,usage=usage,num_samples=10000,num_parallel_workers=workers,shuffle=True)trans = []if usage == "train":trans += [vision.RandomCrop((32, 32), (4, 4, 4, 4)),vision.RandomHorizontalFlip(prob=0.5)]trans += [vision.Resize(resize),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]target_trans = transforms.TypeCast(mstype.int32)# 数据映射操作data_set = data_set.map(operations=trans,input_columns='image',num_parallel_workers=workers)data_set = data_set.map(operations=target_trans,input_columns='label',num_parallel_workers=workers)# 批量操作data_set = data_set.batch(batch_size)return data_set# 获取处理后的训练与测试数据集dataset_train = create_dataset_cifar10(dataset_dir=data_dir,usage="train",resize=image_size,batch_size=batch_size,workers=workers)
step_size_train = dataset_train.get_dataset_size()dataset_val = create_dataset_cifar10(dataset_dir=data_dir,usage="test",resize=image_size,batch_size=batch_size,workers=workers)
step_size_val = dataset_val.get_dataset_size()

数据集可视化


        首先,从训练数据集 dataset_train 中获取一个批次的数据,并将其中的图像数据 images 和标签数据 labels 转换为 numpy 数组,并打印出它们的形状和前 6 个标签。

        然后,读取一个文件获取类别名称,并存储在 classes 列表中。

        最后,使用 matplotlib.pyplot 绘制训练数据集中的前 6 张图片。对每张图片进行了数据处理,包括转置维度、反标准化等操作,并为每个子图添加了对应的类别名称标题,同时关闭了坐标轴显示,最后展示了绘制的图像。

        代码如下:

import matplotlib.pyplot as plt
import numpy as npdata_iter = next(dataset_train.create_dict_iterator())images = data_iter["image"].asnumpy()
labels = data_iter["label"].asnumpy()
print(f"Image shape: {images.shape}, Label shape: {labels.shape}")# 训练数据集中,前六张图片所对应的标签
print(f"Labels: {labels[:6]}")classes = []with open(data_dir + "/batches.meta.txt", "r") as f:for line in f:line = line.rstrip()if line:classes.append(line)# 训练数据集的前六张图片
plt.figure()
for i in range(6):plt.subplot(2, 3, i + 1)image_trans = np.transpose(images[i], (1, 2, 0))mean = np.array([0.4914, 0.4822, 0.4465])std = np.array([0.2023, 0.1994, 0.2010])image_trans = std * image_trans + meanimage_trans = np.clip(image_trans, 0, 1)plt.title(f"{classes[labels[i]]}")plt.imshow(image_trans)plt.axis("off")
plt.show()

        运行结果:

Building Block


        定义了一个名为 ResidualBlockBase 的类,它继承自 mindspore.nn.Cell 。

        首先,定义了类属性 expansion ,其值为 1 ,表示最后一个卷积核数量与第一个卷积核数量相等。

        在 __init__ 方法中,初始化了一些属性:

        如果没有传入 norm 参数,就创建一个 nn.BatchNorm2d 对象作为 norm ;否则使用传入的 norm 。

        定义了两个卷积层 conv1 和 conv2 ,并使用指定的初始化方式 weight_init 。

        定义了 ReLU 激活函数和 down_sample 。

        construct 方法定义了前向传播的计算过程:

        定义 identity 为输入 x ,作为 shortcuts 分支。

        经过主分支的卷积、归一化、激活等操作。

        如果 down_sample 存在,对输入进行处理得到新的 identity 。

        将主分支结果与 shortcuts 分支结果相加,再经过 ReLU 激活函数得到最终输出。

        代码如下:

from typing import Type, Union, List, Optional
import mindspore.nn as nn
from mindspore.common.initializer import Normal# 初始化卷积层与BatchNorm的参数
weight_init = Normal(mean=0, sigma=0.02)
gamma_init = Normal(mean=1, sigma=0.02)class ResidualBlockBase(nn.Cell):expansion: int = 1  # 最后一个卷积核数量与第一个卷积核数量相等def __init__(self, in_channel: int, out_channel: int,stride: int = 1, norm: Optional[nn.Cell] = None,down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlockBase, self).__init__()if not norm:self.norm = nn.BatchNorm2d(out_channel)else:self.norm = normself.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.conv2 = nn.Conv2d(in_channel, out_channel,kernel_size=3, weight_init=weight_init)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):"""ResidualBlockBase construct."""identity = x  # shortcuts分支out = self.conv1(x)  # 主分支第一层:3*3卷积层out = self.norm(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二层:3*3卷积层out = self.norm(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 输出为主分支与shortcuts之和out = self.relu(out)return out

Bottleneck


        定义了一个名为 ResidualBlock 的类,它也是继承自 mindspore.nn.Cell 。

        类属性 expansion 被设置为 4 ,表示最后一个卷积核的数量是第一个卷积核数量的 4 倍。

        在 __init__ 方法中:

        定义了三个卷积层 conv1 、 conv2 、 conv3 ,以及对应的三个 BatchNorm2d 层 norm1 、 norm2 、 norm3 ,并设置了权重初始化方式。

        定义了 ReLU 激活函数和 down_sample 。

        construct 方法定义了前向传播过程:

        定义 identity 为输入 x 作为 shortcuts 分支。

        主分支依次经过三层卷积、对应的归一化和激活操作。

        如果 down_sample 存在,对输入进行处理得到新的 identity 。

        将主分支结果与 shortcuts 分支结果相加,再经过 ReLU 激活函数得到最终输出。

        代码如下:

class ResidualBlock(nn.Cell):expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍def __init__(self, in_channel: int, out_channel: int,stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlock, self).__init__()self.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=1, weight_init=weight_init)self.norm1 = nn.BatchNorm2d(out_channel)self.conv2 = nn.Conv2d(out_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.norm2 = nn.BatchNorm2d(out_channel)self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,kernel_size=1, weight_init=weight_init)self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):identity = x  # shortscuts分支out = self.conv1(x)  # 主分支第一层:1*1卷积层out = self.norm1(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二层:3*3卷积层out = self.norm2(out)out = self.relu(out)out = self.conv3(out)  # 主分支第三层:1*1卷积层out = self.norm3(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 输出为主分支与shortcuts之和out = self.relu(out)return out

构建ResNet50网络


        make_layer 函数用于创建包含指定数量残差块的层。根据条件决定是否需要 down_sample 操作,并依次添加残差块到层中。

        ResNet 类定义了一个残差网络模型。在初始化方法中定义了一系列的卷积层、池化层、残差网络层、平均池化层、全连接层等。construct 方法定义了数据在模型中的前向传播过程。

        _resnet 函数根据给定的参数创建 ResNet 模型,并根据 pretrained 参数决定是否加载预训练模型的参数。

        resnet50 函数具体创建了一个 ResNet50 模型,并指定了预训练模型的 URL 和本地保存路径,以及是否使用预训练模型。

        代码如下:

def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],channel: int, block_nums: int, stride: int = 1):down_sample = None  # shortcuts分支if stride != 1 or last_out_channel != channel * block.expansion:down_sample = nn.SequentialCell([nn.Conv2d(last_out_channel, channel * block.expansion,kernel_size=1, stride=stride, weight_init=weight_init),nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)])layers = []layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))in_channel = channel * block.expansion# 堆叠残差网络for _ in range(1, block_nums):layers.append(block(in_channel, channel))return nn.SequentialCell(layers)
from mindspore import load_checkpoint, load_param_into_netclass ResNet(nn.Cell):def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],layer_nums: List[int], num_classes: int, input_channel: int) -> None:super(ResNet, self).__init__()self.relu = nn.ReLU()# 第一个卷积层,输入channel为3(彩色图像),输出channel为64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)self.norm = nn.BatchNorm2d(64)# 最大池化层,缩小图片的尺寸self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')# 各个残差网络结构块定义self.layer1 = make_layer(64, block, 64, layer_nums[0])self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)# 平均池化层self.avg_pool = nn.AvgPool2d()# flattern层self.flatten = nn.Flatten()# 全连接层self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)def construct(self, x):x = self.conv1(x)x = self.norm(x)x = self.relu(x)x = self.max_pool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avg_pool(x)x = self.flatten(x)x = self.fc(x)return x
def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,input_channel: int):model = ResNet(block, layers, num_classes, input_channel)if pretrained:# 加载预训练模型download(url=model_url, path=pretrained_ckpt, replace=True)param_dict = load_checkpoint(pretrained_ckpt)load_param_into_net(model, param_dict)return modeldef resnet50(num_classes: int = 1000, pretrained: bool = False):"""ResNet50模型"""resnet50_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt"resnet50_ckpt = "./LoadPretrainedModel/resnet50_224_new.ckpt"return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,pretrained, resnet50_ckpt, 2048)

模型训练与评估


        实现了使用预训练的 ResNet50 模型进行微调训练,并在训练过程中进行验证和保存最优模型。

        首先,定义了 ResNet50 网络,并重置了全连接层,设置了学习率、优化器和损失函数。然后创建了训练集和验证集的迭代器,并设置了最佳模型的存储路径。

        定义了 train 函数用于模型的训练,在每个训练批次中计算损失并打印部分批次的损失信息,返回平均损失。evaluate 函数用于模型的验证,计算准确率。

        在训练循环中,对每个 epoch 进行训练和验证,打印当前 epoch 的平均损失和准确率。如果当前准确率高于之前的最优准确率,就保存当前模型为最优模型。

        最后,打印出验证结束后的最优准确率和保存最优模型的路径。

        代码如下:

# 定义ResNet50网络
network = resnet50(pretrained=True)# 全连接层输入层的大小
in_channel = network.fc.in_channels
fc = nn.Dense(in_channels=in_channel, out_channels=10)
# 重置全连接层
network.fc = fc
# 设置学习率
num_epochs = 1
lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,step_per_epoch=step_size_train, decay_epoch=num_epochs)
# 定义优化器和损失函数
opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)
loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')def forward_fn(inputs, targets):logits = network(inputs)loss = loss_fn(logits, targets)return lossgrad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)def train_step(inputs, targets):loss, grads = grad_fn(inputs, targets)opt(grads)return loss
import os# 创建迭代器
data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)
data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)# 最佳模型存储路径
best_acc = 0
best_ckpt_dir = "./BestCheckpoint"
best_ckpt_path = "./BestCheckpoint/resnet50-best.ckpt"if not os.path.exists(best_ckpt_dir):os.mkdir(best_ckpt_dir)
import mindspore.ops as opsdef train(data_loader, epoch):"""模型训练"""losses = []network.set_train(True)for i, (images, labels) in enumerate(data_loader):loss = train_step(images, labels)if i % 100 == 0 or i == step_size_train - 1:print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %(epoch + 1, num_epochs, i + 1, step_size_train, loss))losses.append(loss)return sum(losses) / len(losses)def evaluate(data_loader):"""模型验证"""network.set_train(False)correct_num = 0.0  # 预测正确个数total_num = 0.0  # 预测总数for images, labels in data_loader:logits = network(images)pred = logits.argmax(axis=1)  # 预测结果correct = ops.equal(pred, labels).reshape((-1, ))correct_num += correct.sum().asnumpy()total_num += correct.shape[0]acc = correct_num / total_num  # 准确率return acc
# 开始循环训练
print("Start Training Loop ...")for epoch in range(num_epochs):curr_loss = train(data_loader_train, epoch)curr_acc = evaluate(data_loader_val)print("-" * 50)print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (epoch+1, num_epochs, curr_loss, curr_acc))print("-" * 50)# 保存当前预测准确率最高的模型if curr_acc > best_acc:best_acc = curr_accms.save_checkpoint(network, best_ckpt_path)print("=" * 80)
print(f"End of validation the best Accuracy is: {best_acc: 5.3f}, "f"save the best ckpt file in {best_ckpt_path}", flush=True)

        运行结果:

可视化模型预测


        定义了一个名为 visualize_model 的函数,用于可视化模型在验证集上的预测结果。

        函数首先创建了一个 ResNet50 模型用于对狼和狗图像进行二分类,然后加载最优模型的参数。接着从验证集中获取一批数据,包括图像和标签,并使用模型对这批图像进行预测。通过读取文件获取类别名称,然后绘制图像进行展示。对于每幅图像,如果预测正确,标题显示为蓝色;如果预测错误,标题显示为红色。同时展示了经过处理后的图像,并关闭了坐标轴。最后,调用 visualize_model 函数并传入最优检查点路径和验证集来执行可视化操作。

        代码如下:

import matplotlib.pyplot as pltdef visualize_model(best_ckpt_path, dataset_val):num_class = 10  # 对狼和狗图像进行二分类net = resnet50(num_class)# 加载模型参数param_dict = ms.load_checkpoint(best_ckpt_path)ms.load_param_into_net(net, param_dict)# 加载验证集的数据进行验证data = next(dataset_val.create_dict_iterator())images = data["image"]labels = data["label"]# 预测图像类别output = net(data['image'])pred = np.argmax(output.asnumpy(), axis=1)# 图像分类classes = []with open(data_dir + "/batches.meta.txt", "r") as f:for line in f:line = line.rstrip()if line:classes.append(line)# 显示图像及图像的预测值plt.figure()for i in range(6):plt.subplot(2, 3, i + 1)# 若预测正确,显示为蓝色;若预测错误,显示为红色color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'plt.title('predict:{}'.format(classes[pred[i]]), color=color)picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))mean = np.array([0.4914, 0.4822, 0.4465])std = np.array([0.2023, 0.1994, 0.2010])picture_show = std * picture_show + meanpicture_show = np.clip(picture_show, 0, 1)plt.imshow(picture_show)plt.axis('off')plt.show()# 使用测试数据集进行验证
visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)

        运行结果:

        打印时间:

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

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

相关文章

值得买科技与MiniMax达成官方合作伙伴关系,共建融合生态

7月29日,值得买科技与大模型公司MiniMax宣布达成官方合作伙伴关系。 MiniMax旗下大模型产品海螺AI现已接入值得买“消费大模型增强工具集”,基于海螺AI比价策略,用户可通过海螺AI“悬浮球”功能实现快速比价及跳转购买。 此次合作也标志着值…

操作系统重点总结

文章目录 1. 操作系统重点总结1.1 操作系统简介1.1.1 操作系统的概念和功能1.1.2 操作系统的特征1.1.2.1 并发1.1.2.2 共享1.1.2.3 虚拟1.1.2.4 异步 1.1.3 操作系统的发展与分类1.1.4 中断和异常1.1.5 系统调用1.1.6 操作系统的体系结构1.1.7 操作系统简介总结 1.2 进程1.2.1 …

使用YApi平台来管理接口

快速上手 进入YApi官网,进行注册登录https://yapi.pro/添加项目 3. 添加分类 4. 添加接口 5. 添加参数 添加返回数据 可以添加期望 验证 YAPI(Yet Another Practice Interface)是一个现代化的接口管理平台,由淘宝团队…

企业邮箱如何进行邮件监控

企业邮箱监控保障资产安全、合规性,防范网络攻击,提升员工行为。核心要素包括内容扫描、行为分析、合规性检查等。实施策略涉及技术选择、政策制定、员工培训。企业邮箱如何进行邮件监控呢?Zoho邮箱的eDiscovery功能可实现长期邮件保存和监控…

基于百度paddle检索系统的召回

所谓召回,无非就是用一段不规则文本模拟用户query查询,而要召回的是标准的titlekey,这些是要构建索引库的,所有相似文本对的第二个文本必须要在索引库里存在,不然就没法评估,因为标记都是0,还有召回1,召回5等,并不是什…

在Ubuntu 22 VPS服务器上更改phpMyadmin端口的方法

更改 Ubuntu 22 VPS服务器上的 phpMyAdmin 端口可以增强安全性和可管理性。但是具体应该怎么操作呢?接下来将带您了解在Ubuntu 22 VPS 服务器上更改phpMyadmin的端口全过程,一起来看看吧。 准备你的环境 在开始之前,让我们先确保你已做好一…

【前端逆向】最佳JS反编译利器,原来就是chrome!

有时候需要反编译别人的 min.js。 比如简单改库、看看别人的 min,js 干了什么,有没有重复加载?此时就需要去反编译Javascript。 Vscode 里面有一些反编译插件,某某Beautify等等。但这些插件看人品,运气不好搞的话,反…

实验2-3-8 计算火车运行时间

//实验2-3-8 计算火车运行时间 /* 输入格式:输入在一行中给出2个4位正整数,其间以空格分隔,分别表示火车的出发时间和到达时间。 每个时间的格式为2位小时数(00-23)和2位分钟数(00-59)&#xff…

dockerfile部署镜像 ->push仓库 ->虚拟机安装建木 ->自动部署化 (详细步骤)

目录 创建私服仓库 vi /etc/docker/daemon.json vim deploy.sh判断脚本内容 创建 建木 后端部署 命名空间 设置密码用户名 创建git仓库 gitignore文件内容 图形项目操作 git maven docker镜像 点击流程日志 vim /etc/docker/daemon.json 执行部署脚本 ip 开发…

RuntimeError: No CUDA GPUs are available

RuntimeError: No CUDA GPUs are available 目录 RuntimeError: No CUDA GPUs are available 【常见模块错误】 【解决方案】 解决步骤如下: 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰,211科…

Spring 高级解析 07

文章目录 1. Spring 概述(基本情况)1.1 Spring 的优势1.2 Spring 的核⼼结构 2. 核⼼思想 IoC 和 AOP2.1 什么是IoC?2.2 什么是AOP2.3 AOP在解决什么问题 3. Spring IoC ⾼级应⽤3.1 BeanFactory与ApplicationContext区别3.1.1 BeanFactory3.…

Android虚假定位的实现与防护

Android中常用的定位方式 一,GPS定位 定义:全球卫星定位系统,直接和卫星交互,获取设备经纬度 优点: 走卫星通信通道,无需打开Wifi或流量就能获得位置信息 精确度最高,几米到几十米 缺点&a…

Java面试八股之Spring AOP 和 AspectJ AOP 的区别

Spring AOP 和 AspectJ AOP 的区别 Spring AOP 和 AspectJ AOP 是两种不同的面向切面编程(Aspect-Oriented Programming, AOP)实现。它们各有特点,适用于不同的场景。下面是一些主要的区别: 1. 实现机制 Spring AOP: 基于代理…

为Mac配置Alfred

参考资料: Alfred神器使用手册 | louis blogMacOS神器之Alfred workflow概览GitHub - arpir/Alfred-Workflows-Collection: 一些好用的 Alfred Workflow 一、修改快捷键 Spotlight的默认快捷键是Command Space Alfred的默认快捷键是Option Space 可以将Alfred和…

Alternating Sum

Problem - 963A - Codeforces 处理式子 显然中间式子是等比数列 // Problem: A. Alternating Sum // Contest: Codeforces - Tinkoff Internship Warmup Round 2018 and Codeforces Round 475 (Div. 1) // URL: https://codeforces.com/problemset/problem/963/A // Memory Lim…

awk用法

文章目录 一、awk工具awk工作原理AWK程序的结构awk内置变量 二、案例1.基础案列2.BEGIN END 运算3.数值与字符串的比较4.awk高级用法5. awk if语句6.BEGIN END 流程7.AWK 数组8.awk 循环 一、awk工具 awk工作原理 当读到第一行时,匹配条件,然后执行指定…

【C++11】C++11新纪元:深入探索右值引用与移动语义

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:位图与布隆过滤器 🌹🌹期待您的关注 🌹🌹 ❀C11 📒1. C11简介…

【Qt】修改窗口的标题和图标

以下操作仅对顶层 widget(独⽴窗口),有效。 修改窗口的标题 一.windowTitle属性 1.概念 是一种在用户界面中显示窗口的标题的属性。它可以用来设置窗口的标题栏文本。 2.API API说明windowTitle()获取到控件的窗⼝标题.setWindowTitle(const QString& title)设置控件的…

10 BERT

目录 1 综述 1.1 BERT的核心思想 1.2 BERT的关键技术:预训练阶段 1.3 微调阶段 2 BERT的架构 2.1 输入处理 3. 特征选择/学习模块 BERT 的自注意力过程 4. 预训练任务:同时进行 4.1 Next Sentence Prediction (NSP) 4.2 Masked Language Model…