2021年9月中旬,百度NLP岗位面试题10道

146 阅读3分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

以下是七月在线学员面试遇到的问题,做了下答案解析,供大家参考,欢迎交流。

1、神经网络有哪些初始化的方法、为什么要初始化

不初始化可能会减慢收敛速度,影响收敛效果。

如果使用的是预训练模型,是不需要自己进行初始化的,只有没有预训练模型的时候需要初始化。

常用的权重初始化算法是 「kaiming_normal」 或者 「xavier_normal」

2、python迭代器和生成器

可迭代对象(Iterable Object),简单的来理解就是可以使用 for 来循环遍历的对象。比如常见的 list、set和dict。

可迭代对象具有__iter__ 方法,用于返回一个迭代器,或者定义了 getitem 方法,可以按 index 索引的对象(并且能够在没有值时抛出一个 IndexError 异常),因此,可迭代对象就是能够通过它得到一个迭代器的对象。所以,可迭代对象都可以通过调用内建的 iter() 方法返回一个迭代器。

生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。

3、GBDT为什么拟合负梯度而不是残差

函数中下降最快的方向是导数方向,同理:GBDT中,损失函数减小最快的方向也是本身的导数方向。当损失函数为均方误差时,损失函数的负梯度和残差一样,但当损失函数不为均方误差时,本质上拟合的还是负梯度。

4、用python写一下堆排序

Pythonfrom collections import deque

def swap_param(L, i, j):
    L[i], L[j] = L[j], L[i]
 return L

def heap_adjust(L, start, end):
    temp = L[start]
    i = start
    j = 2 * i
 while j <= end:
 if (j < end) and (L[j] < L[j + 1]):
            j += 1
 if temp < L[j]:
            L[i] = L[j]
            i = j
            j = 2 * i
 else:
 break
    L[i] = temp

def heap_sort(L):
    L_length = len(L) - 1
    first_sort_count = L_length / 2
 for i in range(first_sort_count):
        heap_adjust(L, first_sort_count - i, L_length)
 for i in range(L_length - 1):
        L = swap_param(L, 1, L_length - i)
        heap_adjust(L, 1, L_length - i - 1)
 return [L[i] for i in range(1, len(L))]


def main():
    L = deque([50, 16, 30, 10, 60,  90,  2, 80, 70])
    L.appendleft(0)
 print heap_sort(L)


if __name__ == '__main__':
    main()

5、用python写一下快排排序

Pythondef getPartitionIndex(arr, left, right):
    pivote = arr[left]
 while left < right:
 while arr[right] >= pivote and right > left:
            right -= 1
        arr[left] = arr[right]
 while arr[left] <= pivote and right > left:
            left += 1
        arr[right] = arr[left]
    arr[left] = pivote
 return left
def quickSort(arr, left=None, right=None):
 # print(arr)
    left = 0 if not isinstance(left, (int, float)) else left
    right = len(arr)-1 if not isinstance(right, (int, float)) else right
 if left < right:
        partitionIndex = getPartitionIndex(arr, left, right)
        quickSort(arr, left, partitionIndex)
        quickSort(arr, partitionIndex+1, right)
 return arr

if __name__ == '__main__':
    arr = [3, 2, 1, 5, 0, 4]
    print(quickSort(arr))

6、NLG的评估指标有哪些

  • BLEU (Bilingual Evaluation Understudy)
  • ROUGE (Recall Oriented Understudy for Gisting Evaluation)

BLEU是机器翻译中使用最广泛的评估指标,可以看成是精确率,公式如下:

ROUGE可以看作是召回率,有以下几种:

ROUGE-N:计算 n-gram 的召回率,即算出候选译文和参考译文重合的 n-gram 个数占参考译文的比例;
ROUGE-L:计算最长公共子序列(LCS)的召回率;
ROUGE-W:计算加权的最长公共子序列的召回率(weighted LCS);
ROUGE-S:计算 skip-bigram 的召回率(any pair of words in sentence order allowing for arbitrary gaps)。

7、二叉树的最大路径和

思路:递归

本质就是后序遍历,对于一个二叉树节点,计算左子树和右子树的最大路径和,再加上自己的值,得到该节点的最大路径和。

首先实现一个简化函数maxGain(node),计算二叉树中一个节点的最大贡献值;

计算二叉树的最大路径和,对于二叉树中的一个节点,该节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值,如果子节点的最大贡献值为正,则计入该节点的最大路径和,否则不计入该节点的最大路径和;

维护一个全局变量maxSum存储最大路径和,在递归过程中更新maxSum的值。

代码如下:

Pythonclass Solution:
 def __init__(self):
        self.maxSum = float("-inf")
 def maxPathSum(self, root: TreeNode) -> int:
 def maxGain(node):
 if not node:
 return 0
            leftGain = max(maxGain(node.left),0)
            rightGain = max(maxGain(node.right),0)
            priceNewPath = node.val + leftGain + rightGain

            self.maxSum = max(self.maxSum, priceNewPath)

 return node.val + max(leftGain, rightGain)

        maxGain(root)
 return self.maxSum

时间复杂度:O(N)

空间复杂度:O(N)

8、attention为什么要除以根号下dk

QK进行点击之后,值之间的方差会较大,也就是大小差距会较大;如果直接通过Softmax操作,会导致大的更大,小的更小;进行缩放,会使参数更平滑,训练效果更好。

9、最长上升子序列

如上图所示,用nums表示原数组,results[i]表示截止到nums[i] 当前最长递增子序列长度为results[i],初始值均为1;

因为要找处递增序列,所以我们只需要找出nums[i]>nums[j](其中j < i)的数,并将对应的results[j]保存在tmp临时列表中,然后找出最长的那个序列将nums[i]附加其后面;

示例:假设nums[i] = 5, i = 3

更新results[i]时只需要考虑前面小于results[i]的项,所以results[0-2]均为1;

此时nums[i]前面小于5的项有nums[2],需要将results[2]保存报tmp中,然后选取tmp中最大的数值并加1后赋值给results[i], 即results[5] = 2

tmp是临时列表更新results之后需要清空;

根据上述流程更新所有results[i],即可得到下图:

此时我们只需要找出results中最大的那个值,即为最长递增子序列的长度。

参考代码如下:

Pythonclass Solution:
 def lengthOfLIS(self, nums: List[int]) -> int:
 # 特殊情况判断
 if len(nums) == 0: return 0
 
        results = [1]*len(nums)
 for i in range(1, len(nums)):
            tmp = []
 for j in range(i):
 if nums[i] > nums[j]:
                    tmp.append(results[j])
 if tmp: results[i] = max(tmp) + 1
 return max(results)

10、神经网络有什么调参技巧?

哪些参数可以调?

网络设计相关参数:网络层数、不同层的搭建顺序、隐藏层神经元的参数设置、loss的选择、正则化参数

训练过程相关参数:网络权重初始化方法、学习率、迭代次数、batch_size。

什么时候需要调参?

欠拟合:优化数据集(数据清洗)、增加训练迭代次数、添加更多的层,增大神经元参数等

过拟合:增加样本数量(数据增强),加正则化参数(dropout),使用早停机制等。