tensorflow快速入门--如何定义张量、定义网络结构、超参数设置、模型训练???

前言

  • 由于最近学习的东西涉及到tensorflow的使用,故先简单的学习了一下tensorflow中如何定义张量、定义网络结构、超参数设置、模型训练的API调用过程;
  • 欢迎大家,收藏+关注,本人将持续更新。

文章目录

  • 1、基本操作
    • 1、张量基础操作
      • 创建0维度张量
      • 创建1维张量
      • 创建多维张量
    • 2、转换成numpy
    • 3、常用函数
    • 4、变量
  • 2、用tensorflow构建神经网络
    • 1、数据分析
      • 1、导入库
      • 2、导入数据
      • 3、数据归一化
      • 4、图片展示
      • 5、图片格式归一化
    • 2、构建神经网络
    • 3、设置超参数
    • 4、模型训练
    • 5、预测

1、基本操作

1、张量基础操作

tensorflow中定义常量张量是constant,也就是不能改变的张量。

# 导入库
import tensorflow as tf 
import numpy as np

创建0维度张量

zeros = tf.constant(3)
zeros

输出:

<tf.Tensor: shape=(), dtype=int32, numpy=3>

输出说明:

  • shape: 数据维度,0
  • numpy:数据,3

创建1维张量

tf.constant([1.0, 2.0, 3.0])

输出:

<tf.Tensor: shape=(3,), dtype=float32, numpy=array([1., 2., 3.], dtype=float32)>

输出说明:

  • shape: 数据维度,(1, 3)
  • numpy:数据,array[1., 2., 3.]
  • dtype:数据类型,浮点类型

创建多维张量

tf.constant([[1, 2],
             [3, 4],
             [5, 6]], dtype=tf.float32)

输出:

<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float32)>

输出说明:

  • shape: 数据维度,(3, 2)
  • numpy:数据
  • dtype:数据类型,浮点类型

三维乃至四维都是这样

2、转换成numpy

tf1 = tf.constant([1, 2, 3, 4, 5])
tf1

输出:

<tf.Tensor: shape=(5,), dtype=int32, numpy=array([1, 2, 3, 4, 5])>
#tensor转numpy
#方法一
np.array(tf1)

输出:

array([1, 2, 3, 4, 5])
#方法二
tf1.numpy()

输出:

array([1, 2, 3, 4, 5])

3、常用函数

注意:tensorflow默认不是浮点类型。

# 这样默认是float32
a = tf.constant([[1.0, 2],
                 [3, 4]])

b = tf.constant([[1, 1],
                 [1, 1]], dtype=tf.float32)

注意:constant是创建不可变的张量,不能修改,一下这个不能修改

# 会报错
a[0, 0] = 2
报错如下:
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[9], line 2
      1 # 会报错
----> 2 a[0, 0] = 2

TypeError: 'tensorflow.python.framework.ops.EagerTensor' object does not support item assignment
# 加法
tf.add(a, b)

输出:

<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[2., 3.],
       [4., 5.]], dtype=float32)>
# 乘法
tf.matmul(a, b)

输出:

<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[3., 3.],
       [7., 7.]], dtype=float32)>
# 最大值
tf.reduce_max

输出:

<function tensorflow.python.ops.math_ops.reduce_max(input_tensor, axis=None, keepdims=False, name=None)>
# 最大值索引
tf.argmax(a)

输出:

<tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 1], dtype=int64)>
# 平均值
tf.reduce_mean(a)

输出:

<tf.Tensor: shape=(), dtype=float32, numpy=2.5>

4、变量

tf.Variable:tensorflow是可变类,ptorch没有这个,但是pytorch的张量是可以变的

var = tf.Variable([[1,2],[3,4]])
var

输出:

<tf.Variable 'Variable:0' shape=(2, 2) dtype=int32, numpy=
array([[1, 2],
       [3, 4]])>
# 查看变量的维度
var.shape

输出:

TensorShape([2, 2])
# 查看数据类型
var.dtype

输出:

tf.int32
# 修改变量的值
# 不能直接这样修改值:var[0, 0] = 5
var[0,0].assign(2)

输出:

<tf.Variable 'UnreadVariable' shape=(2, 2) dtype=int32, numpy=
array([[2, 2],
       [3, 4]])>
# 也可以整体修改
var.assign([[3,4],[5,6]])

输出:

<tf.Variable 'UnreadVariable' shape=(2, 2) dtype=int32, numpy=
array([[3, 4],
       [5, 6]])>

输出:

# 但是不能修改成维度不匹配的
var.assgin([2,3]) # 错误
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

Cell In[21], line 2
      1 # 但是不能修改成维度不匹配的
----> 2 var.assgin([2,3]) # 错误
AttributeError: 'ResourceVariable' object has no attribute 'assgin'

2、用tensorflow构建神经网络

以实现手写字体的识别为例,按步骤一步一步实现,核心:

  • 导入数据
  • 构建神经网络
  • 设置超参数
  • 模型训练

1、数据分析

1、导入库

# 导入一些必要库
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt


# 查看是否支持gpu
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")
    
print(gpus)
[]
  • tf: 导入tensorflow框架
  • datasets:提供常用的数据集,方便快速加载和使用。
  • layers:提供各种神经网络层,用于构建模型。
  • models:提供模型类,如 Sequential,用于管理和训练模型。

2、导入数据

tensorflow中可以利用API直接导入mnist数据,导入数据分别依次为训练集图片、训练集标签、测试集图片、测试集标签

(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 4s 0us/step

3、数据归一化

作用:

  • 去除数据的量纲影响,减小数据的方差,使得模型更加准确;
  • 加快算法学习速度。
# 将数据标准化在0-1区间内
train_images, test_images = train_images / 255.0, test_images / 255.0
# 查看数据维度信息
train_images.shape, train_labels.shape, test_images.shape, test_labels.shape

输出:

((60000, 28, 28), (60000,), (10000, 28, 28), (10000,))

4、图片展示

plt.figure(figsize=(20, 10))
for i in range(20):
    plt.subplot(2, 10, i + 1)  # 宽、高、位置
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(train_labels[i])
    
plt.show()


在这里插入图片描述

5、图片格式归一化

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images.shape, train_labels.shape, test_images.shape, test_labels.shape

输出:

((60000, 28, 28, 1), (60000,), (10000, 28, 28, 1), (10000,))

2、构建神经网络

下面是我用AI大模型搜到的一些资料:
在 TensorFlow 中,tf.keras.layers 模块提供了构建神经网络所需的各种层。这些层可以用来构建不同类型的神经网络模型,如卷积神经网络(CNN)、循环神经网络(RNN)等。下面是一些常用的层类型及其简要说明:

基础层

  • Dense:全连接层,用于构建标准的前馈神经网络。
    • 参数:units(输出维度),activation(激活函数),use_bias(是否使用偏置项)等。
  • Activation:独立的激活层,可以应用于任何其他层的输出。
    • 参数:activation(激活函数名或函数对象)。
  • Dropout:用于防止过拟合,通过随机丢弃一部分神经元来实现。
    • 参数:rate(丢弃率,即每个神经元被丢弃的概率)。
  • Flatten:将多维输入展平成一维向量,常用于连接卷积层和全连接层之间。
    • 参数:无。

卷积层

  • Conv1DConv2DConv3D:一维、二维、三维卷积层,分别适用于时间序列数据、图像数据和视频数据。
    • 参数:filters(滤波器数量),kernel_size(卷积核大小),strides(步长),padding(填充方式),activation(激活函数)等。
  • SeparableConv1DSeparableConv2D:深度可分离卷积层,用于减少计算量和参数数量。
    • 参数与普通卷积层类似。
  • DepthwiseConv2D:深度卷积层,用于处理通道之间的信息。
    • 参数:kernel_sizestridespadding等。

池化层

  • MaxPooling1DMaxPooling2DMaxPooling3D:最大池化层,用于降低数据的空间尺寸。
    • 参数:pool_size(池化窗口大小),stridespadding等。
  • AveragePooling1DAveragePooling2DAveragePooling3D:平均池化层,作用类似于最大池化层,但采用的是平均值而不是最大值。
    • 参数与最大池化层相同。

循环层

  • SimpleRNN:简单的循环神经网络层。
    • 参数:units(输出维度),activationuse_bias等。
  • LSTM:长短期记忆网络层,是一种特殊的 RNN 层,能够学习长期依赖关系。
    • 参数与 SimpleRNN 相似。
  • GRU:门控循环单元层,是 LSTM 的简化版本。
    • 参数与 SimpleRNN 和 LSTM 相似。

正则化层

  • BatchNormalization:批量归一化层,用于加速训练过程并减少内部协变量转移。
    • 参数:axis(指定要进行归一化的轴),momentum(移动平均的动量),epsilon(防止除零的小值)等。

输入层

  • InputLayer:显式定义模型的输入层。
    • 参数:input_shape(输入张量的形状),batch_size(批处理大小)等。

注意力机制相关层

  • Attention:注意力机制层,用于在模型中引入注意力机制。
    • 参数:use_scale(是否使用缩放因子),causal(是否为因果注意力)等。

当然,这些只是 tf.keras.layers 模块提供的一部分层。

model = models.Sequential([
    # 激活函数,relu
    # 池化层:平均池化
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),  # 卷积层
    layers.MaxPooling2D((2, 2)),  # 池化层
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层
    layers.MaxPooling2D((2, 2)),   # 池化层
 
    layers.Flatten(),  # 全部展开
    layers.Dense(64, activation='relu'),   # 降维
    layers.Dense(10)  # 根据需要分类数来分类
])
# 打印模型结构
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_5 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 64)                102464    
_________________________________________________________________
dense_5 (Dense)              (None, 10)                650       
=================================================================
Total params: 121,930
Trainable params: 121,930
Non-trainable params: 0
_________________________________________________________________

3、设置超参数

model.compile 方法用于配置模型的训练过程。这个方法允许你指定损失函数、优化器和评估指标等关键参数,以便在训练过程中使用

model.compile(
    # 设置优化器
    optimizer = 'adam',
    # 设置损失率
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    # 评价指标
    metrics=['accuracy']
)

4、模型训练

model.fit是tensorflow中模型训练的核心方法,其主要参数如下:

  • x:训练数据。可以是 NumPy 数组、Python 列表或 TensorFlow 数据集。
  • y:训练数据的标签。可以是 NumPy 数组或 Python 列表。
  • epochs:训练的轮数。每个 epoch 表示模型将遍历整个训练数据集一次。
  • batch_size:每个批次的样本数。默认情况下,model.fit 会在每个 epoch 内将训练数据分成多个批次进行训练。
  • validation_data:验证数据,用于在每个 epoch 结束时评估模型性能。可以是一个元组 (x_val, y_val),其中 x_val 和 y_val 分别是验证数据和标签。
  • validation_split:从训练数据中划分出一部分作为验证数据的比例。如果指定了 validation_split,则不需要再提供 validation_data。
  • shuffle:是否在每个 epoch 开始前打乱训练数据。默认为 True。
  • class_weight:类别权重,用于处理类别不平衡问题。可以是一个字典,键为类别索引,值为对应的权重。
  • sample_weight:样本权重,用于处理样本不平衡问题。可以是一个与训练数据长度相同的数组。
  • initial_epoch:开始训练的初始 epoch。用于恢复中断的训练。
  • steps_per_epoch:每个 epoch 的训练步骤数。当使用 TensorFlow 数据集时,默认情况下会遍历整个数据集。如果数据集很大,可以使用 steps_per_epoch 来限制每个 epoch 的训练步骤数。
  • validation_steps:验证步骤数。类似于 steps_per_epoch,用于限制验证数据集的遍历次数。
  • callbacks:回调函数列表,用于在训练过程中执行特定的操作,如保存模型、调整学习率、记录日志等。
model.fit(
    x = train_images,   # 训练集数据
    y = train_labels,   # 训练集标签
    epochs = 10,        # 训练轮次
    validation_data = (test_images, test_labels)
)
Epoch 1/10
1875/1875 [==============================] - 17s 9ms/step - loss: 0.1485 - accuracy: 0.9548 - val_loss: 0.0455 - val_accuracy: 0.9854
Epoch 2/10
1875/1875 [==============================] - 17s 9ms/step - loss: 0.0489 - accuracy: 0.9850 - val_loss: 0.0390 - val_accuracy: 0.9876
Epoch 3/10
1875/1875 [==============================] - 16s 9ms/step - loss: 0.0350 - accuracy: 0.9892 - val_loss: 0.0396 - val_accuracy: 0.9858
Epoch 4/10
1875/1875 [==============================] - 16s 9ms/step - loss: 0.0252 - accuracy: 0.9919 - val_loss: 0.0292 - val_accuracy: 0.9906
Epoch 5/10
1875/1875 [==============================] - 15s 8ms/step - loss: 0.0187 - accuracy: 0.9940 - val_loss: 0.0278 - val_accuracy: 0.9908
Epoch 6/10
1875/1875 [==============================] - 18s 10ms/step - loss: 0.0140 - accuracy: 0.9957 - val_loss: 0.0315 - val_accuracy: 0.9905
Epoch 7/10
1875/1875 [==============================] - 16s 9ms/step - loss: 0.0108 - accuracy: 0.9964 - val_loss: 0.0361 - val_accuracy: 0.9899
Epoch 8/10
1875/1875 [==============================] - 16s 8ms/step - loss: 0.0099 - accuracy: 0.9966 - val_loss: 0.0327 - val_accuracy: 0.9905
Epoch 9/10
1875/1875 [==============================] - 15s 8ms/step - loss: 0.0079 - accuracy: 0.9976 - val_loss: 0.0353 - val_accuracy: 0.9905
Epoch 10/10
1875/1875 [==============================] - 17s 9ms/step - loss: 0.0072 - accuracy: 0.9977 - val_loss: 0.0349 - val_accuracy: 0.9911

5、预测

model.predict是tensorflow用于预测的API,输出所述类别的概率

# 测试集中第一张图片数据
plt.imshow(test_images[1])


在这里插入图片描述

  • 第一张为数字2
# 测试集预测
pre = model.predict(test_images)
# 输出所属类别概率
pre[1]

输出概率:

array([  4.0634604,  -1.2556026,  25.725822 , -12.4212475,  -8.13141  ,
       -17.905268 ,   2.7954185,  -2.617863 ,  -4.929763 , -12.776581 ],
      dtype=float32)

上述输出分别是:属于数字0-9的概率
分析

  • 属于数字2的类别概率最大,且远超其他,故,他预测结果是数字2

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

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

相关文章

[Python] 编程入门:理解变量类型

文章目录 [toc] 整数常见操作 浮点数字符串字符串中混用引号问题字符串长度计算字符串拼接 布尔类型动态类型特性类型转换结语 收录专栏&#xff1a;[Python] 在编程中&#xff0c;变量是用于存储数据的容器&#xff0c;而不同的变量类型则用来存储不同种类的数据。Python 与 C…

爬虫——爬虫理论+request模块

一、爬虫理论 爬虫——请求网站并提取数据的自动化程序 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟客户端发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动的抓取互联网信息的程序。 原则上&…

SQL第12课——联结表

三点&#xff1a;什么是联结&#xff1f;为什么使用联结&#xff1f;如何编写使用联结的select语句 12.1 联结 SQL最强大的功能之一就是能在数据查询的执行中联结&#xff08;join)表。联结是利用SQL的select能执行的最重要的操作。 在使用联结前&#xff0c;需要了解关系表…

【数据结构 | PTA】栈

文章目录 7-1 汉诺塔的非递归实现7-2 出栈序列的合法性**7-3 简单计算器**7-4 盲盒包装流水线 7-1 汉诺塔的非递归实现 借助堆栈以非递归&#xff08;循环&#xff09;方式求解汉诺塔的问题&#xff08;n, a, b, c&#xff09;&#xff0c;即将N个盘子从起始柱&#xff08;标记…

Golang | Leetcode Golang题解之第447题回旋镖的数量

题目&#xff1a; 题解&#xff1a; func numberOfBoomerangs(points [][]int) (ans int) {for _, p : range points {cnt : map[int]int{}for _, q : range points {dis : (p[0]-q[0])*(p[0]-q[0]) (p[1]-q[1])*(p[1]-q[1])cnt[dis]}for _, m : range cnt {ans m * (m - 1)…

多功能快捷回复软件

各位亲爱的客服宝宝们&#xff0c;每天面对大量的客户咨询&#xff0c;您是否还在手动一个一个地打字回复呢&#xff1f;别担心&#xff0c;我们为您带来了一款多功能快捷回复软件——客服宝。有了它&#xff0c;您的工作将变得无比轻松&#xff01; 客服宝是一款集成了内容存储…

window下‘jps‘ 不是内部或外部命令,也不是可运行的程序或批处理文件,特别是使用idea开发工具的环境

1、在系统环境变量里面查看是否有JAVA_HOME环境变量&#xff0c;如果是用idea来管理环境变量的&#xff0c;需要如图设置指向jbr&#xff0c;如果是单独安装的jdk环境指向自己的安装目录即可 2、设置系统环境Path&#xff0c;需要把jre和bin添加进去

手写mybatis之把反射用到出神入化

前言 但在实操上&#xff0c;很多码农根本没法阅读框架源码。首先一个非常大的问题是&#xff0c;面对如此庞大的框架源码&#xff0c;不知道从哪下手。与平常的业务需求开发相比&#xff0c;框架源码中运用了大量的设计原则和设计模式对系统功能进行解耦和实现&#xff0c;也使…

深度学习----------------------序列到序列学习(seq2seq)

目录 机器翻译Seq2seq编码器-解码器细节训练衡量生成序列的好坏的BLEU总结序列到序列学习实现循环神经网络编码器解码器通过零值化屏蔽不相关的项该部分总代码 通过扩展softmax交叉熵损失函数来遮蔽不相关的预测训练预测BLEU的代码实现该部分总代码 机器翻译 给定一个源语言的…

IDEA几大常用AI插件

文章目录 前言列表GPT中文版TalkXBito AIIDEA自带的AI 前言 最近AI、GPT特别火&#xff0c;IDEA里面又有一堆插件支持GPT&#xff0c;所以做个专题比较一下各个GPT插件 列表 先看idea的plugins里支持哪些&#xff0c;搜索“GPT”之后得到的&#xff0c;我用下来感觉第一第二和…

使用微服务Spring Cloud集成Kafka实现异步通信(消费者)

1、本文架构 本文目标是使用微服务Spring Cloud集成Kafka实现异步通信。其中Kafka Server部署在Ubuntu虚拟机上&#xff0c;微服务部署在Windows 11系统上&#xff0c;Kafka Producer微服务和Kafka Consumer微服务分别注册到Eureka注册中心。Kafka Producer和Kafka Consumer之…

无法编辑PDF文件?试试这3个解决方法!

PDF文件格式广泛应用于工作中&#xff0c;但有时候我们可能遇到无法编辑PDF文件的情况。这可能导致工作效率降低&#xff0c;特别是在需要修改文件内容时显得尤为棘手。遇到PDF不能编辑时&#xff0c;可以看看是否以下3个原因导致的。 原因一&#xff1a;PDF文件设置了编辑权限…

dockertop提示Failed to fetch extensions

解决办法&#xff1a;重装dockertop 第一步&#xff1a;卸载当前的dockertop 如果卸载过程中存在AlibabaProtect的相关软件关不掉&#xff0c;那么参考这篇文章&#xff1a;卸载AlibabaProtect 第二步&#xff1a;删除C:\Program Files路径下的Docker文件夹 第三步&#xff1…

YOLOv5复现(论文复现)

YOLOv5复现&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 YOLOv5复现&#xff08;论文复现&#xff09;概述模型结构正负样本匹配策略损失计算数据增强使用方式训练测试验证Demo 概述 YOLOv5是由Ultralytics公司于2020年6月开源的目标检…

【架构】prometheus+grafana系统监控

文章目录 一、Prometheus简介二、Grafana简介三、PrometheusGrafana系统监控的实现四、优势与应用场景 参考 PrometheusGrafana系统监控是一个强大的组合&#xff0c;用于实时监控和分析系统的性能与状态。以下是对这一组合在系统监控中的详细解析&#xff1a; 一、Prometheus…

【牛顿迭代法求极小值】

牛顿迭代法求极小值 仅供参考 作业内容与要求 作业内容 作业要求 递交报告 代码 编程实现 计算偏导数 故上述非线性方程组的根可能为 f ( x , y ) f(x, y) f(x,y)的极值点&#xff0c;至于是极小值点还是极大值点或鞍点&#xff0c;就需要使用微积分中的黑塞矩阵来判断了。…

避雷!Google Adsense联盟营销七大投放误区

你是否在使用Google AdSense进行广告投放&#xff1f;你是否想进一步优化你的投放策略&#xff1f;那么这篇文章你不可错过啦&#xff01; Google AdSense为跨境商家提供了一个平台&#xff0c;我们可以通过展示相关广告来赚取收入。然而&#xff0c;即使是最有经验的商家也可…

C语言指针plus版练习

上期我们讲了进阶的指针&#xff0c;本期内容我们来强化一下上期学的内容 一、字符串左旋 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 1.1 分析题目 假设字符串为abcde&#xff0c;左旋一个以后就变成bcdea&#xff0c;就是把第一个字符移到一个新的变量里面&#…

【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧

文章目录 C模板进阶编程前言第一章: 非类型模板参数1.1 什么是非类型模板参数&#xff1f;1.1.1 非类型模板参数的定义 1.2 非类型模板参数的注意事项1.3 非类型模板参数的使用场景示例&#xff1a;静态数组的实现 第二章: 模板的特化2.1 什么是模板特化&#xff1f;2.1.1 模板…

Leetcode 10. 正则表达式匹配

1.题目基本信息 1.1.题目描述 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符‘*’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分…