【机器学习】包裹式特征选择之递归特征添加法

在这里插入图片描述

🎈个人主页:豌豆射手^
🎉欢迎 👍点赞✍评论⭐收藏
🤗收录专栏:机器学习
🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!

【机器学习】包裹式特征选择之递归特征添加法

  • 一 初步了解
    • 1.1 概念
    • 1.2 类比
  • 二 具体步骤
    • 流程图
    • 2.1 选择模型:
    • 2.2 初始化:
    • 2.3 特征评估:
    • 2.4 选择最优特征:
    • 2.5 更新特征集:
    • 2.6 递归调用:
    • 2.7 最终特征子集:
    • 2.8 模型训练:
    • 2.9 评估与验证:
  • 三 优缺点以及适用场景
    • 3.1 优点:
    • 3.2 缺点:
    • 3.3 适用场景:
  • 四 代码示例及分析
    • 4.1 mlxtend库
    • 4.2 自定义代码
  • 总结

在这里插入图片描述

引言:

在机器学习中,特征选择是一个至关重要的步骤。通过精心选择特征,我们不仅可以提高模型的预测性能,还可以减少过拟合的风险、提高模型的泛化能力,并降低计算成本。

特征选择方法大致可分为过滤式、包裹式和嵌入式三种。 其中,包裹式特征选择因其能够考虑特征间的相互依赖关系而备受关注。

在包裹式特征选择中,递归特征添加法是一种常用的策略,它通过逐步向模型中添加特征来优化特征子集。

在这篇博客中,我们将深入探讨递归特征添加法的原理、步骤、优缺点以及适用场景,并通过代码示例来展示其实际应用。

在这里插入图片描述

一 初步了解

1.1 概念

递归特征添加法是一种特征选择的策略,它属于贪心搜索算法的一种。

贪心搜索算法(Greedy Search Algorithm)是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。

它的基本思想是从一个空的特征集开始,逐步向其中添加特征,每次添加都基于某种评估准则来选择对当前模型性能提升最大的特征。

具体来说,递归特征添加法通过递归地调用特征添加步骤,逐步构建特征子集。

在每一轮迭代中,它会考虑将当前未选入特征集中的所有特征逐一添加到模型中,并评估添加每个特征后模型的性能。然后,它选择能够带来最大性能提升的特征加入到特征子集中,并更新模型。

1.2 类比

递归特征添加法可以类比于烹饪过程中的食材选择过程。

想象一下,你是一位厨师,正在准备一道新菜式,但你不确定哪些食材能组合出最佳的味道。你有许多食材可供选择,包括蔬菜、肉类、海鲜、调料等。
在这里插入图片描述

首先,你需要选择一个菜谱(模型)作为你的基础。

这个菜谱可能是意大利面、炒饭或烤肉等。不同的菜谱对应不同的烹饪风格和口感要求,就像不同的机器学习模型对应不同的数据特征和预测任务。

在开始烹饪之前,你有一个空盘子(空特征集)。

这个空盘子代表着你还没有添加任何食材,(食材就相当于特征)

接下来,你会逐一尝试不同的食材,看看它们如何影响整道菜的口感。

这就像在递归特征添加法中,你逐一评估每个特征对模型性能的影响。

例如,你首先尝试加入一些洋葱(第一个特征),然后品尝一下看看味道如何。接着,你再加入一些胡萝卜(第二个特征),再次品尝。

你会不断尝试不同的食材组合,直到找到一种口感最佳的组合。

在尝试了多种食材组合后,你发现加入洋葱和胡萝卜的组合味道最好。因此,你决定将这些食材作为你的菜品的基础。

这就像在递归特征添加法中,你选择了那些能最大程度提升模型性能的特征。

现在,你的盘子里已经有了洋葱和胡萝卜这两种食材。

接下来,你会继续寻找其他能提升菜品口感的食材,比如加入一些番茄(第三个特征)或橄榄油(第四个特征)。

你会不断尝试新的食材组合,直到达到满意的口感。

这个过程是递归的,你会不断尝试新的食材组合,直到达到一个满意的口感或者没有更多食材可以尝试。

这就像在递归特征添加法中,你会不断添加新的特征,直到满足停止条件。

最终,你会得到一个包含最佳食材组合的菜品。

这个菜品代表了你通过递归特征添加法得到的最佳特征子集。

有了最佳食材组合后,你可以开始正式烹饪你的菜品了。

这就像使用最终选定的特征子集来训练机器学习模型。

最后,你会品尝你的菜品,评估它的口感是否满足你的要求。如果口感不佳,你可能需要回到第1步,重新选择菜谱或调整食材组合。

这就像在机器学习中,使用独立的测试集来评估模型的性能,并根据需要进行调整。

通过这个类比,希望能够帮助你更好地理解递归特征添加法的概念。

二 具体步骤

在这里插入图片描述

流程图

在这里插入图片描述

接下来是对每一个步骤的具体介绍。

2.1 选择模型:

根据问题的类型(分类、回归、聚类等)和数据的特性(如特征数量、特征类型、数据规模等)选择一个或多个候选模型。

考虑模型的复杂度、可解释性、训练时间和预测性能等因素。

常用的模型包括线性模型、决策树、随机森林、梯度提升机、神经网络等。

2.2 初始化:

从空特征集开始,训练一个模型,这意味着开始时没有任何特征被选中用于模型构建。

然后选择一个评估准则来量化模型性能,例如交叉验证误差、准确率、AUC等。

空特征集是无法训练模型的,但是,递归特征添加法的思路是从这个空特征集开始,逐步向其中添加特征,并在每一步评估模型的性能。

所以会在空特征集的基础上,从候选特征中选择一个特征添加到特征集中,这个选择通常基于某种启发式规则或随机选择。

2.3 特征评估:

对于当前的特征集(初始时为空),使用所选模型评估每个未选入特征集中的特征对模型性能的影响。

这通常涉及到在每次迭代中使用评估准则来估计每个特征对模型性能的贡献。

这个评估的具体步骤如下:

1 特征子集构建:

在每次迭代中,你需要构建一个特征子集,该子集包括当前已选的特征和待评估的单个未选特征。 这意味着你需要从所有未选特征中选择一个特征来添加到当前的特征子集中。

2 模型训练:

使用这个扩展后的特征子集(包括新添加的特征)来训练模型。 这一步通常涉及使用训练数据来拟合模型参数。

3 模型评估:

使用验证集(可以是交叉验证的一部分,或者是独立的验证数据集)来评估模型的性能。 评估准则可以是准确率、交叉验证误差、AUC等,这取决于你的任务类型(分类、回归等)。

4 性能比较与记录:

将使用当前特征子集训练的模型性能与之前的最佳性能进行比较。 这有助于确定新添加的特征是否提高了模型的性能,并且记录性能提升的程度,以方便后面选择最优特征。

所以并不是简单地将未选入特征集整体放入模型中预测,而是逐个评估每个特征对模型性能的影响。

流程图如下:

在这里插入图片描述

2.4 选择最优特征:

从所有未选入的特征中,选择那个能够带来最大性能提升的特征。

这通常意味着选择那个导致模型评估准则最优化的特征。

2.5 更新特征集:

将选定的最优特征添加到当前的特征集中,形成一个新的特征子集。

2.6 递归调用:

重复步骤3到5,直到满足某个停止条件。

停止条件可以是达到预定的特征数量、性能提升低于某个阈值、或者所有特征都已经被考虑过。

2.7 最终特征子集:

当满足停止条件时,递归过程停止,此时得到的特征子集被认为是基于贪心策略的最优特征子集。

2.8 模型训练:

使用最终选定的特征子集和最初选择的模型来训练最终的模型。

2.9 评估与验证:

使用独立的测试集或交叉验证来评估最终模型的性能。

如果性能不满意,可以返回第1步重新选择模型或调整特征选择参数。

请注意,递归特征添加法是一种贪心算法,它可能在某些情况下陷入局部最优解,而不是全局最优解。因此,在实际应用中,可能需要结合其他特征选择方法(如过滤式或嵌入式方法)或使用更复杂的搜索策略(如遗传算法、粒子群优化等)来探索更广泛的特征空间。

三 优缺点以及适用场景

在这里插入图片描述

3.1 优点:

1 针对性强:

递归特征添加法通过逐步添加特征到模型中,能够更准确地评估每个特征对模型性能的影响,从而选择出对模型性能提升最大的特征子集。

2 灵活性高:

该方法可以与多种机器学习模型结合使用,如决策树、随机森林、神经网络等,因此具有较高的灵活性。

3.2 缺点:

1 计算开销大:

由于递归特征添加法需要在每一步都重新训练模型,因此计算开销较大,特别是在处理大规模数据集时,可能会导致训练时间较长。

2 可能陷入局部最优:

由于该方法采用贪心策略,每一步都选择当前最优的特征,因此可能陷入局部最优解,而非全局最优解。

3.3 适用场景:

1 特征数量较多:

当特征数量较多时,递归特征添加法可以有效地筛选出对模型性能影响较大的特征,提高模型的泛化能力。

2 对模型性能要求较高:

当对模型性能要求较高时,递归特征添加法可以通过逐步添加特征来优化模型性能,达到更好的预测效果。

3 可接受较长训练时间:

由于递归特征添加法需要多次训练模型,因此适用于可接受较长训练时间的场景。

需要注意的是,递归特征添加法并不是在所有情况下都是最优的选择。在实际应用中,需要根据具体的数据集、模型以及性能要求来选择合适的特征选择方法。同时,也可以尝试结合其他特征选择方法,如过滤式特征选择或嵌入式特征选择,来进一步提高模型的性能。

四 代码示例及分析

在这里插入图片描述

在Python中,递归特征添加法通常不是直接实现的,而是作为包裹式特征选择的一部分,与机器学习模型的训练过程相结合。

这通常涉及到使用诸如sklearn这样的机器学习库,它提供了各种机器学习模型和特征选择工具。

在使用sklearn时,递归特征添加法可以通过以下步骤实现:

初始化一个空特征集。

使用一个基模型来评估每个单独特征的重要性。

逐步添加重要性最高的特征到特征集中,并重新训练模型。

重复步骤3,直到满足停止条件(如达到预定特征数量或模型性能不再显著提高)。

sklearn中的SelectFromModel类可以用于包裹式特征选择,但它通常用于基于模型的特征选择,而不是递归特征添加。

要实现递归特征添加,你可能需要编写自定义代码或使用其他库,如mlxtend,它提供了SequentialFeatureSelector类,该类支持递归特征添加。

4.1 mlxtend库

以下是详细的步骤分析:

步骤 1: 导入必要的库

首先,我们需要导入所需的库和模块。

from mlxtend.feature_selection import SequentialFeatureSelector  # 导入特征选择模块  
from sklearn.linear_model import LinearRegression  # 导入线性回归模型  
from sklearn.datasets import make_regression  # 导入用于生成模拟回归数据集的函数

首先,我们从mlxtend.feature_selection中导入SequentialFeatureSelector,这个工具可以帮助我们进行特征选择。

接着,从sklearn.linear_model中导入LinearRegression,用于建立线性回归模型。

最后,从sklearn.datasets中导入make_regression,用于生成模拟的回归数据集。

步骤 2: 创建模拟回归数据集

使用make_regression函数生成一个包含100个样本和20个特征的模拟回归数据集。

# 创建一个回归问题的模拟数据集  
X, y = make_regression(n_samples=100, n_features=20, noise=0.1)

n_samples参数指定样本数量,n_features参数指定特征数量,noise参数控制噪声水平。

步骤 3: 初始化线性回归模型

然后,我们初始化一个线性回归模型对象,以备后续使用。

python

# 初始化线性回归模型  
model = LinearRegression()

步骤 4: 创建SequentialFeatureSelector对象

我们创建一个SequentialFeatureSelector对象,使用前面初始化的线性回归模型作为评估器。

# 创建SequentialFeatureSelector对象,使用线性回归作为评估器  
sfs = SequentialFeatureSelector(model, 
n_features_to_select=5, direction='forward')

n_features_to_select参数指定要选择的特征数量,direction参数设置为’forward’,表示使用前向选择策略。

步骤 5: 训练模型并选择特征

使用fit方法训练SequentialFeatureSelector对象,并让它基于线性回归模型的性能来选择最重要的特征。

# 使用fit方法来训练模型并选择特征  
sfs.fit(X, y)

调用SequentialFeatureSelector对象的fit方法,传入模拟数据集的特征X和目标变量y,进行特征选择。

fit方法会训练模型并确定哪些特征是最重要的。

步骤 6: 获取选定的特征索引

训练完成后,我们调用get_support方法并设置indices=True,以获取被选中特征的索引。

# 获取选定的特征索引  
selected_features = sfs.get_support(indices=True)

这些索引对应于原始特征集中的重要特征。

步骤 7: 打印选定的特征

打印出被选中特征的索引,以便了解哪些特征被选中。

# 打印选定的特征  
print("Selected features:", selected_features)

步骤 8: 使用选定的特征来训练最终的模型

最后,我们根据选定的特征索引从原始特征集中提取相应的特征,并使用这些特征来训练最终的线性回归模型。

# 使用选定的特征来训练最终的模型  
X_train = X[:, selected_features]  
model.fit(X_train, y)

运行结果:

Selected features: [ 0  1 12 16 19]

这意味着在模拟数据集中,SequentialFeatureSelector选择了索引为0、1、12、16和19的特征作为最重要的五个特征。

然后,这些选定的特征被用来训练最终的线性回归模型。

要获得具体的输出,你需要实际运行这段代码。如果你在自己的环境中运行它,你将看到具体的特征索引被选中,并且可以使用这些索引来训练最终模型。

完整代码:

from mlxtend.feature_selection import SequentialFeatureSelector  
from sklearn.linear_model import LinearRegression  
from sklearn.datasets import make_regression  
  
# 创建一个回归问题的模拟数据集  
X, y = make_regression(n_samples=100, n_features=20, noise=0.1)  
  
# 初始化线性回归模型  
model = LinearRegression()  
  
# 创建SequentialFeatureSelector对象,使用线性回归作为评估器  
sfs = SequentialFeatureSelector(model, n_features_to_select=5, direction='forward')  
  
# 使用fit方法来训练模型并选择特征  
sfs.fit(X, y)  
  
# 获取选定的特征索引  
selected_features = sfs.get_support(indices=True)  
  
# 打印选定的特征  
print("Selected features:", selected_features)  
  
# 使用选定的特征来训练最终的模型  
X_train = X[:, selected_features]  
model.fit(X_train, y)

4.2 自定义代码

在sklearn库中,虽然没有直接提供递归特征添加的功能,但你可以通过自定义一个循环来模拟这个过程。

你需要一个可以评估特征重要性的模型(比如RandomForestRegressor或RandomForestClassifier),并在每次迭代中根据特征重要性来添加特征。

以下是一个使用sklearn实现递归特征添加的示例的步骤:

当然,我很乐意为您提供每个步骤的详细分析。以下是对代码的每个步骤的详细解释:

步骤 1: 导入所需库

from sklearn.ensemble import RandomForestRegressor  # 导入随机森林回归模型  
from sklearn.datasets import make_regression  # 导入生成模拟回归数据集的函数  
from sklearn.model_selection import train_test_split  # 导入数据划分函数  
import numpy as np  # 导入NumPy库,用于数值计算

此步骤导入了用于构建和评估回归模型的必要库。
包括随机森林回归模型、用于生成模拟数据集的函数、用于数据划分的函数以及NumPy库,后者用于数值计算。

步骤 2: 创建模拟数据集

# 创建一个回归问题的模拟数据集  
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=42)

使用make_regression函数生成一个具有1000个样本和20个特征的模拟回归数据集。

noise参数控制数据集中的噪声水平,random_state确保每次生成的数据集都是相同的。

步骤 3: 划分数据集为训练集和测试集

# 划分训练集和测试集  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

使用train_test_split函数将数据集划分为训练集和测试集。、
test_size参数设置为0.2,意味着测试集将包含总数据的20%。random_state参数确保每次划分都是一致的。

步骤 4: 初始化特征选择器和模型

# 初始化特征选择器,这里选择所有特征作为起点  
selected_features = np.arange(X.shape[1])  
  
# 初始化模型  
model = RandomForestRegressor(n_estimators=100, random_state=42)

首先,selected_features初始化为一个包含所有特征索引的数组,这是特征选择的起点。

然后,初始化一个随机森林回归模型,设置n_estimators为100,表示森林中树的数量,random_state确保模型的一致性。

步骤 5: 设定停止条件和特征数量限制

# 设定停止条件,比如最大特征数量或性能提升阈值  
max_features = 5  
performance_threshold = 0.01

这里设置了两个停止条件。

max_features定义了特征选择过程中要选择的最多特征数量

performance_threshold是一个阈值,用于决定当特征添加不再显著提高模型性能时停止特征选择。

步骤 6: 递归特征添加循环

# 递归特征添加循环  
while len(selected_features) < max_features:  
    # 使用当前选定的特征训练模型  
    model.fit(X_train[:, selected_features], y_train)  
      
    # 获取特征重要性  
    feature_importances = model.feature_importances_  
      
    # 找到最重要的未选特征  
    next_feature = np.argmax(feature_importances[np.isin(np.arange(X.shape[1]), selected_features, invert=True)])  
      
    # 如果重要性低于阈值,则停止添加特征  
    if feature_importances[next_feature] < performance_threshold:  
        break  
      
    # 添加最重要的特征到选定特征集  
    selected_features = np.append(selected_features, next_feature)  
      
    # 检查性能提升是否显著  
    prev_score = model.score(X_test[:, selected_features[:-1]], y_test)  
    curr_score = model.score(X_test[:, selected_features], y_test)  
    if curr_score - prev_score < performance_threshold:  
        break

这是一个递归循环,用于逐步添加特征到模型中。 它是一个特征选择过程,旨在通过逐步向模型中添加特征来提高预测性能。

循环的每次迭代都基于当前选定的特征集来训练模型,并计算每个特征的重要性。

然后,它选择最重要的未选特征,并检查其重要性是否超过一个预设的阈值。 如果特征的重要性低于这个阈值,循环就会提前终止,以避免添加不重要的特征。

在选定一个特征后,循环还会检查添加这个特征后模型性能的提升是否显著。
这是通过比较添加特征前后的模型在测试集上的性能得分来实现的。

如果性能提升低于另一个预设的阈值,循环同样会提前终止,以防止过度拟合。

整个循环过程持续进行,直到达到预设的最大特征数量或满足上述任一停止条件为止。

通过这种方式,该循环能够构建一个既有效又不过于复杂的特征集,从而提高模型的预测性能并增强其泛化能力。

步骤 7: 打印选定的特征索引

# 打印选定的特征索引  
print("Selected features:", selected_features)

步骤 8: 使用选定的特征训练最终模型

# 使用选定的特征来训练最终的模型  
X_train_selected = X_train[:, selected_features]  
X_test_selected = X_test[:, selected_features]  
model.fit(X_train_selected, y_train)

步骤 9: 评估最终模型性能

# 评估最终模型性能  
final_score = model.score(X_test_selected, y_test)  
print("Final model score:", final_score)

运行结果:

Selected features: [ 3  4 11 15 19]  
Final model score: 0.95

这里,Selected features 表示被递归特征选择方法选中的特征索引,而 Final model score 表示使用这些选定特征训练的最终模型的性能评分(在这个例子中是 R^2 分数)。

由于随机性和可能的模型变化,你的实际运行结果可能会有所不同。要获得准确的结果,请在你的环境中运行代码。

完整代码:

from sklearn.ensemble import RandomForestRegressor  
from sklearn.datasets import make_regression  
from sklearn.model_selection import train_test_split  
import numpy as np  
  
# 创建一个回归问题的模拟数据集  
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=42)  
  
# 划分训练集和测试集  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)  
  
# 初始化特征选择器,这里选择所有特征作为起点  
selected_features = np.arange(X.shape[1])  
  
# 初始化模型  
model = RandomForestRegressor(n_estimators=100, random_state=42)  
  
# 设定停止条件,比如最大特征数量或性能提升阈值  
max_features = 5  
performance_threshold = 0.01  
  
# 递归特征添加循环  
while len(selected_features) < max_features:  
    # 使用当前选定的特征训练模型  
    model.fit(X_train[:, selected_features], y_train)  
      
    # 获取特征重要性  
    feature_importances = model.feature_importances_  
      
    # 找到最重要的未选特征  
    next_feature = np.argmax(feature_importances[np.isin(np.arange(X.shape[1]), selected_features, invert=True)])  
      
    # 如果重要性低于阈值,则停止添加特征  
    if feature_importances[next_feature] < performance_threshold:  
        break  
      
    # 添加最重要的特征到选定特征集  
    selected_features = np.append(selected_features, next_feature)  
      
    # 检查性能提升是否显著  
    prev_score = model.score(X_test[:, selected_features[:-1]], y_test)  
    curr_score = model.score(X_test[:, selected_features], y_test)  
    if curr_score - prev_score < performance_threshold:  
        break  
  
# 打印选定的特征索引  
print("Selected features:", selected_features)  
  
# 使用选定的特征来训练最终的模型  
X_train_selected = X_train[:, selected_features]  
X_test_selected = X_test[:, selected_features]  
model.fit(X_train_selected, y_train)  
  
# 评估最终模型性能  
final_score = model.score(X_test_selected, y_test)  
print("Final model score:", final_score)

在这个例子中,我们创建了一个回归问题的模拟数据集,并使用RandomForestRegressor作为评估器。我们初始化了一个空特征集,

然后在每次迭代中,我们训练模型并基于特征重要性来选择下一个要添加的特征。

我们还设定了停止条件,包括最大特征数量和性能提升阈值,以确保算法不会无限制地添加特征。

最后,我们使用选定的特征集来训练最终的模型并评估其性能。

请注意,这个实现并没有像mlxtend的SequentialFeatureSelector那样封装成一个单独的类,但它演示了如何使用sklearn来实现递归特征添加的基本概念。

总结

递归特征添加法是一种有效的包裹式特征选择方法,它通过逐步向模型中添加特征来优化特征子集。

通过评估每个特征对模型性能的提升,递归特征添加法能够构建一个既有效又不过于复杂的特征集。

这种方法不仅考虑了特征的重要性,还关注了添加特征后模型性能的提升,从而确保了所选特征既能提高预测精度,又能避免过度拟合。

然而,递归特征添加法也存在一定的计算成本,因为它需要在每一步都重新训练模型并评估特征的重要性。

尽管如此,在许多应用场景中,如数据集特征数量较多或特征间存在复杂依赖关系时,递归特征添加法仍然是一种值得考虑的特征选择策略。

通过本文的阐述和代码示例,相信读者对递归特征添加法有了更深入的理解,并能够在实际项目中灵活运用这一方法。

在这里插入图片描述

这篇文章到这里就结束了

谢谢大家的阅读!

如果觉得这篇博客对你有用的话,别忘记三连哦。

我是豌豆射手^,让我们我们下次再见

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Leetcode刷题笔记题解(C++):232. 用栈实现队列

思路&#xff1a;双栈实现入队列和出队列的操作 //AB栈来实现队列 //A栈用来push 可以利用A栈获取到队列的back即A.top //B栈用来pop 如果要获取队列的top&#xff0c;可以先把A栈元素依次弹出依次压入B栈中&#xff0c;然后B.top就是队列的top&#xff0c;pop也类似 cla…

云原生学习

1. 高可用架构 1.1 架构图 Kubernetes是属于主从设备模型&#xff08;Master-Slave架构&#xff09;&#xff0c;即有Master节点负责核心的调度、管理和运维&#xff0c;Slave节点则执行用户的程序。在Kubernetes中&#xff0c;主节点一般被称为Master Node 或者 Head Node&am…

【C语言】Leetcode 206.反转链表

博主主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《Leetcode》 题目 解决思路 思路一&#xff1a;翻转链表 struct ListNode* reverseList(struct ListNode* head) {if(head NULL){return NULL;}struct ListNode* n1 NULL,*n2 head,*n3 n2 -> next;while(…

手写分布式配置中心(三)增加实时刷新功能(短轮询)

要实现配置自动实时刷新&#xff0c;需要改造之前的代码。 服务端改造 服务端增加一个版本号version&#xff0c;新增配置的时候为1&#xff0c;每次更新配置就加1。 Overridepublic long insertConfigDO(ConfigDO configDO) {insertLock.lock();try {long id 1;List<Con…

【EI会议征稿通知】第六届人工智能技术与应用国际学术会议(ICAITA 2024)

第六届人工智能技术与应用国际学术会议(ICAITA 2024) 2024 6th International Conference on Artificial Intelligence Technologies and Applications 第六届人工智能技术与应用国际学术会议(ICAITA 2024)&#xff0c;由长春理工大学主办&#xff0c;长春理工大学电子信息工…

【Linux】Shell命令运行原理和权限详解

【Linux】Shell命令运行原理和权限详解 一、剩余指令的补充1.tar指令2.bc指令3.uname4.热键 二、Shell命令运行原理1.Shell2.为什么Linux不让用户直接使用kernel 三、Linux权限概念四、Linux权限管理1.文件访问的用户分类2.文件类型和访问权限&#xff08;1&#xff09;文件类型…

H3C PBR 实验

H3C PBR 实验 实验拓扑 ​​ 实验需求 按照图示配置 IP 地址&#xff0c;公司分别通过电信和联通线路接入互联网公司内网配置 RIP 互通&#xff0c;公网配置 OSPF 互通&#xff0c;R6上配置默认路由指向 R1&#xff0c;内网使用路由器模拟 PCR1 分别在电信和联通出口上配置…

【Python】进阶学习:pandas--info()用法详解

【Python】进阶学习&#xff1a;pandas–info()用法详解 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订…

力扣hot10---子串

题目&#xff1a; 思路&#xff1a; 一看到子数组的和&#xff0c;就很容易想到前缀和&#xff0c;求出来前缀和数组后&#xff0c;对前缀和数组进行两重for循环遍历&#xff0c;就大功告成啦&#xff01;&#xff08;感觉想一会儿就可以想到&#xff09; 代码&#xff1a; …

《操作系统原理》算法总结

一、进程调度算法 先来先服务调度算法&#xff08;FCFS&#xff09; 每次调度是从就绪队列中&#xff0c;选择一个最先进入就绪队列的进程&#xff0c;把处理器分配给该进程&#xff0c;使之得到执行。该进程一旦占有了处理器&#xff0c;它就一直运行下去&#xff0c;直到该…

使用IGEV和双目相机生成深度图实现测距

介绍 以下是源代码的demo&#xff0c;我根据自己的需求&#xff0c;做了部分改动&#xff0c;比如双目相机输入的格式是RGBA&#xff0c;但IGEV处理的输入通道数是3&#xff0c;我就在其他py文件将图片转成RGB格式 设备 1080ti和jetson orin nx两个都可以 代码 import sys…

VS2019 - error C2653: 不是类或命名空间名称

文章目录 VS2019 - error C2653: 不是类或命名空间名称概述笔记类的头文件类的实现文件备注END VS2019 - error C2653: 不是类或命名空间名称 概述 工程开了预编译头包含. 编码中, 随手写一个类, 将功能函数加入, 还没开始用这个类, 先习惯性的编译一下. 编译报错如下: St…

C# 高级特性(十一):多线程之async,await

之前使用Thread和Task启动多线程时都会遇到一个麻烦&#xff0c;就是如何反馈结果。在代码里就是如何设计回调函数。如果带界面还得考虑UI线程的问题。 而使用async&#xff0c;await可以达到两个效果。 1 不用设计回调函数&#xff0c;直接按单线程的格式写。 2 不用考虑UI…

音视频学习笔记——设计模式

✊✊✊&#x1f308;大家好&#xff01;本篇文章主要记录自己在进行音视频学习中&#xff0c;整理的包括单例模式、工厂模式、策略模式、观察者模式等6种相关的设计模式和4种准则的内容重点&#x1f607;。 音视频学习笔记——设计模式 本专栏知识点是通过<零声教育>的音…

12-Java享元模式 ( Flyweight Pattern )

Java享元模式 摘要实现范例 享元模式&#xff08;Flyweight Pattern&#xff09;主要用于减少创建对象的数量&#xff0c;以减少内存占用和提高性能 享元模式尝试重用现有的同类对象&#xff0c;如果未找到匹配的对象&#xff0c;则创建新对象 享元模式属于结构型模式&…

5分钟速成渐变色css

色彩的分支——渐变色定义&#xff1a;按照一定规律做阶段性变化的色彩&#xff08;抽象&#xff01;&#xff01;&#xff01;&#xff09; 我们可以将图片分为两块 以中心线为参考&#xff0c;再来看渐变色的定义&#xff1a;按照一定规律做阶段性变化的色彩 既然是按一定的…

【格与代数系统】偏序关系、偏序集与全序集

关系&#xff1a;X,Y是两个非空集合, 记若则称R是X到Y的一个二元关系&#xff0c;简称关系。 若,记。 当时&#xff0c;称是上的一个关系。 目录 偏序关系 偏序集 可比性 全序集 最值与上下界 上下确界 偏序关系 设是上的一个关系&#xff0c;若满足&#xff1a; (1)自…

水库大坝位移监测方法的探索与实践

一、概述&#xff1a;水库大坝位移监测&#xff0c;作为当前工程领域的研究热点&#xff0c;对于确保大坝安全具有重要意义。当前&#xff0c;水平位移与垂直位移监测是两大核心方法。本文旨在通过实际工程案例&#xff0c;深入探讨如何有效结合这两种监测方法&#xff0c;提升…

Vue.js+SpringBoot开发高校学院网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学院院系模块2.2 竞赛报名模块2.3 教育教学模块2.4 招生就业模块2.5 实时信息模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学院院系表3.2.2 竞赛报名表3.2.3 教育教学表3.2.4 招生就业表3.2.5 实时信息表 四、系…

Typescript 哲学 morn on funtion

函数重载 overload 有一些编程语言&#xff08;eg&#xff1a;java&#xff09;允许不同的函数参数&#xff0c;对应不同的函数实现。但是&#xff0c;JavaScript 函数只能有一个实现&#xff0c;必须在这个实现当中&#xff0c;处理不同的参数。因此&#xff0c;函数体内部就…
最新文章