交叉熵三连(3)——交叉熵及其使用
相关文章:
交叉熵三连(1)——信息熵
交叉熵三连(2)——KL散度(相对熵)
交叉熵三连(3)——交叉熵及其使用
在神经网络中,我们经常使用交叉熵做多分类问题和二分类的损失函数,在通过前面的两篇文章我们了解了信息熵和相对熵(KL散度)的定义和计算方式以及相关的基础知识。在这篇文章中,会主要总结一下关于交叉熵的内容。
一来因为刚开始写博客的缘故,二来所学的知识有限。博客中有很大的篇幅其实是拼凑得来,可能会跟参考资料有大量的重复之处,自己深入的理解相对会少一些,权且是学习的记录。
如果博客中能有帮助到大家的地方,我很开心,如果大家有什么疑问也可以和我沟通讨论,有错误的地方欢迎大家批评指正我尽量第一时间修改,联系方式在签名中给出。
1 交叉熵的定义
交叉熵:表示当基于一个“非自然”分布QQQ对真实分布PPP进行编码时,在事件集合中唯一标识一个事件所需要的平均bitbitbit数。
对于给定的两个概率分布PPP和概率分布QQQ对应的交叉熵的定义如下:
H(P,Q)=EP[−logq]=H(P)+DLKL(P∣∣Q)H(P,Q)=E_P[-log\;q] = H(P) + DL_{KL}(P||Q)H(P,Q)=EP[−logq]=H(P)+DLKL(P∣∣Q)
其中H(P)H(P)H(P)是PPP的熵,DLKL(P∣∣Q)DL_{KL}(P||Q)DLKL(P∣∣Q)是相对熵,那么对于离散分布而言:
H(P,Q)=−∑xP(x)logQ(x)H(P,Q) =- \sum_{x}P(x)\;log\;Q(x)H(P,Q)=−x∑P(x)logQ(x)
2 交叉熵的计算
2.1 二分类交叉熵
在二分类问题中,交叉熵的计算方式如下所示:
L=−[y⋅log(p)+(1−y)⋅log(1−p)]L = -[y \cdot log(p) + (1-y)\cdot log(1-p)]L=−[y⋅log(p)+(1−y)⋅log(1−p)]
其中:
yyy:表示样本 labellabellabel 的值,如果 labellabellabel 正类y=1y=1y=1,负类y=0y=0y=0
ppp:表示样本预测为正的概率
如果上述公式没有办法直接理解,那么根据交叉熵计算公式
H(P,Q)=−∑xP(x)logQ(x)H(P,Q) =- \sum_{x}P(x)\;log\;Q(x)H(P,Q)=−x∑P(x)logQ(x)
对于二分类问题,上述公式转化为如下形式:
H(P,Q)=−∑x∈{0,1}P(x)logQ(x)=−(P(x0)logQ(x0)+P(x1)logQ(x1))H(P,Q) =- \sum_{x\in\{0,1\}}P(x)\;log\;Q(x) \\ =-(P(x_0) \;log\;Q(x_0) + P(x_1)\;log\;Q(x_1))H(P,Q)=−x∈{0,1}∑P(x)logQ(x)=−(P(x0)logQ(x0)+P(x1)logQ(x1))
令P(x0)=yP(x_0) = yP(x0)=y,并且Q(x0)=qQ(x_0)=qQ(x0)=q,那么P(x1)=1−yP(x_1) = 1-yP(x1)=1−y,且Q(x1)=1−qQ(x_1) = 1 - qQ(x1)=1−q
上述公式简化为如下所示
L=−[y⋅log(p)+(1−y)⋅log(1−p)]L = -[y \cdot log(p) + (1-y)\cdot log(1-p)]L=−[y⋅log(p)+(1−y)⋅log(1−p)]如果x0x_0x0表示正样本的话,yyy 的值等于正样本真实的概率等于 labellabellabel 的值, qqq 的值表示为正样本的预测概率。
2.2 多分类交叉熵
对于多分类问题的交叉熵在二分类问题上扩展后的具体计算公式如下:
L=−∑c=1Myclog(pc)L=-\sum_{c=1}^{M}y_c\;log(p_c)L=−c=1∑Myclog(pc)
在上述公式中:
MMM:表示类别的数量
ycy_cyc:当前观测样本属于类 ccc的时候yc=1y_c=1yc=1,否则 yc=0y_c=0yc=0
pcp_cpc:当前观测样本预测到类别ccc的概率
3 为什么是交叉熵
3.1 为什么不是分类错误率
很多人一开始理解损失函数就是分类错误率,我刚开始的时候也是这么认为的,分类错误率的计算公式如下:
Re=CeCaR_e=\frac{C_e}{C_a}Re=CaCe
在上述公式中:
ReR_eRe:表示分类错误率
CeC_eCe:表示分类错的样本个数
CaC_aCa:表示所有的样本的个数
在参考的文章中给出了一张样例表,样例表中给出了三组民意选举预测的结果和对应的标签。
- 模型1
计算结果 | 标签 | 是否正确 |
---|---|---|
0.3 0.3 0.4 | 0 0 1(民主党) | yes |
0.3 0.4 0.3 | 0 1 0 (共和党) | yes |
0.1 0.2 0.7 | 1 0 0 (其他) | no |
在三种结果中选民1和选民2的预测以微弱的优势获胜,选民3的民意预测结果彻底错误,计算得到的分类错误率为:
Re=13R_e=\frac{1}{3}Re=31
- 模型2
计算结果 | 标签 | 是否正确 |
---|---|---|
0.1 0.2 0.7 | 0 0 1(民主党) | yes |
0.1 0.7 0.2 | 0 1 0 (共和党) | yes |
0.3 0.4 0.3 | 1 0 0 (其他) | no |
在模型2中给出了另外一组假设数据,在这组假设数据中选民1和选民2的判断非常准确,选民3以轻微的概率优势判错,分类错误率计算为:
Re=13R_e = \frac{1}{3}Re=31
在上面给出的模型实例中,虽然错误率相等但是从三组样本最后预测的分类概率看,模型2具有相对明显的优势,但是通过分类错误率没有办法较准确的评估。
接下来我们分析一下使用交叉熵计算得到losslossloss的值,在计算过程中采用ACEACEACE(Average cross-entropy error)来计算平均交叉熵,根据多分类问题计算交叉熵计算公式得:
- 模型1
1:−(ln(0.3)∗0+ln(0.3)∗0+ln(0.4)∗1)=−ln(0.4)1 : \;\;\;\; -(ln(0.3) * 0 + ln(0.3) * 0 + ln(0.4) * 1) = -ln(0.4)1:−(ln(0.3)∗0+ln(0.3)∗0+ln(0.4)∗1)=−ln(0.4)
2:−(ln(0.3)∗0+ln(0.4)∗1+ln(0.3)∗0)=−ln(0.4)2 : \;\;\;\; -(ln(0.3) * 0 + ln(0.4) * 1 + ln(0.3) * 0) = -ln(0.4)2:−(ln(0.3)∗0+ln(0.4)∗1+ln(0.3)∗0)=−ln(0.4)
3:−(ln(0.1)∗1+ln(0.2)∗0+ln(0.7)∗0)=−ln(0.1)3 : \;\;\;\; -(ln(0.1) * 1 + ln(0.2) * 0 + ln(0.7) * 0) = -ln(0.1)3:−(ln(0.1)∗1+ln(0.2)∗0+ln(0.7)∗0)=−ln(0.1)
L=−(ln(0.4)+ln(0.4)+ln(0.1))3=1.38L=\frac{-(ln(0.4) + ln(0.4) + ln(0.1))} {3} = 1.38L=3−(ln(0.4)+ln(0.4)+ln(0.1))=1.38 - 模型2:
L=−(ln(0.7)+ln(0.7)+ln(0.3))3=0.64L=\frac{-(ln(0.7) + ln(0.7) + ln(0.3))}{3} = 0.64L=3−(ln(0.7)+ln(0.7)+ln(0.3))=0.64
结论:
- ACE结果准确体现了模型2的效果优于模型1
- cross-entropy 更清晰的描述了真实分布的数据和预测数据的距离
3.2 为什么不是均方误差(MSE)
接下来我们看看使用均方误差作为损失函数是个什么样的效果。首先根据3.1节中给出的数据,我们计算均方误差如下。
模型1
1:(0.3−0)2+(0.3−0)2+(0.4−1)2=0.541 : \;\;\;\; (0.3 - 0)^2 + (0.3 - 0)^2 + (0.4 - 1)^2 = 0.541:(0.3−0)2+(0.3−0)2+(0.4−1)2=0.54
2:(0.3−0)2+(0.4−1)2+(0.3−0)2=0.542 : \;\;\;\; (0.3 - 0)^2 + (0.4 - 1)^2 + (0.3 - 0)^2 = 0.542:(0.3−0)2+(0.4−1)2+(0.3−0)2=0.54
3:(0.1−1)2+(0.2−0)2+(0.7−0)2=1.343 : \;\;\;\; (0.1 - 1)^2 + (0.2 - 0)^2 + (0.7 - 0)^2= 1.343:(0.1−1)2+(0.2−0)2+(0.7−0)2=1.34
L=(0.54+0.54+1.34)3L=\frac{(0.54 + 0.54 + 1.34)}{3}L=3(0.54+0.54+1.34)模型2
L=(0.14+0.14+0.74)3L=\frac{(0.14 + 0.14 + 0.74)}{3}L=3(0.14+0.14+0.74)
根据MSE的计算结果可知,使用MSE好像也能很好的评估模型1和模型2的效果,为什么不用MSE来作为损失函数去优化整个模型的训练结果呢?主要原因有两个:
- 原因1:函数的单调性 。采用MSE做为损失函数的情况下,损失函数是非凸函数具有很多极值点,容易陷入局部最优解。
- 原因2:计算的简洁性。 使用均方误差作为loss函数的时候求导结果比较复杂运算量会比较大,使用交叉熵计算结果的时候比较简单,反向误差的计算比较简单。
3.2.1 求导过程简洁性对比
在分类问题中最后计算每一个类的概率的时候,采用softmaxsoftmaxsoftmax计算映射到每一个类的概率,softmaxsoftmaxsoftmax对应的具体公式如下所示。
softmax(x)i=exp(xi)∑jexp(xj)softmax(x)_i = \frac{exp(x_i)}{\sum_j exp(x_j)}softmax(x)i=∑jexp(xj)exp(xi)
采用MSE计算loss,输出的曲线是波动的,损失函数表现的不是凸函数,有很多局部的极值点,这种情况下难以得到最优解,使用交叉熵函数能够保证在区间内的单调性。
以下我们以二分类为例分别证明MSE损失函数和交叉熵损失函数的单调性,具体的证明情况如下:
1. 交叉熵损失函数的求导过程
在二分类问题钟交叉熵损失的计算过程如下。
我们简单的假设scorescorescore是线性函数输入的结果,假设参数www和得分sss的计算公式为:
s=wi⋅xi+bis=w_i\cdot x_i + b_is=wi⋅xi+bi
根据上述过程,二分类问题正向的LLL计算分为三个阶段
- score得分的计算
s=wi⋅xi+bis = w_i \cdot x_i + b_is=wi⋅xi+bi - sigmoid计算公式
pi=esi1+esip_i=\frac{e^{s_i}}{1 + e^{s_i}}pi=1+esiesi - 交叉熵损失的计算
L=−[y⋅logpi+(1−y)⋅log(1−pi)]L=-[y \cdot log\;p_i + (1-y) \cdot log(1-p_i)]L=−[y⋅logpi+(1−y)⋅log(1−pi)]
根据损失函数的计算过程,我们需要反向地计算偏导∂L∂wi\frac{\partial L}{\partial w_i}∂wi∂L,与上面相反的,我们把求导过程也分为三个部分。 - ∂L∂pi\frac{\partial L}{\partial p_i}∂pi∂L 导数的计算
∂L∂pi=∂(−[y⋅logpi+(1−y)⋅log(1−pi)])∂pi=−ypi+1−y1−pi\frac{\partial L}{\partial p_i} = \frac{ \partial(-[y \cdot log\;p_i + (1-y) \cdot log(1-p_i)])}{\partial p_i} = - \frac{y}{p_i} + \frac{1-y}{1-p_i}∂pi∂L=∂pi∂(−[y⋅logpi+(1−y)⋅log(1−pi)])=−piy+1−pi1−y
∂pi∂si\frac{\partial p_i}{\partial s_i}∂si∂pi 导数的计算
pi=σ(si)=esi1+esip_i = \sigma(s_i)= \frac{e^{s_i}}{1+e^{s_i}}pi=σ(si)=1+esiesi
令:
h(x)=1+exh(x) = 1 + e^{x}h(x)=1+ex
g(x)=exg(x) = e^xg(x)=ex
那么有:
∂p∂si=(g(si)h(si))′=h(si)g′(si)−g(si)h′(si)h2(si)=(1+esi)(esi)′−esi(1+esi)′(1+esi)2=(1+esi)⋅esi−esi⋅esi(1+esi)2=esi(1+esi)2=esi1+esi⋅11+esi=esi1+esi⋅[1−esi1+esi]=σ(si)⋅(1−σ(si))\frac{\partial p}{\partial s_i} = (\frac{g(s_i)}{h(s_i)})' = \frac{h(s_i)g'(s_i)-g(s_i)h'(s_i)}{h^2(s_i)} \\ = \frac{(1+e^{s_i})(e^{s_i})' - e^{s_i}(1+e^{s_i})'}{(1+e^{s_i})^2} \\= \frac{(1+e^{s_i}) \cdot e^{s_i} - e^{s_i} \cdot e^{s_i}}{(1+e^{s_i})^2} \\ = \frac{e^{s_i}}{(1+e^{s_i})^2} \\ = \frac{e^{s_i}}{1+e^{s_i}} \cdot \frac{1}{1+e^{s_i}} \\ =\frac{e^{s_i}}{1+e^{s_i}} \cdot [1-\frac{e^{s_i}}{1+e^{s_i}}] \\ =\sigma(s_i)\cdot(1-\sigma(s_i))∂si∂p=(h(si)g(si))′=h2(si)h(si)g′(si)−g(si)h′(si)=(1+esi)2(1+esi)(esi)′−esi(1+esi)′=(1+esi)2(1+esi)⋅esi−esi⋅esi=(1+esi)2esi=1+esiesi⋅1+esi1=1+esiesi⋅[1−1+esiesi]=σ(si)⋅(1−σ(si))∂si∂wi\frac{\partial s_i}{\partial w_i}∂wi∂si 导数的计算
∂s∂wi=xi\frac{\partial s}{\partial w_i} = x_i∂wi∂s=xi
最终,我们计算∂L∂wi\frac{\partial L}{\partial w_i}∂wi∂L的结果得到
∂L∂wi=∂L∂pi⋅∂pi∂si⋅∂si∂wi=[−ypi+1−y1−pi]⋅σ(si)⋅[1−σ(si)]⋅xi=[−yσ(si)+1−y1−σ(si)]⋅σ(si)⋅[1−σ(si)]⋅xi=[−y+y⋅σ(si)+σ(si)−y⋅σ(si)]⋅xi=[σ(si)−y]⋅xi\frac{\partial L}{\partial w_i} = \frac{\partial L}{\partial p_i} \cdot\frac{\partial p_i}{\partial s_i} \cdot \frac{\partial s_i}{\partial w_i} \\ = [- \frac{y}{p_i} + \frac{1-y}{1-p_i}] \cdot \sigma(s_i) \cdot [1-\sigma(s_i)] \cdot x_i \\ = [- \frac{y}{\sigma(s_i)} + \frac{1-y}{1-\sigma(s_i)}] \cdot \sigma(s_i) \cdot [1-\sigma(s_i)] \cdot x_i \\ = [-y + y \cdot \sigma(s_i) + \sigma(s_i) -y\cdot \sigma(s_i)] \cdot x_i \\ =[\sigma(s_i)-y] \cdot x_i∂wi∂L=∂pi∂L⋅∂si∂pi⋅∂wi∂si=[−piy+1−pi1−y]⋅σ(si)⋅[1−σ(si)]⋅xi=[−σ(si)y+1−σ(si)1−y]⋅σ(si)⋅[1−σ(si)]⋅xi=[−y+y⋅σ(si)+σ(si)−y⋅σ(si)]⋅xi=[σ(si)−y]⋅xi
2. MSE损失函数的求导过程
在使用MSE作为损失函数的时候,计算最终的loss值的大小前两个步骤与使用交叉熵的计算过程相同,第三个阶段计算公式如下:
L=(y−pi)2L=(y-p_i)^2L=(y−pi)2
反向求导过程:
∂L∂pi=−2⋅y+2⋅pi\frac{\partial L}{\partial p_i} = -2\cdot y+ 2 \cdot p_i∂pi∂L=−2⋅y+2⋅pi
我们把常数去掉
∂L∂pi=−y+pi\frac{\partial L}{\partial p_i} = -y +p_i ∂pi∂L=−y+pi
那么对应的∂L∂wi\frac{\partial L}{\partial w_i}∂wi∂L计算的过程如下:
∂L∂wi=∂L∂pi⋅∂pi∂si⋅∂si∂wi=(−y+pi)⋅σ(si)⋅[1−σ(si)]⋅xi=[−y⋅σ(si)+σ(si)⋅σ(si)]⋅[1−σ(si)]⋅xi\frac{\partial L}{\partial w_i} = \frac{\partial L}{\partial p_i} \cdot\frac{\partial p_i}{\partial s_i} \cdot \frac{\partial s_i}{\partial w_i} \\ = (-y + p_i)\cdot \sigma(s_i) \cdot [1-\sigma(s_i)] \cdot x_i \\ =[-y \cdot \sigma(s_i) +\sigma(s_i) \cdot \sigma(s_i)] \cdot [1-\sigma(s_i)] \cdot x_i∂wi∂L=∂pi∂L⋅∂si∂pi⋅∂wi∂si=(−y+pi)⋅σ(si)⋅[1−σ(si)]⋅xi=[−y⋅σ(si)+σ(si)⋅σ(si)]⋅[1−σ(si)]⋅xi
对比权重更新的导数公式,使用交叉熵作为损失函数最后得到导数公式更简洁偏于计算。
3.2.2 损失函数的是否为凸函数
关于损失函数是否为凸函数的问题,我理解的还不是很深刻,常读常新。等我有了进一步理解再来增加更新这一部分的内容,或者是新起一篇博客再具体说一下凸函数优化和非凸优化以及是不是凸函数的问题吧!
如果要进一步探究这个问题,大家可以参考以下几个资料:
【机器学习基础】交叉熵(cross entropy)损失函数是凸函数吗?
二元分类为什么不能用MSE做为损失函数?
不理解为什么分类问题的代价函数是交叉熵而不是误差平方,为什么逻辑回归要配一个sigmod函数?
感觉越看越觉得搞机器学习跟炒股一样是玄学不成?刚开始还觉得对交叉熵理解清楚了,越看越迷糊多问几个为什么就彻底迷糊了,只能把自己稍微觉得有点道理,或者是认同并且可以理解的罗列出来。知之为知之,不知为不知,上下求索吧~
如果有后续,我后续有新的理解我再写交叉熵后传吧!!!
欢迎大家讨论。
3.3 为什么不是相对熵(KL散度)
交叉熵系列的学习和介绍中,我写了三篇博客分别是介绍了信息熵、KL散度(相对熵)和交叉熵。根据前面介绍的内容KL散度可以用来衡量数据的真实分布和预测分布的距离,那么为什么不用KL散度去衡量真实样本和预测结果之间的差距,作为损失函数。
这里我们回顾一下交叉熵的定义:
H(P,Q)=EP[−logq]=H(P)+DLKL(P∣∣Q)H(P,Q)=E_P[-log\;q] = H(P) + DL_{KL}(P||Q)H(P,Q)=EP[−logq]=H(P)+DLKL(P∣∣Q)
对于H(P,Q)H(P,Q)H(P,Q)表示用预测分布QQQ去编码真实分布PPP所需要的平均bitsbitsbits数。因为对于模型的训练过程来说真实分布通过样本的数据分布来估计,所以分布PPP是固定的,那么H(P)H(P)H(P)的值是一个常量。那么:
- 在模型训练的过程中,通过交叉熵和KL散度去评估预测分布和真实分布的距离具有相同的效果。
接下来我们再回顾一下KL散度的计算公式和交叉熵的计算公式。
KL散度计算公式
DLKL=∑iP(xi)log(P(xi))−∑iP(xi)log(Q(xi))DL_{KL} = \sum_{i}{P(x_i) log (P(x_i))} - \sum_iP(x_i)log(Q(x_i)) DLKL=i∑P(xi)log(P(xi))−i∑P(xi)log(Q(xi))
交叉熵的计算公式
Ce=−∑iP(xi)log(Q(xi))C_e = - \sum_iP(x_i)log(Q(x_i)) Ce=−i∑P(xi)log(Q(xi))
根据上述公式对比,使用交叉熵用作损失函数评估真实分布和预测分布距离的时候具有明显的计算上的简洁性。
4 TensorFlow提供的交叉熵接口
tf.nn.sigmoid_cross_entropy_with_logits
tf.nn.softmax_cross_entropy_with_logits
tf.nn.sparse_softmax_cross_entropy_with_logits
tf.nn.weighted_cross_entropy_with_logits
5 参考资料
【1】维基百科 · 交叉熵
【2】知乎 · 损失函数 - 交叉熵损失函数
【3】神经网络的分类模型 LOSS 函数为什么要用 CROSS ENTROPY
【4】知乎 · 为什么用交叉熵做损失函数
【5】github · 03.2-交叉熵损失函数
【6】Tensorflow 中文社区
交叉熵三连(3)——交叉熵及其使用相关推荐
- 自信息/熵/联合熵/条件熵/相对熵/交叉熵/互信息及其相互之间的关系
[深度学习基础]:信息论(一)_自信息/熵/联合熵/条件熵/相对熵/交叉熵/互信息及其相互之间的关系_bqw的博客-CSDN博客 详解机器学习中的熵.条件熵.相对熵和交叉熵 - 遍地胡说 - 博客园
- 熵、联和熵与条件熵、交叉熵与相对熵是什么呢?来这里有详细解读!
熵是一个很常见的名词,在物理上有重要的评估意义,自然语言处理的预备知识中,熵作为信息论的基本和重点知识,在这里我来记录一下学习的总结,并以此与大家分享. 信息论基本知识 1.熵 2.联和熵与条件熵 3 ...
- 交叉熵损失函数python_交叉熵损失函数nn.CrossEntropyLoss()
nn.CrossEntropyLoss() 1.引言 在使用pytorch深度学习框架做多分类时,计算损失函数通常会使用交叉熵损失函数nn.CrossEntropyLoss() 2. 信息量和熵 信息 ...
- 【熵与特征提取】基于“信息熵”的特征指标及其MATLAB代码实现(功率谱熵、奇异谱熵、能量熵)
<三体>中对监听员的日常工作有这样一段描述: ...1379 号监听站已经存在了上千年,像这样的监听站,在三体世界中有⼏千个,它们全神贯注地聆听着宇宙间可能存在的智慧⽂明的信息... .. ...
- Python使用matplotlib可视化两个时间序列的交叉相关性图、交叉相关图显示了两个时间序列之间的滞后性(Cross Correlation plot)
Python使用matplotlib可视化两个时间序列的交叉相关性图.交叉相关图显示了两个时间序列之间的滞后性(Cross Correlation plot) 目录
- 熵是什么?熵的公式是什么?决策树如何把熵的递减变换为信息增益进行树枝的分叉以及树的生长的?
熵是什么?熵的公式是什么?决策树如何把熵的递减变换为信息增益进行树枝的分叉以及树的生长的? 目录
- 判断两条链表是否交叉,若有交叉,返回交叉节点的指针。
上周面试挂了,反思原因,莫非是因为一道算法题没做好吗?这题目是"判断两条链表是否交叉,若有交叉,返回交叉节点的指针." 为了防止反复在同一个阴沟里翻船,决定把最优解写出来. #in ...
- 图像的一维熵和二维熵
图像的一维熵和二维熵 图像的熵是一种特征的统计形式,它反映了图像中平均信息量的多少.图像的一维熵表示图像中灰度分布的聚集特征所包含的信息量,令Pi表示图像中灰度值为i的像素所占的比例,则定义灰度图象的 ...
- 熵 计算机学,计算机科学 – 熵的计算机科学定义是什么?
熵可以表示不同的东西: In computing, entropy is the randomness collected by an operating system or application ...
最新文章
- 【代码笔记】Web-JavaScript-JavaScript调试
- 从Struts2 action 获取json 数据格式 显示到Jquery EasyUI
- 【多线程】0.理解一下5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO
- php curl rst,CURL错误:Recv失败:通过对等方重置连接 - PHP Curl
- TDD测试驱动开发过程
- android9.0 uri,Android9.0源码学习 - Launcher Activity(一)
- 信息安全期末复习整理
- 软件工程(五)软件分析和软件设计
- threejs包围盒的应用
- 【xxl-job源码篇01】xxl-job源码解读 神奇的时间轮 触发流程解读
- 深度学习与传统机器学习的区别
- 快速搭建免费的个人网站
- javascript javascript面向对象的理解及简单的示例
- 宝塔linux取消登录,宝塔面板如何关闭安全入口
- 360惊天后门曝光:“盗梦盒子”重现江湖
- 睡眠时间 数据_享受真正的安心睡眠 华米助眠耳塞Amazfit ZenBuds体验
- allegro 走线切换层_高速信号走线的九大规则
- xml文件解析的三种方式
- shell 循环语句
- 类设计者的工具(四):面向对象程序设计 (继承)
热门文章
- LeetCode:Maximus Square(DP)
- mysql 动态口令_RSA令牌动态口令生成原理
- 饥荒时用java写的吗_【图片】类与对象面向对象编程【饥荒mod制作吧】_百度贴吧...
- 基础--双方常微分方程演化博弈与matlab——matlab2016a版本
- 如何假装成为一名好程序员?
- mii-tool命令手册
- 省级瞪羚企业申报条件
- LWN:关于readahead的讨论!
- 黑苹果的心路历程(matebook14 2020版)
- tyvj p1027 木瓜地