AI实践与学习1_Milvus向量数据库实践与原理分析
前言
随着NLP预训练模型(大模型)以及多模态研究领域的发展,向量数据库被使用的越来越多。
在XOP亿级题库业务背景下,对于试题召回搜索单单靠着ES集群已经出现性能瓶颈,因此需要预研其他技术方案提高试题搜索召回率。
现一个方案就是使用Bert等模型提取试题题干特征,然后存储到向量数据库,检索试题先走向量数据库,拿到具体的试题ID等信息在走ES进行相似题召回,从而提高搜索的性能。需要考虑的就是特征提取的效率,Milvus的性能(比较吃服务器资源),然后进行评估。
本篇博客主要对Bert等模型以及主流的Milvus进行实践以及一些相关知识学习。
目录
- 概述
- 实践
- 原理分析
一、概述
https://milvus.io/
Milvus创建于2019年,其唯一目标是:存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大量嵌入向量。
作为一个专门设计用于处理输入向量查询的数据库,它能够索引万亿级的向量。与现有的关系数据库主要处理遵循预定义模式的结构化数据不同,Milvus是自底向上设计的,用于处理从非结构化数据转换而来的嵌入向量Embedding Vector。
基础概念
- 标量:无向量,只有数值大小没有方向
- 向量:区别于具体的单维度数值标量,可以认为是一条线,有多个数值表示。嵌入向量Embedding Vector是非结构化数据的特征抽象,例如电子邮件、物联网传感器数据、Instagram照片、蛋白质结构等等。从数学上讲,嵌入向量是一个浮点数数组或二进制数组。
- 向量范数:向量范数是指向量的大小或长度,计算向量范式可以用来衡量向量的大小、相似度等。计算方式分为
- L1:曼哈顿范数,将向量元素绝对值相加之和
- L2:欧几里得范数,将向量元素的平房和开更号
- 向量归一化:对向量进行归一化操作,以确保不同维度上的特征权重相等,避免某些维度对结果产生较大影响。可以采用L1、L2归一化,一种常用的归一化方法是使用 L2 范数进行单位化处理,即将向量除以其 L2 范数得到单位向量。
- 向量内积:点积、数量积,两个向量的点积就是吧对应位置元素点积之和,对于某个位置元素的点积a · b = |a|·|b|·cos v。其中||表示向量范数。点乘的几何意义是可以用来表征或计算两个向量之间的夹角,以及在b向量在a向量方向上的投影。
- 向量外积:外积(英语:Outer product),在线性代数中一般指两个向量的张量积,其结果为一矩阵;与外积相对,向量的外积是矩阵的克罗内克积的特殊情况。
- 余弦相似度:向量之间的夹角的余弦值,范围为[-1,1],越接近1表示两个向量越来约相似。
https://oi-wiki.org/math/linear-algebra/product/
数据模型相关概念
- Bitset:位图集合
- Channel:有两个不同的Channel在Milvus。它们是PChannel和VChannel。
- 每个PChannel对应一个日志存储主题。PChannel是物理Channel。每个PChannel对应一个日志存储主题。当Milvus集群启动时,默认情况下将分配一组256个PChannels来存储记录数据插入、删除和更新的日志。
- 每个VChannel对应于集合中的一个分片。VChannel代表逻辑信道。每个VChannel代表集合中的一个分片。每个集合将被分配一组VChannels,用于记录数据插入、删除和更新。VChannel在逻辑上是分离的,但在物理上共享资源。
- Collection:数据实体集合,类比表
- Schema:集合模式,模式是定义数据类型和数据属性的Meta信息。每个集合都有自己的集合模式,该模式定义集合的所有字段、自动ID(主键)分配启用和集合描述。集合架构中还包括定义字段的名称、数据类型和其他属性的字段架构。
- Entity:数据实体,每个实体会有一个主键。
- Field:数据字段,类型可以是数字、字符串、向量等结构化数据。
- Normalization:归一化,归一化是指转换嵌入(向量)以使其范数等于1的过程。如果使用内积(IP)来计算嵌入相似度,则所有嵌入都必须归一化。归一化后,内积等于余弦相似度。
- Vector index:向量索引是从原始数据中派生出来的重组数据结构,可以大大加速向量相似性搜索的过程。Milvus支持多种向量索引类型。
- Vector similarity search:向量相似性搜索是将向量与数据库进行比较以找到与目标搜索向量最相似的向量的过程。近似最近邻(ANN)搜索算法用于计算向量之间的相似性。
系统设计概念,作为云原生矢量数据库,Milvus通过设计将存储和计算分离。为了增强弹性和灵活性,Milvus中的所有组件都是无状态的。
- 接入层:提供访问的API
- 协调服务:大脑,将任务分配给工作节点
- 工作节点:四肢,执行大脑下发的DML命令
- 存储服务:骨骼,负责数据持久化。它包括Meta存储、日志代理和对象存储。
相关概念
- Message storage:消息存储是Milvus的日志存储引擎。
- Dependency:其他依赖,Milvus的依赖项包括etcd(存储Meta数据),MinIO或S3(对象存储)和Pulsar(管理快照日志)。
- Milvus cluster:在Milvus的集群部署中,服务由一组节点提供,以实现高可用性和易扩展性。
- Partition:分区是集合的物理划分。Milvus支持将收集数据划分为物理存储上的多个部分。这个过程称为分区,每个分区可以包含多个段。
- Segment:段是由Milvus自动创建的用于保存插入数据的数据文件。一个集合可以有多个段,一个段可以有多个实体。在向量相似性搜索期间,Milvus扫描每个片段并返回搜索结果。段可以是增长的,也可以是密封的。一个不断增长的段不断接收新插入的数据,直到它被密封。密封的段不再接收任何新数据,并将被刷新到对象存储中,留下新数据插入到新创建的增长段中。增长段将被密封,因为它持有的实体数量达到预定义的阈值,或者因为“增长”状态的跨度超过指定的限制。
- Sharding:分片是指将写操作分配到不同的节点(一个节点可以存储多个分区),以充分利用Milvus集群的并行计算潜力来写数据。默认情况下,单个集合包含两个分片。Milvus采用基于主键哈希的分片方法。Milvus的开发路线图包括支持更灵活的分片方法,如随机和自定义分片。
日志相关概念
- Log Broker:日志代理,支持回放的系统,负责流数据持久化、可靠的异步查询、事件通知和返回查询结果以及当工作节点故障恢复后增量数据的完整性。
- Log sequence:日志序列,记录更改集合状态的所有操作。
- Log snapshot:日志快照,二进制日志,一个较小的段单元,记录和处理对Milvus矢量数据库中数据的更新和更改。来自一个段的数据被持久化在多个binlog中。Milvus中有三种类型的binlog:InsertBinlog、DeleteBinlog和DDLBinlog。
- Log subscriber:日志订阅者订阅日志序列以更新本地数据,并以只读副本的形式提供服务。
二、实践
2.1、安装Milvus服务
因为是云原生的设计架构,安装可以使用k8s、docker compose安装:https://milvus.io/docs/prerequisite-helm.md,内存至少8g,配置挂在目录以及端口:https://milvus.io/docs/configure-docker.md
也可以使用普通安装方式
# Install Milvus
sudo yum https://github.com/milvus-io/milvus/releases/download/v2.0.0-pre-ga/milvus-2.0.0-preGA.1.el7.x86_64.rpm# Check Milvus status
sudo systemctl status milvus
sudo systemctl status milvus-etcd
sudo systemctl status milvus-minio
或者直接使用Python安装轻量级的Milvus Lite,Milvus Lite是Milvus的轻量级版本,可与Google Colab和Google Notebook无缝协作。https://milvus.io/docs/milvus_lite.md
// 安装docker以及docker-compose插件// 下载yml
wget https://github.com/milvus-io/milvus/releases/download/v2.3.3/milvus-standalone-docker-compose.yml -O docker-compose.yml// 启动
docker-compose up -d// 查看启动状态
docker compose ps// 关闭
docker compose down
2.2、安装可视化界面
https://github.com/zilliztech/attu,可以下载桌面版 or docker or k8s
2.3、使用Milvus
SDK支持Python、Java、Go、Nodejs,Python的SDK相对功能完善,其他语言的还在活跃的开发中,https://milvus.io/docs/install-pymilvus.md
1、使用Python SDK
// 安装依赖
python -m pip install pymilvus==2.3.3
2、使用Java SDK
https://github.com/milvus-io/milvus-sdk-java
https://milvus.io/api-reference/java/v2.3.x/About.md
<dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.3.3</version>
</dependency>
使用流程
- 创建数据库:与传统的数据库引擎类似,您也可以在Milvus中创建数据库,并将权限分配给某些用户来管理它们。然后,这些用户有权管理数据库中的集合。Milvus集群最多支持64个数据库。默认存在数据库default。
- 创建集合:集合由一个或多个分区组成。在创建新集合时,如果不指定分区数,Milvus会创建一个默认的partition分区_default。创建集合之前需要指定元数据,支持为标量设置默认值。创建集合可以指定分片数量,相比分区,分区通过指定分区名称来减少读取负载,而分片在多个服务器之间分散写入负载。
- 创建索引:需要指定为某向量字段、普通标量创建索引的类型(标量默认索引类型为字典树),额外参数传入聚类参数nlist。比如IVF_FLAT索引将向量数据划分为nlist聚类单元,然后比较目标输入向量与每个聚类中心之间的距离。根据系统设置为查询的聚类数(nprobe),仅基于目标输入和最相似聚类中的向量之间的比较返回相似性搜索结果-大大减少查询时间。
- 加载集合:将集合、集合分区加载进内存,Milvus2.1允许用户将集合按照分区加载为多个副本,以利用额外查询节点的CPU和内存资源。此功能可提高整体QPS和吞吐量,无需额外硬件。
- 插入数据:可以指定partition_name将数据插入指定分区,可以将文件中的实体数据插入集合,支持manualCompaction手动压缩数据
- 搜索数据:根据创建的向量索引以及指定的相似度度量参数(IP、L2等)来进行相似性索引、标量搜素。
数据字段类型
Type | Description |
---|---|
None | For internal usage. |
Bool | Boolean. |
Int8 | Integer number stored with 8 bit. |
Int16 | Integer number stored with 16 bit. |
Int32 | Integer number stored with 32 bit. |
Int64 | Integer number stored with 64 bit. |
Float | Floating-point numbers. |
Double | 64-bit IEEE 754 floating point numbers. |
String | Reserved. Do not use this. |
VarChar | Variable-length string with a limit on the maximum length. |
BinaryVector | Binary vector. Each dimension is represented by 1 bit. |
FloatVector | Float vector. Each dimension is represented by 1 float (4 bits) value. |
动态数据类型
为了使Milvus插入数据更加灵活,对于之前创建的集合可以指定动态元数据模式。
动态模式使用户能够将具有新字段的实体插入到Milvus集合中,而无需修改现有模式。这意味着用户可以在不知道集合的完整架构的情况下插入数据,并且可以包括尚未定义的字段。
索引类型
ANN紧邻搜索的索引实现的几种方式
- Tree-based index
- Graph-based index
- Hash-based index
- Quantization-based index
在Milvus中根据数据类型将向量索引种类分为
- 内存索引
- 浮点嵌入索引
- 二进制嵌入索引
- 标量前缀索引
- 磁盘索引:默认启用DiskANN,可选择关闭。
https://milvus.io/api-reference/java/v2.3.x/Misc/IndexType.md
INVALID | For internal usage. |
---|---|
FLAT | Only for FloatVector type field. |
IVF_FLAT | Only for FloatVector type field. |
IVF_SQ8 | Only for FloatVector type field. |
IVF_PQ | Only for FloatVector type field. |
HNSW | Only for FloatVector type field. |
ANNOY | Only for FloatVector type field. |
DISKANN | Only for FloatVector type field. |
BIN_FLAT | Only for BinaryVector type field. |
BIN_IVF_FLAT | Only for BinaryVector type field. |
TRIE | Only for VARCHAR type field. |
聚类近似搜索
其中IVF_FLAT、IVF_SQ8、IVF_PQ、BIN_FLAT等索引创建的时候支持 nlist,查询时候支持nporbe参数,将向量数据划分为nlist聚类单元,然后比较目标输入向量与每个聚类中心之间的距离。根据系统设置为查询的聚类数(nprobe),仅基于目标输入和最相似聚类中的向量之间的比较返回相似性搜索结果-大大减少查询时间。
聚类单元是指进行聚类分析时,将数据点划分为不同的簇或群组的基本单位。每个聚类单元代表一个特定的数据集合,其内部的数据点在某种程度上相似。聚类算法通过计算各个数据点之间的距离或相似性来确定如何将它们分配到不同的聚类单元中。
聚类单元可以用于对数据进行分类、识别隐藏的模式和结构,并产生有关数据集的洞察力。利用聚类单元可以将复杂的数据集简化为更易理解和解释的形式,同时可作为进一步分析、预测和决策制定的基础。
相似度量规则
Type | Description |
---|---|
INVALID | For internal usage. |
L2 | Euclidean distance. Only for float vectors. |
IP | Inner product. Only for normalized float vectors. |
COSINE | Cosine Similarity. Only for normalized float vectors. |
HAMMING | Only for binary vectors. |
JACCARD | Only for binary vectors. |
TANIMOTO | Only for binary vectors. |
代码demo
具体的API参考官网文档下面举例向量+标量的混合搜索demo
milvusClient.loadCollection(LoadCollectionParam.newBuilder().withCollectionName("book").build()
);final Integer SEARCH_K = 2;
final String SEARCH_PARAM = "{\"nprobe\":10, \”offset\”:5}";
List<String> search_output_fields = Arrays.asList("book_id");
List<List<Float>> search_vectors = Arrays.asList(Arrays.asList(0.1f, 0.2f));SearchParam searchParam = SearchParam.newBuilder().withCollectionName("book").withMetricType(MetricType.L2).withOutFields(search_output_fields).withTopK(SEARCH_K).withVectors(search_vectors).withVectorFieldName("book_intro").withExpr("word_count <= 11000").withParams(SEARCH_PARAM).build();
R<SearchResults> respSearch = milvusClient.search(searchParam);
Python SDK demo
// 执行demo代码
# hello_milvus.py demonstrates the basic operations of PyMilvus, a Python SDK of Milvus.
# 1. connect to Milvus
# 2. create collection
# 3. insert data
# 4. create index
# 5. search, query, and hybrid search on entities
# 6. delete entities by PK
# 7. drop collection
import timeimport numpy as np
from pymilvus import (connections,utility,FieldSchema, CollectionSchema, DataType,Collection,
)fmt = "\n=== {:30} ===\n"
search_latency_fmt = "search latency = {:.4f}s"
num_entities, dim = 3000, 8#################################################################################
# 1. connect to Milvus
# Add a new connection alias `default` for Milvus server in `localhost:19530`
# Actually the "default" alias is a buildin in PyMilvus.
# If the address of Milvus is the same as `localhost:19530`, you can omit all
# parameters and call the method as: `connections.connect()`.
#
# Note: the `using` parameter of the following methods is default to "default".
print(fmt.format("start connecting to Milvus"))
connections.connect("default", host="localhost", port="19530")has = utility.has_collection("hello_milvus")
print(f"Does collection hello_milvus exist in Milvus: {has}")#################################################################################
# 2. create collection
# We're going to create a collection with 3 fields.
# +-+------------+------------+------------------+------------------------------+
# | | field name | field type | other attributes | field description |
# +-+------------+------------+------------------+------------------------------+
# |1| "pk" | VarChar | is_primary=True | "primary field" |
# | | | | auto_id=False | |
# +-+------------+------------+------------------+------------------------------+
# |2| "random" | Double | | "a double field" |
# +-+------------+------------+------------------+------------------------------+
# |3|"embeddings"| FloatVector| dim=8 | "float vector with dim 8" |
# +-+------------+------------+------------------+------------------------------+
fields = [FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=False, max_length=100),FieldSchema(name="random", dtype=DataType.DOUBLE),FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]schema = CollectionSchema(fields, "hello_milvus is the simplest demo to introduce the APIs")print(fmt.format("Create collection `hello_milvus`"))
hello_milvus = Collection("hello_milvus", schema, consistency_level="Strong")################################################################################
# 3. insert data
# We are going to insert 3000 rows of data into `hello_milvus`
# Data to be inserted must be organized in fields.
#
# The insert() method returns:
# - either automatically generated primary keys by Milvus if auto_id=True in the schema;
# - or the existing primary key field from the entities if auto_id=False in the schema.print(fmt.format("Start inserting entities"))
rng = np.random.default_rng(seed=19530)
entities = [# provide the pk field because `auto_id` is set to False[str(i) for i in range(num_entities)],rng.random(num_entities).tolist(), # field random, only supports listrng.random((num_entities, dim)), # field embeddings, supports numpy.ndarray and list
]insert_result = hello_milvus.insert(entities)# 测试打印
for x in range(3):print(entities[x])hello_milvus.flush()
print(f"Number of entities in Milvus: {hello_milvus.num_entities}") # check the num_entities################################################################################
# 4. create index
# We are going to create an IVF_FLAT index for hello_milvus collection.
# create_index() can only be applied to `FloatVector` and `BinaryVector` fields.
print(fmt.format("Start Creating index IVF_FLAT"))
index = {"index_type": "IVF_FLAT","metric_type": "L2","params": {"nlist": 128},
}hello_milvus.create_index("embeddings", index)################################################################################
# 5. search, query, and hybrid search
# After data were inserted into Milvus and indexed, you can perform:
# - search based on vector similarity
# - query based on scalar filtering(boolean, int, etc.)
# - hybrid search based on vector similarity and scalar filtering.
## Before conducting a search or a query, you need to load the data in `hello_milvus` into memory.
print(fmt.format("Start loading"))
hello_milvus.load()# -----------------------------------------------------------------------------
# search based on vector similarity
print(fmt.format("Start searching based on vector similarity"))
vectors_to_search = entities[-1][-2:]
search_params = {"metric_type": "L2","params": {"nprobe": 10},
}start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, output_fields=["random"])
end_time = time.time()for hits in result:for hit in hits:print(f"hit: {hit}, random field: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))# -----------------------------------------------------------------------------
# query based on scalar filtering(boolean, int, etc.)
print(fmt.format("Start querying with `random > 0.5`"))start_time = time.time()
result = hello_milvus.query(expr="random > 0.5", output_fields=["random", "embeddings"])
end_time = time.time()print(f"query result:\n-{result[0]}")
print(search_latency_fmt.format(end_time - start_time))# -----------------------------------------------------------------------------
# pagination
r1 = hello_milvus.query(expr="random > 0.5", limit=4, output_fields=["random"])
r2 = hello_milvus.query(expr="random > 0.5", offset=1, limit=3, output_fields=["random"])
print(f"query pagination(limit=4):\n\t{r1}")
print(f"query pagination(offset=1, limit=3):\n\t{r2}")# -----------------------------------------------------------------------------
# hybrid search
print(fmt.format("Start hybrid searching with `random > 0.5`"))start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, expr="random > 0.5", output_fields=["random"])
end_time = time.time()for hits in result:for hit in hits:print(f"hit: {hit}, random field: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))###############################################################################
# 6. delete entities by PK
# You can delete entities by their PK values using boolean expressions.
ids = insert_result.primary_keysexpr = f'pk in ["{ids[0]}" , "{ids[1]}"]'
print(fmt.format(f"Start deleting with expr `{expr}`"))result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"query before delete by expr=`{expr}` -> result: \n-{result[0]}\n-{result[1]}\n")hello_milvus.delete(expr)result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"query after delete by expr=`{expr}` -> result: {result}\n")###############################################################################
# 7. drop collection
# Finally, drop the hello_milvus collection
# print(fmt.format("Drop collection `hello_milvus`"))
# utility.drop_collection("hello_milvus")
3、Bert实践
使用NLP模型对文本进行特征提,将特征向量存储到Milvus数据库,然后进行相似搜索。
参考:
-
https://www.cnblogs.com/henx/p/13802855.html
-
https://zhuanlan.zhihu.com/p/567922534
// TODO
相关文章:

AI实践与学习1_Milvus向量数据库实践与原理分析
前言 随着NLP预训练模型(大模型)以及多模态研究领域的发展,向量数据库被使用的越来越多。 在XOP亿级题库业务背景下,对于试题召回搜索单单靠着ES集群已经出现性能瓶颈,因此需要预研其他技术方案提高试题搜索召回率。…...

3Dexcite deltgen 2022x 新功能
3DEXCITE DELTAGEN 2022x 现已发布,此次新版发布包含 DELTAGEN 2022x,DELTAGEN MARKETING SUITE 2022x,DELTAGEN XPLORE 2022x,以及软件开发工具包 SDK FOR DELTAGEN 2022x 版本。赶快来获取最新 DG 版本,了解新增内容…...

代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形 文章链接:柱状图中最大的矩形 视频链接:柱状图中最大的矩形 1. LeetCode 84. 柱状图中最大的矩形 1.1 思路 本题是给一个数组形象得画出图后求矩形的最大面积是多少。本题和42. 接雨水…...

【2023云栖】陈守元:阿里云开源大数据产品年度发布
本文根据 2023 云栖大会演讲实录整理而成,演讲信息如下: 演讲人:陈守元 | 阿里云计算平台事业部开源大数据产品总监 演讲主题:阿里云开源大数据产品年度发布 随着云计算的不断发展,未来数据处理和应用的趋势将围绕C…...

Element UI 禁用数字输入框组件添加鼠标滚动事件
Element UI 禁用数字输入框组件添加鼠标滚动事件 <el-input type"number" mousewheel.native.prevent DOMMouseScroll.native.prevent :min"0" onkeyup"this.valuethis.value.match(/\d\.?\d{0,2}/);"v-model"form.threeYearDevelop…...

担忧CentOS停服?KeyarchOS系统来支撑
担忧CentOS停服?KeyarchOS系统来支撑 近年发生的“微软黑屏门”、“微软操作系统停更”等安全事件,敲响了我国 IT 产业的警钟,建立由我国主导的 IT 产业生态尤为迫切。对此,我国信息技术应用创新行业乘势而起,旨在通过…...

聚观早报 |联想集团Q2财季业绩;小鹏汽车Q3营收
【聚观365】11月17日消息 联想集团Q2财季业绩 小鹏汽车Q3营收 微软发布两款自研AI芯片 FAA批准SpaceX再次发射星际飞船 2023 OPPO开发者大会 联想集团Q2财季业绩 全球数字经济领导企业联想集团公布截至2023年9月30日的2023/24财年第二财季业绩:整体营收达到10…...

SAP ABAP权限控制中常用TCODE
权限控制中的几个TCODE 1.创建新的权限对象并在程序中使用 利用SU21创建权限对象Z_TEST,在程序中检查授权。 检查的代码如下: AUTHORITY-CHECK OBJECT ‘Z_TEST’ID ‘ACTION’ FIELD ‘44′ID ‘BUKRS’ FIELD DUMMY .IF sy-subrc NE 0.MESSAGE e00…...

云计算赛项容器云2023搭建
部署容器云平台[5 分] 使 用 OpenStack 私 有 云 平 台 创 建 两 台 云 主 机 , 云 主 机 类 型 使 用 4vCPU/12G/100G 类型,分别作为 Kubernetes 集群的 Master 节点和 node 节点, 然后完成 Kubernetes 集群的部署,并完成 Istio …...

11.1 文件拷贝移动与删除
在编程中,针对磁盘与目录的操作也是非常重要的,本章将重点介绍如何实现针对文件目录与磁盘的操作方法,其中包括了删除文件,文件拷贝,文件读写,目录遍历输出,遍历磁盘容量信息,磁盘格…...

redhat下使用CentOS yum源,并安装docker
一、安装yum源 1.卸载yum # 查看系统自身安装的yum软件包 rpm -qa | grep yum # 卸载软yum件包 rpm -e 软件包名称 --nodeps #可以使用简称如 rpm -e yum-* --nodeps2. 安装yum [rootbogon ~]# rpm -ivh --nodeps https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/Pa…...

基于单片机体温脉搏检测控制系统及源程序
一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20传感器检测体温。 3、红外对接管采集心率值送到液晶1602显示。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 /lcd1602初始化设置*/ void init_1602() { write_com(0x38); //显示…...

MyBatis-Plus逻辑删@TableLogic
MyBatis-Plus逻辑删除指,在数据库中删除数据时,并没有真正的删除,而是更改指定字段的值,这个字段的值可以为0或1,0代表未删除,1代表已删除,所以delete操作实际上是update操作,查询操作也是要加w…...

本地私域线上线下 线上和线下的小程序
私域商城是一种新型的零售模式,它将传统的线下实体店与线上渠道相结合,通过会员、营销、效率等方式,为消费者提供更加便利和高效的购物体验。私域商城的发展趋势表明,它将成为未来零售业的重要模式,引领零售业的创新和…...

【前端学java】java中的Object类(8)
往期回顾: 【前端学java】JAVA开发的依赖安装与环境配置 (0)【前端学 java】java的基础语法(1)【前端学java】JAVA中的packge与import(2)【前端学java】面向对象编程基础-类的使用 (…...

TensorFlow实战教程(二十六)-什么是生成对抗网络GAN?基础原理和代码普及
从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章分享了Keras实现经典的深度学习文本分类算法,包括LSTM、BiLSTM、BiLSTM+Attention和CNN、TextCNN。这篇文章将详细介绍生成对抗网络GAN的基础知识,包括什么是GAN、常用算法(CGAN、DCGAN、…...

IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -Maven依赖管理,版本号管理,继承和聚合
第一章 Maven的依赖管理 1.1 依赖范围 依赖语法:<scope> compile【默认值】:在main、test、Tomcat【服务器】下均有效。test:只能在test目录下有效 junit provided:在main、test下均有效,Tomcat【服务器】无效…...

OpenVPN Connect使用连接公网VPN服务器实现内网穿透
安装并运行OpenVPN Connect 点击AGREE 添加配置.OVPN文件 点击连接 连接成功 两个内网主机通过公网VPN穿透...

Redis(集合Set和有序集合SortedSet)
SET集合中的元素是不允许重复的,SET中的命令都是以S开头的。 使用SADD 在集合中添加元素,使用SMEMBERS查看元素。 当添加重复元素时,会返回0代表添加失败,查询还是就Redis一个元素。 使用SISMEMBER查询元素是否在集合中ÿ…...

黔院长 | 《黄帝内经》——奇病论!
世界之大,无奇不有,就连病症也是如此,近年更是新增各类奇形怪状的疾病,今天就带大家一同走进《黄帝内经》的奇病篇,一起了解部分罕见的疾病及其特征! “奇病论”当中提到,有些妇女怀孕到第九个月…...

手撕单链表(C语言)
目录 1.单链表的物理结构 2.头文件的实现 3.SList.c文件的实现 3.1尾插、创建节点 3.2打印 3.3头插 3.4尾删 3.5头删 3.6查找 3.7指定位置之前插入数据 3.8指定位置之后插入数据 3.9删除指定位置节点 3.10删除pos之后的节点 3.11销毁链表 4 所有的代码 1.单链表的物理结构 众所…...

60 权限提升-MYMSORA等SQL数据库提权
目录 数据库应用提权在权限提升中的意义WEB或本地环境如何探针数据库应用数据库提权权限用户密码收集等方法目前数据库提权对应的技术及方法等 演示案例Mysql数据库提权演示-脚本&MSF1.UDF提权知识点: (基于MYSQL调用命令执行函数)读取数据库存储或备份文件 (了…...

【C++上层应用】2. 预处理器
文章目录 【 1. #define 预处理 】【 2. #ifdef、#if 条件编译 】2.1 #ifdef2.2 #if2.3 实例 【 3. # 和 ## 预处理 】3.1 # 替换预处理3.2 ## 连接预处理 【 4. 预定义宏 】 预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是…...

ISP--Black Level Correction(黑电平矫正)
图像的每一个像素点都是由一个光电二极管控制的,由二极管将电信号,转换为数字信号。 那么,我们知道了,图像的像素值是与电信号强度相关的。但是,我们得知道,每一个光电二极管要想工作,都得有一定…...

python项目源码基于django的宿舍管理系统dormitory+mysql数据库文件
基于Django的宿舍管理系统 运行效果 个人亲自制作python项目源码基于django的宿舍管理系统dormitorymysql数据库文件 1. 介绍 宿舍管理系统是一个基于Django框架开发的项目,旨在简化和优化宿舍管理的流程。该系统包括学生和管理员两个角色,学生可以通过…...

Java和 JS 的10大不同之处,你清楚吗?
还记得刚开始学习编程时,我就在想:“Java和JavaScript是同一种语言吗?”。就是因为看到它们名称中都带“java”,所以才会误以为它们有关系。实际上,它们并没有太大的联系。 这两者的关系,就和英语与斯瓦希…...

vue动态配置路由
文章目录 前言定义项目页面格式一、vite 配置动态路由新建 /router/utils.ts引入 /router/utils.ts 二、webpack 配置动态路由总结如有启发,可点赞收藏哟~ 前言 项目中动态配置路由可以减少路由配置时间,并可减少配置路由出现的一些奇奇怪怪的问题 路由…...

科技云报道:全球勒索攻击创历史新高,如何建立网络安全的防线?
科技云报道原创。 最简单的方式,往往是最有效的,勒索软件攻击就属于这类。 近两年,随着人类社会加速向数字世界进化,勒索软件攻击成为网络安全最为严重的威胁之一。今年以来,勒索软件攻击在全球范围内呈现快速上升态…...

通过bat命令启动jar后缀软件
要通过bat命令启动一个带有.jar后缀的软件,可以使用以下的bat文件命令: echo off java -jar "路径\文件名.jar" pause请将路径\文件名.jar替换为实际的文件路径和文件名。例如,如果你的文件位于C:\Program Files\MyApp\app.jar&am…...

Python选择排序和冒泡排序算法
选择排序和冒泡排序都是常见的排序算法。以下是这两种算法的Python实现: 选择排序(Selection Sort) 选择排序的基本思想是在未排序的序列中找到最小(或最大)元素,存放到排序序列的起始位置,然…...