机器学习周报第四周(7.15-7.21)

文章目录

    • 摘要
    • Abstract
    • 1.批次(Batch)和动量(momentum)
      • 1.1 批次(Batch)
      • 1.2 Momentum
    • 2.自动调整学习速率(Learning rate)
      • 2.1 Adagrad 算法
      • 2.2 RMSProp
      • 2.3 Adam
      • 2.4 学习率调度
    • 3.朴素贝叶斯理论
      • 3.1 贝叶斯定理
      • 3.2 朴素贝叶斯
      • 3.3 朴素贝叶斯优缺点
    • 总结

摘要

本周学习了 batch,以及当 batch size过大或过小时的对比分析。对Momentum与梯度下降相结合进行优化模型的方法进行分析。在进行梯度下降过程中,学习率是一个重要的参数,学习率的大小决定着模型训练的平滑程度和稳定性。本文介绍了如何自动调整学习率,学习率会随着梯度的改变而改变。从而在各个情况下采用合适的学习率。同时也介绍了Adagard算法和Prop算法,Learning Rate Decay和Warm up是机器学习中的优化技术,这两种方式可以改变学习率中的 η \eta η,将 η \eta η随着时间的改变而改变,从而可以避免 “梯度爆炸” 等现象;同时搜索相关资料学习朴素贝叶斯理论。

Abstract

This week we learned about batch and comparative analysis when batch size is too large or too small. The method of combining Momentum and gradient descent to optimize the model is analyzed. In the process of gradient descent, the learning rate is an important parameter, which determines the smoothness and stability of model training. This article describes how to automatically adjust the learning rate, which will change as the gradient changes. Thus, the appropriate learning rate is adopted in each case. At the same time, Adagard algorithm and Prop algorithm are also introduced. Learning Rate Decay and Warm up are optimization techniques in machine learning. These two methods can change η \eta ηin learning rate and change η \eta ηwith the change of time, so as to avoid “gradient explosion” and other phenomena. At the same time, search relevant materials to learn naive Bayes theory.

1.批次(Batch)和动量(momentum)

1.1 批次(Batch)

实际上在计算梯度的时候,并不是对所有数据的损失Loss计算梯度,而是把所有的数据分成一个一个的批量(batch),每次更新参数时,会用每个Batch的数据计算出Loss值和梯度值,进行更新参数。

遍历所有批量的过程称为一个回合(epoch)。

在把数据分为批量的时候,我们还会进行随机打乱(shuffle)。随机打乱有很多不同的做法,一个常见的做法是在每一个回合开始之前重新划分批量,也就是说,每个回合的批量的数据都不一样。
在这里插入图片描述

批次的大小对Gradient descent的影响?

假设我们现在有20组训练数据。有两种极端的情况:

  1. 下图左图情况,没有使用批次,批次大小为训练数量大小,这种使用全批次(Full Batch)的数据来更新参数的方法即批次梯度下降法(Batch Gradient Descent,BGD)。此时模型必须把 20 笔训练数据都看完,才能够计算损失和梯度,参数才能够更新一次。参数更新频率较低,模型的训练过程更加稳定。

  2. 下图右图情况,Batch Size = 1 时,此时 Batch Size 最小,此时参数更新频率较高,模型的训练过程不稳定,同时在进行梯度估计时,会引入更多的噪声,导致梯度估计的不准确性增加。

在这里插入图片描述

当 Batch Size 比较大时,训练过程所花费的时间不一定比 Batch Size 比较小的时候所花费的时间长。如下图所示,这是一个手写数字辨识案例,在该案例中,Batch Size为1时所花费的时间与 Batch Size为1000时所花费的时间几乎相等。这是利用了GPU并行计算的优势,提高了训练效率。但是GPU并行计算的能力是有一个限度的。
在这里插入图片描述

假设训练数据只有 60000 笔,批量大小设为1,要 60000 个更新(update)才能“跑”完一个回合(epoch);如果批量大小等于 1000,60 个更新(update)才能“跑”完一个回合(epoch),计算梯度的时间差不多。但是60000次update和60次update比起来,时间差距是很大的。

下图中右图为跑完一个完整的回合(epoch)需要花的时间,BatchSize越大,跑完一个回合的时间越少。

因此实际上,在有考虑并行计算的时候,大的批量大小反而是较有效率的,一个回合大的批量花的时间反而是比较少的。

在这里插入图片描述

大的批量更新比较稳定,小的批量的梯度的方向是比较有噪声的(noisy)。但实际上有,噪声的的梯度反而可以帮助训练。

下图中横轴是批量大小,纵轴是正确率。
批量大小越大,验证集准确率越差。但这不是过拟合,因为批量大小越大,训练准确率也是越低。因为用的是同一个模型,所以这不是模型偏见的问题。 但大的批量大小往往在训练的时候,结果比较差。这个是优化的问题,大的批量大小优化可能会有问题,小的批量大小优化的结果反而是比较好的。

在这里插入图片描述

为什么 Batch Size 较小时引入更多噪声,但却能使得我们的训练结果更好呢?

假设我们此时选择的是 Full Batch,那我们在更新参数时,则是沿着一个 Loss function来更新,当参数更新到局部最小点或者鞍点时,梯度下降也就随之停止。如果此时我们选择的是 Small Batch,我们在更新参数时,选择第一个 Batch 时,是用 L 1 L^{1} L1这个function来更新,选择第二个 Batch 时,我们是用 L 2 L^{2} L2来更新,如果我们用 L 1 L^{1} L1计算梯度时,更新到梯度为0的点停止了,由于 L 2 L^{2} L2的funciton与 L 1 L^{1} L1不同,因此在 L 1 L^{1} L1 更新至梯度为0的点,此点在 L 2 L^{2} L2不一定梯度为0,因此即便在 L 1 L^{1} L1处无法更新参数了,但是在 L 2 L^{2} L2 处仍然可以更新参数。

在这里插入图片描述

如下图:训练损失上面有多个局部最小值,这些局部最小值的损失都很低,其损失可能都趋近于 0。但是局部最小值有好最小值跟坏最小值之分,如果局部最小值在一个“峡谷”里面,它是坏的最小值;如果局部最小值在一个平原上,它是好的最小值。

如果发生训练时的Loss跟测试时的Loss不一样,虽然只是差一点点。但对在右边在“峡谷”里面的最小值,一差就可以天差地远 。虽然它在训练集上的损失很低,但训练跟测试之间的损失函数不一样,因此测试时,损失函数一变,计算出的损失就变得很大。

大的批量大小会让我们倾向于走到“峡谷”里面,而小的批量大小倾向于让我们走到“盆地”里面。小的批量有很多的损失,其更新方向比较随机,其每次更新的方向都不太一样。即使“峡谷”非常窄,它也可以跳出去,之后如果有一个非常宽的“盆地”,它才会停下来。
在这里插入图片描述

在有并行计算的情况下,小的批量跟大的批量运算的时间并没有太大的差距(除非BatchSize特别大)。
在这里插入图片描述

1.2 Momentum

动量法(momentum method)是另外一个可以对抗鞍点或局部最小值的方法。

假设误差表面就是真正的斜坡,参数是一个球,把球从斜坡上滚下来,如果使用梯度下降,球走到局部最小值或鞍点就停住了。 但是在物理的世界里,一个球如果从高处滚下来,就算滚到鞍点或鞍点,因为惯性的关系它还是会继续往前走。如果球的动量足够大,其甚至翻过小坡继续往前走。 因此在物理的世界里面,一个球从高处滚下来的时候,它并不一定会被鞍点或局部最小值卡住,如果将其应用到梯度下降中,这就是动量。

在这里插入图片描述

引入动量后,每次在移动参数的时候,不是只往梯度的反方向来移动参数,而是根据梯度的反方向加上前一步移动的方向决定移动方向。

图中红色虚线方向是梯度的反方向,蓝色虚线方向是前一次更新的方向,蓝色实线的方向是下一步要移动的方向。把前一步指示的方向跟梯度指示的方向相加就是下一步的移动方向。

具体来说,首先我们需要有一个初始的参数 θ 0 \theta_0 θ0,假设一开始前一步的Movement变化量为0,即 M o v e m e n t Movement Movement m 0 = 0 m^0=0 m0=0,接下来通过初始参数计算出 g 0 g^0 g0,更新Movement参数,即 m 1 = λ m 0 − η g 0 m^1=\lambda m^0-\eta g^0 m1=λm0ηg0,然后更新我们的 θ \theta θ参数, θ 1 = θ 0 + m 1 \theta^1=\theta^0+m^1 θ1=θ0+m1,以此类推,不断反复更新参数。

在这里插入图片描述

m i m^i mi也可以理解为过去所计算所有gradient的总和,其中 η \eta η是学习率, λ \lambda λ是钱一个方向的权重参数,是需要调的。
在这里插入图片描述

如下图,红色表示负梯度方向,蓝色虚线表示前一步的方向,蓝色实线表示真实的移动量。;假设我们在进行梯度下降过程中,当梯度更新至0时,也就是到达局部最小值点时,此时无法继续更新参数,但根据 Last Movement 和 Real Movement,我们仍然可以继续更新参数,并不会卡在 “山谷” 中,甚至如果当梯度从0逐步增大后时,如果在某点的 Last Movement 比所求梯度还要大时,在 Last Movement 助力之下,可以成功的翻越下一个 “小山坡”,从而找到Loss值更低的点,找到更优的参数。

在这里插入图片描述

2.自动调整学习速率(Learning rate)

临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍,下面两个图中,上面的图横坐标代表更新的次数,竖坐标表示损失;一般在训练一个网络的时候,Loss值原来很大,随着参数不断的更新,Loss值会越来越小,最后就卡住了,最终Loss值会逐渐趋于平稳。虽然最后Loss值是趋于平稳,但是gradient的值还会突然上升。

在这里插入图片描述

可能是这种情况,下图是一个error surface,gradient在这个谷底两侧来回震荡,此时Loss值确实不再减少,但是也没有卡到临界点。
在这里插入图片描述

一般的训练方法是很难走到临界点(critical point),此时Loss值已经下降到很低了,但是gradient值还很大。所以我们要动态改变学习率,需要学习率随着梯度变化而变化。

在这里插入图片描述

图中学习率 η = 1 0 − 2 \eta=10^{-2} η=102比较大,参数一直在谷底两侧震荡,梯度值一直很大降不下去,降低学习率为 η = 1 0 − 7 \eta=10^{-7} η=107,参数不在震荡,但是也永远无法到达终点,因为学习率太小了。

我们往常都是采用所有参数都采用同一个学习率,这样显然不可行。如果在某一个方向上,梯度的值很小,非常平坦,我们会希望学习率调大一点;如果在某一个方向上非常陡峭,坡度很大,我们会希望学习率可以设得小一点。
在这里插入图片描述

2.1 Adagrad 算法

在这里插入图片描述

例如:两个参数 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 θ 1 \theta_1 θ1坡度小, θ 2 \theta_2 θ2坡度达。
因为 θ 1 \theta_1 θ1坡度小,计算出来的梯度小,由上述 σ i t \sigma_i^t σit计算机公式计算出来的 σ \sigma σ都小,故学习率就大。相反,因为 θ 2 \theta_2 θ2坡度大,计算出来的梯度大,由上述 σ i t \sigma_i^t σit计算机公式计算出来的 σ \sigma σ都大,故学习率就小。

因此有了 这一项 σ i t \sigma_i^t σit以后,就可以随着梯度的不同,每一个参数的梯度的不同,来自动调整学习率的大小。
在这里插入图片描述

2.2 RMSProp

同一个参数需要的学习率,也会随着时间而改变,如果考虑横轴方向,绿色箭头处坡度比较陡峭,需要较小的学习率,但是走到红色箭头处,坡度变得平坦了起来,需要较大的学习率。因此同一个参数的同个方向,学习率也是需要动态调整的,于是就有了一个新的方法
在这里插入图片描述

RMSprop 第一步跟 Adagrad 的方法是相同的,即
θ i 0 = ( g i 0 ) 2 = ∣ g i 0 ∣ \theta_i^0=\sqrt{(g_i^0)^2}=|g_i^0| θi0=(gi0)2 =gi0
在这里插入图片描述
其中 0 < α < 1,其是一个可以调整的超参数。
Adagrad算法中,每一个梯度都有同等的重要性,但在 RMSprop 里面,可以自己调整现在的这个梯度的重要性。如果 α 很小趋近于 0,代表 g i t g_i^t git 相较于之前算出来的梯度而言,比较重要,如果 α 设很大趋近于 1,代表 g i t g_i^t git 比较不重要,之前算出来的梯度比较重要。

球就从 A 走到 B,AB 段的路很平坦,g 很小,更新参数的时候,我们会走比较大的步伐。走到BC 段后梯度变大了,AdaGrad 反应比较慢,而 RMSprop 会把 α 设小一点,让新的、刚看到的梯度的影响比较大,很快地让 θ i t \theta_i^t θit的值变大,很快地让步伐变小,RMSprop 可以很快地“踩刹车”。如果走到 CD 段,CD 段是平坦的地方,可以调整 α,让其比较看重最近算出来的梯度,梯度一变小, θ i t \theta_i^t θit的值就变小了,走的步伐就变大了。

在这里插入图片描述

2.3 Adam

最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estimation)Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自适应调整学习率。PyTorch 里面已经写好了 Adam 优化器,这个优化器里面有一些超参数需要人为决定,但是往往用 PyTorch 预设的参数就足够好了。

2.4 学习率调度

我们加入自动调整学习率之后,一开始优化的时候很顺利,在左转的时候,有Adagard以后,也可以继续顺利走下去,走到非常接近终点的位置。走到 BC 段时,因为横轴方向的梯度很小,所以学习率会自动变大,步伐就可以变大,从而不断前进。

但是有一个新的问题:图中红圈的地方,快走到终点的时候突然“爆炸”了。 σ i t \sigma_i^t σit是把过去所有的梯度拿来作平均。在 AB段梯度很大,但在 BC 段,纵轴的方向梯度很小,因此纵轴方向累积了很小的 σ i t \sigma_i^t σit,累计到一定程度后,步伐就变很大,但有办法修正回来。因为步伐很大,其会走到梯度比较大的地方。走到梯度比较大的地方后 σ i t \sigma_i^t σit会慢慢变大,更新的步伐大小会慢慢变小,从而回到原来的路线
在这里插入图片描述

学习率调度方法一:学习率衰减(learning rate decay)

在这里插入图片描述

学习率调度方法一:预热(Warm up)
在这里插入图片描述
使用 Warm up 的目的是在训练初期防止模型陷入局部最优解,并帮助模型跳出局部最优点,更好地探索训练空间。通过逐渐增加学习率,模型可以在初始阶段进行更大的权重更新,然后在后期以较小的步伐进行微调。

在这里插入图片描述

其中 m i t m_i^t mit是动量,把过去所有算出梯度的方向做一个加权总和当作更新的方向。接下来的步伐大小为 m i t σ i t \frac{m_i^t}{\sigma_i^t} σitmit,最后通过 η t \eta^t ηt最后通过

在这里插入图片描述

3.朴素贝叶斯理论

朴素贝叶斯(Naive Bayes)是一种简单经典的分类算法

3.1 贝叶斯定理

先验概率:即基于统计的概率,是基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件。

后验概率:则是从条件概率而来,由因推果,是基于当下发生了事件之后计算的概率,依赖于当前发生的条件。

在这里插入图片描述

在这里插入图片描述

3.2 朴素贝叶斯

假设每个特征之间没有联系,给定训练数据集,其中每个样本x都包括n维特征,即 x = ( x 1 , x 2 , x 3 , . . . . . , x n ) x=(x_1,x_2,x_3,.....,x_n) x=(x1,x2,x3,.....,xn),类标记集合含有k种类别,即 y = y 1 , y 2 , . . . . , y n y={y_1,y_2,....,y_n} y=y1,y2,....,yn;

对于给定的新样本x,判断其属于那个类别,根据贝叶斯定理得,x属于类别 y k y_k yk的概率为:
P ( y k ∣ x ) = P ( y k ) P ( x ∣ y k ) P ( x ) = P ( y k ) P ( x ∣ y k ) ∑ i = 0 n P ( y i ) P ( x ∣ y i ) P(y_k|x)=\frac{P(y_k)P(x|y_k)}{P(x)}=\frac{P(y_k)P(x|y_k)}{\sum_{i=0}^{n} P(y_i)P(x|y_i)} P(ykx)=P(x)P(yk)P(xyk)=i=0nP(yi)P(xyi)P(yk)P(xyk)

朴素贝叶斯算法对条件概率分布作出了独立性的假设,通俗地讲就是说假设各个维度的特征 x 1 , x 2 , . . . . . . . . x n x_1,x_2,........x_n x1,x2,........xn互相独立,在这个假设的前提上,条件概率可以转化为: P ( x ∣ y k ) = P ( x 1 , x 2 , . . . . , x n ∣ y k ) = ∏ i = 1 n P ( x i ∣ y k ) P(x|y_k)=P(x_1,x_2,....,x_n|y_k)=\prod_{i=1}^nP(x_i|y_k) P(xyk)=P(x1,x2,....,xnyk)=i=1nP(xiyk)

代入上面贝叶斯公式中,得到:

P ( y k ∣ x ) = P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) P ( x ) P(y_k|x)=\frac{P(y_k)\prod_{i=1}^nP(x_i|y_k)}{P(x)} P(ykx)=P(x)P(yk)i=1nP(xiyk)
= P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) ∑ k = 0 n P ( y k ) ∏ i = 1 n P ( x i ∣ y k ) =\frac{P(y_k)\prod_{i=1}^nP(x_i|y_k)}{\sum_{k=0}^{n} P(y_k)\prod_{i=1}^nP(x_i|y_k)} =k=0nP(yk)i=1nP(xiyk)P(yk)i=1nP(xiyk)

例:

症状职业疾病
打喷嚏护士感冒
打喷嚏农夫过敏
头痛建筑工人脑震荡
头痛建筑工人感冒
打喷嚏教师感冒
头痛教师脑震荡

现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?即 P ( 感冒 ∣ 打喷嚏 × 建筑工人 ) P(感冒|打喷嚏×建筑工人) P(感冒打喷嚏×建筑工人)

由朴素贝叶斯得
P ( 感冒 ∣ 打喷嚏 × 建筑工个人 ) P(感冒|打喷嚏×建筑工个人) P(感冒打喷嚏×建筑工个人)
= P ( 打喷嚏 × 建筑工人 ∣ 感冒 ) P ( 感冒 ) P ( 打喷嚏 × 建筑工人 ) =\frac{P(打喷嚏×建筑工人|感冒)P(感冒)}{P(打喷嚏×建筑工人)} =P(打喷嚏×建筑工人)P(打喷嚏×建筑工人感冒)P(感冒)

= P ( 打喷嚏 ∣ 感冒 ) P ( 建筑工人 ∣ 感冒 ) P ( 感冒 ) P ( 打喷嚏 ) P ( 建筑工人 ) =\frac{P(打喷嚏|感冒)P(建筑工人|感冒)P(感冒)}{P(打喷嚏)P(建筑工人 )} =P(打喷嚏)P(建筑工人)P(打喷嚏感冒)P(建筑工人感冒)P(感冒)
= 0.66 × 0.33 × 0.5 0.5 × 0.33 = 0.66 =\frac{0.66×0.33×0.5}{0.5×0.33}=0.66 =0.5×0.330.66×0.33×0.5=0.66

3.3 朴素贝叶斯优缺点

  • 优点:
  1. 朴素贝叶斯模型有稳定的分类效率。
  2. 对小规模的数据表现很好,能处理多分类任务,适合增量式训练,尤其是数据量超出内存时,可以一批批的去增量训练。
  3. 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
  • 缺点:
  1. 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳
  2. 对输入数据的表达形式很敏感(离散、连续,值极大极小之类的)

总结

我们将所有数据分成若干个 batch,然后对每个 batch 求微分,求损失(Loss)值,根据每个batch的顺序,依次梯度下降优化参数。这样大大加快了梯度下降的计算效率。但是也需要合理选择batch的大小,如果过大,模型参数更新至局部最小点或鞍点处就无法更新。如果过小,模型参数仍可以继续更新,这通过batch间接的解决了局部最小点和鞍点的问题。最后我也了解了动量(momentum),Momentum算法在计算每个梯度的时候会考虑这个梯度在先前更新中的权重,将当前梯度与先前权重的指数加权和相加,然后再通过这个更新结果来更新权重值。这样即便梯度为0时,也可以继续优化参数,跨越局部最小点、鞍点。

同时我知道了如何自动调整学习率,也理解了Adagrad算法的优缺点,Adagrad算法的主要思想是根据每个参数的梯度历史信息来自适应地调整学习率。但是 Adagrad 算法只是针对不同参数而动态改变学习率,为此我们引入了改进后的RMSProp算法,此算法引入了一个衰减系数 α \alpha α用来控制梯度平方累加项的贡献程度,可以根据梯度的值来合理的增大和减少学习率,从而避免出现学习率过大,导致梯度来回震荡。避免学习率过小,梯度下降过程十分缓慢。

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

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

相关文章

美摄科技企业级视频拍摄与编辑SDK解决方案

在数字化浪潮汹涌的今天&#xff0c;视频已成为企业传递信息、塑造品牌、连接用户不可或缺的强大媒介。为了帮助企业轻松驾驭这一视觉盛宴的制作过程&#xff0c;美摄科技凭借其在影视级非编技术领域的深厚积累&#xff0c;推出了面向企业的专业视频拍摄与编辑SDK解决方案&…

JVM系列(二) -类的加载过程

一、背景介绍 我们知道 Java 是先通过编译器将.java类文件转成.class字节码文件&#xff0c;然后再通过虚拟机将.class字节码文件加载到内存中来实现应用程序的运行。 那么虚拟机是什么时候加载class文件&#xff1f;如何加载class文件&#xff1f;class文件进入到虚拟机后发…

干部任免管理系统(五)开源了一个c#开发的任免审批表转word的程序

前言&#xff1a; 好久没有写博文了&#xff0c;最近有几位csdn的网友想找过来借鉴开发的管理系统&#xff0c;因为工作调整我已经不在公司管理干部了&#xff0c;整套系统当时本身就是为了方便自己工作捣鼓的&#xff0c;现在也没人用了。牵涉到打架java运行环境&#xff0c;数…

HP ilo4服务器硬件监控指标解读

随着企业IT架构的复杂化&#xff0c;服务器的稳定性和可靠性成为保障业务连续性的关键因素。HP ilo4作为HP服务器的一个重要组件&#xff0c;提供了强大的远程管理和监控功能。本文将对使用监控易软件通过HP ilo4进行服务器硬件监控的指标进行解读&#xff0c;帮助运维团队更好…

802.11无线网络权威指南(二):无线帧结构

802.11无线网络权威指南&#xff08;二&#xff09;&#xff1a;无线帧结构 无线协议桢的三种类型无线网络帧结构完整帧格式control frameDuration/IDAddressSequence ControlQoS ControlHT Control 字段Frame Body 帧体FCS 校验域 帧细节管理帧控制帧RTS 帧CTS 帧ACK 帧格式PS…

6.1 面向对象技术-面向对象相关概念

大纲 面向对象基本概念 面向对象分析

LeetCode 热题 HOT 100 (010/100)【宇宙最简单版】

【链表】No. 0206 反转链表 【简单】&#x1f449;力扣对应题目指路 希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【力扣详解】谢谢你的支持&#xf…

鸿蒙仓颉语言【cryptocj 库】(介绍与SHA、MD5、HMAC摘要算法)

cryptocj 库 介绍 cryptocj 是一个安全的密码库&#xff0c;包括常用的密码算法、常用的密钥生成和签名验证。 该库是对 C 语言的 openSSL 封装的仓颉加密算法 1 提供SHA、MD5、HMAC摘要算法。 前置条件&#xff1a;NA 场景&#xff1a; OHOS&#xff0c; Linux&#xff…

C#使用csvhelper实现csv的操作

新建控制台项目 安装csvhelper 33.0.1 写入csv 新建Foo.cs namespace CsvSut02;public class Foo {public int Id { get; set; }public string Name { get; set; } }批量写入 using System.Globalization; using CsvHelper; using CsvHelper.Configuration;namespace Csv…

Meta发布Llama 3.1模型

Llama 3.1模型 Meta&#xff08;原Facebook&#xff09;开发的一款大型语言模型&#xff08;LLM&#xff09;&#xff0c;该模型在多个方面展现出了强大的性能和广泛的应用潜力。关于Llama 3.1模型的规模与参数&#xff0c;具体概述如下&#xff1a; 一、模型规模 Llama 3.1…

VBA实例-从Excel整理数据到Word

实现目录 功能需求数据结构复制数据到新sheet并分类数据添加序号、日期、时间三列数据添加序号列添加时间列 将名称和类别复制到word文件中将参数5和参数9中的一个复制到word文件中 实例 功能需求 1、将原始数据中不要的数据剔除 2、原始数据中增加序号、日期和时间三列数据&a…

opengl 写一个3D立方体——计算机图形学编程 第4章 管理3D图形数据 笔记

计算机图形学编程&#xff08;使用OpenGL和C&#xff09; 第4章 管理3D图形数据 笔记 数据处理 想要绘制一个对象&#xff0c;它的顶点数据需要发送给顶点着色器。通常会把顶点数据在C端放入 一个缓冲区&#xff0c;并把这个缓冲区和着色器中声明的顶点属性相关联。 初始化立…

【Unity2D 2022:UI】无法拖拽TextMeshPro组件

在预制体Card上挂载了四个Text Mesh Pro组件&#xff0c;分别命名为Name、HP、ATK、Description。 将预制体Card挂载脚本CardDisplay用来在预制体上显示属性&#xff0c;并创建TextMeshPro对象来接收TextMeshPro组件。 using TMPro; using UnityEngine; using UnityEngine.UI;…

leetcode日记(49)旋转链表

其实不难&#xff0c;就是根据kk%len判断需要旋转的位置&#xff0c;再将后半段接在前半段前面就行。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : …

2、springboot3 vue3开发平台-后端-基础数据准备,MybatisPlus整合

文章目录 1. 基础数据准备2. 整合MybatisPlus3. MybatisPlus 配置3.1 数据源配置3.2 mybatis-plus 分页插件配置3.3 mybatis-plus 自动填充3.4 代码生成器 1. 基础数据准备 直接拿前辈做的表结构使用。 /*Navicat Premium Data TransferSource Server : localhost_my…

sql server 连接报错error 40

做个简单的记录,造成40 的原因有很多,你的错误并不一定就是我遇到的这种情况. 错误描述: 首先我在使用ssms 工具连接的时候是可以正常连接的,也能对数据库进行操作. 在使用 ef core 连接 Sql Server 时报错: Microsoft.Data.SqlClient.SqlException (0x80131904): A network-r…

【Linux】从零开始认识多线程 --- 线程互斥

人生有许多事情 正如船后的波纹 总要过后才觉得美的 -- 余光中 线程互斥 1 线程类的封装1.1 框架搭建1.2 线程启动1.3 线程终止1.4 线程等待1.5 运行测试 2 线程互斥2.1 多线程访问的问题2.2 解决办法 --- 锁2.3 从原理角度理解锁 Thanks♪(&#xff65;ω&#xff65;)&am…

后端返回一个图片链接,前端如何实现下载功能?

纯原创文章&#xff0c;转载请说明来源。 一、背景 要实现一个下载功能&#xff0c;后端直接返回了一个图片的地址https://xxxxx/pic.jpg。如果我们直接通过window.open(url, _blank) 的方式去下载这个图片&#xff0c;会发现 Chrome 浏览器会对这个图片进行预览&#xff0c;…

氧气传感器在汽车制氧检测中的应用

在当今汽车工业中&#xff0c;技术的快速发展不仅带来了驾驶安全性和舒适性的显著提升&#xff0c;还为车辆增加了各种智能功能&#xff0c;以应对不同的驾驶环境和需求。氧气传感器作为一种关键的技术装置&#xff0c;在汽车制氧检测系统中的应用&#xff0c;尤其是针对疲劳驾…

DDoS 究竟在攻击什么?

分布式拒绝服务&#xff08;DDoS&#xff09;攻击是一种常见的网络攻击形式&#xff0c;攻击者通过向目标服务端发送大量的请求&#xff0c;使目标服务端无法进行网络连接&#xff0c;无法正常提供服务。 DDoS 攻击通常是由大量的分布在全球各地的 “僵尸” 计算机&#xff08…