【解决(几乎)任何机器学习问题】:超参数优化篇(超详细)

这篇文章相当长,您可以添加至收藏夹,以便在后续有空时候悠闲地阅读。
有了优秀的模型,就有了优化超参数以获得最佳得分模型的难题。那么,什么是超参数优化呢?假设您的机器学习项⽬有⼀个简单的流程。有⼀个数据集,你直接应⽤⼀个模型,然后得到结 果。模型在这⾥的参数被称为超参数,即控制模型训练/拟合过程的参数。如果我们⽤ SGD 训练线性回归,模型的参数是斜率和偏差,超参数是学习率。你会发现我在本章和本书中交替使⽤这些术语。假设模型中有三个参数 a、b、c,所有这些参数都可以是 1 到 10 之间的整数。这些参数 的 "正确 "组合将为您提供最佳结果。因此,这就有点像⼀个装有三拨密码锁的⼿提箱。不过,三拨密码锁只有⼀个正确答案。⽽模型有很多正确答案。那么,如何找到最佳参数呢?⼀种⽅法是对所有组合进⾏评估,看哪种组合能提⾼指标。让我们看看如何做到这⼀点。
best_accuracy = 0
best_parameters = {"a": 0, "b": 0, "c": 0}
for a in range(1, 11):for b in range(1, 11):for c in range(1, 11):model = MODEL(a, b, c)model.fit(training_data)preds = model.predict(validation_data)accuracy = metrics.accuracy_score(targets, preds)if accuracy > best_accuracy:best_accuracy = accuracybest_parameters["a"] = abest_parameters["b"] = bbest_parameters["c"] = c
在上述代码中,我们从 1 到 10 对所有参数进⾏了拟合。因此,我们总共要对模型进⾏ 1000 次(10 x 10 x 10)拟合。这可能会很昂贵,因为模型的训练需要很⻓时间。不过,在这种情况下应 该没问题,但在现实世界中,并不是只有三个参数,每个参数也不是只有⼗个值。 ⼤多数模型参 数都是实数,不同参数的组合可以是⽆限的。
让我们看看 scikit-learn 的随机森林模型。
RandomForestClassifier(n_estimators=100,criterion='gini',max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight_fraction_leaf=0.0,max_features='auto',max_leaf_nodes=None,min_impurity_decrease=0.0,min_impurity_split=None,bootstrap=True,oob_score=False,n_jobs=None,random_state=None,verbose=0,warm_start=False,class_weight=None,ccp_alpha=0.0,max_samples=None,)
有 19 个参数,⽽所有这些参数的所有组合,以及它们可以承担的所有值,都将是⽆穷⽆尽的。通常情况下,我们没有⾜够的资源和时间来做这件事。因此,我们指定了⼀个参数⽹格。在这个⽹格上寻找最佳参数组合的搜索称为⽹格搜索。我们可以说,n_estimators 可以是 100、200、250、300、400、500;max_depth 可以是 1、2、5、7、11、15;criterion 可以是 gini 或 entropy。这些参数看起来并不多,但如果数据集过⼤,计算起来会耗费⼤量时间。我们可以像之前⼀样创建三个 for 循环,并在验证集上计算得分,这样就能实现⽹格搜索。还必须注意的是,如果要进⾏ k 折交叉验证,则需要更多的循环,这意味着需要更多的时间来找到完美的参数。因此,⽹格搜索并不流⾏。让我们以根据 ⼿机配置预测⼿机价格范围 数据集为例,看看它是如何实现的。

 

1 :⼿机配置预测⼿机价格范围数据集展⽰
训练集中只有 2000 个样本。我们可以轻松地使⽤分层 kfold 和准确率作为评估指标。我们将使⽤ 具有上述参数范围的随机森林模型,并在下⾯的⽰例中了解如何进⾏⽹格搜索。
# rf_grid_search.py
import numpy as np
import pandas as pd
from sklearn import ensemble
from sklearn import metrics
from sklearn import model_selectionif __name__ == "__main__":df = pd.read_csv("./input/mobile_train.csv")X = df.drop("price_range", axis=1).valuesy = df.price_range.valuesclassifier = ensemble.RandomForestClassifier(n_jobs=-1)param_grid = {"n_estimators": [100, 200, 250, 300, 400, 500],"max_depth": [1, 2, 5, 7, 11, 15],"criterion": ["gini", "entropy"]}model = model_selection.GridSearchCV(estimator=classifier,param_grid=param_grid,scoring="accuracy",verbose=10,n_jobs=1,cv=5)model.fit(X, y)print(f"Best score: {model.best_score_}")print("Best parameters set:")best_parameters = model.best_estimator_.get_params()for param_name in sorted(param_grid.keys()):print(f"\t{param_name}: {best_parameters[param_name]}")
这⾥打印了很多内容,让我们看看最后⼏⾏。
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 , score = 0.895 ,
total = 1.0 s
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 ...............
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 , score = 0.890 ,
total = 1.1 s
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 ...............
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 , score = 0.910 ,
total = 1.1 s
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 ...............
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 , score = 0.880 ,
total = 1.1 s
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 ...............
[ CV ] criterion = entropy , max_depth = 15 , n_estimators = 500 , score = 0.870 , total = 1.1 s
[ Parallel ( n_jobs = 1 )]: Done 360 out of 360 | elapsed : 3.7 min finished
Best score : 0.889
Best parameters set :
criterion : 'entropy'
max_depth : 15
n_estimators : 500
最后,我们可以看到,5折交叉检验最佳得分是 0.889,我们的⽹格搜索得到了最佳参数。我们可 以使⽤的下⼀个最佳⽅法是 随机搜索 。在随机搜索中,我们随机选择⼀个参数组合,然后计算交 叉验证得分。这⾥消耗的时间⽐⽹格搜索少,因为我们不对所有不同的参数组合进⾏评估。我们 选择要对模型进⾏多少次评估,这就决定了搜索所需的时间。代码与上⾯的差别不⼤。除了GridSearchCV 外,我们使⽤ RandomizedSearchCV。
if __name__ == "__main__":classifier = ensemble.RandomForestClassifier(n_jobs=-1)param_grid = {"n_estimators": np.arange(100, 1500, 100),"max_depth": np.arange(1, 31),"criterion": ["gini", "entropy"]}model = model_selection.RandomizedSearchCV(estimator=classifier,param_distributions=param_grid,n_iter=20,scoring="accuracy",verbose=10,n_jobs=1,cv=5)model.fit(X, y)print(f"Best score: {model.best_score_}")print("Best parameters set:")best_parameters = model.best_estimator_.get_params()for param_name in sorted(param_grid.keys()):print(f"\t{param_name}: {best_parameters[param_name]}")

我们更改了随机搜索的参数⽹格,结果似乎有了些许改进。

Best score : 0.8905
Best parameters set :
criterion : entropy
max_depth : 25
n_estimators : 300
如果迭代次数较少,随机搜索⽐⽹格搜索更快。使⽤这两种⽅法,你可以为各种模型找到最优参 数,只要它们有拟合和预测功能,这也是 scikit-learn 的标准。有时,你可能想使⽤管道。例如假设我们正在处理⼀个多类分类问题。在这个问题中,训练数据由两列⽂本组成,你需要建⽴⼀个模型来预测类别。让我们假设你选择的管道是⾸先以半监督的⽅式应⽤ tf-idf,然后使⽤SVD 和SVM 分类器。现在的问题是,我们必须选择 SVD 的成分,还需要调整 SVM 的参数。下⾯的代段展⽰了如何做到这⼀点。

import numpy as np
import pandas as pd
from sklearn import metrics
from sklearn import model_selection
from sklearn import pipeline
from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVCdef quadratic_weighted_kappa(y_true, y_pred):return metrics.cohen_kappa_score(y_true, y_pred, weights="quadratic")if __name__ == '__main__':train = pd.read_csv('./input/train.csv')idx = test.id.values.astype(int)train = train.drop('id', axis=1)test = test.drop('id', axis=1)y = train.relevance.valuestraindata = list(train.apply(lambda x:'%s %s' % (x['text1'], x['text2']), axis=1))testdata = list(test.apply(lambda x:'%s %s' % (x['text1'], x['text2']), axis=1))tfv = TfidfVectorizer(min_df=3,max_features=None,strip_accents='unicode',analyzer='word',token_pattern=r'\w{1,}',ngram_range=(1, 3),use_idf=1,smooth_idf=1,sublinear_tf=1,stop_words='english')tfv.fit(traindata)X = tfv.transform(traindata)X_test = tfv.transform(testdata)svd = TruncatedSVD()scl = StandardScaler()svm_model = SVC()clf = pipeline.Pipeline([('svd', svd),('scl', scl),('svm', svm_model)])param_grid = {'svd__n_components': [200, 300],'svm__C': [10, 12]}kappa_scorer = metrics.make_scorer(quadratic_weighted_kappa,greater_is_better=True)model = model_selection.GridSearchCV(estimator=clf,param_grid=param_grid,scoring=kappa_scorer,verbose=10,n_jobs=-1,refit=True,cv=5)model.fit(X, y)print("Best score: %0.3f" % model.best_score_)print("Best parameters set:")best_parameters = model.best_estimator_.get_params()for param_name in sorted(param_grid.keys()):print("\t%s: %r" % (param_name, best_parameters[param_name]))best_model = model.best_estimator_best_model.fit(X, y)preds = best_model.predict(X_test)
这⾥显⽰的管道包括 SVD(奇异值分解)、标准缩放和 SVM(⽀持向量机)模型。请注意,由于没有训练数据,您⽆法按原样运⾏上述代码。当我们进⼊⾼级超参数优化技术时,我们可以使⽤ 不同类型的 最⼩化算法 来研究函数的最⼩化。这可以通过使⽤多种最⼩化函数来实现,如下坡单 纯形算法、内尔德-梅德优化算法、使⽤⻉叶斯技术和⾼斯过程寻找最优参数或使⽤遗传算法。 我将在 "集合与堆叠(ensembling and stacking) "⼀章中详细介绍下坡单纯形算法和 NelderMead 算法的应⽤。⾸先,让我们看看⾼斯过程如何⽤于超参数优化。这类算法需要⼀个可以优化的函数。⼤多数情况下,都是最⼩化这个函数,就像我们最⼩化损失⼀样。因此,⽐⽅说,你想找到最佳参数以获得最佳准确度,显然,准确度越⾼越好。现在,我们不能最⼩化精确度,但我们可以将精确度乘以-1。这样,我们是在最⼩化精确度的负值,但事实上,我们是在最⼤化精确度。 在⾼斯过程中使⽤⻉叶斯优化,可以使⽤ scikit-optimize (skopt) 库中的 gp_minimize 函数。让我们看看如何使⽤该函数调整随机森林模型的参数。

# rf_gp_minimize.py
import numpy as np
import pandas as pd
from functools import partial
from sklearn import ensemble
from sklearn import metrics
from sklearn import model_selection
from skopt import gp_minimize
from skopt import spacedef optimize(params, param_names, x, y):params = dict(zip(param_names, params))model = ensemble.RandomForestClassifier(**params)kf = model_selection.StratifiedKFold(n_splits=5)accuracies = []for idx in kf.split(X=x, y=y):train_idx, test_idx = idx[0], idx[1]xtrain = x[train_idx]ytrain = y[train_idx]xtest = x[test_idx]ytest = y[test_idx]model.fit(xtrain, ytrain)preds = model.predict(xtest)fold_accuracy = metrics.accuracy_score(ytest, preds)accuracies.append(fold_accuracy)return -1 * np.mean(accuracies)if __name__ == "__main__":df = pd.read_csv("./input/mobile_train.csv")X = df.drop("price_range", axis=1).valuesy = df.price_range.valuesparam_space = [space.Integer(3, 15, name="max_depth"),space.Integer(100, 1500, name="n_estimators"),space.Categorical(["gini", "entropy"], name="criterion"),space.Real(0.01, 1, prior="uniform", name="max_features")]param_names = ["max_depth","n_estimators","criterion","max_features"]optimization_function = partial(optimize,param_names=param_names,x=X,y=y)result = gp_minimize(optimization_function,dimensions=param_space,n_calls=15,n_random_starts=10,verbose=10)best_params = dict(zip(param_names,result.x))print(best_params)

这同样会产⽣⼤量输出,最后⼀部分如下所⽰。

Iteration No : 14 started . Searching for the next optimal point .
Iteration No : 14 ended . Search finished for the next optimal point .
Time taken : 4.7793
Function value obtained : - 0.9075
Current minimum : - 0.9075
Iteration No : 15 started . Searching for the next optimal point .
Iteration No : 15 ended . Search finished for the next optimal point .
Time taken : 49.4186
Function value obtained : - 0.9075
Current minimum : - 0.9075
{ 'max_depth' : 12 , 'n_estimators' : 100 , 'criterion' : 'entropy' ,
'max_features' : 1.0 }
看来我们已经成功突破了 0.90的准确率。这真是太神奇了!
我们还可以通过以下代码段查看(绘制)我们是如何实现收敛的。
from skopt . plots import plot_convergence
plot_convergence ( result )

收敛图如图 2 所⽰。

2:随机森林参数优化的收敛图
Scikit- optimize 就是这样⼀个库。 hyperopt 使⽤树状结构帕岑估计器(TPE)来找到最优参数。请看下⾯的代码⽚段,我在使⽤ hyperopt 时对之前的代码做了最⼩的改动。

import numpy as np
import pandas as pd
from functools import partial
from sklearn import ensemble
from sklearn import metrics
from sklearn import model_selection
from hyperopt import hp, fmin, tpe, Trials
from hyperopt.pyll.base import scopedef optimize(params, x, y):model = ensemble.RandomForestClassifier(**params)kf = model_selection.StratifiedKFold(n_splits=5)accuracies = []for idx in kf.split(X=x, y=y):train_idx, test_idx = idx[0], idx[1]xtrain = x[train_idx]ytrain = y[train_idx]xtest = x[test_idx]ytest = y[test_idx]model.fit(xtrain, ytrain)preds = model.predict(xtest)fold_accuracy = metrics.accuracy_score(ytest, preds)accuracies.append(fold_accuracy)return -1 * np.mean(accuracies)if __name__ == "__main__":df = pd.read_csv("./input/mobile_train.csv")X = df.drop("price_range", axis=1).valuesy = df.price_range.valuesparam_space = {"max_depth": scope.int(hp.quniform("max_depth", 1, 15, 1)),"n_estimators": scope.int(hp.quniform("n_estimators", 100, 1500, 1)),"criterion": hp.choice("criterion", ["gini", "entropy"]),"max_features": hp.uniform("max_features", 0, 1)}optimization_function = partial(optimize,x=X,y=y)trials = Trials()hopt = fmin(fn=optimization_function,space=param_space,algo=tpe.suggest,max_evals=15,trials=trials)print(hopt)
正如你所看到的,这与之前的代码并⽆太⼤区别。你必须以不同的格式定义参数空间,还需要改
变实际优化部分,⽤ hyperopt 代替 gp_minimize。结果相当不错!
❯ python rf_hyperopt . py
100 %| ██████████████████ | 15 / 15 [ 0 4 : 38 < 0 0 : 0 0 , 18.57 s / trial , best loss : -
0.9095000000000001 ]
{ 'criterion' : 1 , 'max_depth' : 11.0 , 'max_features' : 0.821163568049807 ,
'n_estimators' : 806.0 }

我们得到了⽐以前更好的准确度和⼀组可以使⽤的参数。请注意,最终结果中的标准是 1。这意味着选择了 1,即熵。 上述调整超参数的⽅法是最常⻅的,⼏乎适⽤于所有模型:线性回归、逻辑回归、基于树的⽅法、梯度提升模型(如 xgboost、lightgbm),甚⾄神经⽹络!
虽然这些⽅法已经存在,但学习时必须从⼿动调整超参数开始,即⼿⼯调整。⼿动调整可以帮助 你学习基础知识,例如,在梯度提升中,当你增加深度时,你应该降低学习率。如果使⽤⾃动⼯ 具,就⽆法学习到这⼀点。请参考下表,了解应如何调整。RS* 表⽰随机搜索应该更好.
⼀旦你能更好地⼿动调整参数,你甚⾄可能不需要任何⾃动超参数调整。创建⼤型模型或引⼊⼤ 量特征时,也容易造成训练数据的过度拟合。为避免过度拟合,需要在训练数据特征中引⼊噪声 或对代价函数进⾏惩罚。这种惩罚称为 正则化 ,有助于泛化模型。在线性模型中,最常⻅的正则 化类型是 L1 和 L2。L1 也称为 Lasso 回归,L2 称为 Ridge 回归。说到神经⽹络,我们会使⽤ dropout、添加增强、噪声等⽅法对模型进⾏正则化。利⽤超参数优化,还可以找到正确的惩罚⽅法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Rust】使用Rust实现一个简单的shell

一、Rust Rust是一门系统编程语言&#xff0c;由Mozilla开发并开源&#xff0c;专注于安全、速度和并发性。它的主要目标是解决传统系统编程语言&#xff08;如C和C&#xff09;中常见的内存安全和并发问题&#xff0c;同时保持高性能和底层控制能力。 Rust的特点包括&#x…

java8-使用流-2

筛选各异的元素 流还支持一个叫作aistinct的方法&#xff0c;它会返回一个元素各异(根据流所生成元素的hashcode和eguals方法实现)的流。例如&#xff0c;以下代码会筛选出列表中所有的偶数&#xff0c;并确保没有重复。图5-2直观地显示了这个过程。 List<Integer>number…

Panalog 日志审计系统 sessiptbl.php 前台RCE漏洞复现

0x01 产品简介 Panalog是一款日志审计系统,方便用户统一集中监控、管理在网的海量设备。 0x02 漏洞概述 Panalog日志审计系统 sessiptbl.php接口处存在远程命令执行漏洞,攻击者可执行任意命令,接管服务器权限。 0x03 影响范围 version <= MARS r10p1Free 0x04 复现…

勒索病毒最新变种.faust勒索病毒来袭,如何恢复受感染的数据?

引言&#xff1a; 随着我们进入数字化时代&#xff0c;数据的重要性变得愈发显著&#xff0c;而网络安全威胁也日益增加。.faust勒索病毒是其中一种备受恶意分子钟爱的危险工具&#xff0c;它通过加密用户文件并勒索高额赎金来对个人和组织发起攻击。本文将深入探讨.faust勒索…

thinkphp+vue企业产品展示网站f7enu

本文首先介绍了企业产品展示网站管理技术的发展背景与发展现状&#xff0c;然后遵循软件常规开发流程&#xff0c;首先针对系统选取适用的语言和开发平台&#xff0c;根据需求分析制定模块并设计数据库结构&#xff0c;再根据系统总体功能模块的设计绘制系统的功能模块图&#…

紫微斗数双星组合:廉贞破军在卯酉

文章目录 前言内容总结 前言 紫微斗数双星组合&#xff1a;廉贞破军在卯酉 内容 紫微斗数双星组合&#xff1a;廉贞破军在卯酉 性格分析 廉贞星、破军星二星同宫&#xff0c;具有冒险开创的精神和领导能力&#xff0c;忍耐力强&#xff0c;工作积极稳重&#xff0c;冲劲大&a…

FreeSWITCH在session上执行定时挂机与取消

一、实验场景环境描述 FreeSWITCH测试机&#xff1a;192.168.137.32 会议室&#xff1a; test1 分机&#xff1a; 1000 模拟的场景&#xff1a; 1&#xff09;会议室test1邀请分机1000加入会议室 在邀请时&#xff0c;添加定时挂机任务。 2&#xff09;分机1000接通后&#x…

【51单片机】利用STC-ISP软件工具【定时器计算器】配置【定时器】教程(详细图示)(AT89C52)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

Python入门知识点分享——(二十一)多继承和运算符重载

在介绍新的知识之前&#xff0c;我们先对之前的内容做一点补充&#xff0c;在面向对象编程的过程中&#xff0c;一个对象常常被要求具备多方面的功能&#xff0c;从而和多个类产生联系&#xff0c;而这一步的实现就用到了“多继承”。多继承是指一个子类可以继承自多个父类&…

QGIS教程 加载shape数据 矢量数据(批量)

一. 前言 本篇文章主要介绍QGIS的使用&#xff0c;包括如何加载矢量shape数据、查看数据属性、如何加载txt属性数据、怎么用脚本批量加载矢量数据等内容。 如果想了解QGIS&#xff0c;可以参考博文&#xff1a; QGIS基本介绍 如果想了解shape数据格式详情&#xff0c;可以参考…

CVE-2023-41892 漏洞复现

CVE-2023-41892 开题&#xff0c;是一个RCE Thanks for installing Craft CMS! You’re looking at the index.twig template file located in your templates/ folder. Once you’re ready to start building out your site’s front end, you can replace this with someth…

leetcode刷题--贪心算法

七. 贪心算法 文章目录 七. 贪心算法1. 605 种花问题2. 121 买卖股票的最佳时机3. 561 数组拆分4. 455 分发饼干5. 575 分糖果6. 135 分发糖果7. 409 最长回文串8. 621 任务调度器9. 179 最大数10. 56 合并区间11. 57 插入区间13. 452 用最少数量的箭引爆气球14. 435 无重叠区间…

【AIGC】Stable Diffusion的ControlNet插件

ControlNet 介绍 ControlNet 插件是 Stable Diffusion 中的一个重要组件&#xff0c;用于提供对模型的控制和调整。以下是 ControlNet 插件的主要特点和功能&#xff1a; 模型控制&#xff1a; ControlNet 允许用户对 Stable Diffusion 中的模型进行精细的控制和调整。用户可以…

[GXYCTF2019]禁止套娃

进来发现只有这句话&#xff0c;习惯性访问一下flag.php&#xff0c;发现不是404&#xff0c;那就证明flag就在这了&#xff0c;接下来要想办法拿到flag.php的源码。 这道题是.git文件泄露网页源码&#xff0c;githack拿到index.php源码 这里观察到多次判断&#xff0c;首先要…

电脑监控屏幕软件有哪些(监控电脑屏幕的软件)

随着信息技术的迅猛发展&#xff0c;电脑屏幕监控软件已成为企业、家庭以及教育机构保护数据安全、提升工作效率以及进行行为分析的重要工具。本文将详细介绍几款主流的电脑屏幕监控软件&#xff0c;包括它们的功能、特点以及适用场景&#xff0c;帮助读者更好地了解并选择合适…

Flink理论—容错之状态后端(State Backends)

Flink理论—容错之状态后端(State Backends) Flink 使用流重放和 检查点的组合来实现容错。检查点标记每个输入流中的特定点以及每个运算符的相应状态。通过恢复运算符的状态并从检查点点重放记录&#xff0c;可以从检查点恢复流数据流&#xff0c;同时保持一致性 容错机制不…

【sgSearch】自定义组件:常用搜索栏筛选框组件(包括表格高度变化兼容)。

sgSearch源码 <template><div :class"$options.name" :expand"expandSearch" :showCollapseBtn"showCollapseBtn"><!-- v-clickoutside"(d) > (expandSearch false)" --><ul class"search-list"&…

【教学类-16-02】20240214《数字卡片1-9(正方形9格)华光彩云_CNKI》

背景需求&#xff1a; 前期坐过长方形A4纸的数字卡片 【教学类-16-01】20221121《数字卡片9*2》&#xff08;中班)_数字卡片pdf-CSDN博客文章浏览阅读897次。【教学类-16-01】20221121《数字卡片9*2》&#xff08;中班)_数字卡片pdfhttps://blog.csdn.net/reasonsummer/artic…

最短路径(dijstra算法,链式前向星,堆优化)

【模板】单源最短路径&#xff08;弱化版&#xff09; 对于这题我们使用邻接矩阵的话会导致弓箭复杂度会大大提升&#xff0c;所以我们就需要学习一种新的数据结构&#xff0c;名叫链式前向星&#xff0c;在链式前向星中&#xff0c;我们需要定义一个结构体数组&#xff0c;其中…

【Go语言】Go项目工程管理

GO 项目工程管理&#xff08;Go Modules&#xff09; Go 1.11 版本开始&#xff0c;官方提供了 Go Modules 进行项目管理&#xff0c;Go 1.13开始&#xff0c;Go项目默认使用 Go Modules 进行项目管理。 使用 Go Modules的好处是不再需要依赖 GOPATH&#xff0c;可以在任意位…