当前位置: 首页 > news >正文

TDengine+OpenVINO+AIxBoard,助力时序数据分类

时间序列数据分析在工业,能源,医疗,交通,金融,零售等多个领域都有广泛应用。其中时间序列数据分类是分析时序数据的常见任务之一。本文将通过一个具体的案例,介绍 Intel 团队如何使用 TDengine 作为基础软件存储实验数据,并通过 TDengine 高效的查询能力在 OpenVINO 部署深度学习模型,最终在 AIxBoard 开发板上实时运行分类任务。

模型简介

近年来机器学习和深度学习在时序数据分类任务中取得了显著进展,HIVE-COTE 和 InceptionTime 模型都取得了不错的成果。相比基于 Nearest Neighbor 和 DTW 算法的 HIVE-COTE 模型,基于一维卷积 (Conv1D) 的 InceptionTime 模型成果更为显著,其在极大降低计算复杂度的基础上,还达到了与 HIVE-COTE 相当的分类精度。

如下图所示,Inception 模块是 InceptionTime 模型的基本组成模块,由多个一维卷积 (Conv1D) 操作堆叠,并于残差连接而成。

TDengine+OpenVINO+AIxBoard,助力时序数据分类 - TDengine Database 时序数据库

完整的 InceptionTime 模型由多个 Inception 模块连接而成。

TDengine+OpenVINO+AIxBoard,助力时序数据分类 - TDengine Database 时序数据库

关于 InceptionTime 的更多细节请参考论文:https://arxiv.org/abs/1909.04939。

数据集

TDengine+OpenVINO+AIxBoard,助力时序数据分类 - TDengine Database 时序数据库

本文采用的数据集来自 Time Series Classification Website,由 128 个时间序列分类任务组成。其中的 Wafer 数据集包含 1000 条训练数据和和 6164 条测试数据,每条数据均包含标签值和长度 152 的时间序列数据。数据通过程序提前写入到 TDengine 中。

这里描述的时序数据是晶片生成过程中同一个工具通过单个传感器记录的时间序列数据。下图展示了正常 (class 1) 和异常 (class 0) 两种标签对应的时序数据示例。

TDengine+OpenVINO+AIxBoard,助力时序数据分类 - TDengine Database 时序数据库

不难看出,这是一个标准的监督学习分类任务。我们希望找到一个模型,在每输入长度 152 的时序数据时,模型输出 0 或 1,以此判断输入时序数据对应的晶片在生成过程是否存在异常。

模型训练

本文中我们将使用 Wafer 数据集训练一个 InceptionTime 模型。训练得到的模型可以根据晶片生产过程中传感器记录的时序数据,判断某个晶片的生产过程是否存在异常。

InceptionTime 的作者开源了基于 tensorflow.keras 的实现,本文的模型代码基于 InceptionTime 开源版本并集成 TDengine 支持 GitHub - sangshuduo/InceptionTime: InceptionTime: Finding AlexNet for Time Series Classification。

首先加载 Python 库。

from os import path
import numpy as np
from sklearn import preprocessingfrom tensorflow import keras
from tensorflow.keras.layers import (Activation, Add, BatchNormalization, Concatenate,Conv1D, Dense, Input, GlobalAveragePooling1D, MaxPool1D
)from sqlalchemy import create_engine, text

然后使用 TDengine 的 SQLAlchemy 驱动加载 Wafer 数据集并进行预处理。

def readucr(conn, dbName, tableName):data = pd.read_sql(text("select * from " + dbName + "." + tableName),conn,)y = data[:, 0]x = data[:, 1:]return x, ydef load_data(db):engine = create_engine("taos://root:taosdata@localhost:6030/" + db)try:conn = engine.connect()except Exception as e:print(e)exit(1)if conn is not None:print("Connected to the TDengine ...")else:print("Failed to connect to taos")exit(1)x_train, y_train = readucr(conn, db + '_TRAIN.tsv')x_test, y_test = readucr(conn, db + '_TEST.tsv')n_classes = len(np.unique(y_train))enc = preprocessing.OneHotEncoder()y = np.concatenate((y_train, y_test), axis=0).reshape(-1,1)enc.fit(y)y_tr = enc.transform(y_train.reshape(-1,1)).toarray()y_te = enc.transform(y_test.reshape(-1,1)).toarray()x_tr, x_te = map(lambda x: x.reshape(x.shape[0], x.shape[1], 1), [x_train, x_test])return x_tr, y_tr, x_te, y_te, n_classesx_tr, y_tr, x_te, y_te, n_classes = load_data('Wafer')

再使用 tensorflow.keras 实现 IncetionTime,并创建模型。

def inception_module(input_tensor, filters, kernel_size, bottleneck_size,activation='relu', use_bottleneck=True):if use_bottleneck and int(input_tensor.shape[-1]) > 1:input_inception = Conv1D(filters=bottleneck_size, kernel_size=1, padding='same',activation=activation, use_bias=False)(input_tensor)else:input_inception = input_tensorkernel_size_s = [kernel_size // (2 ** i) for i in range(3)] # [40, 20, 10]conv_list = []for i in range(len(kernel_size_s)):conv = Conv1D(filters=filters, kernel_size=kernel_size_s[i],strides=1, padding='same', activation=activation,use_bias=False)(input_inception)conv_list.append(conv)max_pool = MaxPool1D(pool_size=3, strides=1, padding='same')(input_tensor)conv_6 = Conv1D(filters=filters, kernel_size=1, padding='same',activation=activation, use_bias=False)(max_pool)conv_list.append(conv_6)x = Concatenate(axis=2)(conv_list)x = BatchNormalization()(x)x = Activation(activation='relu')(x)return xdef shortcut_layer(input_tensor, output_tensor):y = Conv1D(filters=int(output_tensor.shape[-1]), kernel_size=1,padding='same', use_bias=False)(input_tensor)y = BatchNormalization()(y)x = Add()([y, output_tensor])x = Activation(activation='relu')(x)return xdef build_model(input_shape, n_classes, depth=6,filters=32, kernel_size=40, bottleneck_size=32,use_residual=True):input_layer = Input(input_shape)x = input_layerinput_res = input_layerfor d in range(depth):x = inception_module(x, filters, kernel_size, bottleneck_size)if use_residual and d % 3 == 2:x = shortcut_layer(input_res, x)input_res = xgap_layer = GlobalAveragePooling1D()(x)output_layer = Dense(n_classes, activation="softmax")(gap_layer)model = keras.Model(input_layer, output_layer)return modelmodel = build_model(x_tr.shape[1:], n_classes)model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy']
)

训练模型:

ckpt_path = path.sep.join(['.', 'models', 'inception_wafer.h5'])callbacks = [keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=20, min_lr=0.0001),keras.callbacks.EarlyStopping(monitor='val_loss', patience=20, verbose=1),keras.callbacks.ModelCheckpoint(filepath=ckpt_path, monitor='val_loss', save_best_only=True)
]batch_size = 32
epochs = 500history = model.fit(x_tr, y_tr, batch_size, epochs, verbose='auto', shuffle=True, validation_split=0.2, callbacks=callbacks)

简单显示一下训练过程:

metric = 'accuracy'
plt.figure(figsize=(10, 5))
plt.plot(history.history[metric])
plt.plot(history.history['val_'+metric])
plt.title("model " + metric)
plt.ylabel(metric, fontsize='large')
plt.xlabel('epoch', fontsize='large')
plt.legend(["train", "val"], loc="best")
plt.show()
plt.close()

TDengine+OpenVINO+AIxBoard,助力时序数据分类 - TDengine Database 时序数据库

使用测试数据验证模型的推理精度。

classifier = keras.models.load_model(ckpt_path)
test_loss, test_acc = classifier.evaluate(x_te, y_te)
print("Test accuracy: ", test_acc)
print("Test loss: ", test_loss)
193/193 [==============================] - 2s 11ms/step - loss: 0.0142 - accuracy: 0.9958
Test accuracy: 0.9957819581031799
Test loss: 0.014155667275190353

我们的模型在 Wafer 测试数据上取得了 99.58% 的精度。

模型转换

为了达成使用 OpenVINO Runtime 进行推理计算的目的,我们需要将 tensorflow 模型转换为 OpenVINO IR 格式。

from pathlib import Path
from openvino.tools import mo
from tensorflow import kerasmodel = keras.models.load_model('models/inception_wafer.h5')model_path = Path('models/inception.0_float')
model.save(model_path)model_dir = Path("ov")
model_dir.mkdir(exist_ok=True)
ir_path = Path("ov/inception.xml")input_shape = [1, 152, 1]if not ir_path.exists():print("Exporting TensorFlow model to IR...")ov_model = mo.convert_model(saved_model_dir=model_path, input_shape=input_shape, compress_to_fp16=True)serialize(ov_model, ir_path)
else:print(f"IR model {ir_path} already exists.")

转换完成后,生成的 IR 格式模型被存储为模型定义文件 inception.xml 和二进制文件 inception.bin。

模型部署

接下来我们在 AIxBoard 开发板上部署刚刚训练的 IncetpionTime 模型。首先将 inception.bin、inception.xml 和 Wafer_TEST.tsv 几个文件复制到 AIxBoard 板上。

加载 Python 库。

from pathlib import Path
import numpy as np
from openvino.runtime import Core, serialize

使用 OpenVINO 运行 Inception 模型。

ir_path = Path("inception.xml")
core = Core()
model = core.read_model(ir_path)
import ipywidgets as widgetsdevice = widgets.Dropdown(options=core.available_devices + ["AUTO"],value='AUTO',description='Device:',disabled=False
)device
0.995782

使用OpenVINO推理的精度跟tensorflow模型推理精度一致,同样达到了99.58%。我们在模型转换时将原模型数据格式压缩为 FP16,这一操作并没有导致精度下降。

性能测试

使用 OpenVINO 自带的 benchmark 工具可以轻松地在 AIxBoard 上进行性能测试。

benchmark_app -m inception.xml -hint latency -d CPU
[ INFO ] First inference took 8.59 ms
[Step 11/11] Dumping statistics report
[ INFO ] Execution Devices:['CPU']
[ INFO ] Count:            8683 iterations
[ INFO ] Duration:         60012.27 ms
[ INFO ] Latency:
[ INFO ]    Median:        6.44 ms
[ INFO ]    Average:       6.81 ms
[ INFO ]    Min:           6.34 ms
[ INFO ]    Max:           37.13 ms
[ INFO ] Throughput:   144.69 FPS
benchmark_app -m inception.xml -hint latency -d GPU
[ INFO ] First inference took 10.58 ms
[Step 11/11] Dumping statistics report
[ INFO ] Execution Devices:['GPU.0']
[ INFO ] Count:            7151 iterations
[ INFO ] Duration:         60026.34 ms
[ INFO ] Latency:
[ INFO ]    Median:        7.50 ms
[ INFO ]    Average:       8.23 ms
[ INFO ]    Min:           7.04 ms
[ INFO ]    Max:           21.78 ms
[ INFO ] Throughput:   119.13 FPS

从上面结果可以看出,使用AIxBoard的CPU运行InceptionTime模型推理,平均时长为6.81ms。使用集成 GPU 推理,平均时长为 8.23ms。

总结

本文介绍了如何利用 TDengine 支持时间序列数据的底层存储,以及如何通过分类模型 InceptionTime 在 UCR 时序数据集的 Wafer 分类任务上进行训练。最后,我们使用 OpenVINO 将该模型部署在 AIxBoard 开发板上,实现了高效的实时时序数据分类任务。希望本文的内容能够帮助大家在项目中利用 TDengine、OpenVINO 和 AIxBoard 来解决更多的时间序列分析问题。


关于 AIxBoard

英特尔开发者套件 AIxBoard(爱克斯开发板)是专为支持入门级边缘 AI 应用程序和设备而设计,能够满足人工智能学习、开发、实训等应用场景。该开发板是类树莓派的 x86 主机,可支持 Linux Ubuntu 及完整版 Windows 操作系统,板载一颗英特尔 4 核处理器,最高运行频率可达 2.9 GHz,且内置核显(iGPU),板载 64GB eMMC 存储及 LPDDR4x 2933MHz(4GB/6GB/8GB),内置蓝牙和 Wi-Fi 模组,支持 USB 3.0、HDMI 视频输出、3.5mm 音频接口,1000Mbps 以太网口,完全可把它作为一台 mini 小电脑来看待,且其可集成一块 Arduino Leonardo 单片机,可外拓各种传感器模块。此外,其接口与 Jetson Nano 载板兼容,GPIO 与树莓派兼容,能够最大限度地复用树莓派、Jetson Nano 等生态资源,无论是摄像头物体识别,3D 打印,还是 CNC 实时插补控制都能稳定运行,不仅可作为边缘计算引擎用于人工智能产品验证、开发,也可作为域控核心用于机器人产品开发。

产品链接:首页_蓝蛙智能

关于 TDengine

TDengine 核心是一款高性能、集群开源、云原生的时序数据库(Time Series Database,TSDB),专为物联网、工业互联网、电力、IT 运维等场景设计并优化,具有极强的弹性伸缩能力。同时它还带有内建的缓存、流式计算、数据订阅等系统功能,能大幅减少系统设计的复杂度,降低研发和运营成本,是一个高性能、分布式的物联网、工业大数据平台。当前 TDengine 主要提供两大版本,分别是支持私有化部署的 TDengine Enterprise 以及全托管的物联网、工业互联网云服务平台 TDengine Cloud,两者在开源时序数据库 TDengine OSS 的功能基础上有更多加强,用户可根据自身业务体量和需求进行版本选择。

关于作者

冯伟,英特尔软件架构师,16 年软件研发经验,涵盖浏览器、计算机视觉、虚拟机等多个领域。2015 年加入英特尔,近年来专注于边缘计算、深度学习模型落地,以及时序数据分析等方向。


了解更多 TDengine Database的具体细节,可在GitHub上查看相关源代码。

相关文章:

TDengine+OpenVINO+AIxBoard,助力时序数据分类

时间序列数据分析在工业,能源,医疗,交通,金融,零售等多个领域都有广泛应用。其中时间序列数据分类是分析时序数据的常见任务之一。本文将通过一个具体的案例,介绍 Intel 团队如何使用 TDengine 作为基础软件…...

设计模式——16. 迭代器模式

1. 说明 迭代器模式(Iterator Pattern)是一种行为型设计模式,它用于提供一种访问聚合对象(如列表、数组、集合等)元素的统一接口,而不需要了解底层数据结构的具体实现。迭代器模式将遍历聚合对象的操作封装在一个独立的迭代器对象中,这样可以隔离遍历算法和数据结构,使…...

flink redis connector需要防止包冲突

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <dependency><groupId>org.apache.bahir</groupId><artifactId...

socket can查看详细信息 命令 ip -details -statistics link show can0

ip -details -statistics link show can0 ip -details link show can0 ip -statistics link show can0 也可以像第一行那样结合使用...

打造虚拟企业展厅,开启商务活动新时代

引言: 虚拟企业展厅是一种基于数字技术的全新商务模式&#xff0c;正在改变传统商务活动的方式&#xff0c;它比传统的企业展厅更便利&#xff0c;也更能凸显企业优势&#xff0c;展示企业风貌。 一&#xff0e;虚拟企业展厅的好处 1.打破地域限制 传统的商务活动通常需要参…...

03黑马店评-添加商户缓存和商户类型的缓存到Redis

商户查询缓存 什么是缓存 实际开发过程中数据量可以达到几千万,缓存可以作为避震器防止过高的数据访问猛冲系统,避免系统内的操作线程无法及时处理信息而瘫痪 缓存(Cache)就是数据交换的缓冲区(储存临时数据的地方),我们俗称的"缓存"实际就是缓冲区内的数据(一般从…...

LabVIEW玩转魔方

LabVIEW玩转魔方 使用LabVIEW创建一个3D魔方&#xff0c;并找出解谜题的秘密&#xff0c;给朋友留下深刻深刻的印象。游戏中内置的机制使每张脸都能独立转动&#xff0c;从而混合颜色。要解决难题&#xff0c;每个面必须是相同的纯色 魔方的奥秘在于它的简单性和不可解性。这是…...

大数据学习(1)-Hadoop

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博>主哦&#x…...

常用时序模型

常用时序模型 RNN (Recurrent Neural Network): 基本概念: RNN是一种可以处理序列数据的神经网络。它在每一时间步都接收一个新的输入,并将前一个时间步的隐藏状态作为额外的输入。问题: 它的主要问题是在处理长序列时遇到的梯度消失和梯度爆炸。这使得RNN难以捕获长期依赖关…...

阿里云/腾讯云国际站:私服服务器:什么是游戏虚拟服务器及用途讲解?

游戏虚拟服务器是一种新兴的技术&#xff0c;它可以为玩家提供更好的游戏体验。私服服务器它可以将游戏服务器的负载分散到多台服务器上&#xff0c;从而提高游戏的流畅度和稳定性。此外&#xff0c;游戏虚拟服务器还可以提供更多的游戏功能&#xff0c;比如游戏聊天室、游戏排…...

ssti 前置学习

python venv环境 可以把它想象成一个容器&#xff0c;该容器供你用来存放你的Python脚本以及安装各种Python第三方模块&#xff0c;容器里的环境和本机是完全分开的 创建venv环境安装flask #apt install python3.10-venv #cd /opt #python3 -m venv flask1 #cd /opt 选…...

uni-app:服务器端数据绘制echarts图标(renderjs解决手机端无法显示问题)

效果 代码 <template><view click"echarts.onClick" :prop"option" :change:prop"echarts.updateEcharts" id"echarts" class"echarts"></view> </template><script>export default {data()…...

Python集合魔法:解锁数据去重技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;涛哥聊Python 在Python编程的魔法世界中&#xff0c;有一种数据类型几乎被忽视&#xff0c;但却拥有强大的超能力&#xff0c;那就是集合&#xff08;Set&#xff09;。 集合是一种无序、唯一的数据类型&#xff0c;它以其独…...

flutter开发实战-inappwebview实现flutter与Javascript的交互JSBridge

flutter开发实战-inappwebview实现flutter与Javascript的交互JSBridge 在使用webview中&#xff0c;需要实现flutter与Javascript交互&#xff0c;在使用webview_flutter插件的时候&#xff0c;整理了一下webview与Javascript的交互JSBridge&#xff0c;具体可以查看 https:/…...

私有云盘:lamp部署nextcloud+高可用集群

目录 一、实验准备&#xff1a; 二、配置mariadb主从复制 三台主机下载mariadb 1&#xff09;主的操作 2&#xff09;从的操作 3&#xff09;测试数据是否同步 三、配置nfs让web服务挂载 1、安装 2、配置nfs服务器 3、配置web服务的httpd 4、测试 四、web 服务器 配…...

在线制作课程表

失业在家&#xff0c;开启一天一个应用的创作节奏&#xff0c;最近学了uniapp&#xff0c;特别想做点啥&#xff0c;正好家里小孩子要打印课程表&#xff0c;而且课程表还有调课的需求&#xff0c;就寻思做一个方便大家&#xff0c;到目前位置服务完全免费的&#xff0c;新鲜上…...

聊聊分布式架构06——[NIO入门]简单的Netty NIO示例

目录 Java NIO和Netty NIO比较 Java NIO&#xff1a; Netty&#xff1a; Netty NIO中的主要模块 Transport&#xff08;传输层&#xff09; Buffer&#xff08;缓冲区&#xff09; Codec&#xff08;编解码器&#xff09; Handler&#xff08;处理器&#xff09; Even…...

H5逆向之远程RPC

引言前一讲说过H5 怎么去抓包,逆向分析。其中说到RPC。这一节详细讲一下。有一种情况,JS 比较复杂,混淆的厉害。 这个时候就用到RPC。原理就是,hook web 浏览器,直接调用js 里边的方法。 Node 服务。为什么用到Node 服务,先来看下这架构 Node 对外提供各种接口,外部可以…...

解决Ubuntu18.04安装好搜狗输入法后无法打出中文的问题

首先下载安装 搜狗拼音输入法 &#xff0c;下载选择&#xff1a; x86_64 在ubuntu中设置 fcitx 最后发现安装好了&#xff0c;图标有了 &#xff0c;但是使用时不能输入中文&#xff0c;使用下面的命令解决&#xff1a; sudo apt install libqt5qml5 libqt5quick5 libqt5qu…...

Ubuntu LabelMe AI 识别

1.创建虚拟环境 conda create -n labelme python3.9 2.激活虚拟环境 conda activate labelme 3.安装labelme pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple pip install labelme -i ht…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...