Elasticsearch:崭新的打分机制 - Learning To Rank (LTR)

警告:“学习排名 (Learning To Rank)” 功能处于技术预览版,可能会在未来版本中更改或删除。 Elastic 将努力解决任何问题,但此功能不受官方 GA 功能的支持 SLA 的约束。

注意:此功能是在版本 8.12.0 中引入的,并且仅适用于某些订阅级别。 有关更多信息,请参阅 https://www.elastic.co/subscriptions。

Learning To Rank (LTR) 使用经过训练的机器学习(ML)模型来构建搜索引擎的排名函数。通常,该模型用作第二阶段的重新排序器,以提高简单的第一阶段检索算法返回的搜索结果的相关性。LTR 函数接收文档列表和搜索上下文作为输入,并输出排名后的文档:

搜索上下文

除了需要排序的文档列表之外,LTR 函数还需要一个搜索上下文。通常,这个搜索上下文至少包括用户提供的搜索词(上述示例中的 text_query)。搜索上下文还可以提供排名模式中使用的其他信息。这可能是关于执行搜索的用户的信息(例如人口统计数据、地理位置或年龄);关于查询的信息(例如查询长度);或者在查询上下文中的文档信息(例如标题字段的得分)。

评判列表 - judgment list

LTR 模型通常是基于一个评判列表进行训练的,这是一组带有相关性等级的查询和文档的集合。评判列表可以由人工或机器生成:通常通过行为分析数据来填充,并经常有人工监督。评判列表确定了给定搜索查询的结果的理想排序。LTR 的目标是使模型尽可能地符合新查询和文档的评判列表排名。

评判列表是训练模型的主要输入。它包括一个数据集,该数据集包含查询和文档的配对,以及它们对应的相关性标签。相关性判断通常是二元的(相关/不相关)或更细致的标签,例如从0(完全不相关)到4(高度相关)的等级。下面的示例使用了分级的相关性判断。

注意事项:评判列表

虽然评判列表可以由人工手动创建,但也有技术可利用用户参与数据(如点击或转化)自动构建评判列表。

评判列表的数量和质量将极大地影响 LTR 模型的整体性能。在构建评判列表时,应非常注意以下几个方面:

  • 大多数搜索引擎可以使用不同类型的查询进行搜索。例如,在电影搜索引擎中,用户可以按照电影标题、演员或导演进行搜索。在评判列表中,保持每种查询类型的示例数量平衡非常重要。这可以防止过度拟合,并使模型能够在所有查询类型上有效地泛化。
  • 用户通常会提供更多的正面示例而不是负面示例。通过平衡正面和负面示例的数量,可以帮助模型更准确地区分相关和不相关的内容。

特征提取 - feature extraction

仅有查询和文档对并不足以提供足够的信息来训练用于 LTR 的机器学习模型。评判列表中的相关性评分依赖于多种属性或特征。必须提取这些特征,以确定各种组件如何组合以确定文档的相关性。评判列表加上提取的特征构成了 LTR 模型的训练数据集。

这些特征分为三个主要类别:

  • 文档特征:这些特征直接从文档属性中派生。例如:电子商务商店中的产品价格。
  • 查询特征:这些特征直接从用户提交的查询中计算得出。例如:查询中的单词数量。
  • 查询-文档特征:用于提供有关查询上下文中的文档信息的特征。例如:标题字段的 BM25 分数。

为了准备训练数据集,将这些特征添加到评判列表中:

在 Elasticsearch 中,可以使用模板化查询来提取特征,这样做可以在构建训练数据集以及在查询时进行推断。以下是一个模板化查询的示例:

[
  {
    "query_extractor": {
      "feature_name": "title_bm25",
      "query": { "match": { "title": "{{query}}" } }
    }
  }
]

模型

LTR 的核心当然是一个机器学习(ML)模型。该模型使用上面描述的训练数据结合一个目标进行训练。在 LTR 的情况下,目标是根据一个排序度量标准(如 nDCG 或 MAP)在最佳方式下对结果文档进行排序,考虑到一个评判列表 (judgment list)。该模型仅依赖于来自训练数据的特征和相关性标签。

LTR 领域正在快速发展,许多方法和模型类型正在进行实验。在实践中,Elasticsearch 专门依赖于梯度提升决策树(gradient boosted decision tree - GBDT)模型进行 LTR 推断。

请注意,Elasticsearch 支持模型推断,但训练过程必须在 Elasticsearch 之外进行,使用 GBDT 模型。在今天使用的最受欢迎的 LTR 模型中,LambdaMART 在低推断延迟的情况下提供了强大的排名性能。它依赖于 GBDT 模型,因此非常适合用于 Elasticsearch 中的 LTR。

XGBoost 是一个众所周知的库,提供了 LambdaMART 的实现,使其成为 LTR 的热门选择。我们在 eland 中提供了一些辅助工具,以便将训练的 XBGRanker 模型作为你在 Elasticsearch 中的 LTR 模型进行集成。

部署和管理学习排名模型

使用 Eland 训练和部署模型

通常,XGBoost 模型训练过程使用标准的 Python 数据科学工具,如 Pandas 和 scikit-learn。

我们在 elasticsearch-labs 仓库中开发了一个示例 notebook。这个交互式 Python 笔记本详细介绍了端到端的模型训练和部署工作流程。

我们强烈建议在你的工作流程中使用 eland,因为它提供了在 Elasticsearch 中使用 LTR 所需的重要功能。使用 eland 可以:

  • 配置特征提取
  • 提取用于训练的特征
  • 在 Elasticsearch 中部署模型

在 Eland 中配置特征提取

特征提取器是使用模板化查询定义的。Eland 提供了 eland.ml.ltr.QueryFeatureExtractor 来直接在 Python 中定义这些特征提取器:

from eland.ml.ltr import QueryFeatureExtractor

feature_extractors=[
    # We want to use the score of the match query for the title field as a feature:
    QueryFeatureExtractor(
        feature_name="title_bm25",
        query={"match": {"title": "{{query}}"}}
    ),
    # We can use a script_score query to get the value
    # of the field rating directly as a feature:
    QueryFeatureExtractor(
        feature_name="popularity",
        query={
            "script_score": {
                "query": {"exists": {"field": "popularity"}},
                "script": {"source": "return doc['popularity'].value;"},
            }
        },
    ),
    # We can execute a script on the value of the query
    # and use the return value as a feature:
    QueryFeatureExtractor(
        feature_name="query_length",
        query={
            "script_score": {
                "query": {"match_all": {}},
                "script": {
                    "source": "return params['query'].splitOnToken(' ').length;",
                    "params": {
                        "query": "{{query}}",
                    }
                },
            }
        },
    ),
]

一旦定义了特征提取器,它们就会被封装在一个 eland.ml.ltr.LTRModelConfig 对象中,以便在后续的训练步骤中使用:

from eland.ml.ltr import LTRModelConfig

ltr_config = LTRModelConfig(feature_extractors)

提取特征进行训练

构建数据集是训练过程中的一个关键步骤。这包括提取相关特征并将它们添加到你的判定列表中。我们推荐使用 Eland 的 eland.ml.ltr.FeatureLogger 辅助类来完成此过程。

from eland.ml.ltr import FeatureLogger

# Create a feature logger that will be used to query {es} to retrieve the features:
feature_logger = FeatureLogger(es_client, MOVIE_INDEX, ltr_config)

FeatureLogger 提供了一个 extract_features 方法,它使您能够从你的判定列表中为一系列特定文档提取特征。同时,你可以传递先前定义的查询参数给特征提取器:

feature_logger.extract_features(
    query_params={"query": "foo"},
    doc_ids=["doc-1", "doc-2"]
)

我们的示例 notebook 解释了如何使用 FeatureLogger 构建训练数据集,通过向判定列表添加特征。

有关特征提取需要注意的地方:

  • 我们强烈建议不要自行实现特征提取。在特征提取方面保持一致性非常重要,即在训练环境和 Elasticsearch 中进行推断时。通过使用与 Elasticsearch 开发和测试一起的 eland 工具,你可以确保它们之间保持一致的功能。
  • 特征提取是通过在 Elasticsearch 服务器上执行查询来执行的。这可能会给你的集群带来很大压力,特别是当你的判定列表包含很多示例或具有许多特征时。我们的特征记录器实现旨在最小化发送到服务器的搜索请求数量并减少负载。但是,最好使用与任何面向用户的生产流量隔离的 Elasticsearch 集群构建您的训练数据集。

将你的模型部署到 Elasticsearch 中

一旦你的模型训练完成,你就可以将其部署到你的 Elasticsearch 集群中。你可以使用 Eland 的 MLModel.import_ltr_model 方法:

from eland.ml import MLModel

LEARNING_TO_RANK_MODEL_ID="ltr-model-xgboost"

MLModel.import_ltr_model(
    es_client=es_client,
    model=ranker,
    model_id=LEARNING_TO_RANK_MODEL_ID,
    ltr_model_config=ltr_config,
    es_if_exists="replace",
)

此方法会将训练后的模型以及学习排名配置(包括特征提取)序列化成 Elasticsearch 能够理解的格式。然后,该模型通过 Create Trained Models API 部署到 Elasticsearch。

目前支持以下类型的模型用于 Elasticsearch 的学习排名(LTR):

  • DecisionTreeRegressor
  • RandomForestRegressor
  • LGBMRegressor
  • XGBRanker
  • XGBRegressor

未来将支持更多类型的模型。

学习排名模型管理

一旦你的模型在 Elasticsearch 中部署,你可以使用 trained model APIs 来管理它。现在,你已经准备好在搜索时使用你的 LTR 模型作为重新评分器。

Demo

安装 Elasticsearch 及 Kibana

接下来,我们将使用一个 Python notebook 来进行展示。

如果你还没有安装好自己的 Elasticsearch 及 Kibana,请参考如下的链接来进行安装:

  • 如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch
  • Kibana:如何在 Linux,MacOS 及 Windows上安装 Elastic 栈中的 Kibana

在安装的时候,我们选择 Elastic Stack 8.x 来进行安装。

在首次启动 Elasticsearch 的时候,我们可以看到如下的输出:

我们需要记住超级用户 elastic 的密码。

为了能够使得 LTR 正常工作(请参考 订阅 | Elastic Stack 产品和支持 | Elastic),我们需要启动白金试用功能:

下载代码并启动 jupyter notebook

我们在地址 GitHub - liu-xiao-guo/elasticsearch-labs: Notebooks & Example Apps for Search & AI Applications with Elasticsearch 下载代码:

git clone https://github.com/liu-xiao-guo/elasticsearch-labs

然后我们进入到如下的目录并启动 jupyter:

$ pwd
/Users/liuxg/python/elasticsearch-labs/notebooks/search
$ ls
00-quick-start.ipynb                README.md
01-keyword-querying-filtering.ipynb _nbtest.setup.ipynb
02-hybrid-search.ipynb              _nbtest.teardown.03-ELSER.ipynb
03-ELSER.ipynb                      _nbtest.teardown.ipynb
04-multilingual.ipynb               articles.json
05-query-rules.ipynb                data.json
06-synonyms-api.ipynb               movies.json
08-learning-to-rank.ipynb           query-rules-data.json
Makefile                            sample_data
$ jupyter notebook

我们选择 08-learning-to-rank.ipynb  文件来进行。

我们在当前的目录下创建一个叫做 .env 的文件:

$ pwd
/Users/liuxg/python/elasticsearch-labs2/notebooks/search
$ ls
00-quick-start.ipynb                _nbtest.setup.ipynb
01-keyword-querying-filtering.ipynb _nbtest.teardown.03-ELSER.ipynb
02-hybrid-search.ipynb              _nbtest.teardown.ipynb
03-ELSER.ipynb                      articles.json
04-multilingual.ipynb               data.json
05-query-rules.ipynb                http_ca.crt
06-synonyms-api.ipynb               movies.json
07-inference.ipynb                  query-rules-data.json
08-learning-to-rank.ipynb           sample_data
README.md
$ ls .env
.env
$ cat .env
ES_USER="elastic"
ES_PASSWORD="wKWgjujKB4gOOKw4Zk=E"
ES_ENDPOINT="localhost"

如上所示,我们可以根据自己的 Elasticsearch 的配置来定义上面的 ES_USER, ES_PASSWORD 及 ES_EDNPINT。

我们同时需要拷贝 Elasticsearch 的证书到当前的目录下:

$ pwd
/Users/liuxg/python/elasticsearch-labs/notebooks/search
$ cp ~/elastic/elasticsearch-8.13.2/config/certs/http_ca.crt .
$ ls http_ca.crt 
http_ca.crt

这样我们的配置就完成了。

运行 notebook

安装所需的包

!pip3 install -qU elasticsearch eland "eland[scikit-learn]" xgboost tqdm

from tqdm import tqdm

# Setup the progress bar so we can use progress_apply in the notebook.
tqdm.pandas()

配置你的 Elasticsearch 部署

import os
from dotenv import load_dotenv
from elasticsearch import Elasticsearch

load_dotenv()

ES_USER = os.getenv("ES_USER")
ES_PASSWORD = os.getenv("ES_PASSWORD")
ES_ENDPOINT = os.getenv("ES_ENDPOINT")
 
url = f"https://{ES_USER}:{ES_PASSWORD}@{ES_ENDPOINT}:9200"

print(url)

es_client = Elasticsearch(
    hosts=[url], 
    ca_certs = "./http_ca.crt", 
    verify_certs = True
    )

print(es_client.info())

配置数据集

我们将使用源自 MSRD(电影搜索排名数据集)的数据集。

该数据集可在此处获取并包含以下文件:

  • movie_corpus.jsonl.gz:要索引的电影数据集。
  • movie_judgements.tsv.gz:一组查询的相关性判断的判断列表。
  • movie_index_settings.json:要应用于文档和索引的设置。
from urllib.parse import urljoin

#DATASET_BASE_URL = "https://raw.githubusercontent.com/elastic/elasticsearch-labs/main/notebooks/search/sample_data/learning-to-rank/"
DATASET_BASE_URL = "file:/Users/liuxg/python/elasticsearch-labs/notebooks/search/sample_data/learning-to-rank/"

CORPUS_URL = urljoin(DATASET_BASE_URL, "movies-corpus.jsonl.gz")
JUDGEMENTS_FILE_URL = urljoin(DATASET_BASE_URL, "movies-judgments.tsv.gz")
INDEX_SETTINGS_URL = urljoin(DATASET_BASE_URL, "movies-index-settings.json")

我们需要根据自己的文档位置对上面的文件路径进行修改。

导入文档语料库

这一步会将语料库的文档导入到 movies 索引中。

文档包含以下字段:

Field nameDescription
idId of the document
titleMovie title
overviewA short description of the movie
actorsList of actors in the movies
directorDirector of the movie
charactersList of characters that appear in the movie
genresGenres of the movie
yearYear the movie was released
budgetBudget of the movies in USD
votesNumber of votes received by the movie
ratingAverage rating of the movie
popularityNumber use to measure the movie popularity
tagsA list of tags for the movies
import json
import elasticsearch.helpers as es_helpers
import pandas as pd
from urllib.request import urlopen

MOVIE_INDEX = "movies"

# Delete index
print("Deleting index if it already exists:", MOVIE_INDEX)
es_client.options(ignore_status=[400, 404]).indices.delete(index=MOVIE_INDEX)

print("Creating index:", MOVIE_INDEX)
index_settings = json.load(urlopen(INDEX_SETTINGS_URL))
es_client.indices.create(index=MOVIE_INDEX, **index_settings)

print(f"Loading the corpus from {CORPUS_URL}")
corpus_df = pd.read_json(CORPUS_URL, lines=True)

print(f"Indexing the corpus into {MOVIE_INDEX} ...")
bulk_result = es_helpers.bulk(
    es_client,
    actions=[
        {"_id": movie["id"], "_index": MOVIE_INDEX, **movie}
        for movie in corpus_df.to_dict("records")
    ],
)
print(f"Indexed {bulk_result[0]} documents into {MOVIE_INDEX}")

我们可以在 Kibana 中进行查看:

上面显示我们写入了 9750 个文档。

加载判断列表

判断列表包含我们将用来训练 “学习排名” 模型的人工评估。

每行代表一个具有关联相关性等级的查询-文档对,并包含以下列:

ColumnDescription
query_idPairs for the same query are grouped together and received a unique id.
queryActual text of the query.
doc_idID of the document.
gradeThe relevance grade of the document for the query.

注意:在此示例中,相关性等级是二进制值(相关或不相关)。 你还可以使用代表相关程度的数字(例如从 0 到 4)。

judgments_df = pd.read_csv(JUDGEMENTS_FILE_URL, delimiter="\t")
judgments_df

配置特征提取

特征是我们模型的输入。 它们表示有关单独查询、单独结果文档或查询上下文中的结果文档的信息,例如 BM25 分数。

特征是使用标准模板查询和查询 DSL 定义的。

为了简化训练期间定义和细化特征提取的过程,我们直接在 eland 中合并了许多 primitives。

from eland.ml.ltr import LTRModelConfig, QueryFeatureExtractor

ltr_config = LTRModelConfig(
    feature_extractors=[
        # For the following field we want to use the score of the match query for the field as a features:
        QueryFeatureExtractor(
            feature_name="title_bm25", query={"match": {"title": "{{query}}"}}
        ),
        QueryFeatureExtractor(
            feature_name="actors_bm25", query={"match": {"actors": "{{query}}"}}
        ),
        # We could also use a more strict matching clause as an additional features. Here we want all the terms of our query to match.
        QueryFeatureExtractor(
            feature_name="title_all_terms_bm25",
            query={
                "match": {
                    "title": {"query": "{{query}}", "minimum_should_match": "100%"}
                }
            },
        ),
        QueryFeatureExtractor(
            feature_name="actors_all_terms_bm25",
            query={
                "match": {
                    "actors": {"query": "{{query}}", "minimum_should_match": "100%"}
                }
            },
        ),
        # Also we can use a script_score query to get the document field values directly as a feature.
        QueryFeatureExtractor(
            feature_name="popularity",
            query={
                "script_score": {
                    "query": {"exists": {"field": "popularity"}},
                    "script": {"source": "return doc['popularity'].value;"},
                }
            },
        ),
    ]
)

构建训练数据集

现在我们已经加载了基本数据集并配置了特征提取,我们将使用我们的判断列表来得出最终的训练数据集。 数据集将由包含 <query, document> 对的行以及训练模型所需的所有特征组成。 为了生成此数据集,我们将从判断列表中运行每个查询,并将提取的特征添加为每个标记结果文档的列。

例如,如果我们有一个包含两个标记文档 d3 和 d9 的查询 q1,训练数据集最终将有两行 — 每对 <q1, d3> 和 <q1, d9> 一行。

请注意,由于这会在您的 Elasticsearch 集群上执行查询,因此运行此操作的时间将根据集群的托管位置以及此笔记本的运行位置而有所不同。 例如,如果你在与 Elasticsearch 集群相同的服务器或主机上运行笔记本,则此操作往往会在示例数据集上运行得非常快(< 2 分钟)

import numpy

from eland.ml.ltr import FeatureLogger

# First we create a feature logger that will be used to query Elasticsearch to retrieve the features:
feature_logger = FeatureLogger(es_client, MOVIE_INDEX, ltr_config)


# This method will be applied for each query group in the judgment log:
def _extract_query_features(query_judgements_group):
    # Retrieve document ids in the query group as strings.
    doc_ids = query_judgements_group["doc_id"].astype("str").to_list()

    # Resolve query params for the current query group (e.g.: {"query": "batman"}).
    query_params = {"query": query_judgements_group["query"].iloc[0]}

    # Extract the features for the documents in the query group:
    doc_features = feature_logger.extract_features(query_params, doc_ids)

    # Adding a column to the dataframe for each feature:
    for feature_index, feature_name in enumerate(ltr_config.feature_names):
        query_judgements_group[feature_name] = numpy.array(
            [doc_features[doc_id][feature_index] for doc_id in doc_ids]
        )

    return query_judgements_group


judgments_with_features = judgments_df.groupby(
    "query_id", group_keys=False
).progress_apply(_extract_query_features)

judgments_with_features

从上面,我们可以看出提取的特征值。

创建并训练模型

LTR rescorer 支持 XGBRanker 训练的模型。

在 XGBoost 文档中了解更多信息。

from xgboost import XGBRanker
from sklearn.model_selection import GroupShuffleSplit


# Create the ranker model:
ranker = XGBRanker(
    objective="rank:ndcg",
    eval_metric=["ndcg@10"],
    early_stopping_rounds=20,
)

# Shaping training and eval data in the expected format.
X = judgments_with_features[ltr_config.feature_names]
y = judgments_with_features["grade"]
groups = judgments_with_features["query_id"]

# Split the dataset in two parts respectively used for training and evaluation of the model.
group_preserving_splitter = GroupShuffleSplit(n_splits=1, train_size=0.7).split(
    X, y, groups
)
train_idx, eval_idx = next(group_preserving_splitter)

train_features, eval_features = X.loc[train_idx], X.loc[eval_idx]
train_target, eval_target = y.loc[train_idx], y.loc[eval_idx]
train_query_groups, eval_query_groups = groups.loc[train_idx], groups.loc[eval_idx]

# Training the model
ranker.fit(
    X=train_features,
    y=train_target,
    group=train_query_groups.value_counts().sort_index().values,
    eval_set=[(eval_features, eval_target)],
    eval_group=[eval_query_groups.value_counts().sort_index().values],
    verbose=True,
)

将模型导入 Elasticsearch

模型训练完成后,我们可以使用 Eland 将其加载到 Elasticsearch 中。

请注意,MLModel.import_ltr_model 方法包含 LTRModelConfig 对象,该对象定义如何为导入的模型提取特征。

from eland.ml import MLModel

LEARNING_TO_RANK_MODEL_ID = "ltr-model-xgboost"

MLModel.import_ltr_model(
    es_client=es_client,
    model=ranker,
    model_id=LEARNING_TO_RANK_MODEL_ID,
    ltr_model_config=ltr_config,
    es_if_exists="replace",
)

一旦部署完毕,我们可以在  Kibana 中进行查看:

使用 rescorer

将模型上传到 Elasticsearch 后,你将能够在 _search API 中将其用作 rescorer,如本示例所示:

GET /movies/_search
{
   "query" : {
      "multi_match" : {
         "query": "star wars",
         "fields": ["title", "overview", "actors", "director", "tags", "characters"]
      }
   },
   "rescore" : {
      "window_size" : 50,
      "learning_to_rank" : {
         "model_id": "ltr-model-xgboost",
         "params": { 
            "query": "star wars"
         }
      }
   }
}
query = "star wars"

# First let's display the result when not using the rescorer:
search_fields = ["title", "overview", "actors", "director", "tags", "characters"]
bm25_query = {"multi_match": {"query": query, "fields": search_fields}}

bm25_search_response = es_client.search(index=MOVIE_INDEX, query=bm25_query)

[
    (movie["_source"]["title"], movie["_score"], movie["_id"])
    for movie in bm25_search_response["hits"]["hits"]
]

# Now let's display result when using the rescorer:

ltr_rescorer = {
    "learning_to_rank": {
        "model_id": LEARNING_TO_RANK_MODEL_ID,
        "params": {"query": query},
    },
    "window_size": 100,
}

rescored_search_response = es_client.search(
    index=MOVIE_INDEX, query=bm25_query, rescore=ltr_rescorer
)

[
    (movie["_source"]["title"], movie["_score"], movie["_id"])
    for movie in rescored_search_response["hits"]["hits"]
]

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

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

相关文章

【云计算】云数据中心网络(七):负载均衡

《云网络》系列&#xff0c;共包含以下文章&#xff1a; 云网络是未来的网络基础设施云网络产品体系概述云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC云数据中心网络&#xff08;二&#xff09;&#xff1a;弹性公网 IP云数据中心网络&#xff08;三&#xff09;…

防火墙如何工作

防火墙是网络安全的重要组成部分&#xff0c;充当受信任的内部网络与外部世界之间的保护屏障。它根据预定的安全规则监视和控制传入和传出的网络流量。您是否知道防火墙的概念可以追溯到 20 世纪 80 年代&#xff0c;当时互联网还处于早期阶段&#xff1f;从那时起&#xff0c;…

SpringBoot项目启动的时候直接退出了?

SpringBoot项目启动的时候直接退出了&#xff1f; 如下图&#xff1a; 在启动SpringBoot项目的时候仅仅用了1.209s&#xff0c;然后直接退出了&#xff0c;也没有出现启动的项目对应的服务器端口号&#xff1f;为什么会这样呢&#xff1f;因为既然有服务器端口号 那么肯定会有…

linux系统是未来_大小写敏感_case_sensitive_编程原生态

修改 py 文件 &#x1f94a; 回忆上次内容 上次尝试了 两个vim 同时打开 同一py文件 vim出现了Error 有各种选择 错误拼写 pront 导致 运行时 出现了NameError 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 错误(Error) 不是 我们 无能的标记 …

k8s pod使用sriov

之前的文章中讲了k8s multus的使用&#xff0c;本章节来讲述下如何使用multus来实现sriov的使用。 一、sriov 简介 SR-IOV在2010年左右由Intel提出&#xff0c;但是随着容器技术的推广&#xff0c;intel官方也给出了SR-IOV技术在容器中使用的开源组件&#xff0c;例如&#…

力扣(leetcode) 407. 接雨水 II 3D接雨水

力扣(leetcode) 407. 接雨水 II 3D接雨水 给你一个 m x n 的矩阵&#xff0c;其中的值均为非负整数&#xff0c;代表二维高度图每个单元的高度&#xff0c;请计算图中形状最多能接多少体积的雨水。 示例 1: 输入: heightMap [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] 输…

Excel vlookup函数的使用教程 和 可能遇到的错误解决方法

使用VLOOKUP示例 被查询的表格 表一 A列B列C列A1aB2bC3c 要匹配的列 表二 F列G列H列ACBDA 要G列匹配字母&#xff0c;H列匹配数字 G 使用公式VLOOKUP(F5,A:D,3,0) 参数说明 F5 是表二 F列第五行的A A:D表是要匹配的数据列表在A到D列&#xff0c;就是表一 &#xff08;注意…

day03-(docker)

文章目录 DockerDocker和虚拟机的差别docker在linux安装配置镜像命令容器命令介绍Docker-容器&#xff08;基本操作&#xff09;docker基本操作&#xff08;数据卷&#xff09;数据卷挂载直接挂载四.Dockerfile自定义镜像五.Docker-Compose 安装修改权限镜像仓库![在这里插入图…

在城市与自然中穿行:探索自然的全新方式,健康、环保、快乐的生活方式

一辆单车&#xff0c;三五好友&#xff0c;骑行穿过城市与大自然。无论是在悠闲的周末打卡城市古建筑&#xff0c;还是选择充满挑战的“川藏线”&#xff0c;无论是在城郊绿道感受清风拂面&#xff0c;还是在洱海湖畔欣赏美好风光……如今&#xff0c;越来越多人加入骑行队伍&a…

解读币安Megadrop:如何参加第一期BounceBit活动?

币安推出新的代币发行平台 Megadrop&#xff0c;第一期为 BounceBit。 跟 launchpool 相比&#xff0c; 主要不同是 1&#xff09;锁仓 bnb 有收益的倍数加成 2&#xff09;做任务有收益加成。 我认为核心目的有两个&#xff1a; 1&#xff09;更多收益给 BNB 长期持有者&am…

Docker pull镜像名称 把本地镜像推送到远程详解

Docker pull镜像名称 把本地镜像推送到远程详解&#xff1a; Docker 镜像 仓库 容器介绍 以及镜像仓库详解 下载一个alpine的镜像演示&#xff0c;alpine是一个比较小的的linux镜像。 docker pull alpinedocker tag d4ff818577bc docker.io/itying/alpine:v1.0.1docker tag d4…

基于Linux的Ncurse库的贪吃蛇项目

贪吃蛇项目的意义 承上启下&#xff1a;从C语言基础的学习&#xff1a;数据结构链表基础、C变量、流程控制、函数、指针、结构体等。过渡到Linux系统编程&#xff1a;文件编程、进程、线程、通信、第三方等。 Linux终端图形库curses curses的名字起源于"cursor optimiz…

ELK创建仪表盘

仪表盘 一、保存search二、生成饼图三、创建仪表盘 一、保存search 首先保存一段时间内的search&#xff0c;可以添加想要的字段&#xff0c;并保存这个search方便下次直接打开该search&#xff0c;并方便在可视化和仪表盘中使用该search. 二、生成饼图 点击Visualize 选择…

C语言——内存函数的实现与模拟

1. memcpy 函数 与strcpy 函数类似 1.头文件 <string.h> 2.基本格式 • 函数memcpy从source的位置开始向后复制num个 字节 的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果source和destination有任何的重叠&#xff0…

Redis入门到通关之数据结构解析-动态字符串SDS

文章目录 Redis数据结构-动态字符串动态扩容举例二进制安全SDS优点与C语言中的字符串的区别 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间…

Spring Kafka—— KafkaListenerEndpointRegistry 隐式注册分析

由于我想在项目中实现基于 Spring kafka 动态连接 Kafka 服务&#xff0c;指定监听 Topic 并控制消费程序的启动和停止这样一个功能&#xff0c;所以就大概的了解了一下 Spring Kafka 的几个重要的类的概念&#xff0c;内容如下&#xff1a; ConsumerFactory 作用&#xff1a;…

使用JavaScript及HTML、CSS完成秒表计时器

案例要求 1.界面为一个显示计时面板和三个按钮分别为:开始&#xff0c;暂停&#xff0c;重置 2.点击开始&#xff0c;面板开始计时&#xff0c; 3.点击暂停&#xff0c;面板停止 4.点击重置&#xff0c;计时面板重新为0 案例源码 <!DOCTYPE html> <html lang"…

sqlplus / as sysdba登陆失败,(ORA-01017)

周一上班检查alert log&#xff0c;看到某个库报出大量的错误 提示无法连接到ASM实例&#xff0c;这是某知名MES厂商DBA创建的11G RAC刚刚​转交到我手上的&#xff0c;这又是给我挖了什么坑&#xff1f; 报错为ORA-01017​用户名密码不对&#xff1f;​what&#xff1f; 登陆o…

负载均衡的原理及算法

一、定义 负载均衡&#xff08;Load Balancing&#xff09;是一种计算机网络和服务器管理技术&#xff0c;旨在分配网络流量、请求或工作负载到多个服务器或资源&#xff0c;以确保这些服务器能够高效、均匀地处理负载&#xff0c;并且能够提供更高的性能、可用性和可扩展性。…

OpenCV-复数矩阵点乘ComplexMatrixDotMultiplication

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 需求说明 一般用到FFT&#xff0c;就涉及到复数的计算&#xff0c;为了便于调用&#xff0c;我自行封装了一个简单的复数矩阵点乘…