知乎
企业类型: 互联网
地点: 北京
实习类型: 日常实习
岗位: NLP算法工程师
一面—视频面
基础知识询问+做题
自我介绍
生成式模型与判别式模型的区别?
- 生成式模型先对数据的联合分布 进行建模,然后再通过贝叶斯公式计算样本属于各类别的后验概率 。
- 判别式模型直接进行条件概率建模,由数据直接学习决策函数 或条件概率分布作为预测的模型。判别方法不关心背后的数据分布,关心的是对于给定的输入,应该预测什么样的输出。
- 用一句话总结就是生成模型估计的是联合概率分布,判别式模型估计的是条件概率分布。
模型的方差和偏差是指什么?
- 偏差(Bias):表示模型的预测值和真实值之间的差异程度。用所有可能的训练数据集
训练出的所有模型的输出的平均值与真实模型的输出值之间的差异。如果模型的偏差很高,说明模型无法捕捉到数据中的所有信息,因此模型的预测值和真实值之间的差异会很大。例如,在房屋预测的例子中,如果模型只考虑了房屋的面积这一个特征,那么模型的偏差就会很高,因为模型无法考虑到其他特征(比如卧室数量、浴室数量等)对房价的影响。
- 方差(Variance):表示模型对于不同的训练集的预测结果分散程度。如果模型的方差很高,说明模型对于不同的训练集的预测结果差异很大,也就是说,模型无法捕捉到数据中的一般规律,而过度拟合了训练数据。例如,在房屋预测的例子中,如果我们使用非常复杂的模型(比如高阶多项式回归),那么模型的方差就会很高,因为模型过度拟合了训练数据,而无法捕捉到一般规律。
二分类模型的评估指标有哪些?
- 在二分类模型中,我们通常将样本分为两类:正例和反例。在评估模型性能时,我们需要考虑以下四个指标:
- 准确率(Accuracy):预测正确的样本占总样本数的比例。
- 精确率(Precision):预测为正例的样本中,真正为正例的比例。
- 召回率(Recall):真正为正例的样本中,被预测为正例的比例。
- F1值:精确率和召回率的调和平均数,常用于综合评估模型性能。
- 此外,我们还可以使用ROC曲线和AUC来评估模型的性能。ROC曲线是以假正率(False Positive Rate, FPR)为横坐标,真正率(True Positive Rate, TPR)为纵坐标绘制的曲线,用于衡量模型在不同阈值下的性能。AUC则是ROC曲线下的面积,用于综合评估模型的性能。AUC的取值范围为0.5到1,值越大,模型性能越好。
AUC刻画的什么?说明了什么意思?
- AUC(Area Under the ROC Curve)是机器学习领域中常用的一个性能度量指标,用于衡量分类器对样本的分类能力。ROC(Receiver Operating Characteristic)曲线是以假正率(False Positive Rate, FPR)为横坐标,真正率(True Positive Rate, TPR)为纵坐标绘制的曲线,用于衡量模型在不同阈值下的性能。AUC则是ROC曲线下的面积,用于综合评估模型的性能。AUC的取值范围在0.5到1之间,值越大,分类器性能越好。
- 具体来讲,AUC刻画了分类器对正负样本的分类能力,即对于一个随机的正负样本对,分类器给出正样本的预测值高于负样本的概率。AUC越高,说明分类器在区分正负样本时具有更好的能力。在实际场景中,例如医学诊断、金融风控等领域,AUC是评估分类器性能的重要指标之一。
- 需要注意的是,AUC并不是一个完美的指标,因为它并不能告诉我们分类器在不同的阈值下的表现,而且对于类别不平衡的数据集,AUC可能会给出误导性的结果。因此,在实际应用中,我们需要综合考虑多个性能度量指标来评估分类器的性能。
分类里面常用的损失函数?
- 在分类问题中,损失函数是衡量模型预测结果与真实标签之间差异的一种度量方式。常用的分类损失函数中,交叉熵损失函数是最为常见的一种。它可以有效地解决分类问题中的梯度消失和梯度爆炸问题,并且具有良好的数学性质和计算效率。除此之外,Hinge loss和指数损失函数也是常用的分类损失函数。Hinge loss在支持向量机中得到了广泛的应用,而指数损失函数则常用于排名问题和推荐系统中。在实际应用中,选择合适的损失函数可以帮助我们更好地训练模型,提高模型的性能。
交叉熵函数刻画的什么?
- 交叉熵函数是机器学习中常用的一种损失函数。它常用于评估两个概率分布之间的差异,尤其是在神经网络中用于度量模型输出与真实标签之间的差距。交叉熵函数的基本思想是将模型的输出概率与真实标签的概率进行比较,通过计算两个概率分布之间的交叉熵(cross-entropy)来衡量它们的相似程度。在分类任务中,我们通常将标签表示为一个one-hot向量,即只有一个元素为1,其余元素都为0。假设有n个类别,样本的真实标签为 y∈{0,1}n,模型的预测值为 y^∈[0,1]n,则交叉熵的定义如下:
- H(y,y^)=−∑i=1nyilogy^i
- 其中,yi 表示真实标签中第 i 个元素的取值,y^i表示模型输出中第 i 个元素的取值。交叉熵函数的值越小,说明模型的预测结果与真实标签越接近。因此,我们可以将交叉熵函数作为损失函数,通过最小化损失函数来训练模型,提高模型的预测精度。
- 交叉熵函数具有以下几个优点:首先,交叉熵函数可以有效地解决梯度消失和梯度爆炸的问题,因此在深度学习中得到了广泛的应用;其次,交叉熵函数具有良好的数学性质和计算效率,可以方便地进行优化和求导;最后,交叉熵函数可以用于多分类和二分类等不同类型的任务,具有较好的通用性。
对于非常大的分类类别,对于softmax有哪些优化方法?
- 当分类类别非常大时,计算softmax的复杂度会变得非常高,因为softmax的计算复杂度是与类别数成正比的。因此,需要采用一些优化方法来加速softmax的计算。
- 一种常见的优化方法是基于交叉熵的方法,这包括hierarchical softmax和noise-contrastive estimation(NCE)。hierarchical softmax通过将所有的类别组织成一棵二叉树,并对每个节点定义一个概率值,从而将原问题转化为对一系列二分类问题的求解。这样就可以减少softmax计算的次数,从而提高运行速度。NCE是一种用于训练softmax模型的替代方法,它通过最大化正确标签和噪声标签之间的差异来训练模型。与传统的softmax方法不同,NCE不需要计算所有类别的概率,因此在类别数非常大时可以大大提高运行速度。
- 另一种优化softmax的方法是采用近似softmax方法,例如采用采样的方法进行训练。这包括采样自适应重要性抽样(sampled softmax)、target sampling和sparsemax等。sampled softmax通过随机采样一小部分类别来近似计算softmax概率,从而减少计算量。target sampling是一种基于重要性采样的方法,它根据类别的频率对类别进行采样,从而减少少数类别的影响。sparsemax是一种类似于softmax的激活函数,但是它产生的分布更加稀疏,因此可以减少计算量。
- 总之,当我们需要处理非常大的分类问题时,需要采用一些优化方法来加速softmax的计算,从而提高运行速度和效率。不同的优化方法有不同的适用场景,需要根据具体情况进行选择。
softmax除了作为激活函数,在深度学习中还有哪些用途?
- 除了作为激活函数,还可以使用softmax进行软归一化,而且在transformer中,softmax在注意力机制中计算注意力,主要是软最大化。
softmax(dmKTQ)∗V
Transformer与RNN的区别和优缺点?
- RNN采用一种类似于递归的方式运行,无法执行并行化操作,也就无法利用GPU强大的并行化能力,而Transfomer基于Attention机制,使得模型可以并行化操作,而且能够拥有全局的信息**12**。
- RNN容易出现梯度消失或爆炸的问题,而Transformer通过残差连接和层归一化来缓解这个问题3。
- Transformer可以更好地捕捉长距离依赖关系,因为它不需要按顺序处理输入序列**43**。
- Transformer需要额外引入位置编码来表示词语在序列中的位置信息,而RNN可以自然地利用时间步来表示位置信息5。
- Transformer参数量较大,需要更多的计算资源和训练数据**56**。
Transformer是否有梯度消失和爆炸的情况吗?
- Transformer也可能会遇到梯度消失或爆炸的问题,尤其是当网络层数很多时**12**。为了解决这个问题,Transformer采用了一些技巧,比如:
- 残差连接和层归一化,可以保持数据的分布稳定,避免梯度过大或过小**32**。
- 梯度裁剪,可以设置一个阈值,当梯度超过这个阈值时将它限制在这个范围内4。
- ReZero方法,可以让每一层的输出乘以一个可学习的权重因子,从而控制每一层对最终结果的贡献程度1。
编程题:
给定一个正数,求翻转其中任意两位数字一次后的最大值
int maximumSwap(int num) {
string s = to_string(num);
int n = s.size();
char max = '0'; // 记录每个位置上的最大值
vector<int> max_index(n); // 记录每个位置上最大值的下标
for (int i = n - 1; i >= 0; i--) { // 从右往左遍历字符串
if (s[i] > max) { // 如果当前数比最大值大
max = s[i]; // 更新最大值
}
max_index[i] = max - '0'; // 存储最大值的下标
}
for (int i = 0; i < n; i++) { // 从左往右遍历字符串
if (s[i] < max_index[i] + '0') { // 如果当前数比最大值小
swap(s[i], s[max_index[i]]); // 交换两个数
break; // 只交换一次,退出循环
}
}
return stoi(s); // 返回结果
}
#知乎##知乎面经#