GBDT算法超参数评估

GBDT(Gradient Boosting Decision Tree)算法是一种强大的机器学习技术,广泛应用于分类、回归等任务。然而,为了充分发挥其性能,超参数的合理设置至关重要。超参数,如学习率、树的最大深度、子样本比例等,直接影响到模型的复杂度、训练速度和预测精度。因此,对GBDT算法的超参数进行细致的评估和调整,是确保模型性能达到最优的关键步骤。

弱评估器数量:参数n_estimators

n_estimators指的是集成算法中弱评估器的数量。对于Boosting算法来说,可以使用任意弱评估器,当然了默认的弱评估器还是决策树。GBDT算法无论是分类器还是回归器,默认弱评估器都是回归树。

X_c,y_c = load_wine(return_X_y=True,as_frame=True) #分类数据
X_r,y_r = fetch_california_housing(return_X_y=True,as_frame=True) #回归数据

# 建立GBDT分类器和回归器
clf = GBC(n_estimators=2).fit(X_c,y_c)
reg = GBR(n_estimators=2).fit(X_r,y_r)

# n_estimators_:实际迭代次数
clf.n_estimators_
2

reg.n_estimators_
2

# estimators_:实际建立的弱评估器数量
clf.estimators_

array([[DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)],
       [DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)]],
      dtype=object)

reg.estimators_


array([[DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)],
       [DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)]],
      dtype=object)
  • 对于 GradientBoostingRegressor,因为处理的是回归问题,每个迭代步骤只构建一个回归树来预测连续的目标变量。所以,在回归器的 estimators_ 中有两个 DecisionTreeRegressor 实例,与指定的 n_estimators=2 相匹配。 
  • 对于 GradientBoostingClassifier,如果数据是多类别的(比如 wine 数据集可能有多个类别),则在每个提升迭代中,算法会为每个类别构建一个回归树来预测该类别的概率。因此,如果数据集有三个类别,每个迭代步骤将会构建三个树,每个树预测一个类别的概率。
  • 如果是二分类则不会出现这种现象

出现这种情况的根本原因在于:GBDT的弱评估器为回归树,在实际调用GBDT来完成分类任务时,需要softmax函数或者sigmoid函数对回归树输出的结果进行处理。对于二分类来说,就是直接调用sigmoid函数,输出的概率值大于0.5就被预测为类别1 ,反之预测为类别0。

对于多分类来说,就比较复杂了。在多分类任务中,我们必须求解出所有标签类别所对应的概率,在所有这些概率当中,最大的概率所对应的标签才是多分类的预测标签。此时,我们需要softmax函数(归一化指数函数)帮助我们将回归值转化为概率。而**softmax函数是接受K个连续型结果,并输出K个相对概率的函数。所以在使用softmax之前我们需要准备每个类别的概率值,因此就需要建立同等数量的弱评估器。 

不难发现,使用GBDT完成多分类任务时,计算量以及弱评估器数量都会远远超出二分类以及回归类问题。

参数n_estimators对模型效果的影响:

X,y = load_breast_cancer(return_X_y=True,as_frame=True)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=0)

# 绘制n_estimators的学习曲线

# ===========【TIME WARNING:2min】============#
scores = []
for i in np.arange(1,300,10):
    gbc = GBC(n_estimators=i)
    s = cross_val_score(gbc,X,y,cv=5).mean()
    scores.append(s)

print(f"当n_estimators={np.arange(1,300,10)[scores.index(max(scores))]}时,准确率取得最大值{max(scores)}")
plt.plot(np.arange(1,300,10),scores,label = "GBDT")
plt.show()

# 细化学习曲线
scores = []
for i in np.arange(1,50):
    gbc = GBC(n_estimators=i)
    s = cross_val_score(gbc,X,y,cv=5).mean()
    scores.append(s)

print(f"当n_estimators={np.arange(1,50)[scores.index(max(scores))]}时,准确率取得最大值{max(scores)}")
plt.plot(np.arange(1,50),scores,label = "GBDT")
plt.show()

 

可以看出,随着参数n_estimators的增大,模型的效果是逐渐变好的。但是,n_estimators达到一定的程度之后,GBDT的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。所以对于这个参数,我们是渴望在模型训练难度和模型效果之间取得平衡。 

学习率:参数`learning_rate`

在Boosting集成算法中,集成算法最终的输出结果往往是多个弱评估器输出结果的加权平均结果。但是这个最终结果并不是在所有的弱评估器建好之后才统一加权求解的,而是在逐渐建立弱评估器的过程中就随着迭代不断计算出来的。

例如,对于样本x_i,集成算法当中一共有T棵树(也就是参数`n_estimators`的取值),现在正在建立第t个弱评估器,则第t个弱评估器上x_i的结果可以表示为f_t(x_i)。假设整个Boosting算法对样本x_i输出的结果为H(x_i),则该结果一般可以被表示为t=1~t=T过程当中,所有弱评估器结果的加权求和:

  • 以上式子为boosting算法中计算方式的一般规则,并不是具体到某一个Boosting集成算法的具体公式

# 绘制不同n_estimators、learning_rate下,模型效果变化
plt.figure(figsize=(10,6))
for i in [3,10,50,100,200]:
    scores = []
    for j in np.arange(0.001,0.5,0.01):
        gbc = GBC(n_estimators=i,learning_rate=j,random_state=0)
        s = cross_val_score(gbc,X,y,cv=5).mean()
        scores.append(s)
    plt.plot(np.arange(0.001,0.5,0.01),scores,label = f"n_estimators={i}")
    plt.legend()

 

初始预测结果的设置:参数init

  • 传入实例的参数

from sklearn.metrics import mean_squared_error as MSE

X,y = fetch_california_housing(return_X_y=True,as_frame=True)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=0)

for init in [DTR(),RFR(),"zero",None]:
    reg = GBR(init = init,random_state=0)
    reg = reg.fit(Xtrain,Ytrain)
    MSE_train = MSE(Ytrain,reg.predict(Xtrain))
    MSE_test = MSE(Ytest,reg.predict(Xtest))
    
    print(f"{init}:")
    print(f"训练集MSE:{MSE_train}")
    print(f"测试集MSE:{MSE_test}")
    print("\n")


zero:
训练集MSE:0.25572269323849983
测试集MSE:0.289857007749968


None:
训练集MSE:0.25572269022058913
测试集MSE:0.2897994977087412

  • 不难发现,初始参数的具体输入会对模型的最终结果造成巨大影响,在init中输入训练好的模型会加重GBDT的过拟合,但同时也可能得到更好的测试集结果。

GBDT的6种损失函数:参数loss 

GBDT算法的损失函数非常多,我们在调参的时候可以把损失函数作为需要调整的参数进行考量。在sklearn中,控制具体损失函数的参数为:loss。GBDT中的损失函数因GBDT具体执行的预测任务而存在区别,同时也因标签的分布而存在区别。

老版本

对于梯度提升分类树来说,loss的备选项有2种:{"deviance", "exponential"},默认值为"deviance"。

  • "deviance":直译为偏差,特指逻辑回归的损失函数——**交叉熵损失**;
  • "exponential":表示的是 指数损失函数。需要注意的是:此损失函数只能支持二分类数据**。

新版本 

deviance ->log_loss

对于梯度提升回归树来说,loss的备选项有如下几种:

  • “squared_error”:指回归的平方误差;
  • “absolute_error”:指回归的绝对误差;
  • “huber”:平方误差和绝对误差的结合(使用alpha进行调节);
  • “quantile”:表示允许分位数回归(使用alpha 指定分位数)

其中的alpha是需要我们自己设置的超参数,由参数alpha控制。在huber损失中,alpha是阈值,在quantile损失中,alpha用于辅助计算损失函数的输出结果,默认为0.9。

=========更新警告=========

在sklearn1.0版本及后续版本当中,损失函数"ls"与"lad"被删除了,其中"ls"的功能被"squared_error"取代,而"lad"被"absolute_error"取代。如果你在运行代码时,发现你的参数默认值、参数名称与课件中不相同,或者在运行过程中出现报错、警告等现象,你可能需要更新你的sklearn。

=========================

GBDT是工业应用最广泛的模型,工业数据大部分都极度偏态、具有长尾,因此GBDT必须考虑离群值带来的影响。数据中的离群值会极大程度地影响模型地构建,当离群值在标签当中、而我们是依赖于减小损失函数来逐渐构建算法时,这种影响会前所未有地大。因此Boosting是天生更容易被离群值影响的模型、也更擅长学习离群值的模型。

举例来说,若离群值的标签为1000,大部分正常样本的标签在0.1~0.2之间,算法一定会异常努力地学习离群值的规律,因为将离群值预测错误会带来巨大的损失。在这种状况下,最终迭代出的算法可能是严重偏离大部分数据的规律的。同样,我们也会遇见很多离群值对我们很关键的业务场景:例如,电商中的金额离群用户可能是VIP用户,风控中信用分离群的用户可能是高风险用户,这种状况下我们反而更关注将离群值预测正确。不同的损失函数可以帮助我们解决不同的问题——

  • 当高度关注离群值、并且希望努力将离群值预测正确时,选择平方误差squared_error

  • 这在工业中是大部分的情况。在实际进行预测时,离群值往往比较难以预测,因此离群样本的预测值和真实值之间的差异一般会较大。MSE作为预测值和真实值差值的平方,会放大离群值的影响,会让算法更加向学习离群值的方向进化,这可以帮助算法更好地预测离群值。

  • 努力排除离群值的影响、更关注非离群值的时候,选择绝对误差absolute_error

  • MAE对一切样本都一视同仁,对所有的差异都只求绝对值,因此会保留样本差异最原始的状态。相比其MSE,MAE对离群值完全不敏感,这可以有效地降低GBDT在离群值上的注意力。

  • 试图平衡离群值与非离群值、没有偏好时,选择huber或者quantile

  • Huberloss损失结合了MSE与MAE,在Huber的公式中,当预测值与真实值的差异大于阈值时,则取绝对值,小于阈值时,则取平方。在真实数据中,部分离群值的差异会大于阈值,部分离群值的差异会小于阈值,因此比起全部取绝对值的MAE,Huberloss会将部分离群值的真实预测差异求平方,相当于放大了离群值的影响(但这种影响又不像在MSE那样大)。因此HuberLoss是位于MSE和MAE之间的、对离群值相对不敏感的损失。

弱评估器的不纯度衡量指标:参数criterion 

GBDT算法的弱评估器为决策树(确切地说是回归树),我们已经熟悉各种剪枝参数对模型的影响。因此,我们对于Boosting算法中控制弱评估器的参数应该也不陌生:

这些参数在GBDT中的用法与默认值与决策树类DecisionTreeRegressor中基本上一致(除了GBDT中max_depth=3),专门用于对决策树进行剪枝、控制单个弱评估器的结构,考虑到大家在决策树中已经充分掌握这些参数,我们不再对这些参数一一进行详细说明了。在这里,需要重点说明的有两部分内容,一部分梯度提升树中默认的弱评估器复杂度所带来的问题,另一部分则是梯度提升树独有的不纯度衡量指标。

  1. 基尼系数(Gini Impurity):
    • 表示为gini
    • 计算公式:(gini = 1 - p2 - (1-p)2),其中p是样本属于某一类的概率。
    • 基尼系数越小,表示数据集的不纯度越低,即数据的纯度越高。
    • 基尼系数的计算不涉及对数,因此相对于信息熵来说,计算速度更快。
  2. 信息熵(Entropy):
    • 表示为entropy
    • 计算公式:(entropy = -\sum_{i=1}^{n} p_i \log_2(p_i)),其中(p_i)是样本属于第i类的概率,n是类别总数。
    • 信息熵用于表示数据的不确定性或混乱程度;熵值越高,数据的不确定性越大。
    • 信息熵对不纯度更加敏感,因此它作为指标时,决策树的生长可能会更加“精细”。然而,在高维数据或噪音较多的情况下,这可能导致过拟合。
    • 信息熵的计算涉及对数运算,因此相对于基尼系数来说,计算速度可能稍慢。

梯度提升树中的弱评估器复杂度:max_depth 

在随机森林中,控制过拟合的参数基本都处于“关闭状态”,比如:max_depth的默认值为None,表示弱评估器不限制深度,因此随机森林中长出的树基本上都是剪枝前的树,如果随机森林算法出现过拟合现象,那么我们就可以通过对弱评估器进行剪枝来限制集成算法的过拟合。然而,这种情况并不适用于Boosting算法一族。


从GBDT的默认参数我们可以看到,对GBDT来说,无论是分类器还是回归器,默认的弱评估器最大深度都为3,这说明GBDT默认就对弱评估器进行了剪枝操作。所以当GBDT等Boosting算法处于过拟合状态时,很难再通过剪枝的手段来控制过拟合,只能从数据上下手控制过拟合了(例如,使用参数max_features,在GBDT中其默认值为None)。

也因此,通常认为Boosting算法比Bagging算法更不容易过拟合,也就是说在相似的数据上,Boosting算法表现出的过拟合程度会较轻。

cross_validateKFold:

from sklearn.datasets import load_iris  
from sklearn.model_selection import cross_validate, KFold  
from sklearn.svm import SVC  
  
# 加载数据集  
iris = load_iris()  
X = iris.data  
y = iris.target  
  
# 初始化SVM分类器  
clf = SVC(kernel='linear', C=1, random_state=42)  
  
# 初始化KFold对象,进行5折交叉验证  
kf = KFold(n_splits=5, shuffle=True, random_state=42)  
  
# 使用cross_validate函数进行交叉验证  
scoring = ['accuracy', 'precision_macro', 'recall_macro']  
cv_results = cross_validate(clf, X, y, cv=kf, scoring=scoring)  
  
# 打印交叉验证结果  
print(cv_results)

# cross_validate函数会返回一个字典,其中包含了每次迭代的评分、拟合时间和评分时间等信息
  • cross_validate:这是一个用于评估模型性能的函数,它执行交叉验证并返回每次迭代的评分以及其他相关信息。
  • KFold:这是一个类,用于实现k折交叉验证的数据划分。它本身不进行评估,而是为交叉验证提供数据划分的机制。
  • GridSearchCV:这是一个类,用于执行网格搜索和交叉验证,以找到模型的最佳超参数组合。它不仅进行数据划分和模型评估,还搜索参数空间以找到最优配置。
from sklearn.model_selection import cross_validate,KFold

#定义所需的交叉验证方式
cv = KFold(n_splits=5,shuffle=True,random_state=12)

# 分类数据
X_c,y_c = load_breast_cancer(return_X_y=True,as_frame=True)

modelname = ["GBDT","RF"]
colors = ["green","orange"]
clf_models = [GBC(random_state=12),RFC(random_state=12)]

xaxis = range(1,6)
plt.figure(figsize=(10,6),dpi=65)

for name,model,color in zip(modelname,clf_models,colors):
    result = cross_validate(model,X_c,y_c,cv=cv
                            ,return_train_score=True)
    plt.plot(xaxis,result["train_score"], color=color, label = name+"_Train")
    plt.plot(xaxis,result["test_score"], color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=12)
plt.ylabel("Accuracy",fontsize=12)
plt.title("GBDT vs RF")
plt.legend()
plt.show()
  • cross_validateKFold是两个用于模型选择和评估的工具

# 回归数据
X_r,y_r = fetch_california_housing(return_X_y=True,as_frame=True)

# modelname = ["GBDT","RF"]
# colors = ["green","orange"]
reg_models = [GBR(random_state=12),RFR(random_state=12)]

xaxis = range(1,6)
plt.figure(figsize=(10,6),dpi=65)

for name,model,color in zip(modelname,reg_models,colors):
    result = cross_validate(model,X_r,y_r,cv=cv,scoring="neg_mean_squared_error"
                            ,return_train_score=True)
    plt.plot(xaxis,result["train_score"], color=color, label = name+"_Train")
    plt.plot(xaxis,result["test_score"], color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=12)
plt.ylabel("MSE",fontsize=12)
plt.title("GBDT vs RF")
plt.legend()
plt.show()

 

对GBDT来说,不纯度的衡量指标有2个:

  • friedman_mse:弗里德曼均方误差
  • squared_error:平方误差

其中平方误差我们非常熟悉,就是直接计算父节点的平方误差与子节点平方误差的加权求和之间的差异。弗里德曼均方误差是由Friedman在论文《贪婪函数估计:一种梯度提升机器》(GREEDY FUNCTION APPROXIMATION: A GRADIENT BOOSTING MACHINE)中提出的全新的误差计算方式。根据论文中的描述,弗里德曼均方误差使用调和平均数来控制左右叶子节点上的样本数量,相比普通地求均值,调和平均必须在左右叶子节点上的样本量/样本权重相差不大的情况下才能取得较大的值(F1 score也是用同样的方式来调节Precision和recall)。这种方式可以令不纯度的下降得更快,让整体分枝的效率更高 

  • 大部分时候,使用弗里德曼均方误差可以让梯度提升树得到很好的结果,因此GBDT的默认参数就是Friedman_mse。不过许多时候,我们会发现基于平方误差的分割与基于弗里德曼均方误差的分割会得到相同的结果。

梯度提升树的提前停止 

在学习机器学习理论与方法时,我们极少提及迭代的提前停止问题。在机器学习中,依赖于迭代进行工作的算法并不算多,同时课程中的数据量往往也比较小,因此难以预见需要提前停止迭代以节省计算资源或时间的情况。但对于工业界使用最广泛的GBDT而言,提前停止是需要考虑的关键问题。

对于任意需要迭代的算法,迭代的背后往往是损失函数的最优化问题。例如在逻辑回归中,我们在进行梯度下降的迭代时,是希望找到交叉熵损失函数的最小值;而在梯度提升树中,我们在一轮轮建立弱评估器过程中,也是希望找到对应损失函数的最小值。理想状态下,无论使用什么算法,只要我们能够找到损失函数上真正的最小值,那模型就达到“收敛”状态,迭代就应该被停止

然而遗憾的是,我们和算法都不知道损失函数真正的最小值是多少,而算法更不会在达到收敛状态时就自然停止。在机器学习训练流程中,我们往往是通过给出一个极限资源来控制算法的停止,比如,我们通过超参数设置允许某个算法迭代的最大次数,或者允许建立的弱评估器的个数。因此无论算法是否在很短时间内就锁定了足够接近理论最小值的次小值、或者算法早已陷入了过拟合状态、甚至学习率太低导致算法无法收敛,大多数算法都会持续(且无效地)迭代下去,直到我们给与的极限资源全部被耗尽。对于复杂度较高、数据量较大的Boosting集成算法来说,无效的迭代常常发生,因此作为众多Boosting算法的根基算法,梯度提升树自带了提前停止的相关超参数。另外,逻辑回归看起来会自然停止,是因为逻辑回归内置提前停止机制。

我们根据以下原则来帮助梯度提升树实现提前停止:

  • 当GBDT已经达到了足够好的效果(非常接近收敛状态),持续迭代下去不会有助于提升算法表现
  • GBDT还没有达到足够好的效果(没有接近收敛),但迭代过程中呈现出越迭代算法表现越糟糕的情况
  • 虽然GBDT还没有达到足够好的效果,但是训练时间太长/速度太慢,我们需要重新调整训练

在实际数据训练时,我们往往不能动用真正的测试集进行提前停止的验证,因此我们需要从训练集中划分出一小部分数据,专用于验证是否应该提前停止。那我们如何找到这个验证集损失不再下降、准确率不再上升的“某一时间点”呢?此时,我们可以规定一个阈值,例如,当连续n_iter_no_change次迭代中,验证集上损失函数的减小值都低于阈值tol,或者验证集的分数提升值都低于阈值tol的时候,我们就令迭代停止。此时,即便我们规定的n_estimators或者max_iter中的数量还没有被用完,我们也可以认为算法已经非常接近“收敛”而将训练停下。这种机制就是提前停止机制Early Stopping。这种机制中,需要设置阈值tol,用于不断检验损失函数下降量的验证集,以及损失函数连续停止下降的迭代轮数n_iter_no_change。在GBDT当中,这个流程刚好由以下三个参数控制:

  • validation_fraction:从训练集中提取出、用于提前停止的验证数据占比,值域为[0,1]。
  • n_iter_no_change:当验证集上的损失函数值连续n_iter_no_change次没有下降或下降量不达阈值时,则触发提前停止。平时则设置为None,表示不进行提前停止。
  • tol:损失函数下降的阈值,默认值为1e-4,也可调整为其他浮点数来观察提前停止的情况。

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

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

相关文章

尝试使用blazor(二)Blazor WebAssembly(WASM)与Server之间有什么区别?

要使用Blazor,你得先选择一种模式,因为它有两种模式。Blazor网络框架允许将Razor组件以不同的方式托管。它们可以在ASP.NET Core(Blazor Server)中在服务器端运行,也可以在基于WebAssembly的.NET运行时在浏览器中在客户…

便捷生活,从便民平台开始

想要生活更轻松、更便捷吗?那就来试试我们的便民平台吧!生活中的琐事总是让人头疼不已,但有了我们的便民平台,一切问题都迎刃而解! 咸阳便民平台的张总说:无论您是需要家政服务、维修安装,还是寻…

支持微信支付宝账单,极空间Docker部署一个开箱即用的私人账本『cashbook』

支持微信支付宝账单,Docker部署一个开箱即用的私人账本『cashbook』 哈喽小伙伴好,我是Stark-C~ 不知道屏幕前的各位富哥富姐们有没有请一个专业的私人财务助理管理自己的巨额资产,我不是给大家炫耀,我在月薪300的时候就已经有了…

ICC2:如何获取get_xx -filter后可用的属性有哪些?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 report_attribute -app -class cell $instname 这种直接告诉你指定cell有哪些属性,以及对应的值是什么 或者直接用list_attribute也可以 list_attribute -help可以…

STM32自己从零开始实操05:接口电路原理图

一、TTL 转 USB 驱动电路设计 1.1指路 延续使用芯片 CH340E 。 实物图 原理图与封装图 1.2数据手册重要信息提炼 1.2.1概述 CH340 是一个 USB 总线的转接芯片,实现 USB 与串口之间的相互转化。 1.2.2特点 支持常用的 MODEM 联络信号 RTS(请求发送&…

不吃饭也要搞懂的 git 命令

昨天睿哥布置了一个任务给我,让我学习一下 Git 的一些命令。 我问睿哥,到底我们在实际开发中用哪些命令会比较多,睿哥是这样回答我的: 而且他推荐我用 IDEA 自带的那个 Git 面板来执行 git 命令,他说直接敲命令太麻烦…

WPF学习(2)--类与类的继承2-在窗口的实现

一、代码分析 1.Animal.cs 1.1 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace AnimalNamespace {public class Animal{public string Name { get; set; }public int Age { get; set…

【乐吾乐2D可视化组态编辑器】条件变化,触发告警动画

条件触发告警动画 乐吾乐2D可视化组态编辑器地址:https://2d.le5le.com/ 如图所示,左侧文本图元数值一直在变化,当数值大于等于50的时候,右侧矩形图元执行告警动画,当数值小于50的时候,右侧图元恢复正常。…

Blender雕刻建模_UV展开

UV展开的标准:展平,不重叠,均匀展开 ZenUV插件 切到边模式 -Mark,标记缝合边 -Unmark,取消标记 -Unmark All,全部取消标记 -Mirror Seams,镜像缝合边 -Zen Unwrap,全部展开 纹…

Python私教张大鹏 Vue3整合AntDesignVue之Checkbox 多选框

何时使用 在一组可选项中进行多项选择时; 单独使用可以表示两种状态之间的切换,和 switch 类似。区别在于切换 switch 会直接触发状态改变,而 checkbox 一般用于状态标记,需要和提交操作配合。 案例:多选框组件 核心…

Django中使用下拉列表过滤HTML表格数据

在Django中,你可以使用下拉列表(即选择框)来过滤HTML表格中的数据。这通常涉及两个主要步骤:创建过滤表单和处理过滤逻辑。 创建过滤表单 首先,你需要创建一个表单,用于接收用户选择的过滤条件。这个表单可…

Laravel 6 - 第十九章 模型文件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

基于JSP的超市管理系统

你好呀,我是计算机学长猫哥!如果有相关需求,文末可以找到我的联系方式。 开发语言:Java 数据库:MySQL 技术:JSP MyBatis 工具:IDEA/Eclipse、Navicat、Maven 系统展示 员工管理界面图 管…

香港户口需要什么条件?有学历要求吗?最新香港落户途径详解!

香港户口需要什么条件?有学历要求吗?最新香港落户途径详解! 由于香港放开“落户”窗口,想去香港发展或者想拿香港身份的朋友都想抓住这个机会赶紧申请。 只是,香港户口办理是有条件的,而且有学历要求&…

方法分享 |公网IP怎么指定非433端口实现https访问

公网IP可以通过指定非443端口实现HTTPS访问。在网络配置中,虽然HTTPS协议默认使用443端口,但没有规定不能在其他端口上实施HTTPS服务。使用非标准端口进行HTTPS通信需要正确配置服务器和SSL证书,并确保客户端能够连接到指定的端口。下面说明如…

tracetcp下载 安装 使用 网络工具 windows trace工具 tcp协议

省流 Tracetcp是一个类似于Tracert的工具,使用如下: 1. 安装winpcap , 下载链接:WinPcap Download 2.下载tracetcp软件,下载链接: https://github.com/0xcafed00d/tracetcp/releases 命令:…

工业交换机的供电功率配置

在工业领域中,交换机作为网络设备中的重要组成部分,其供电功率配置必不可少。工业交换机的供电功率配置不仅关系到设备的稳定运行,还直接影响到整个工业生产系统的效率和安全性。因此,在选择工业交换机时,必须对供电功…

WPF视频学习-简单应用篇图书馆程序(一)

1.登录界面和主界面跳转 先把登录界面分为三行《Grid》 先添加两行&#xff1a; <Grid><!--//分三行&#xff0c;行排列--><Grid.RowDefinitions><RowDefinition Height"auto"/><RowDefinition Height"auto"/><RowDef…

GD32 MCU超频后无法再次下载程序的解决办法

我们知道&#xff0c;MCU的系统时钟主频就相当于人的心跳或脉搏&#xff0c;为所有的工作单元提供时间基数&#xff0c;所以一般在程序最开始的地方都需要进行主频配置。 GD32固件库中提供了多种宏定义&#xff0c;可以很方便的将系统时钟配置为想要的频率。 GD32固件库中所用…

[C#]winform使用onnxruntime部署LYT-Net轻量级低光图像增强算法

【训练源码】 https://github.com/albrateanu/LYT-Net 【参考源码】 https://github.com/hpc203/Low-Light-Image-Enhancement-onnxrun 【算法介绍】 一、研究动机 1.研究目标 研究的目标是提出一种轻量级的基于YUV Transformer 的网络&#xff08;LYT-Net&#xff09;&…