2023.3.3周报

目录

摘要

一、文献阅读

1、题目

2、摘要

3、模型架构

4、文献解读

一、Introduction

二、实验

三、结论

二、PINN

一、PINN比传统数值方法有哪些优势

二、PINN方法

三、正问题与反问题

三、PINN实验

一、数学方程

二、模型搭建

总结

摘要

本周我阅读了一篇题目为Deep Residual Learning for Image Recognition的文献,文章的贡献是作者提出了残差网络的思想,且证明了更深层的残差网络具有比VGG网络更低的复杂度和更高的准确性,同时,残差网络实现了更容易的训练过程。其次,对PINN进行了继续的学习,PINN 是一种科学机器在传统数值领域的应用方法,特别是用于解决与偏微分方程相关的各种问题,包括方程求解、参数反演、模型发现、控制与优化等。

This week, I read a paper titled "Deep Residual Learning for Image Recognition." The contribution of the paper is that the author introduces the concept of residual networks and demonstrates that deeper residual networks have lower complexity and higher accuracy compared to VGG networks. Additionally, residual networks achieve a more straightforward training process. Furthermore, I gained preliminary insights into Physics-Informed Neural Networks (PINN). PINN is an application of scientific machine learning in traditional numerical domains, particularly for solving various problems related to partial differential equations. This includes equation solving, parameter inversion, model discovery, control, and optimization.

一、文献阅读

1、题目

题目:Deep Residual Learning for Image Recognition  

链接:https://arxiv.org/abs/1512.03385

2、摘要

本文展示了一种残差学习框架,能够简化使那些非常深的网络的训练,该框架使得层能根据其输入来学习残差函数而非原始函数。作者提出了残差网络的思想,且证明了更深层的残差网络具有比VGG网络更低的复杂度和更高的准确性。同时,残差网络实现了更容易的训练过程。

This article presents a residual learning framework that simplifies the training of very deep networks. The framework allows layers to learn residual functions based on their inputs rather than the original functions. The author introduces the concept of residual networks and demonstrates that deeper residual networks have lower complexity and higher accuracy compared to VGG networks. Additionally, residual networks achieve a more straightforward training process.

 

95966e72468a4e26b6143d01bda29528.png

3、模型架构

f8c9a1824aa6417286cd6ee33a93839d.png

Plain Network
受VGG网络的影响,plain网络(如下图中间)的卷积层主要是3*3的滤波器,加权层的层数为34,在网络的最后是全局的平均pooling层和一个1000种类的包含softmax函数的全连接层。plain网络比VGG网络有更少的滤波器(卷积核后面的64,128,256等代表个数)和更低的计算复杂度,VGG-19模型有196亿个FLOPS,plain网络含有36亿个FLOPS。
Residual Network
在plain网络的基础上,加入shortcut连接,就变成了相应的残差网络,上图中所加实线表明可以直接使用恒等shortcuts,虚线表示维度不匹配时的情况,需要先调整维度再相加,调整维度的方法有两种:(A)仍然使用恒等映射,只是在增加的维度上使用0来填充,这种方法不会引入额外的参数;(B)使用1x1的卷积映射shortcut来调整维度保持一致。这两种方法都使用stride为2的卷积。

4、文献解读

一、Introduction

神经网络模型的深度对训练任务起着至关重要的作用,但是当模型深度太大时,会存在梯度消失/梯度爆炸的问题,尽管normalized initial-ization和intermediate normalization可以在一定程度上解决这个问题,但是准确率依然会在达到饱和后迅速退化,因此错误率甚至会更高,如下图所示,越深的网络有越高的训练错误率和测试错误率。
 

589737b635314e04a1e24e8d5cf1802b.png

文章提出了深度残差学习(deep residual learning)框架来解决上图中的问题,如下图所示,通过前馈神经网络的shortcut connections来跨过一个层或者多个层,将前层的输出直接与卷积层的输出叠加,相当于做了个恒等映射。在极端情况下,如果恒等映射最优,可以将残差设置为0就简单地实现了恒等映射。简单来说,残差学习就是将一层的输入与另一层的输出结果一起作为一整个块的输出。

ResNet 之所以叫残差网络(Residual Network),是因为 ResNet 是由很多残差块(Residual Block)组成的。而残差块的使用,可以解决前面说到的退化问题。残差块如下图所示。

f01a5a6d923344158127f6b92e3bd1b5.png

残差(residual)在数理统计中是指实际观察值(观测值)与估计值(拟合值)之间的差。
假设上图中的 weight layer 是 3×3 的卷积层;F(x) 表示经过两个卷积层计算后得到的结果;identity x 表示恒等映射(identity mapping),也称为shortcut connections。其实就是把 x 的值是不做任何处理直接传过去。最后计算 F(x)+x,这里的 F(x) 跟 x 是种类相同的信号,所以将其对应位置进行相加。我们让 H(x) = F(x)+x ,所以 H(x) 就是观测值,x 就是估计值。
我们如果使用plain networks(一般的卷积神经网络)那么 H(x) = F(x)  ,这样某一层达到最优之后在加深就会出现退化问题。残差就体现在:F(x) = H(x)-x  ,我们假设优化残差映射比优化原始的、未引用残差的映射更容易。在极端情况下,如果一个恒等映射 x 是最优的,那么将残差 F(x) 推到 0 比通过一堆非线性层来拟合一个恒等映射要容易得多。

二、实验

1、数据集

数据集:ImageNet 2012 classifi-cation dataset(1000类)
数据量:128 万张训练图像,5万张测试图像
标准:评估 top-1 和 top-5 错误率

2、参数设置

从一张图像或者它的水平翻转图像中随机采样一个224*224的crop,每个像素都减去均值。图像使用标准的颜色增强。我们在每一个卷积层之后,激活层之前均使用batch normalization(BN)。我们根据He2014spatial来初始化权值然后从零开始训练所有plain/残差网络。
我们使用的mini-batch的尺寸为256。学习率从0.1开始,每当错误率平稳时将学习率除以10,整个模型进行次迭代训练。我们将权值衰减设置为0.0001,a 动量为0.9。

3、实验结果

普通网络,结论:
(1)较深的 34 层普通网络比较浅的 18 层普通网络具有更高的验证误差。34 层普通网络在整个训练过程中具有较高的训练误差,尽管 18 层普通网络的解空间是 34 层网络的子空间。
(2)论文认为这种优化困难不是由梯度消失引起的。这些普通网络使用 BN 进行训练,确保前向传播的信号具有非零方差。我们还验证了反向传播的梯度在 BN 中表现出健康的范数。所以前向和后向信号都不会消失。事实上,34 层的普通网络仍然能够达到有竞争力的精度(表 3),这表明求解器在一定程度上起作用。我们推测深的普通网络的收敛速度可能呈指数级低,这会影响训练误差的减少。

ResNet,结论:
(1)34 层 ResNet 优于 18 层 ResNet(提高 2.8%)。更重要的是,34 层的 ResNet 表现出相当低的训练误差,并且可以推广到验证数据。这表明退化问题在此设置中得到了很好的解决,可以通过增加深度来获得准确度。
(2)相比普通网络ResNet 将 top-1 误差降低了 3.5%(表 2),这是由于成功降低了训练误差。这种比较验证了残差学习在极深系统上的有效性。
(3)我们还注意到 18 层的普通/残差网络相当准确,但 18 层的 ResNet 收敛速度更快。当网络“不太深”(此处为 18 层)时,当前的 SGD 求解器仍然能够为普通网络找到好的解决方案。在这种情况下,ResNet 通过在早期提供更快的收敛来简化优化。
ae9d1d245dbb4525a6a0c522614982bd.png

三、结论

残差结构的主要作用是传递信号,把深度学习浅层的网络信号直接传给深层的网络。深度学习中不同的层所包含的信息是不同的,一般我们认为深层的网络所包含的特征可能对最后模型的预测更有帮助,但是并不是说浅层的网络所包含的信息就没用,深层网络的特征就是从浅层网络中不断提取而得到的。现在我们给网络提供一个捷径,也就是Shortcut Connections,它可以直接将浅层信号传递给深层网络,跟深层网络的信号结合,从而帮助网络得到更好的效果。
 

二、PINN

一、PINN比传统数值方法有哪些优势

PINN是一种(深度)网络,在定义时空区域中给定一个输入点,在训练后在微分方程的该点中产生估计的解。结合对控制方程的嵌入得到残差,利用残差构造损失项。本质原理就是将方程(物理知识)集成到网络中,并使用来自控制方程的残差项来构造损失函数,由该项作为惩罚项来限制可行解的空间。用PINN来求解方程并不需要有标签的数据,比如先前模拟或实验的结果。PINN算法本质上是一种无网格技术,通过将直接求解控制方程的问题转换为损失函数的优化问题来找到偏微分方程解。

1、传统数值方法主要针对复杂问题的正计算,比如说已知边界条件、已知控制方程的正计算,在正计算上,深度学习的方法逊色一些,但是针对一些反问题,比如说一些测量数据和部分物理(方程中某些参数未知、边界条件未知),深度学习方法可以形成数据和物理双驱动的模型,比传统数值方法的效率更高。

2、当面对一些数值问题时,PINN可以不需要用数值格式去推导求解,可以直接利用加物理损失的方法得到一个参考解,当问题边界需要不停地换时,或者很多资源不停的变化的情况下,如果利用大量时间去训练一个网络,在推断阶段可以实现快速预测。

二、PINN方法

先构建一个输出结果为eq?%5Cwidehat%7Bu%7D 的神经网络,将其作为PDE解的代理模型,将PDE信息作为约束,编码到神经网络损失函数中进行训练。损失函数主要包括4部分:偏微分结构损失(PDE loss),边值条件损失(BC loss)、初值条件损失(IC loss)以及真实数据条件损失(Data loss)。5b97bf34d4bc443faf035184c6cad33a.png

 0fd7addc8f394614864cc97483bea44b.jpeg

后,利用梯度优化算法最小化损失函数,直到找到满足预测精度的网络参数 eq?%5Ctheta%20%5E%7B*%7D

对于逆问题(即方程中的某些参数未知),若只知道PDE方程及边界条件,PDE参数未知,该问题为非定问题,所以必须要知道其他信息,如部分观测点u的值。此时,PINN做法可将方程中的参数作为未知变量,加到训练器中进行优化,损失函数包括Data loss。

三、正问题与反问题

正问题和反问题的正经定义可以解释为:正问题,已知原因,根据已有的模型和规律,得到结果状态或者观测,而反问题则是已知结果状态或者观测,来反推原因。正问题例子包括设计飞机的方案参数,然后通过模拟,可以知道飞机的性能,反问题则是根据飞机的设计需求,反推应该给什么设计方案。因此,工程界通常称正问题为模拟问题,反问题为设计问题。对于一个PDE方程,我们这样来定义正问题,已知PDE方程,求解PDE方程在场域内的解为正问题;反问题我们定义为,已知一些场域内的观测情况,来反推最优的PDE方程的系数/参数的值。 

对于PDE问题而言,PINN的正问题就是根据已有的PDE来求解场域内的解。建立一个神经网络 eq?G,来学习PDE的特性。具体来说,就是建立时间坐标eq?t和空间坐标eq?x与解eq?y的映射,即:eq?G%3At%2Cx%5Crightarrow%20y

神经网络的训练需要一个目标函数,PDE方程其实就是一个损失函数,如果不满足等式关系,就会产生损失,因此,把神经网络的eq?t%2Cx%2C%5Cwidehat%7By%7D%3DG%28t%2Cx%29放进PDE里面获取损失。

从数学角度看,和传统的机器学习相比,它最大的不同就是在要求0阶常数项与系统一致的基础上,同时要求高阶梯度项与系统一致。从泰勒展开的角度来看,它显然具有更高的精度,因为它更满足系统的高维特征。 从机器学习和问题的适配角度来看,采用神经网络而不是别的机器学习方法也是非常有见地的设计,因为神经网络的可微性带来了梯度求解的可行性。求解正问题时,PINN完全不需要数据,只需要随意在空间和时间步上采样,然后让PDE方程来评估神经网络的建模是否准确;或者说真实数据是基于PDE损失函数的中间量。

PINN 解反问题的任务是需要反推出PDE中的各项的超参数。这个问题的设定意味着我们没有真实可靠的PDE方程来做评判 ,因此,需要实际的观测(场域的值)来提供损失函数。简而言之,我们就是在一族的PDE中挑一个最合适的来拟合实际的系统。

三、PINN实验

一、数学方程

使用一个最简单的常微分方程:

                                                               eq?%7Bf%7D%27%28x%29%3Df%28x%29 

                                                                eq?f%280%29%3D1

这个微分方程其实就是:

                                                                eq?f%28x%29%3De%5E%7Bx%7D

二、模型搭建

核心-使用最简单的全连接层:

class Net(nn.Module):def __init__(self, NL, NN): # NL n个l(线性,全连接)隐藏层, NN 输入数据的维数,# NL是有多少层隐藏层# NN是每层的神经元数量super(Net, self).__init__()self.input_layer = nn.Linear(1, NN)self.hidden_layer = nn.linear(NN,int(NN/2)) ## 原文这里用NN,我这里用的下采样,经过实验验证,“等采样”更优。更多情况有待我实验验证。self.output_layer = nn.Linear(int(NN/2), 1)def forward(self, x):out = torch.tanh(self.input_layer(x))out = torch.tanh(self.hidden_layer(out))out_final = self.output_layer(out)return out_final

 偏微分方程定义,也就是第一个公式:

def ode_01(x,net):y=net(x)y_x = autograd.grad(y, x,grad_outputs=torch.ones_like(net(x)),create_graph=True)[0]return y-y_x   # y-y' = 0

源码:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from torch import autograd"""
用神经网络模拟微分方程,f(x)'=f(x),初始条件f(0) = 1
"""class Net(nn.Module):def __init__(self, NL, NN): # NL n个l(线性,全连接)隐藏层, NN 输入数据的维数,# NL是有多少层隐藏层# NN是每层的神经元数量super(Net, self).__init__()self.input_layer = nn.Linear(1, NN)self.hidden_layer = nn.Linear(NN,int(NN/2)) ## 原文这里用NN,我这里用的下采样,经过实验验证,“等采样”更优。更多情况有待我实验验证。self.output_layer = nn.Linear(int(NN/2), 1)def forward(self, x):out = torch.tanh(self.input_layer(x))out = torch.tanh(self.hidden_layer(out))out_final = self.output_layer(out)return out_finalnet=Net(4,20) # 4层 20个
mse_cost_function = torch.nn.MSELoss(reduction='mean') # Mean squared error 均方误差求
optimizer = torch.optim.Adam(net.parameters(),lr=1e-4)  # 优化器def ode_01(x,net):y=net(x)y_x = autograd.grad(y, x,grad_outputs=torch.ones_like(net(x)),create_graph=True)[0]return y-y_x   # y-y' = 0# requires_grad=True).unsqueeze(-1)plt.ion()  # 动态图
iterations=200000
for epoch in range(iterations):optimizer.zero_grad()  # 梯度归0## 求边界条件的损失函数x_0 = torch.zeros(2000, 1)y_0 = net(x_0)mse_i = mse_cost_function(y_0, torch.ones(2000, 1))  # f(0) - 1 = 0## 方程的损失函数x_in = np.random.uniform(low=0.0, high=2.0, size=(2000, 1))pt_x_in = autograd.Variable(torch.from_numpy(x_in).float(), requires_grad=True)  # x 随机数pt_y_colection=ode_01(pt_x_in,net)pt_all_zeros= autograd.Variable(torch.from_numpy(np.zeros((2000,1))).float(), requires_grad=False)mse_f=mse_cost_function(pt_y_colection, pt_all_zeros)  # y-y' = 0loss = mse_i + mse_floss.backward()  # 反向传播optimizer.step()  # 优化下一步。This is equivalent to : theta_new = theta_old - alpha * derivative of J w.r.t thetaif epoch%1000==0:y = torch.exp(pt_x_in)  # y 真实值y_train0 = net(pt_x_in) # y 预测值print(epoch, "Traning Loss:", loss.data)print(f'times {epoch}  -  loss: {loss.item()} - y_0: {y_0}')plt.cla()plt.scatter(pt_x_in.detach().numpy(), y.detach().numpy())plt.scatter(pt_x_in.detach().numpy(), y_train0.detach().numpy(),c='red')plt.pause(0.1)

结果展示:

训练0次时的结果也就是没训练,蓝色是真实值、红色是预测值:

a200224724a84a60994b6bd58e84f54d.png

 训练2000次时的结果,蓝色是真实值、红色是预测值:

0e1f38ee59534974aa40b635a9d6a688.png

训练20000时的结果,蓝色是真实值、红色是预测值,不过红色已经完全把蓝色覆盖了,也就是完全拟合了:

8eeb11035853464d9e39105a0c787e9f.png

总结

ResNet网络的最初原始论文说明:一味地加深网络深度会使得网络达到了一种饱和状态(论文中强调不是过拟合现象,而是一种网络深度到一定程度之后的退化问题),而导致精度的下降。PINN的原理就是通过训练神经网络来最小化损失函数来近似PDE的求解,所谓的损失函数项包括初始和边界条件的残差项,以及区域中选定点(按传统应该称为"配点")处的偏微分方程残差。

 

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

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

相关文章

Postman上传文件的操作方法

前言 调用某个接口,测试上传文件功能。一时间不知如何上传文件,本文做个操作记录,期望与你有益。 步骤一、设置Headers key:Content-Type value:multipart/form-data 步骤二、设置Body 选择form-data key:file下拉框选择file类型value&…

STM32(8)NVIC编程

中断源由部分片上外设产生 在misc.h中找,杂项 配置NVIC GPIO和AFIO不能产生中断源,但能通过EXTI,由EXTI产生中断源 NVIC不需要开启时钟,因为NVIC模块位于内核内部,芯片一上电就能工作。 中断响应函数 中断向量表在启…

Java:JVM基础

文章目录 参考JVM内存区域程序计数器虚拟机栈本地方法栈堆方法区符号引用与直接引用运行时常量池字符串常量池直接内存 参考 JavaGuide JVM内存区域 程序计数器 程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器,各线程…

Unity 常用的4种灯光、制作镜子、灯光的调用修改数值、

创建灯光时,一般用4种:定向光、点光源、聚光、区域光、 定向光:太阳 点光源:灯泡 聚光灯:手电筒 区域光:烘焙-贴图 灯光选择已烘焙 需要先选择被烘焙的物体,然后再选择Contribute GI 等待进…

java中的set

Set Set集合概述和特点 不可以存储重复元素 没有索引,不能使用普通for循环遍历 哈希值 哈希值简介 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值 如何获取哈希值 Object类中的public int hashCode():返回对象的哈希码值。 哈希值的特点 同一个…

分布式ID生成算法|雪花算法 Snowflake | Go实现

写在前面 在分布式领域中,不可避免的需要生成一个全局唯一ID。而在近几年的发展中有许多分布式ID生成算法,比较经典的就是 Twitter 的雪花算法(Snowflake Algorithm)。当然国内也有美团的基于snowflake改进的Leaf算法。那么今天我们就来介绍一下雪花算法…

计算机视觉基础知识(二)---数字图像

像素 像素是分辨率的单位;构成位图图像的最基本单元;每个像素都有自己的颜色; 图像分辨率 单位英寸内的像素点数;单位为PPI(Pixels Per Inch),为像素每英寸;PPI表示每英寸对角线上所拥有的像素数目:,x:长度像素数目,y:宽度像素数目,Z:屏幕大小;屏幕尺寸(大小)指的是对角线长…

springer模板参考文献不显示

Spring期刊模板网站,我的问题是23年12月的版本 https://www.springernature.com/gp/authors/campaigns/latex-author-support/see-where-our-services-will-take-you/18782940 参考文献显示问好,在sn-article.tex文件中,这个sn-mathphys-num…

数据结构c版(3)——排序算法

本章我们来学习一下数据结构的排序算法! 目录 1.排序的概念及其运用 1.1排序的概念 1.2 常见的排序算法 2.常见排序算法的实现 2.1 插入排序 2.1.1基本思想: 2.1.2直接插入排序: 2.1.3 希尔排序( 缩小增量排序 ) 2.2 选择排序 2.2…

rtt的io设备框架面向对象学习-io设备管理层

目录 1.设备基类2.rtt基类2.1 rtt基类定义2.2 对象容器定义2.3 rtt基类构造函数 3.io设备管理接口4.总结 这层我的理解就是rtt基类和设备基类所在,所以抽离出来好点,不然每个设备类都要重复它。 1.设备基类 /include/rtdef.h中定义了设备基类struct rt_…

STM32(11)按键产生中断

1.初始化IO引脚,设置模式,速度等 2.设置AFIO(配置EXTI的引脚映射),记得开启时钟 3.配置EXTI的通道(EXTI0和EXTI1) 4.配置NVIC 4.1 中断优先级分组 4.2 配置中断 5.编写中断响应函数 在中断向量…

蓝桥ACM培训-实战1

前言&#xff1a; 今天老师没讲课&#xff0c;只让我们做了一下几道题目。 正文&#xff1a; Problem:A 小蓝与操作序列&#xff1a; #include<bits/stdc.h> using namespace std; stack<int> a; int main(){int n,flag1,ans;string cz;cin>>n;for(int i1;…

访问修饰符、Object(方法,使用、equals)、查看equals底层、final--学习JavaEE的day15

day15 一、访问修饰符 含义&#xff1a; 修饰类、方法、属性&#xff0c;定义使用的范围 理解&#xff1a;给类、方法、属性定义访问权限的关键字 注意&#xff1a; ​ 1.修饰类只能使用public和默认的访问权限 ​ 2.修饰方法和属性可以使用所有的访问权限 访问修饰符本类本包…

JetCache源码解析——API实现(持续更新中……)

在JetCache中不仅可以通过在类和接口的函数上使用注解Cached、CacheUpdate和CacheInvalidate等实现缓存加载、更新和删除操作&#xff0c;也支持通过调用API接口的形式来实现缓存的加载、更新和删除操作。 缓存接口 缓存接口的定义如下&#xff1a; /*** 缓存接口&#xff0…

【计算机网络】HTTPS 协议原理

https 一、HTTPS 是什么二、加密1. 加密概念2. 加密的原因3. 常见的加密方式&#xff08;1&#xff09;对称加密&#xff08;2&#xff09;非对称加密 三、数据摘要(数据指纹)四、HTTPS 的工作原理探究1. 只使用对称加密2. 只使用非对称加密3. 双方都使用非对称加密4. 非对称加…

Linux:kubernetes(k8s)部署CNI网络插件(4)

在上一章进行了node加入master Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;node节点加入master主节点&#xff08;3&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136420447?spm1001.2014.3001.5501 但是他们显示还是没准备好 看一下…

面试笔记系列五之MySql+Mybaits基础知识点整理及常见面试题

目录 Myibatis myibatis执行过程 mybatis的优缺点有哪些&#xff1f; mybatis和hibernate有什么区别&#xff1f; mybatis中#{}和${}的区别是什么&#xff1f; 简述一下mybatis插件运行原理及开发流程&#xff1f;&#xff08;插件四大天王&#xff09; mybatis的mapper没…

2.模拟问题——5.星期几与字符串对应

输入输出示例 输入&#xff1a; 9 October 2001 14 October 2001 输出&#xff1a; Tuesday Sunday 【原题链接】 字符串处理 C风格的字符串 字符数组&#xff0c;以’\0‘结尾建议在输入输出语句中使用 C风格的字符串 #include <string> using namespace std;初始化…

【字符串】马拉车(Manacher)算法

本篇文章参考&#xff1a;比较易懂的 Manacher&#xff08;马拉车&#xff09;算法配图详解 马拉车算法可以求出一个字符串中的最长回文子串&#xff0c;时间复杂度 O ( n ) O(n) O(n) 因为字符串长度的奇偶性&#xff0c;回文子串的中心可能是一个字符&#xff0c;也可能是…

uniapp聊天记录本地存储(详细易懂)

目录 目录 1、通过websocket拿取数据 2、获取聊天数据 3、聊天信息存储 、更新 4、读取聊天记录 5、发送信息&#xff0c;信息获取 6、最终效果 1.聊天信息的存储格式 2、样式效果 写聊天项目&#xff0c;使用到了本地存储。需要把聊天信息保存在本地&#xff0c;实时获…