机器学习实战教程(九):模型泛化

news2024/9/21 12:43:50

泛化能力

模型泛化是指机器学习模型对新的、未见过的数据的适应能力。在机器学习中,我们通常会将已有的数据集划分为训练集和测试集,使用训练集训练模型,然后使用测试集来评估模型的性能。模型在训练集上表现得好,并不一定能在测试集或实际应用中表现得好。因此,我们需要保证模型具有良好的泛化能力,才能确保其在实际场景中的效果。

为了提高模型的泛化能力,我们通常需要采取一系列措施,例如增加数据集的大小、特征选择、特征缩放、正则化、交叉验证等。通过这些方法可以减少模型的过拟合,提高对新数据的预测能力。

总之,模型泛化是机器学习中非常重要的一个概念。它直接关系到模型在实际应用中的效果,并且也是评估机器学习算法和模型的重要指标之一。

模型评价与选择

差错分析

机器预测时就好像在投飞镖,越接近靶心则预测越准。可以把差错分为两类:偏差(bias)和方差(variance)。可以用下图来形象描绘:
在这里插入图片描述
具体到学习任务上,若假设函数取得不够好,拟合结果可能会出现两种问题:

  • 欠拟合(underfit):参数过少,假设函数太不自由,过于简单,连样本集都拟合不好,预测时容易偏向一侧,偏差大。
  • 过拟合(overfit):参数过多,假设函数太自由,不抗干扰,对样本集拟合得很好,但是假设函数过于畸形,预测时忽左忽右,方差大。

欠拟合与过拟合可用下图来形象地说明:
在这里插入图片描述
在改变模型的复杂度和训练集大小时,训练集和测试集的误差的函数图(改变模型复杂度时的误差):
在这里插入图片描述
改变数据集时的误差

解决欠拟合比较简单,增加参数或增加特征就行了,麻烦的是过拟合。
解决过拟合的办法有:

  • 减少该模型的参数,或者改为更简单的模型。
  • 正则化。
  • 增大训练集,减少噪音成分等。

泛化误差

θ \theta θ代表超参数, J 未知 J_{未知} J未知 { \{ { θ \theta θ } \} }代表训练出模型 θ \theta θ参数后对于未知数据的误差,越小泛化能力越强, J t e s t J_{test} Jtest { \{ { θ \theta θ } \} }代表模型对测试机的误差,越小泛化能力越强。

我们希望我们的模型有泛化能力,即面对未训练到的、未知的情景也能发挥作用。泛化误差(generalization error)指的是模型在处理未知数据时的代价函数: J 未知 J_{未知} J未知 { \{ { θ \theta θ } \} }
的值,它可以量化模型的泛化能力。
然而,我们训练和测试模型时,并没有未知的数据。我们会根据模型在训练集上的表现改进模型,再进行训练与测试。但在测试集上最终算出的: J t e s t J_{test} Jtest { \{ { θ \theta θ } \} }已经对测试集进行优化了,它明显对泛化误差的估计过于乐观,会偏低。也就是说,把模型放在实际应用中的效果,会比预想的差很多。
为了解决这个问题,人们提出了交叉验证(cross validation)的方法

交叉验证

交叉验证的步骤

  1. 把训练集进一步分为子训练集与交叉验证集。把测试集藏好,先不用它。(测试集是对未知数据的模拟)
  2. 使用各种不同的模型在子训练集上训练,并测出各模型在交叉验证集上的 J c v J_{cv} Jcv { \{ { θ \theta θ } \} }
  3. 选择 J c v J_{cv} Jcv { \{ { θ \theta θ } \} }最小的模型,认为它最佳。把子训练集和交叉验证集合并为训练集,训练出最终的模型。

在这里插入图片描述
交叉验证的改进方法是K折(K-fold)交叉验证(图6):把训练集分为许多小块,每一种情况取其中一小块作为交叉验证集,其余部分合并作为子训练集,求出该模型的 J c v J_{cv} Jcv { \{ { θ \theta θ } \} },把每一种情况算遍,求出该模型的平均 J c v J_{cv} Jcv { \{ { θ \theta θ } \} },认为平均最小的模型为最佳模型。最终仍然是用整个训练集训练最佳模型,在测试集上估计泛化误差。

在这里插入图片描述
K折交叉验证的优点是进一步确保交叉验证集没有特殊性,对泛化误差的估计更为准确。

KFold拆分

在sklearn中,我们可以使用KFold类来实现k折交叉验证。
在进行k折交叉验证时,KFold对象会将原始数据集随机分成k个近似大小的子集,每个子集称为“折”(fold)。,比如10个元素数组,k=5的话会拆分为5个数据集,每个折数据集就是2个,5个折数据集都会被作为一次测试机,所以会有5个组合。

from sklearn.model_selection import KFold
import numpy as np

# 创建一个包含10个元素的数组作为样本数据
X = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 定义K值
k = 5

# 创建KFold对象,并指定n_splits参数为K
kf = KFold(n_splits=k)

# 遍历KFold对象中的每一组训练集和测试集
for train_index, test_index in kf.split(X):
    print("train_index:", train_index, "test_index:", test_index)

输出结果如下:

train_index: [2 3 4 5 6 7 8 9] test_index: [0 1]
train_index: [0 1 4 5 6 7 8 9] test_index: [2 3]
train_index: [0 1 2 3 6 7 8 9] test_index: [4 5]
train_index: [0 1 2 3 4 5 8 9] test_index: [6 7]
train_index: [0 1 2 3 4 5 6 7] test_index: [8 9]

fold的值也就决定了最后使用cv数据集验证的得分个数。

cross_val_score实战

cross_val_score函数是Scikit-learn库中用于评估模型性能的快速方法之一。它计算基于交叉验证的模型评分,并返回每个fold的测试性能得分。与KFold不同,cross_val_score不需要显示拆分数据集。您只需提供模型和数据集即可进行评估,该函数将自动处理交叉验证过程,从而使代码更加简洁和易于理解。

数据集和模型

load_digits 是 Scikit-learn 库中的一个函数,用于加载手写数字图像数据集。这个数据集包含 8x8 像素大小的 1797 张手写数字图像,每张图像都对应一个 0 到 9 的数字标签。

from sklearn.datasets import load_digits

digits = load_digits()
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=1, ncols=5, figsize=(10, 3))

for i, ax in enumerate(axes):
    ax.imshow(digits.images[i], cmap='gray')
    ax.set_title(digits.target[i])

plt.show()

在这里插入图片描述
在Scikit-learn库中的KNeighborsClassifier实现了k近邻算法,其中的超参数k和p影响着模型的性能。

  • n_neighbors(即k):指定要考虑的最近邻居的个数。默认情况下,它为5,表示预测一个新样本时将使用数据集中距离其最近的5个数据点的标签,5个中最多的那个标签就是当前数据的标签。
  • p:用于计算距离的指标。默认情况下,使用Minkowski距离,p 为2,表示使用欧几里得距离。不同的 p 值对应不同的距离度量方式,例如,p=1 表示曼哈顿距离,p=3 可以使用一种更为复杂的曼哈顿距离度量方式。

使用数据集和测试集获取最佳k,p

将数据集拆分为训练集和测试集,然后k从1到11,p从1到6,测试训练集的得分,得到最佳的k和p。

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

digits = datasets.load_digits()
x = digits.data
y = digits.target

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4, random_state=666)

best_score, best_p, best_k = 0, 0, 0 
for k in range(2, 11):
    for  p in range(1, 6):
        knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
        knn_clf.fit(x_train, y_train)
        score = knn_clf.score(x_test, y_test)
        if score > best_score:
            best_score, best_p, best_k = score, p, k

print("Best K=", best_k)
print("Best P=", best_p)
print("Best score=", best_score)

输出结果:

Best K= 3
Best P= 4
Best score= 0.9860917941585535

使用交叉验证获取最佳k,p

cross_val_score函数默认使用的交叉验证方法是3-Fold交叉验证,即将数据集分为3个相等的部分,其中2个部分用于训练,1个部分用于测试。在每个fold迭代中,使用测试集得到性能度量得分,然后将所有fold的结果平均并返回。

需要注意的是,cross_val_score还有一个名为cv的参数,可以用来指定交叉验证的折叠数量,即k值。例如,cv=5表示5-Fold交叉验证,将数据集拆分为5个相等的部分,其中4个部分用于训练,1个部分用于测试。对于分类问题和回归问题,通常选择 3, 5 或 10 折交叉验证。通常,交叉验证的折叠数量越多,模型的评估结果越可靠,但计算成本也会增加。

总之,在没有显式设置cv参数时,默认情况下cross_val_score使用的是3-Fold交叉验证,即默认的k值是3。

best_score, best_p, best_k = 0, 0, 0 
for k in range(2, 11):
    for  p in range(1, 6):
        knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
        scores = cross_val_score(knn_clf, x_train, y_train)
        score = np.mean(scores)
        if score > best_score:
            best_score, best_p, best_k = score, p, k

print("Best K=", best_k)
print("Best P=", best_p)
print("Best score=", best_score)

输出

Best K= 2
Best P= 2
Best score= 0.9823599874006478

对比第一种情况,我们发现得到的最优超参数是不一样的,虽然score会稍微低一些,但是一般第二种情况更加可信。但是这个score只是说明这组参数最优,并不是指的是模型对于测试集的准确率,因此接下来看一下准确率。

best_knn_clf = KNeighborsClassifier(weights='distance', n_neighbors=2, p=2)
best_knn_clf.fit(x_train, y_train)
best_knn_clf.score(x_test, y_test)

输出结果:0.980528511821975,这才是模型的准确度。

正则化(regularization)

原理

在这里插入图片描述
想要理解什么是正则化,首先我们先来了解上图的方程式。当训练的特征和数据很少时,往往会造成欠拟合的情况,对应的是左边的坐标;而我们想要达到的目的往往是中间的坐标,适当的特征和数据用来训练;但往往现实生活中影响结果的因素是很多的,也就是说会有很多个特征值,所以训练模型的时候往往会造成过拟合的情况,如上图所示。
以图中的公式为例,往往我们得到的模型是:

θ 0 + θ 1 x + θ 2 x 2 + θ 3 x 3 + θ 4 x 4 \theta_{0}+\theta_{1}x+\theta_{2}x^2+\theta_{3}x^3+\theta_{4}x^4 θ0+θ1x+θ2x2+θ3x3+θ4x4

为了能够得到中间坐标的图形,肯定是希望θ3和θ4越小越好,因为这两项越小就越接近于0,就可以得到中间的图形了。
对于损失函数:
( 1 2 m [ ∑ i = 1 m ( h θ ( x i ) − y i ) 2 ] ) ({1\over2m}[\sum_{i=1}^{m}{(h_\theta(x^i)-y^i)^2}]) (2m1[i=1m(hθ(xi)yi)2])
在线性回归中,就是通过最小二乘法计算损失函数的最小值
m i n ( 1 2 m [ ∑ i = 1 m ( h θ ( x i ) − y i ) 2 ] ) min({1\over2m}[\sum_{i=1}^{m}{(h_\theta(x^i)-y^i)^2}]) min(2m1[i=1m(hθ(xi)yi)2])
而计算出每个特征的 θ \theta θ值。
如果损失函数加上一个数求最小值,那个这个数肯定越趋近于0,最小是肯定越小
那么这个值加什么了,我们是希望 θ \theta θ趋近于0对于损失函数的影响越小越好,也就是减少特征。
把公式通用化得:
1 2 m [ ∑ i = 1 m ( h θ ( x i ) − y i ) 2 ] ) + λ ∑ j = 1 n θ j 2 {1\over2m}[\sum_{i=1}^{m}{(h_\theta(x^i)-y^i)^2}])+\lambda\sum_{j=1}^{n}\theta_{j}^2 2m1[i=1m(hθ(xi)yi)2])+λj=1nθj2

为了损失函数求得最小值,使θ值趋近于0,这就达到了我们的目的。
相当于在原始损失函数中加上了一个惩罚项(λ项)
这就是防止过拟合的一个方法,通常叫做L2正则化,也叫作岭回归。

我们可以认为加入L2正则项后,估计参数长度变短了,这在数学上被称为特征缩减(shrinkage)。

shrinkage方法介绍:指训练求解参数过程中考虑到系数的大小,通过设置惩罚系数,使得影响较小的特征的系数衰减到0,只保留重要特征的从而减少模型复杂度进而达到规避过拟合的目的。常用的shinkage的方法有Lasso(L1正则化)和岭回归(L2正则化)等。
Lasso(L1正则化)公式:
1 2 m [ ∑ i = 1 m ( h θ ( x i ) − y i ) 2 ] + λ ∑ j = 1 n ∣ θ j ∣ {1\over2m}[\sum_{i=1}^{m}{(h_\theta(x^i)-y^i)^2}]+\lambda\sum_{j=1}^{n}|\theta_{j}| 2m1[i=1m(hθ(xi)yi)2]+λj=1nθj

上面的逻辑可能看出是拉格朗日乘子法的应用

采用shrinkage方法的主要目的包括两个:

  1. 一方面因为模型可能考虑到很多没必要的特征,这些特征对于模型来说就是噪声,shrinkage可以通过消除噪声从而减少模型复杂度;
  2. 另一方面模型特征存在多重共线性(变量之间相互关联)的话可能导致模型多解,而多解模型的一个解往往不能反映模型的真实情况,shrinkage可以消除关联的特征提高模型稳定性。

对应图形

我们可以简化L2正则化的方程:
J = J 0 + λ ∑ w w 2 J=J_{0}+\lambda\sum_ww^2 J=J0+λww2
J0表示原始的损失函数,咱们假设正则化项为:
假设是2个特征w有两个值w1和w2
L = λ ( w 1 2 + w 2 2 ) L=\lambda(w_{1}^2+w_{2}^2) L=λ(w12+w22)
我们不妨回忆一下圆形的方程:
( x − a ) 2 + ( y − b ) 2 = r 2 (x-a)^2+(y-b)^2=r^2 (xa)2+(yb)2=r2
其中(a,b)为圆心坐标,r为半径。那么经过坐标原点的单位元可以写成:
正和L2正则化项一样,同时,机器学习的任务就是要通过一些方法(比如梯度下降)求出损失函数的最小值。
此时我们的任务变成在L约束下求出J0取最小值的解(拉格朗日乘子法)。

求解J0的过程可以画出等值线。同时L2正则化的函数L也可以在w1w2的二维平面上画出来。如下图:
在这里插入图片描述
L表示为图中的黑色圆形,随着梯度下降法的不断逼近,与圆第一次产生交点,而这个交点很难出现在坐标轴上。

这就说明了L2正则化不容易得到稀疏矩阵,同时为了求出损失函数的最小值,使得w1和w2无限接近于0,达到防止过拟合的问题。

岭回归(Ridege Regression)

就是L2正则化
测试用例:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x + 3 + np.random.normal(0, 1, size=100)

plt.scatter(x, y)
plt.show()

在这里插入图片描述

使用20项式来进行拟合(模拟过拟合)

from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

def PolynomiaRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression()),
    ])


np.random.seed(666)
x_train, x_test, y_train, y_test = train_test_split(X, y)

poly_reg = PolynomiaRegression(degree=20)
poly_reg.fit(x_train, y_train)

y_poly_predict = poly_reg.predict(x_test)
print(mean_squared_error(y_test, y_poly_predict))
# 167.9401085999025
import matplotlib.pyplot as plt
x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly_reg.predict(x_plot)

plt.scatter(x, y)
plt.plot(x_plot[:,0], y_plot, color='r')
plt.axis([-3, 3, 0, 6])
plt.show()

在这里插入图片描述
封装一个函数生成测试集并测试模型

def plot_model(model):
    x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
    y_plot = model.predict(x_plot)

    plt.scatter(x, y)
    plt.plot(x_plot[:,0], y_plot, color='r')
    plt.axis([-3, 3, 0, 6])
    plt.show()

使用岭回归:

from sklearn.linear_model import Ridge
def RidgeRegression(degree, alpha):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', Ridge(alpha=alpha)),
    ])

ridege1_reg = RidgeRegression(20, alpha=0.0001)
ridege1_reg.fit(x_train, y_train)

y1_predict = ridege1_reg.predict(x_test)
print(mean_squared_error(y_test, y1_predict))
# 跟之前的136.相比小了很多
plot_model(ridege1_reg)

输出误差:1.3233492754136291
在这里插入图片描述
调整 α \alpha α=1

ridege2_reg = RidgeRegression(20, alpha=1)
ridege2_reg.fit(x_train, y_train)

y2_predict = ridege2_reg.predict(x_test)
print(mean_squared_error(y_test, y2_predict))
plot_model(ridege2_reg)

输出:1.1888759304218461
在这里插入图片描述
调整 α \alpha α=100

ridege2_reg = RidgeRegression(20, alpha=100)
ridege2_reg.fit(x_train, y_train)

y2_predict = ridege2_reg.predict(x_test)
print(mean_squared_error(y_test, y2_predict))
# 1.3196456113086197
plot_model(ridege2_reg)

输出:1.3196456113086197
在这里插入图片描述
调整 α \alpha α=1000000

ridege2_reg = RidgeRegression(20, alpha=1000000)
ridege2_reg.fit(x_train, y_train)

y2_predict = ridege2_reg.predict(x_test)
print(mean_squared_error(y_test, y2_predict))
# 1.8404103153255003
plot_model(ridege2_reg)

输出:1.8404103153255003
在这里插入图片描述
通过上面几种alpha的取值可以看出我们可以在1-100进行更加细致的搜索,找到最合适的一条相对比较平滑的曲线去拟合。这就是L2正则。

LASSO Regularization

封装

#%%

import numpy as np
import matplotlib.pyplot as plt
from skimage.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
np.random.seed(42)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x + 3 + np.random.normal(0, 1, size=100)
np.random.seed(666)
x_train, x_test, y_train, y_test = train_test_split(X, y)

plt.scatter(x, y)
plt.show()

#%%

from sklearn.linear_model import Lasso
def plot_model(model):
    x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
    y_plot = model.predict(x_plot)

    plt.scatter(x, y)
    plt.plot(x_plot[:,0], y_plot, color='r')
    plt.axis([-3, 3, 0, 6])
    plt.show()
def LassoRegression(degree, alpha):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', Lasso(alpha=alpha)),
    ])
def TestRegression(degree, alpha):
    lasso1_reg = LassoRegression(degree, alpha) 
    #这里相比Ridge的alpha小了很多,这是因为在Ridge中是平方项
    lasso1_reg.fit(x_train, y_train)
    
    y1_predict = lasso1_reg.predict(x_test)
    print(mean_squared_error(y_test, y1_predict))
    # 1.149608084325997
    plot_model(lasso1_reg)

使用lasso回归:
调整 α \alpha α=0.01

TestRegression(20,0.01)

输出:1.149608084325997
在这里插入图片描述

调整 α \alpha α=0.1

TestRegression(20,0.1)

输出:1.1213911351818648
在这里插入图片描述
调整 α \alpha α=1

TestRegression(20,1)

输出:1.8408939659515595
在这里插入图片描述

解释Ridge和LASSO

在这里插入图片描述
通过这两幅图进行对比发现,LASSO拟合的模型更倾向于是一条直线,而Ridge拟合的模型更趋向与一条曲线。这是因为两个正则的本质不同,Ridge是趋向于使所有
的加和尽可能的小,而Lasso则是趋向于使得一部分
的值变为0,因此可作为特征选择用,这也是为什么叫Selection Operation的原因。

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

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

相关文章

Redis源码分析(基于Redis7,对比Redis6)

PS: redis7.0.9版本的 1.Redis 源代码分类 1.1Redis 基本的数据结构 基础 Redis对象object.c字符串t_string.c列表t_list.c字典t_hash.c集合及有序集合t_set.c和z_set.c数据流 t_stream 底层实现结构 listpack.c 和 rax.c 简单动态字符串 sds.c整数集合 intset.c压缩列表 z…

【dp】最长递增子序列

文章目录 方法一:动态规划方法二:贪心 二分查找构造最长递增子序列 方法一:动态规划 dp[i]:末尾元素为arr[i]的最长子序列的长度 从0遍历到i - 1,若遍历到的元素小于当前值arr[i],表示当前值arr[i]可以和…

国考省考行测:词句理解,词的对象指代,就近原则,主语一致法,语意语境分析上下文找出指代含义

国考省考行测:词句理解,词的对象指代,就近原则,主语一致法,语意语境分析上下文找出指代含义 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带行测和申论,而常规国…

3年100亿!苏宁易购与倍科达成重磅战略合作

紧抓消费复苏机遇,家电行业迎来重磅合作。4月20日,苏宁易购与国际知名家电品牌倍科在南京召开战略合作发布会,共同宣布升级战略合作伙伴关系。双方将围绕3年100亿战略合作目标开展独家品牌授权、发起“BIS”计划、打造生态开放平台、升级用户…

5G基站外市电改造建设方案 (ppt可编辑)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除 外市电定义及分类 定义:由供电部门提供的专用高压电源或非专用高压电源或低压电源均称为市电。分类: (1)按电压等级分类 ①提供…

贝叶斯学习(Bayesian Learning)基础篇

Bayesian Learning 前言Motivation and IntroductionThink about Spam Filtering.先验概率后验概率似然度边际概率 Basic assumptionRelevancePractical diculties Bayes TheoremProbability: random eventsBayesian Learning Maximum A Posteriori HypothesisBayes Optimal Cl…

合同管理的6个最佳实践

合同管理不善会使你的合同流程效率低下,并产生负面影响: -收入损失 谈判缓慢、审批延迟和里程碑缺失等低效合同代价高昂。如果没有办法自动跟踪最后期限,并得到通知来执行时间敏感的行动,就会有错过最后期限的风险。 -协作和…

数组【有点难,要注重实战】

目录 1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的存储 3. 数组越界4. 数组作为函数参数4.1 冒泡排序函…

JavaEE-一文了解IP协议与IP地址

目录 IP协议什么是IP地址IP地址的组成动态分配IPNAT机制(网络地址转换) IP协议 IP协议是不可靠、无连接的 不可靠:表示IP协议不能保证IP数据报能成功的到达目的地。IP仅提供传输服务,任何可靠性的要求都必须由上层来提供(如TCP)。如果传输过…

【C++|排序算法】冒泡、快排、归并、堆排序算法模版

目录 简介冒泡排序快速排序归并排序堆排序结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国…

字节跳动五面都过了,结果被刷了,问了hr原因竟说是...

摘要 说在前面,面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到几个原因:1、虚报工资,比实际高30%;2、有更好的人选,这个可能性不大&…

反垃圾邮件产品技术要求

声明 本文是学习信息安全技术 反垃圾邮件产品技术要求和测试评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 反垃圾邮件产品技术要求 引言 为指导反垃圾邮件产品的研制、生产、测试和评价工作的开展,本标准依据《信息技术 安全技…

基于Spring注解 + MyBatis + Servlet 实现数据库交换的小小Demo

基于Spring注解 MyBatis Servlet 实现数据库交换的小小Demo 第一步 创建web 项目&#xff0c;这一步省略&#xff0c;有不会的可以参考之前发布的文档 第二步 配置pom.xml文件 <dependencies><!-- Spring常用依赖 --><dependency><groupId>org.spr…

SpringCloud --- Eureka注册中心

一、场景 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图 思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c;order-service调用时该…

【LeetCode】剑指 Offer 67. 把字符串转换成整数 p318 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/ 1. 题目介绍&#xff08;67. 把字符串转换成整数&#xff09; 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 …

day1 什么是互联网

目录 计算机网络的定义与分类 网络的网络 互联网的组成 互联网的边缘部分 互联网基础结构发展的三个阶段 第一阶段&#xff08;1969 - 1990&#xff09; 第二阶段&#xff08;1985 - 1993&#xff09; 第三阶段&#xff08;1993 - 现在&#xff09; 20世纪90年代&#xff…

项目经验总结——送给测试岗做项目的朋友们

目录 前言 1、项目排期时的时间预估能力欠佳 2、QA写单元测试 3、集成测试方案不够精简 4、排了优先级也很难取舍 5、搭完redis集群却不了解redis运行机制 总结 结语 前言 最近负责的L项目从3月初开始开发到6月底正式上线&#xff0c;这是我在工作快1年时间里第一次独…

机械键盘、口袋打印机,万元奖金等你拿!「万象格新」AI绘画X海报设计大赛即将开启...

号外&#xff01;「万象格新」大赛开启 如果阳光暖到你心里&#xff0c;那一定是一格在想你~ 春夏交替&#xff0c;万物焕发生机&#xff0c;明媚色彩娱情惬意 在这样一个美好的时节 如果你&#xff1a; 心中荡漾着色彩斑斓的 AI 绘画创意 想要 show 出独到的审美与非凡设计能力…

【系统集成项目管理工程师】项目干系人管理

&#x1f4a5;十大知识领域&#xff1a;项目干系人管理 项目干系人管理包括以下 4 个过程: 识别干系人规划干系人管理管理干系人参与控制干系人参与 一、识别干系人 输入工具与技术输出项目章程采购文件事业环境因素组织过程资产组织相关会议专家判断干系人分析干系人登记册 …

servlet(1)—javaEE

文章目录 1.认识servlet2.使用servlet2.1创建项目2.2引入依赖2.3创建目录2.4编写代码2.5打包2.6部署2.7运行2.8验证 3.开发步骤4.部署方式4.1打包4.2安装插件 5.访问出错的情况5.1 4045.2 4055.3其他 6.servlet的三大生命周期方法7.servlet api7.1HttpServlet7.2HttpServletReq…