【人工智能Ⅱ】实验2:VGG图像分类

news2024/9/26 5:22:35

实验2:VGG图像分类

一:实验目的与要求

1:掌握VGG网络的原理与结构。

2:学会利用VGG网络建立训练模型,并对模型进行评估。

3:学会使用VGG网络进行分类。

二:实验内容

1:用VGG网络对自选图像数据集进行多分类预测。

2:应用图像增强方法进行数据集的扩充。

3:调整VGG网络参数(如:batch_size、激活函数、优化器、学习率、训练epoch等),比较结果差异。

三:实验环境

本实验所使用的环境条件如下表所示。

操作系统

Ubuntu(Linux)

程序语言

Python(3.11.4)

第三方依赖

torch, torchvision, matplotlib

四:方法原理

VGG是一种针对网络加深的CNN结构,其主要思想是通过重复使用简单的基础块来构建深度学习模型。

VGG系列的经典网络有VGG16和VGG19。VGG共有6种配置,分别为A、A-LRN、B、C、D、E。其中,D类对应VGG16,E类对应VGG19。

各类VGG都由5个卷积块和3个全连接层组成。第一个卷积块的每个卷积层共有64个输出通道,第二个卷积块的每个卷积层共有128个输出通道,第三个卷积块的每个卷积层共有256个输出通道,第四个卷积块的每个卷积层共有512个输出通道,第五个卷积块的每个卷积层共有512个输出通道。

各类VGG的卷积计算示意图如下图所示。

 

五、方法流程

本实验方法设计的流程如下:

  1. 下载公开数据集(https://aistudio.baidu.com/datasetdetail/171121),分析数据集的特点,并分别选择其中的苹果的病虫害图像数据集作为后续训练和测试的数据集,样本量为4000
  2. 配置容器的运行环境,并将数据集通过远程连接协议传入容器。
  3. 按照【数据集读取】——【数据集划分】——【模型实例化】——【损失函数和优化器选择】——【迭代训练模型】——【训练结果可视化】的步骤撰写代码。
  4. 得到基本框架的训练结果,分析结果产生的原因。
  5. 改变VGG网络的参数,例如batch_size、激活函数、优化器、学习率、训练epoch等,多次重复实验。
  6. 分析对比实验的结果,总结VGG网络的特点。

六、实验展示(训练过程和训练部分结果进行可视化)

1:VGG16的baseline训练

在VGG16的baseline训练中,各个基本参数的内容如下表所示。

基本参数

参数值

Batch_size

32

激活函数

ReLU

优化器

Adam

学习率

0.001

训练epoch

30

 基于VGG16进行初步训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,在VGG16的baseline中,训练集上的分类准确率最高可达99.25%,测试集上的分类准确率最高可达97.63%

2:VGG19的baseline训练

在VGG19的baseline训练中,各个基本参数的内容如下表所示。

基本参数

参数值

Batch_size

32

激活函数

ReLU

优化器

Adam

学习率

0.001

训练epoch

30

基于VGG19进行初步训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,在VGG19的baseline中,训练集上的分类准确率最高可达100.0%,测试集上的分类准确率最高可达98.39%

对比第1部分的【VGG16】训练内容,VGG19在该数据集上的表现更佳,因此后续将选择VGG19进行参数调整的对比实验训练。

3:修改batch_size的对比实验(基于VGG19)

在深度学习中,batch_size(批大小)是指在训练神经网络时每次迭代所使用的样本数量。

常见的batch_size大小通常在以下范围内:

  1. 小批量(Small Batch):通常在2到64之间。
  2. 中等批量(Medium Batch):通常在64到256之间。
  3. 大批量(Large Batch):通常在256以上。

由于baseline中已经获得了batch_size=32的小批量训练结果,因此后续将采用batch_size=128获得中等批量的训练结果。

修改batch_size为【128】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改batch_size为【128】后,训练集上的分类准确率最高可达98.86%,测试集上的分类准确率最高可达97.52%。与baseline相比,batch_size为【128】时的分类损失值和准确率出现了较大的波动,同时最高的测试准确率也比baseline低。因此,中等批量的训练结果比小批量的训练结果差。

4:修改激活函数的对比实验(基于VGG19)

VGG模型主要由两大部分组成:特征提取部分(features)和分类部分(classifier)。如果要修改预训练的VGG16模型中的激活函数,则需要直接访问并修改模型中包含激活函数的层,并替换激活函数类型。在本节实验中,激活函数从ReLU替换为LeakyReLU

修改激活函数为【LeakyReLU】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改激活函数为【LeakyReLU】后,训练集上的分类准确率最高可达99.30%,测试集上的分类准确率最高可达98.28%。与baseline相比,激活函数为【LeakyReLU】时最高的训练准确率和测试准确率均比baseline低。因此,LeakyReLU的训练结果比ReLU的训练结果差。

5:修改优化器的对比实验(基于VGG19)

修改优化器为【SGD】后进行训练的迭代过程如下图所示。


在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改优化器为【SGD】后,训练集上的分类准确率最高可达100.0%,测试集上的分类准确率最高可达100.0%。与baseline相比,优化器为【SGD】时最高的训练准确率和测试准确率均比baseline高。因此,SGD的训练结果比Adam的训练结果好。

6:修改学习率的对比实验(基于VGG19)

【学习率增大】

修改学习率为【0.01】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改学习率为【0.01】后,训练集上的分类准确率最高可达34.45%,测试集上的分类准确率最高可达37.14%。与baseline相比,学习率为【0.01】时最高的训练准确率和测试准确率均比baseline低。因此,学习率为【0.01】的训练结果比学习率为【0.001】的训练结果差。

【学习率减小】

修改学习率为【0.0001】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改学习率为【0.0001】后,训练集上的分类准确率最高可达100.0%,测试集上的分类准确率最高可达100.0%。与baseline相比,学习率为【0.0001】时最高的训练准确率和测试准确率均比baseline高。因此,学习率为【0.0001】的训练结果比学习率为【0.001】的训练结果好。

6:修改训练epoch的对比实验(基于VGG19)

【训练epoch减小】

修改训练epoch为【10】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改训练epoch为【10】后,训练集上的分类准确率最高可达98.44%,测试集上的分类准确率最高可达96.88%。与baseline相比,训练epoch为【10】时最高的训练准确率和测试准确率均比baseline低。因此,训练epoch为【10】的训练结果比训练epoch为【30】的训练结果差。

【训练epoch增大】
修改训练epoch为【50】后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,修改训练epoch为【50】后,训练集上的分类准确率最高可达100.0%,测试集上的分类准确率最高可达98.92%。与baseline相比,训练epoch为【50】时最高的训练准确率和测试准确率均比baseline高。因此,训练epoch为【50】的训练结果比训练epoch为【30】的训练结果好。

7:数据增强的对比实验(基于VGG19)

    数据增强需要在transform处进行修改,例如RandomRotation。同时由于数据增强只在训练集上使用而不在测试集上使用,因此需要将训练集数据和测试集数据分开加载。

    本部分数据增强采用了【随机裁剪】的数据增强技术,代码修改如下。

# 训练集的转换:包含数据增强

train_transform = transforms.Compose([

    transforms.Resize((224, 224)),

    transforms.RandomCrop(224, padding=4),  # 添加随机裁剪

    transforms.ToTensor(),

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

])

# 测试集/验证集的转换:不包含数据增强

test_transform = transforms.Compose([

    transforms.Resize((224, 224)),

    transforms.ToTensor(),

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

])

dataroot = "/home/ubuntu/apple"

# 加载数据集时应用相应的转换

train_dataset_full = torchvision.datasets.ImageFolder(root=dataroot, transform=train_transform)

test_dataset_full = torchvision.datasets.ImageFolder(root=dataroot, transform=test_transform)

# 划分 train test 数据集

train_size = int(0.8 * len(train_dataset_full))

test_size = len(train_dataset_full) - train_size

# 这里使用相同的索引划分方法来确保训练集和测试集的一致性

train_indices = torch.arange(0, train_size)

test_indices = torch.arange(train_size, train_size + test_size)

train_dataset = torch.utils.data.Subset(train_dataset_full, train_indices)

val_dataset = torch.utils.data.Subset(test_dataset_full, test_indices)

# 创建数据加载器

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)

val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)

dataset = test_dataset_full

采用数据增强后进行训练的迭代过程如下图所示。

在训练集和测试集上的分类准确率如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

在训练集和测试集上的分类损失值如下图所示(橘色部分为测试集结果,蓝色部分为训练集结果)。

综上所述,采用数据增强后,训练集上的分类准确率最高可达99.92%,测试集上的分类准确率最高可达99.57%。与baseline相比,采用数据增强时最高的测试准确率均比baseline高。因此,采用数据增强后的训练结果比baseline的训练结果好。

七、实验结论

1:VGG整体具备层数多,后面层的感受野大,包含更多的全局信息。相比于AlexNet,VGG的模型参数更少。

2:VGG对卷积核和池化大小进行了统一,网络中进行 3×3的卷积操作和2×2

的最大池化操作。VGG主要采用卷积层堆叠的策略,即多个具有小卷积核的卷积层串联的方式。一方面能够减少网络参数,另一方面提高感受野范围,增强网络的学习能力和特征表达能力。同时,VGG在每层卷积之后进行ReLU(激活函数)的非线性操作。

3:在batch_size的分类中,主要包括小批量、中等批量和大批量。小批量适合于较小的数据集或计算资源有限的情况,可以提供较高的梯度更新频率,但可能会导致训练过程中的噪声较多;中等批量通常是在一般情况下的默认选择,适用于中等大小的数据集和计算资源;大批量通常用于具有大型数据集和强大计算资源的情况下,可以加快训练速度,但可能需要更多的内存。

4:合适的参数设置可以显著提高模型性能。调整模型参数需要通过多次尝试和错误来找到最优的参数组合。每个参数的调整都需要基于对模型工作原理的深入理解。

5:数据增强是提高图像分类模型泛化能力的有效方法。适当的数据增强不仅可以增加数据量,还可以引入多样性,帮助模型学习到更加鲁棒的特征。

八、遇到的问题和解决方法

问题1:一开始使用pytorch搭建的VGG16网络,在数据集上的分类准确率只有33%。

解决1:将模型实例化改为torch集成的VGG模型,修改后的分类准确率可超过90%。


问题2:在batch_size=256的训练过程中,出现以下报错。

解决2:上述报错的原因是batch_size设置过大导致内存不足,需要降低batch_size,因此本实验无法训练大批量(batch_size>=256)的结果。

九、程序源代码

import torch

import torchvision

import torchvision.transforms as transforms

from torchvision import models

import torch.nn as nn

import torch.optim as optim

from torch.utils.data import DataLoader, random_split

import torch.nn.functional as F

import matplotlib.pyplot as plt

# visualization part

def plot_loss(train_losses, val_losses):

    plt.figure(figsize=(10, 5))

    plt.plot(train_losses, label='Training Loss')

    plt.plot(val_losses, label='Validation Loss')

    plt.xlabel('Epoch')

    plt.ylabel('Loss')

    plt.title('Training and Validation Loss')

    plt.legend()

    # plt.show()

    plt.savefig('loss-vgg.png')

def plot_accuracy(train_accuracies, val_accuracies):

    plt.figure(figsize=(10, 5))

    plt.plot(train_accuracies, label='Training Accuracy')

    plt.plot(val_accuracies, label='Validation Accuracy')

    plt.xlabel('Epoch')

    plt.ylabel('Accuracy')

    plt.title('Training and Validation Accuracy')

    plt.legend()

    # plt.show()

    plt.savefig('acc-vgg.png')

# Data Preparation

transform = transforms.Compose([

    transforms.Resize((224, 224)),

    transforms.ToTensor(),

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

])

dataroot = r"/home/ubuntu/apple"

dataset = torchvision.datasets.ImageFolder(root=dataroot, transform=transform)

# 划分 train test 数据集

train_size = int(0.8 * len(dataset))

test_size = len(dataset) - train_size

train_dataset, val_dataset = random_split(dataset, [train_size, test_size])

# 创建数据加载器

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)

val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)

# 实例化模型

# model = VGG16(num_classes=6)

model = models.vgg16(pretrained=True)

# 修改分类器部分

model.classifier = nn.Sequential(

    nn.Flatten(),

    nn.LayerNorm(25088),

    nn.Linear(25088, len(dataset.classes))

)

# Training and Evaluation

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

model.to(device)

criterion = nn.CrossEntropyLoss()

# optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for i, layer in enumerate(model.features):

    if isinstance(layer, nn.ReLU):

        model.features[i] = nn.LeakyReLU(negative_slope=0.01)

for i, layer in enumerate(model.classifier):

    if isinstance(layer, nn.ReLU):

        model.classifier[i] = nn.LeakyReLU(negative_slope=0.01)

# Training loop

num_epochs = 30

train_losses = []

val_losses = []

train_accuracies = []

val_accuracies = []

for epoch in range(num_epochs):

    # train

    model.train()

    running_loss = 0.0

    correct = 0

    total = 0

    test_correct = 0

    test_total = 0

   

    for i, (inputs, labels) in enumerate(train_loader):

        inputs, labels = inputs.to(device), labels.to(device)

       

        optimizer.zero_grad()

        outputs = model(inputs)

        loss = criterion(outputs, labels)

        loss.backward()

        optimizer.step()

       

        running_loss += loss.item()

        _, predicted = torch.max(outputs.data, 1)

        total += labels.size(0)

        correct += (predicted == labels).sum().item()

   

    train_losses.append(running_loss / len(train_loader))

    train_accuracies.append(100 * correct / total)

   

    # evaluate

    model.eval()

    with torch.no_grad():

        val_loss = 0.0

        val_correct = 0

        val_total = 0

        for inputs, labels in val_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            outputs = model(inputs)

            loss = criterion(outputs, labels)

            val_loss += loss.item()

            _, predicted = torch.max(outputs.data, 1)

            val_total += labels.size(0)

            val_correct += (predicted == labels).sum().item()

       

    val_losses.append(val_loss / len(val_loader))

    val_accuracies.append(100 * val_correct / val_total)

       

    print(f"Epoch {epoch+1}, Loss: {train_losses[-1]}, Accuracy: {train_accuracies[-1]}%, Validation Loss: {val_losses[-1]}, Validation Accuracy: {val_accuracies[-1]}%")

# 绘制损失曲线和准确率曲线

plot_loss(train_losses, val_losses)

plot_accuracy(train_accuracies, val_accuracies)

print('Finished')

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

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

相关文章

扩展欧拉定理

为了求a^bmodm的余数,我们可以利用扩展欧拉定理给出的同余方程,转化成一个好求的式子,首先我们要能够解出欧拉函数.欧拉函数讲解可以看看这篇欧拉函数最全总结-CSDN博客(原理我不懂,只会用) 下面给出代码 using i64 long long; int phi(int n) {int res n;for (int i 2; i…

【C语言】内存管理内存管理函数文件管理文件管理函数

主页:醋溜马桶圈-CSDN博客 专栏:C语言_醋溜马桶圈的博客-CSDN博客 gitee:mnxcc (mnxcc) - Gitee.com 目录 1.C/C程序的内存开辟 2.内存相关的函数 2.1 memcpy 2.1.1 memcpy函数的使用 2.1.2 memcpy函数的模拟实现 2.2 memmove 2.2.2 me…

四阶Runge-Kutta方法求解高阶微分方程

一、经典的Runge-Kutta方法(四级四阶RK方法) Runge-Kutta法(简写为RK方法)既可达到较高精度,又可避免高阶导数计算。 对微分方程,在区间上的四阶Runge-Kutta方法的公式如下: 二、利用4阶Runge-Kutta方法计…

Elasticsearch - Docker安装Elasticsearch8.12.2

前言 最近在学习 ES,所以需要在服务器上装一个单节点的 ES 服务器环境:centos 7.9 安装 下载镜像 目前最新版本是 8.12.2 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2创建配置 新增配置文件 elasticsearch.yml http.host…

.locked勒索病毒是什么,企业数据被加密了如何恢复?

.locked勒索病毒介绍 .locked勒索病毒是一种恶意软件,它利用加密技术锁定用户的数据或系统,并以此进行勒索。用户一旦感染此病毒,将无法访问其重要文件,病毒会要求用户支付一笔赎金以获取解密密钥。这种病毒通常使用强大的加密算法…

为什么选VR全景技术进行乡村展示,VR全景技术助力乡村振兴

引言: 在科技飞速发展的当下,乡村振兴成为国家重要战略,如何创新性地展示乡村特色,提升乡村吸引力,成为当务之急。VR全景技术,作为一种新兴的展示手段,可以为乡村展示提供全新的视角&#xff0…

可观测性体系建设后,该如何挖掘数据及工具价值?

在现代企业的运维管理中,构建高效且可靠的可观测性体系是保障系统稳定性和业务连续性的关键。然而,运维团队成员的技术能力参差不齐往往成为实现这一目标的障碍。尤其在处理复杂系统故障时,高度依赖专业知识和经验的可观测性工具很难被全员有…

如何在Linux Ubuntu系统安装Nginx服务并实现无公网IP远程连接

文章目录 1. 安装Docker2. 使用Docker拉取Nginx镜像3. 创建并启动Nginx容器4. 本地连接测试5. 公网远程访问本地Nginx5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 在开发人员的工作中,公网远程访问内网是其必备的技术需求之一。对于…

vue key的bug

今天遇到一个bug,列表删除元素时,明明在外层设置了key,但是列表元素的状态居然复用了,找了好久原因,最后是key的取值问题,记录一下。 首先key可以取undefine,这个是不会报错的 然后项目的代码结…

C#配置连接数据库字段

在Web.config文件中 添加如下配置 <!--连接数据库字段--><connectionStrings><add name"sql" connectionString"server.;uidsa;pwd8888;databaseArticleWebSite" /></connectionStrings>

element plus等框架中属性值是组件如何传入,替换分页图标

在 Vue 中替换element plus 分页图标 正常写法引入组件 import prevIcon from /components/xx.vue;<el-pagination layout"prev, pager, next" :prev-icon"prevIcon" :total"5" />利用 h 函数写法 const prevIcon h(div, [xr]);可以写…

发送邮件接口的工作原理?有哪些常用参数?

发送邮件接口的功能有哪些&#xff1f;如何选择发送邮件接口&#xff1f; 无论是商务沟通、信息传递还是个人交流&#xff0c;发送邮件都是一种高效且便捷的方式。而在这背后&#xff0c;发送邮件接口发挥着至关重要的作用。那么&#xff0c;发送邮件接口的工作原理究竟是怎样…

springboot网站开发如何配置log4j日志插件

springboot网站开发如何配置log4j日志插件&#xff01;为了便于服务器等环境下的错误情况的排查根源&#xff0c;还是很有必要使用日志插件的&#xff0c;它可以记录下我们提前埋下的锚点信息。 在遇到故障&#xff0c;查看这些锚点记录的日志信息&#xff0c;可以快速高效的解…

C++第九弹---类与对象(六)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 日期类 1、日期类的分析和设计 1.1、日期类的功能说明 1.2、日期类的分析和设计 1.2.1、数据结构的分析 1.2.2、文件结构设计 2、日期类的结构分析…

深度学习 精选笔记(13.1)卷积神经网络-LeNet模型

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增)&#xff0c;以达到集多方教程的精华于一文的目的。 ③非常推荐上面&#xff08;学习参考&#x…

HCIA复习

上面的文件里有思维导图哦~ 一、情景再现&#xff1a;ISP网络为学校提供了DNS服务&#xff0c;所以&#xff0c;DNS服务器驻留在ISP网络内&#xff0c;而不再学校网络内。DHCP服务器运行在学校网络的路由器上。 小明拿了一台电脑&#xff0c;通过网线&#xff0c;接入到校园网…

使用el-cascader组件写下拉级联多选并且具有全选功能

样式 说明: 级联选择器中加上全选的按钮, 并且保证数据响应式。 思路 因为是有全选的功能,所以不能直接使用el-cascader组件, 而是选择使用el-select组件, 在此组件内部使用el-cascader-panel级联面板全选按钮也是写在el-select组件中, 并且去监听全选按钮的状态, 根…

The Open Group开放数字标准组合|管理您的数字景观

据麻省理工学院斯隆Sloan和凯捷咨询Capgemini称&#xff0c;90%的首席执行官认为数字经济将影响他们的行业&#xff0c;但只有不到15%的首席执行官正在执行数字战略。 数字化转型对于企业在当今不断变化的市场和技术环境中持续保持竞争力至关重要。近年来&#xff0c;商业世界发…

‍Java OCR技术全面解析:六大解决方案比较

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

HarmonyOS ArkTS 基础组件

目录 一、常用组件 二、文本显示&#xff08;Text/Span) 2.1 创建文本 2.2 属性 2.3 添加子组件(Span) 2.4 添加事件 三、按钮&#xff08;Button&#xff09; 3.1 创建按钮 3.2 设置按钮类型 3.3 悬浮按钮 四、文本输入&#xff08;TextInput/TextArea&#xff09;…