Bert旨在通过联合左侧和右侧的上下文,从未标记文本中预训练出一个深度双向表示模型。因此,BERT可以通过增加一个额外的输出层来进行微调,就可以达到为广泛的任务创建State-of-the-arts 模型的效果,比如QA、语言推理任务。Bert的构成:由12层Transformer Encoder构成。bert的基本任务:mask language model 和 next sentence predict,mask language model的遮盖⽅式:选择15%的token进⾏遮盖,再选择其中80%进⾏mask,10%进⾏随机替换,10%不变
BLEU(Bilingual Evaluation understudy) 是一种流行的机器翻译评价指标,一种基于精度的相似度量方法, 用于分析候选译文和参考译文中n元组共同出现的程度
ROUGE(Recall-Oriented Understudy for Gisting Evaluation) 一种基于召回率的相似度量方法,和BLEU类似, 无Fmeans 评价功能,主要考察翻译的充分性和忠实性, 无法评价参考译文的流畅度, 其计算的时N元组(Ngram)在参考译文和待测评译文的共现概率.
Transformer encoder的组成:self-Attention和feed forward组成 中间穿插残差⽹络;残差⽹络的作⽤:缓解层数加深带来的信息损失,采⽤两个线性变换激活函数为relu,同等层数的前提下残差⽹络也收敛得更快。随着神经网络深度的不断增加,利用sigmoid激活函数来训练被证实不如非平滑、低概率性的ReLU有效,因为ReLU基于输入信号做出门控决策。研究者提出了一种新的非线性激活函数,名为高斯误差线性单元(Gaussian Error Linear Unit)。
GELU与随机正则化有关,因为它是自适应Dropout的修正预期。这表明神经元输出的概率性更高,研究者发现,在计算机视觉、自然语言处理和自动语音识别等任务上,使用GELU激活函数的模型性能与使用RELU或者ELU的模型相当或者超越了它们。
import numpy as np
import matplotlib.pyplot as plt
def gelu_1(x):
# 使用numpy实现
return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x ** 3)))
def gelu_dao(inputs):
return ((np.tanh((np.sqrt(2) * (0.044715 * inputs ** 3 + inputs)) / np.sqrt(np.pi)) + ((np.sqrt(2) * inputs * (
0.134145 * inputs ** 2 + 1) * ((1 / np.cosh(
(np.sqrt(2) * (0.044715 * inputs ** 3 + inputs)) / np.sqrt(np.pi))) ** 2)) / np.sqrt(np.pi) + 1))) / 2
def plot_gelu():
x1 = np.arange(-8, 8, 0.1)
y1 = gelu_1(x1)
plt.plot(x1,y1)
y2 = gelu_dao(x1)
plt.plot(x1, y2)
plt.show()
if __name__ == '__main__':
plot_gelu()
self-Attetion的组成和作⽤
多头机制类似于“多通道”特征抽取,self attention通过attention mask动态编码变⻓序列,解决⻓距离依赖(⽆位置偏差)、可并⾏计算;
FFN 将每个位置的Multi-Head Attention结果映射到⼀个更⼤维度的特征空间,然后使⽤ReLU引⼊⾮线性进⾏筛选,最后恢复回原始维度。
Self-Attention的输出会经过Layer Normalization,为什么选择Layer Normalization⽽不是Batch Normalization?此时,我们应该先对我们的数据形状有个直观的认识,当⼀个batch的数据输⼊模型的时候,⼤⼩为(batch_size, max_len, embedding),其中batch_size为batch的批数,max_len为每⼀批数据的序列最⼤⻓度,embedding则为每⼀个单词或者字的embedding维度⼤⼩。
⽽Batch Normalization是对每个Batch的每⼀列做normalization,相当于是对batch⾥相同位置的字或者单词embedding做归⼀化,Layer Normalization是Batch的每⼀⾏做normalization,相当于是对每句话的embedding做归⼀化。显然,LN更加符合我们处理⽂本的直觉。
BERT基于“字输⼊”还是“词输⼊”好?如果基于“词输⼊”,会出现OOV(Out Of Vocabulary)问题,会增⼤标签空间,需要利⽤更多语料去学习标签分布来拟合模型。随着Transfomer特征抽取能⼒,分词不再成为必要,词级别的特征学习可以纳⼊为内部特征进⾏表示学习。
BERT的词嵌入由符号嵌入(Token Embedding)、片段嵌入(Segmentation Embedding)和位置嵌入(Position Embedding)合成得到,表示为
E w o r d = E t o k e n + E s e g + E p o s E_{word}=E_{token}+E_{seg}+E_{pos} Eword=Etoken+Eseg+Epos
三个嵌入分量都可以表达为“独热”(one-hot)编码表示输入与嵌入矩阵的乘积形式,即
E w o r d = O t o k e n W t o k e n ∣ V ∣ ∗ H + O s e g W s e g ∣ S ∣ ∗ H + O p o s W p o s ∣ P ∣ ∗ H E_{word}= O_{token}W_{token}^{|V|*H} +O_{seg}W_{seg}^{|S|*H} +O_{pos}W_{pos}^{|P|*H} Eword=OtokenWtoken∣V∣∗H+OsegWseg∣S∣∗H+OposWpos∣P∣∗H
其中, O t o k e n O_{token} Otoken︰依据符号在词典中位置下标、对输入符号构造的one-hot编码表示; O s e g O_{seg} Oseg∶依据符号在两个序列中隶属标签(更一般的为符号属性)下标、对输入符号构造的one-hot编码表示; O p o s O_{pos} Opos :以符号在句子位置下标、对输入符号构造的one-hot编码表示: W t o k e n ∣ V ∣ ∗ H , W s e g ∣ S ∣ ∗ H , W p o s ∣ P ∣ ∗ H W_{token}^{|V|*H},W_{seg}^{|S|*H},W_{pos}^{|P|*H} Wtoken∣V∣∗H,Wseg∣S∣∗H,Wpos∣P∣∗H分别为其对应的待训练嵌入参数矩阵;|V|、|S|和|P|分别为字典维度、序列个数(更一般的为符号属性)和最大位置数;H为嵌入维度。三个one-hot编码向量与嵌入矩阵相乘,等价于构造三个以one-hot编码向量作为输入,输入维度分别为|V|、|S和|P|,输出维度均为H的全连接网络。求和即为特征融合。
bert预训练任务的损失函数,两个任务是联合学习,可以使得 BERT 学习到的表征既有 token 级别信息,同时也包含了句⼦级别的语义信息。bert的损失函数组成:第⼀部分是来⾃ Mask-LM 的单词级别分类任务;另⼀部分是句⼦级别的分类任务;
在第一部分的损失函数中,如果被mask的词集合为M,因为它是一个词典大小V上的多分类问题,所用的损失函数叫做负对数似然函数(且是最小化,等价于最大化对数似然函数),那么具体说来有:
L 1 ( θ , θ 1 ) = − ∑ i = 1 M l o g p ( m = m i ∣ θ , θ 1 ) , m i ∈ [ 1 , 2 , . . . , ∣ V ∣ ] L_1(\theta,\theta_1)=-\sum_{i=1}^Mlogp(m=m_i|\theta,\theta_1),m_i\in[1,2,...,|V|] L1(θ,θ1)=−i=1∑Mlogp(m=mi∣θ,θ1),mi∈[1,2,...,∣V∣]
在第二部分的损失函数中,在句子预测任务中,也是一个分类问题的损失函数:
L 2 ( θ , θ 2 ) = − ∑ j = 1 N l o g p ( n = n i ∣ θ , θ 2 ) , n i ∈ [ i s n e x t , n o t n e x t ] L_2(\theta,\theta_2)=-\sum_{j=1}^Nlogp(n=n_i|\theta,\theta_2),n_i\in[isnext,notnext] L2(θ,θ2)=−j=1∑Nlogp(n=ni∣θ,θ2),ni∈[isnext,notnext]
自回归与自编码
RNN的统—定义为
h t = f ( x t , h t − 1 ; θ ) h_t=f(x_t,h_{t-1};\theta) ht=f(xt,ht−1;θ)
其中 h t h_t ht是每一步的输出,它由当前输入 x t x_t xt和前一时刻输出 h t − 1 h_{t-1} ht−1共同决定,而 θ \theta θ则是可训练参数。在做最基本的分析时,我们可以假设 h t , h t − 1 , θ h_t , h_{t-1},\theta ht,ht−1,θ都是一维的,这可以让我们获得最直观的理解,并且其结果对高维情形仍有参考价值。要求我们定义的模型有一个比较合理的梯度。我们可以求得:
d h t d θ = δ h t δ h t − 1 d h t − 1 δ θ + δ h t δ θ \frac{d~ h_t}{d~ \theta}=\frac{\delta h_t}{\delta h_{t-1}}\frac{d~ h_{t-1}}{\delta \theta} +\frac{\delta h_t}{\delta \theta} d θd ht=δht−1δhtδθd ht−1+δθδht
所以步数多了,梯度消失或爆炸几乎都是不可避免的,我们只能对于有限的步数去缓解这个问题。
梯度爆炸︰设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。梯度值变得非常大,从而对参数的更新产生巨大影响。这可能会导致模型无法收敛或收敛速度过慢。
可能引起梯度爆炸的原因(这其实就是根据反向传播的三个函数链式求导,一个是上一个神经元激活函数,一个是损失函数导数,一个是激活函数导数:
饱和性质的激活函数是指在输入数据较大或较小时,激活函数的导数趋近于0,导致梯度消失或爆炸。这种情况下,神经网络可能会面临训练困难、收敛缓慢等问题。
常见的饱和性质的激活函数有Sigmoid函数和双曲正切(Tanh)函数。它们在输入接近极端值时,导数接近于0。对于Sigmoid函数而言,在输入非常大或非常小时,输出值会趋向于1或0,并且导数几乎为0;对于Tanh函数而言,在输入非常大或非常小时,输出值也会趋向于1或-1,并且导数同样几乎为0。
ReLU是一种简单但广泛使用的不饱和性质的激活函数。当输入为正时,ReLU将保持原始值作为输出;当输入为负时,则返回零作为输出。ReLU在实践中被证明可以有效地解决梯度消失问题,并提高神经网络模型的训练速度与效果。
Leaky ReLU是对ReLU的改进,它在输入为负时不返回零,而是返回一个小的非零值。这样可以避免ReLU中出现的“神经元死亡”问题(即某些神经元永远不会被激活),并且有助于增加模型的表达能力。
| 激活函数 | 表达式 | 导数 |
|---|---|---|
| sigmoid | f ( x ) = 1 1 + e x f(x)=\frac{1}{1+e^x} f(x)=1+ex1 | f ′ ( x ) = f ( x ) ( 1 − f ( x ) ) f'(x)=f(x)(1-f(x)) f′(x)=f(x)(1−f(x)) |
| tanh | f ( x ) = e 2 x − 1 e 2 x + 1 f(x)=\frac{e^{2x}-1}{e^{2x}+1} f(x)=e2x+1e2x−1 | f ′ ( x ) = 1 − ( f ( x ) ) 2 f'(x)=1-(f(x))^2 f′(x)=1−(f(x))2 |
| Relu | f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x) | f ′ ( x ) = s g n ( x ) f'(x)=sgn(x) f′(x)=sgn(x) |
| Bnll | f ( x ) = l o g ( 1 + e x ) f(x)=log(1+e^x) f(x)=log(1+ex) | f ′ ( x ) e x 1 + e x f'(x)\frac{e^x}{1+e^x} f′(x)1+exex |
| Gelu | f ( x ) = 0.5 x ( 1 + t a n h ( 2 π ( x + 0.044715 x 3 ) ) ) f(x)=0.5x(1+tanh(\sqrt\frac2\pi(x+0.044715x^3))) f(x)=0.5x(1+tanh(π2(x+0.044715x3))) | |
| swish | f ( x ) = x ∗ s i g m o i d ( β ∗ x ) f(x)=x*sigmoid(\beta*x) f(x)=x∗sigmoid(β∗x) | |
| Leaky relu |
f
(
x
)
=
{
x
if x>0
γ
∗
x
if x<=0
f(x) = | |
| Elu |
f
(
x
)
=
{
x
if x>0
α
(
e
x
−
1
)
if x<=0
f(x) = | |
| softmax | f ( x ) = e i ∑ j e j f(x)=\frac{e^i}{\sum_je^j} f(x)=∑jejei |
为了解决梯度爆炸问题,可以采取以下措施:
梯度消失是指在深层神经网络中,随着反向传播过程的进行,较早层的权重更新变得非常小或趋近于零,导致这些层对整个网络参数的学习贡献几乎为零。这可能会导致模型无法有效地学习和优化。
LSTM有输⼊⻔、输出⻔、遗忘⻔
batch_size与学习率
学习率直接影响模型的收敛状态,batchsize则影响模型的泛化性能,两者又是分子分母的直接关系,相互也可影响。
W t + 1 = W t − η 1 b ∑ x ∈ B Δ l ( x , W t ) W_{t+1}=W_t-\eta\frac1b\sum_{x\in\mathcal{B}}\Delta l(x,W_t) Wt+1=Wt−ηb1x∈B∑Δl(x,Wt)
大的batchsize减少训练时间,提高稳定性。这是肯定的,同样的epoch数目,大的batchsize需要的迭代数目减少了,所以可以减少训练时间。另一方面,大的batch size梯度的计算更加稳定,因为模型训练曲线会更加平滑。在微调的时候,大的batch size可能会取得更好的结果。
ROC与AUC
ROC要计算FPR和TPR,曲线上的每个点代表不同阈值时的FPR和TPR。在正负样本数量不均衡的时候,比如负样本的数量增加到原来的10倍,那TPR不受影响,FPR的各项也是成比例的增加,并不会有太大的变化。因此,在样本不均衡的情况下,同样ROC曲线仍然能较好地评价分类器的性能,这是ROC的一个优良特性,也是为什么一般ROC曲线使用更多的原因。
ROC曲线的横坐标是假阳性率(False Positive Rate),纵坐标是真阳性率(True Positive Rate),相应的还有真阴性率(True Negative Rate)和假阴性率(False Negative Rate)。这四类指标的计算方法如下:
假阳性率(FPR):判定为正例却不是真正例的概率,即真负例中判为正例的概率
F P R = F P F P + T N FPR=\frac{FP}{FP+TN} FPR=FP+TNFP
真阳性率(TPR):判定为正例也是真正例的概率,即真正例中判为正例的概率(也即正例召回率)
T P R = T P T P + F N TPR=\frac{TP}{TP+FN} TPR=TP+FNTP
假阴性率(FNR):判定为负例却不是真负例的概率,即真正例中判为负例的概率。
真阴性率(TNR):判定为负例也是真负例的概率,即真负例中判为负例的概率。
| 预测为真 | 预测为假 | 合计 | |
|---|---|---|---|
| 实际为真 | true positive | false negative | TP+FN (Recall,TPR分母) |
| 实际为假 | false positive | true negative | FP+TN (FPR分母) |
| 合计 | TP+FP (Precision分母) | FN+TN | TP+FP+TN+FN |
A c c = T P + T N T P + F P + T N + F N R e c a l l = T P T P + F N = T P R P r e c i s i o n = T P T P + F P Acc=\frac{TP+TN}{TP+FP+TN+FN}\\ Recall=\frac{TP}{TP+FN}=TPR\\ Precision=\frac{TP}{TP+FP} Acc=TP+FP+TN+FNTP+TNRecall=TP+FNTP=TPRPrecision=TP+FPTP
在一个二分类模型中,对于所得到的连续结果,假设已确定一个阀值,比如说 0.6,大于这个值的实例划归为正类,小于这个值则划到负类中。如果减小阀值,减到0.5,固然能识别出更多的正类,也就是提高了识别出的正例占所有正例 的比类,即TPR,但同时也将更多的负实例当作了正实例,即提高了FPR。
ROC曲线上的每一个点对应于一个threshold,对于一个分类器,每个threshold下会有一个TPR和FPR。比如Threshold最大时,TP=FP=0,对应于原点;Threshold最小时,TN=FN=0,对应于右上角的点(1,1)。随着阈值theta增加,TP和FP都减小,TPR和FPR也减小,ROC点向左下移动;而auc就是roc曲线与下方坐标轴围成的面积。
A U C = ∑ i ∈ 正样本 R a n k i − M ( 1 + M ) 2 M ∗ N M 为正样本数, N 为负样本数目 AUC=\frac{\sum_{i\in正样本}Rank_i-\frac{M(1+M)}{2}}{M*N}\\ M为正样本数,N为负样本数目 AUC=M∗N∑i∈正样本Ranki−2M(1+M)M为正样本数,N为负样本数目
import numpy as np
from sklearn.metrics import roc_curve
from sklearn.metrics import auc
def auc_calculate(labels,preds,n_bins=100):
postive_len = sum(labels) #正样本数量(因为正样本都是1)
negative_len = len(labels) - postive_len #负样本数量
total_case = postive_len * negative_len #正负样本对
pos_histogram = [0 for _ in range(n_bins)]
neg_histogram = [0 for _ in range(n_bins)]
bin_width = 1.0 / n_bins
for i in range(len(labels)):
nth_bin = int(preds[i]/bin_width)
if labels[i]==1:
pos_histogram[nth_bin] += 1
else:
neg_histogram[nth_bin] += 1
accumulated_neg = 0
satisfied_pair = 0
for i in range(n_bins):
satisfied_pair += (pos_histogram[i]*accumulated_neg + pos_histogram[i]*neg_histogram[i]*0.5)
accumulated_neg += neg_histogram[i]
return satisfied_pair / float(total_case)
if __name__ == '__main__':
y = np.array([1,0,0,0,1,0,1,0,])
pred = np.array([0.9, 0.8, 0.3, 0.1,0.4,0.9,0.66,0.7])
fpr, tpr, thresholds = roc_curve(y, pred, pos_label=1)
print("sklearn:",auc(fpr, tpr))
print("验证:",auc_calculate(y,pred))
AUC即ROC曲线下的面积,AUC越大,说明分类器越可能把正样本排在前面,衡量的是一种排序的性能。AUC的优点:
AUC对正负样本均衡并不敏感,在样本不均衡的情况下,也可以做出合理的评估。
AUC的缺点:
AUC反应了太过笼统的信息。⽆法反应召回率、精确率等在实际业务中经常关⼼的指标;
L1正则化和L2正则化分别适用于什么样的场景:
归⼀化:对不同特征维度的伸缩变换的⽬的是使各个特征维度对⽬标函数的影响权重是⼀致的,即使得那些扁平分布的数据伸缩变换成类圆形。这也就改变了原始数据的⼀个分布。
标准化:对不同特征维度的伸缩变换的⽬的是使得不同度量之间的特征具有可⽐性。同时不改变原始数据的分布。使得不同度量之间的特征具有可⽐性,对⽬标函数的影响体现在⼏何分布上,⽽不是数值上
逻辑回归假设数据服从伯努利分布,通过极⼤化似然函数的⽅法,利⽤梯度下降求解参数,来达到将数据⼆分类的⽬的。逻辑回归的第⼆个假设是:样本为正的概率 p = 1 1 + e − θ T x p=\frac{1}{1+e^{-\theta ^{T}x}} p=1+e−θTx1 ,逻辑回归即h(x;θ)=p。伯努利试验是单次随机试验,只有"成功(值为1)"或"失败(值为0)"这两种结果,是由瑞士科学家雅各布**·伯努利(1654 - 1705)提出来的。其概率分布称为伯努利分布**(Bernoulli distribution),也称为两点分布或者0-1分布,是最简单的离散型概率分布。我们记成功概率为p(0≤p≤1),则失败概率为q=1-p。逻辑回归的损失函数就是h(x;θ)的极⼤似然函数
L θ ( x ) = ∏ i = 1 m h θ ( x i ; θ ) y i ∗ ( 1 − h θ ( x i ; θ ) ) 1 − y i L_\theta(x)=\prod^m_{i=1}h_{\theta}(x^i;\theta)^{y_i}*(1-h_\theta(x^i;\theta))^{1-y^i} Lθ(x)=i=1∏mhθ(xi;θ)yi∗(1−hθ(xi;θ))1−yi
极⼤似然的核⼼思想是如果现有样本可以代表总体,那么极⼤似然估计就是找到⼀组参数使得出现现有样本的可能性最⼤。
批梯度下降会获得全局最优解,缺点是在更新每个参数的时候需要遍历所有的数据,计算量会很大,并且会有很多的冗余计算,显存不友好,导致的结果是当数据量大的时候,每个参数的更新都会很慢。
随机梯度下降是以高方差频繁更新,优点是使得sgd会跳到新的和潜在更好的局部最优解,缺点是使得收敛到局部最优解的过程更加的复杂。
小批量梯度下降结合了sgd和batch gd的优点,每次更新的时候使用n个样本。减少了参数更新的次数,可以达到更加稳定收敛结果,一般在深度学习当中我们采用这种方法。
设在特征空间中,位于 x 附近的训练数据中正例所占的比例为 p ,模型在 x 处给出的输出为 y。用cross entropy 作为损失函数,位于 x 附近的这些训练数据,对损失函数的贡献就是:
L = − p l o g y − ( 1 − p ) l o g ( 1 − y ) L=-plogy-(1-p)log(1-y) L=−plogy−(1−p)log(1−y)
容易算出,使得 L 最小的 y 就等于P,也就是说模型的输出会等于在 x 附近取一个数据,它属于正类的概率。
SVM本质是在求⽀持向量到超平⾯的⼏何间隔的最⼤值,svm适合解决⼩样本、⾮线性、⾼纬度的问题,核函数:样本集在低维空间线性不可分时,核函数将原始数据映射到⾼维空间,或者增加数据维度,使得样本线性可分。常⽤核函数:
svm的⽬标函数(硬间隔),有两个⽬标:第⼀个是使间隔最⼤化,第⼆个是使样本正确分类,由此推出⽬标函数:
min w , b 1 2 ∣ ∣ w ∣ ∣ 2 y i ( w T x i + b ) > = 1 , i = 1 , 2 , . . . , n \min_{w,b}\frac12||w||^2\\ y_i(w^Tx_i+b)>=1,i=1,2,...,n w,bmin21∣∣w∣∣2yi(wTxi+b)>=1,i=1,2,...,n
这是⼀个有约束条件的最优化问题,⽤拉格朗⽇函数来解决
min w , b max α = 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) \min_{w,b}\max_\alpha=\frac12||w||^2+\sum_{i=1}^m\alpha_i(1-y_i(w^Tx_i+b)) w,bminαmax=21∣∣w∣∣2+i=1∑mαi(1−yi(wTxi+b))
不管直接在原特征空间,还是在映射的⾼维空间,我们都假设样本是线性可分的。虽然理论上我们总能找到⼀个⾼维映射使数据线性可分,但在实际任务中,寻找⼀个合适的核函数核很困难。此外,由于数据通常有噪声存在,⼀味追求数据线性可分可能会使模型陷⼊过拟合,因此,我们放宽对样本的要求,允许少量样本分类错误。这样的想法就意味着对⽬标函数的改变,之前推导的⽬标函数⾥不允许任何错误,并且让间隔最⼤,现在给之前的⽬标函数加上⼀个误差,就相当于允许原先的⽬标出错,引⼊松弛变量 εi≥0,公式变为:
min w , b , η 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 n η i \min_{w,b,\eta}\frac12||w||^2+\sum_{i=1}^n\eta_i w,b,ηmin21∣∣w∣∣2+i=1∑nηi
那么这个松弛变量怎么计算呢,最开始试图⽤0,1损失去计算,但0,1损失函数并不连续,求最值时求导的时候不好求,所以引⼊合⻚损失(hinge loss):
l h i n g e ( z ) = m a x ( 0 , 1 − z ) l_{hinge}(z)=max(0,1-z) lhinge(z)=max(0,1−z)
理解起来就是,原先制约条件是保证所有样本分类正确, y i ( w T x i + b ) ≥ 1 y^i (w^Tx_i+b) ≥1 yi(wTxi+b)≥1,现在出现错误的时候,一定是这个式子不被满足了,即 y i ( w T x i + b ) < 1 , 任意 i 错误 y_i (w^T x_i + b)<1,任意 i 错误 yi(wTxi+b)<1,任意i错误,衡量一下错了多少呢?因为左边一定小于1,那就跟 1 比较,因为1是边界,所以用 1 减去 y i ( w T x i + b ) y_i(w^Tx_i+ b) yi(wTxi+b)来衡量错误了多少,所以目标变为(正确分类的话损失为0,错误的话付出代价,但这个代价需要一个控制的因子,引入C>0,惩罚参数,)∶
min w , b 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n m a x ( 0 , 1 − y i ( w T x i + b ) ) \min_{w,b}\frac12||w||^2+C\sum^n_{i=1}max(0,1-y_i(w^Tx_i+b)) w,bmin21∣∣w∣∣2+Ci=1∑nmax(0,1−yi(wTxi+b))
可以想象,C越大说明把错误放的越大,说明对错误的容忍度就小,反之亦然。当C无穷大时,就变成一点错误都不能容忍,即变成硬间隔。实际应用时我们要合理选取C,C越小越容易欠拟合,C越大越容易过拟合。
LR与SVM的相同点:都是有监督的分类算法;如果不考虑核函数,LR和SVM都是线性分类算法。它们的分类决策⾯都是线性的。LR和SVM都是判别式模型。
LR与SVM的不同点:本质上是loss函数不同,或者说分类的原理理不不同。SVM是结构⻛险最⼩化(经验+正则),LR则是经验⻛险最⼩化。SVM只考虑分界⾯附近的少数点,⽽LR则考虑所有点。在解决⾮线性问题时,SVM可采⽤核函数的机制,⽽LR通常不采⽤核函数的⽅法。SVM计算复杂,但效果⽐LR好,适合⼩数据集;LR计算简单,适合⼤数据集,可以在线训练。
⼀个单词被选作 negative sample 的概率跟它出现的频次有关,出现频次越⾼的单词越容易被选作negative words。在论⽂中作者指出指出对于⼩规模数据集,建议选择 5-20 个 negative words,对于⼤规模数据集选择 2-5个negative words.
TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆⽂件频率)是⼀种统计⽅法,⽤以评估⼀字词对于⼀个⽂件集或⼀个语料库中的其中⼀份⽂件的重要程度。字词的᯿要性随着它在⽂件中出现的次数成正⽐增加,但同时会随着它在语料库中出现的频率成反⽐下降。TF(Term Frequency, 词频)表示词条在⽂本中出现的频率;IDF(Inverse Document Frequency, 逆⽂件频率)表示关键词的普遍程度
jieba分词:依据统计词典(模型中这部分已经具备,也可⾃定义加载)构建统计词典中词的前缀词典。前缀词典构造是将在统计词典中出现的每⼀个词的每⼀个前缀提取出来,统计词频,如果某个前缀词在统计词典中没有出现,词频统计为0。依据前缀词典对输⼊的句⼦进⾏DAG(有向⽆环图)的构造。以每个字所在的位置为键值key,相应划分的末尾位置构成的列表为value。使⽤动态规划的⽅法在DAG上找到⼀条概率最⼤路径,依据此路径进⾏分词。每⼀个词出现的概率等于该词在前缀⾥的词频除以所有词的词频之和。如果词频为0或是不存在,当做词频为1来处理。这⾥会取对数概率,即在每个词概率的基础上取对数,⼀是为了防⽌下溢,⼆后⾯的概率相乘可以变成相加计算。对于未收录词(是指不在统计词典中出现的词),使⽤HMM(隐⻢尔克夫模型)模型,⽤Viterbi(维特⽐)算法找出最可能出现的隐状态序列。
感受野(receptive field,RF)也许是CNN中最重要的概念之一,从文献上来看,它应当引起足够的重视。目前所有最好的图像识别方法都是在基于感受野理念来设计模型架构。感受野指的是一个特定的CNN特征(特征图上的某个点)在输入空间所受影响的区域。一个感受野可以用中心位置(center location)和大小(size)来表征。然而,对于一个CNN特征来说,感受野中的每个像素值(pixel)并不是同等重要。一个像素点越接近感受野中心,它对输出特征的计算所起作用越大。这意味着某一个特征不仅仅是受限在输入图片中某个特定的区域(感受野),并且呈指数级聚焦在区域的中心。
卷积层(conv)和池化层(pooling)都会影响感受野,而激活函数层通常对于感受野没有影响,当前层的步长并不影响当前层的感受野,感受野和填补(padding)没有关系, 计算当层感受野的公式如下:
R F i + 1 = R F i + ( k − 1 ) ∗ S i RF_{i+1}=RF_i+(k-1)*S_i RFi+1=RFi+(k−1)∗Si
其中, R F i + 1 RF_{i+1} RFi+1 表示当前层的感受野, R F i RF_i RFi 表示上一层的感受野, k 表示卷积核的大小,例如3*3的卷积核,则 k=3 , S i S_i Si 表示之前所有层的步长的乘积(不包括本层)。通常上述公式求取的感受野通常很大,而实际的有效感受野(Effective Receptive Field)往往小于理论感受野,因为输入层中边缘点的使用次数明显比中间点要少,因此作出的贡献不同,所以经过多层的卷积堆叠后,输入层对于特征图点做出的贡献分布呈高斯分布形状。
卷积操作的输入与输出尺寸之间的关系如下所示。注意下列除法为 向下取整。
H o u t = ⌞ H i n + 2 ∗ p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ∗ ( k e r n e l [ 0 ] − 1 ) s t r i d e [ 0 ] + 1 ⌟ H_{out}=\llcorner\frac{H_{in}+2*padding[0]-dilation[0]*(kernel[0]-1)}{stride[0]}+1 \lrcorner Hout=└stride[0]Hin+2∗padding[0]−dilation[0]∗(kernel[0]−1)+1┘
kernel_size (int or tuple) – 卷积核的大小;卷积核尺寸,尺寸越大‘感受野’越大,及处理的特征单位越大,同时计算量也越大
stride (int or tuple, optional) – 卷积步长(默认为1);卷积核移动的步数,默认1步,增大步数会忽略局部细节计算,适用于高分辨率的计算提升
padding (int, tuple or str, optional) – 输入信号四周的填充,默认填充0。就是填充的意思,通过padding,可以填充图片的边缘,让图片的边缘的特征得到更充分的计算(不至于被截断)
dilation (int or tuple, optional) – 卷积核元素之间的间距,默认为1,也就是常规的卷积方式;
转置卷积,也称为反卷积(deconvlution)和分部卷积(fractionally-strided convolution)。为卷积的逆操作,即把特征的维度压缩,但尺寸放大。注意它 不是真正意义上 的卷积的逆操作。通过反卷积,只能恢复原矩阵的大小,但并不能完全恢复原矩阵的数值。
KNN 算法,对未知类别属性的数据集中的每个点依次执⾏以下操作:
决策树的⽣成算法,信息熵越⼤信息的纯度越低。数据的信息熵: − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ l o g 2 ∣ C k ∣ ∣ D ∣ -\sum_{k=1}^{K}\frac{\left | C_{k} \right |}{\left | D \right |}log_{2}\frac{\left | C_{k} \right |}{\left| D \right |} −∑k=1K∣D∣∣Ck∣log2∣D∣∣Ck∣ Ck表示集合D中属于第k类样本的样本⼦集。信息增益=信息熵-条件熵,信息增益是非对称的,用以度量两种概率分布P和Q的差异,从P到Q的信息增益通常不等于从Q到P的信息增益。
条件熵: H ( X ∣ Y ) = ∑ x , y p ( x , y ) l o g ( p ( x ∣ y ) ) 条件熵:H(X|Y)=\sum_{x,y}p(x,y)log(p(x|y)) 条件熵:H(X∣Y)=x,y∑p(x,y)log(p(x∣y))
信息增益是知道了某个条件后,事件的不确定性下降的程度,知道了某个条件后,原来事件不确定性降低的幅度。
ID3:根据信息增益分类
C4.5:根据信息增益率划分
CART:根据基尼指数分类,越⼩越好
G i n i ( D ) = ∑ k = 1 K p k ( 1 − p k ) = 1 − s u m k = 1 K p k 2 Gini(D)=\sum_{k=1}^Kp_k(1-p_k)=1-sum_{k=1}^Kp_k^2 Gini(D)=k=1∑Kpk(1−pk)=1−sumk=1Kpk2
pk为Ck表示集合D中属于第k类样本的样本⼦集的概率,CART 在 C4.5 的基础上进⾏了很多提升。
C4.5 为多叉树,运算速度慢,CART 为⼆叉树,运算速度快;C4.5 只能分类,CART 既可以分类也可以回归;CART 使⽤ Gini 系数作为变ᰁ的不纯度量,减少了⼤量的对数运算;CART 采⽤代理测试来估计缺失值,⽽ C4.5 以不同概率划分到不同节点中;CART 采⽤“基于代价复杂度剪枝”⽅法进⾏剪枝,⽽ C4.5 采⽤悲观剪枝⽅法。CART 的⼀⼤优势在于:⽆论训练数据集有多失衡,它都可以将其主动消除不需要建模⼈员采取其他操作。
| ID3 | C4.5 | CART | |
|---|---|---|---|
| 划分标准 | 信息增益,偏向特征值多的特征 | 信息增益率,偏向于特征值⼩的特征 | 基尼指数,克服 C4.5 需要求 log 的巨⼤计算量,偏向于特征值较多的特征 |
| 使⽤场景 | 只能⽤于分类问题;是多叉树,速度较慢 | 只能⽤于分类问题;多叉树,速度较慢 | 可以⽤于分类和回归问题;⼆叉树,计算速度很快 |
| 样本数据 | 只能处理离散数据且缺失值敏感 | 连续性数据且有多种⽅式处理缺失值;小样本;多次扫描,处理耗时高 | 连续性数据且有多种⽅式处理缺失值;大数据量 |
| 样本特征 | 层级之间只使⽤⼀次特征 | 层级之间只使⽤⼀次特征 | 可多次重复使⽤特征 |
| 剪枝策略 | 没有剪枝策略 | 悲观剪枝策略来修正树的准确性 | 通过代价复杂度剪枝 |
bagging,每个基学习器都会对训练集进⾏有放回抽样得到⼦训练集,每个基学习器基于不同⼦训练集进⾏训练,并综合所有基学习器的预测值得到最终的预测结果。Bagging 常⽤的综合⽅法是投票法,票数最多的类别为预测类别。
boosting,基模型的训练是有顺序的,每个基模型都会在前⼀个基模型学习的基础上进⾏学习,最终综合所有基模型的预测值产⽣最终的预测结果,⽤的⽐较多的综合⽅式为加权法
stacking,并通过训练⼀个元模型来组合它们,然后基于这些弱模型返回的多个预测结果形成新的训练集,通过新的训练集去训练组合模型得到新模型去预测。其中⽤了k-折交叉训练。假设我们想要拟合由 L 个弱学习器组成的 stacking 集成模型。我们必须遵循以下步骤:
为什么集成学习会好于单个学习器呢?
Bagging和Stacking中的基模型为强模型(偏差低,⽅差⾼),⽽Boosting中的基模型为弱模型(偏差⾼,⽅差低)。
随机森林 = Bagging+CART决策树
Adaboost,前⼀个基本分类器分错的样本会得到加强,加权后的全体样本再次被⽤来训练下⼀个基本分类器。同时,在每⼀轮中加⼊⼀个新的弱分类器,直到达到某个预定的⾜够⼩的错误率或达到预先指定的最⼤迭代次数。
GDBT = Gradient boosting + CART决策树
GBDT 由三个概念组成:Regression Decision Tree(即 DT)、Gradient Boosting(即 GB),和 Shrinkage(⼀个重要演变)
GBDT 中的树都是回归树;梯度迭代:GBDT 的每⼀步残差计算其实变相地增⼤了被分错样本的权重,⽽对与分对样本的权重趋于 0,这样后⾯的树就能专注于那些被分错的样本;缩减:不直接⽤残差修复误差,⽽是只修复⼀点点,把⼤步切成⼩步。
可以⾃动进⾏特征组合,拟合⾮线性数据;可以灵活处理各种类型的数据。对异常点敏感。
与Adaboost的对⽐:都是 Boosting 家族成员,使⽤弱分类器;都使⽤前向分布算法;
迭代思路不同:Adaboost 是通过提升错分数据点的权重来弥补模型的不⾜(利⽤错分样本),⽽ GBDT 是通过算梯度来弥补模型的不⾜(利⽤残差);损失函数不同:AdaBoost 采⽤的是指数损失,GBDT 使⽤的是绝对损失或者 Huber 损失函数;
MSE 和 MAE 各有优点和缺点,那么有没有一种激活函数能同时消除二者的缺点,集合二者的优点呢?答案是有的。Huber Loss 就具备这样的优点,Huber Loss 是对二者的综合,包含了一个超参数 δ。δ 值的大小决定了 Huber Loss 对 MSE 和 MAE 的侧重性,当 |y−f(x)| ≤ δ 时,变为 MSE;当 |y−f(x)| > δ 时,则变成类似于 MAE,因此 Huber Loss 同时具备了 MSE 和 MAE 的优点,减小了对离群点的敏感度问题,实现了处处可导的功能。其公式如下:
f
(
x
)
=
{
1
2
(
y
−
f
(
x
)
)
2
if |y−f(x)| ≤ δ
δ
∣
y
−
f
(
x
)
∣
−
1
2
δ
2
if |y−f(x)| > δ
f(x) =
XGBoost 是⼤规模并⾏ boosting tree 的⼯具,它是⽬前最快最好的开源 boosting tree ⼯具包