ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

网易NLP算法实习笔试复盘:基础原理与编程硬核考点全解析

网易NLP算法实习笔试复盘:基础原理与编程硬核考点全解析 2018年春招那会儿我还在为研究生的暑期实习到处投简历。网易这个岗位开放时我第一时间投了NLP算法实习生。笔试是在在线平台上完成的两个小时题量不算小从机器学习基础到字符串算法再到一些开放性场景题都有涉及。做完最大的感受是基础不牢真的会当场露馅。后来我又陆续参加了其他几家公司的笔试回过头来再看网易这套题其实代表了一批互联网公司NLP实习笔试的典型风格基础概念占比大、算法题有硬货、开放题看思维习惯。这篇文章就把这类笔试的考察方向、常考原理和答题思路掰开聊一聊给准备NLP算法实习岗的同学一个可参考的复盘样本。1. 整张卷子长什么样题型分布与考察意图1.1 题量、时间与分值结构从我在线笔试的实际体验来看网易这类大厂实习生招聘笔试基本都是客观题加主观题混合出题时长在90到120分钟之间。我印象中当时的题型大致可以分成四块单项选择题、多项选择题、编程题、开放问答。单选题每道分值不高但架不住量大覆盖范围非常散多选题最麻烦的地方在于漏选、错选都不得分对知识点的精确度要求很高编程题一般一到两道难度中等偏上考的是数据结构和基础算法开放问答通常会结合业务场景比如“如何设计一个短文本情感分析模块”这样的题考察你把理论转化为工程方案的能力。用一个表格来还原我当时遇到的考察范围分布会更直观一些题型考察内容举例大概占比单选机器学习基础、NLP基础、数学概率、线性代数35%多选模型原理细节、边界条件、易混淆概念20%编程题字符串处理、数据结构、动态规划、贪心25%开放题场景设计、方案选型、问题排查思路20%这个比例不是精确的原始卷面数据但方向上八九不离十。如果你准备的是其他公司的NLP实习笔试大概率也会在类似框架内浮动。1.2 网易这届笔试风格透露出的三个信号第一个信号是重基础且基础题不送分。比如贝叶斯公式、TF-IDF的平滑处理、朴素贝叶斯为什么在特征强相关时效果变差这些看起来“人人都知道”的知识点题目会往细节处挖。很多同学只背结论不推公式遇到“换了个说法”的选择题就懵。第二个信号是编程题不追求偏题怪题但要求一次写对。在线笔试的编程题不像面试手撕代码那样有面试官提示你面对的只有题目描述和编译器。考察重点集中在KMP、排序、动态规划、贪心等经典问题但数据范围设置得很“阴”暴力解法往往只能过部分用例。这意味着你不仅要会写还要写对复杂度正确的解法。第三个信号是开放题没有标准答案但很看答题结构。同样是“如何解决数据稀疏问题”有的人答两三行笼统的话有的人会从回退平滑、加一平滑、词向量扩充、子词切分几个层面递进展开。后者在阅卷人眼里就是明显的加分项。这也是为什么我建议准备笔试时不要只刷题要刻意练习“结构化表达”。2. NLP基础理论考点从n-gram到CRF必须吃透的原理2.1 语言模型与n-gram平滑和困惑度是高频点语言模型这块我当时遇到的选择题主要集中在n-gram模型的概率计算、平滑方法的作用、以及困惑度的比较。n-gram的核心假设是马尔可夫性一个词出现的概率只和前面n-1个词有关。一般化公式是P(w_i | w_1...w_{i-1}) ≈ P(w_i | w_{i-n1}...w_{i-1})实际计算时用极大似然估计P(w_i | w_{i-n1}...w_{i-1}) count(w_{i-n1}...w_i) / count(w_{i-n1}...w_{i-1})问题出在数据稀疏语料里总会出现没见过的n-gram组合直接算概率是0这在很多任务里会直接崩掉。所以平滑方法就成了必考点。加一平滑Laplace平滑把每个n-gram的计数加1简单但会过度惩罚高频词Kneser-Ney平滑在当年属于进阶内容实习笔试一般不会考到那么深但至少要知道“平滑是解决零概率问题而不是简单改变词频”。困惑度的定义也需要理解得透彻一点。对测试集计算困惑度公式是PP(W) P(w_1 w_2 ... w_N)^(-1/N)。困惑度越低说明模型对测试集的预测概率越高泛化能力越好。但笔试可能会反过来问为什么困惑度低的模型不一定在具体任务上表现更好这时候要从“语言模型是生成式建模而下游任务往往是判别式需求”的角度去答。2.2 词向量与分布式表示one-hot、TF-IDF、word2vec的差异NLP笔试几乎必考词表示。one-hot向量的问题很直观维度爆炸、无法体现词与词之间的相似度。TF-IDF解决了一部分“常见词权重过高”的问题但它仍然是基于词袋的稀疏表示对语义相近的词无能为力比如“汽车”和“轿车”在TF-IDF空间里完全独立。word2vec是当年的高频考点也是现在很多模型的启蒙。它的核心思路是用一个浅层神经网络把词映射成低维稠密向量使得语义相近的词在向量空间中距离更近。CBOW是根据上下文预测中心词Skip-gram是根据中心词预测上下文。笔试常见问题包括为什么用负采样因为softmax归一化需要对词表里所有词计算概率词表几十万维太慢。负采样把多分类问题转化为二分类问题只采样少量负样本做区分。层次softmax是怎么优化的利用霍夫曼树把softmax的计算复杂度从O(V)降为O(log V)。word2vec和Glove有什么区别word2vec利用局部滑动窗口信息Glove还引入了全局共现统计两者在训练方式和优化目标上不同但都能得到有意义的词向量。这类问题不需要背诵答案关键是要能画出模型结构图讲清楚损失函数的形式以及训练时间和效果之间的权衡。2.3 序列标注与概率图HMM和CRF到底哪里不一样NLP算法岗笔试里序列标注是逃不开的话题。因为分词、词性标注、命名实体识别都依赖它。HMM是生成式模型它建模的是联合概率P(X, Y)要算出转移概率和发射概率然后通过维特比算法求最优状态序列。CRF是判别式模型直接建模条件概率P(Y|X)用特征函数的方式把上下文信息糅合进来再通过前向-后向算法和维特比算法做推断。我当年遇到的经典选择题是CRF相比HMM的优势是什么答案的核心有两点。第一CRF可以引入任意形式的特征函数不止是当前的词和当前的标签还可以是前缀、后缀、词形、词典匹配等而HMM只能通过发射概率间接利用观测特征。第二CRF解决了标注偏置问题。HMM和MEMM在做局部归一化时转移分数低的路径会被过早抑制而CRF在全局范围做归一化能选出一条全局最优的序列。这里给一个便于理解的类比HMM像是一个只能看前后相邻两站来决定路线的公交司机CRF则像拿着全局地图同时考虑整条线路的站点分布来选最优路线。笔试中如果遇到“给定一个句子用HMM标注结果可能哪里出错”这类题思路就是站在“只看局部”的角度找漏洞。2.4 检索与文本匹配TF-IDF和BM25的细节不能含糊搜索引擎、问答系统、关键词抽取都绕不开TF-IDF和BM25。我在复习时发现很多同学只知道TF-IDF是“词频乘以逆文档频率”但具体公式写不全。这里把关键公式写出来TF(t, d)词t在文档d中出现的次数 / 文档d总词数或者用原始频次都可以不同实现略有差异。 IDF(t) log(N / df(t))N是文档总数df(t)是包含词t的文档数。BM25在TF-IDF的基础上引入了文档长度归一化和词频饱和机制公式里k1和b两个参数很关键。k1控制词频饱和度k1越大词频对分数的贡献越不容易到达上限b控制文档长度的影响程度b0时完全不考虑文档长度b1时完全归一化。真题可能会给出一个具体检索场景问“某个长文档和短文档都包含同一个关键词BM25会如何区分它们”。答案就是短文档的得分会更高因为短文档中出现一个关键词意味着这个关键词对文档主题的代表性更强。这种题没有复杂的计算但概念不清就答不出来。3. 编程题里的算法硬仗KMP、排序、DP与贪心的真实考法3.1 KMP的next数组用abacaba完整推导一遍编程题里字符串处理是重头戏KMP作为经典模式匹配算法出镜率非常高。但很多人在笔试现场会卡在next数组的定义上。这里必须提醒一句不同教材对next数组的定义是有差异的有的直接是前缀函数也就是最长相同前后缀长度有的是失配时模式串指针回退到的位置还有的会整体右移一位再补-1。做题前先看清题目给的公式别自己想当然。以模式串 p “abacaba” 为例我完整推一遍前缀表也就是最长相同前后缀长度下标从0开始。先算每个前缀子串的最长相同前后缀p[0] “a”前缀集合空后缀集合空最长前后缀长度为0。p[0..1] “ab”前缀{“a”}后缀{“b”}没有交集为0。p[0..2] “aba”前缀{“a”, “ab”}后缀{“ba”, “a”}最长交集为“a”长度1。p[0..3] “abac”前缀{“a”, “ab”, “aba”}后缀{“bac”, “ac”, “c”}无交集为0。p[0..4] “abaca”前缀{“a”, “ab”, “aba”, “abac”}后缀{“baca”, “aca”, “ca”, “a”}最长交集为“a”长度1。p[0..5] “abacab”前缀{“a”, “ab”, “aba”, “abac”, “abaca”}后缀{“bacab”, “acab”, “cab”, “ab”, “b”}最长交集为“ab”长度2。p[0..6] “abacaba”前缀{“a”, “ab”, “aba”, “abac”, “abaca”, “abacab”}后缀{“bacaba”, “acaba”, “caba”, “aba”, “ba”, “a”}最长交集为“aba”长度3。所以前缀表 pi [0, 0, 1, 0, 1, 2, 3]。如果题目把next数组定义为“失配时需要回退到的位置”采用的是将前缀表右移一位、首位补-1的做法那对应的next数组就是 [-1, 0, 0, 1, 0, 1, 2]。答题时先写明自己的定义再列结果阅卷人就不会觉得你错了。KMP前缀表的计算代码基本就是这套模板vectorint prefixFunction(const string s) { int n s.size(); vectorint pi(n, 0); for (int i 1; i n; i) { int j pi[i - 1]; while (j 0 s[i] ! s[j]) { j pi[j - 1]; } if (s[i] s[j]) { j; } pi[i] j; } return pi; }笔试中如果时间紧张我建议先把暴力匹配写出来拿部分分再优化成KMP。暴力匹配在绝大多数在线判题系统中只能过30%到50%的用例但拿了分总比卡死在一道题上好。3.2 排序算法与复杂度不只背结论要会推排序算法在笔试里考察频率极高但很少直接考“快速排序时间复杂度是多少”这种送分题更多是考察你在一组约束条件下的选择能力。比如链表排序应该用什么排序算法答案通常是归并排序因为链表不支持随机访问快排的partition操作在链表上效率很低而归并排序天然适合用指针合并。我当时复习时自己做了一张对比表笔试前反复看几遍排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n^2)O(n^2)O(1)稳定快速排序O(n log n)O(n^2)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定插入排序O(n^2)O(n^2)O(1)稳定希尔排序O(n log^2 n)O(n^2)O(1)不稳定常见考点还包括堆排序建堆的时间复杂度是多少答案不是O(n log n)而是O(n)。很多人会在这里栽跟头。为什么因为从最后一个非叶子节点开始自底向下调整每个节点的调整代价和节点高度相关整体时间复杂度摊下来是O(n)。另一个高频考点是稳定性的实际意义。比如按“先按分数排序再按姓名排序”希望最终结果中分数相同的人仍然按姓名有序这时候第二轮的排序算法必须选择稳定排序。不稳定排序会破坏第一轮已经排好的顺序。3.3 DP和贪心的边界什么时候不能用贪心动态规划和贪心算法是笔试编程题里拉开差距的主要阵地。常见题目包括编辑距离、最长公共子序列、背包问题、最长上升子序列、区间调度等。考得多了你会发现出题人喜欢在一个经典问题上加一个约束条件让“一眼贪心”的解法失效。我拿一个很经典的例子说明找零钱问题。如果硬币面额是1、5、11需要凑出15元贪心会先拿11元剩下4元需要4个1元总共5枚硬币但最优解是3个5元只需要3枚硬币。这就是贪心失效的典型场景。硬币面额不满足倍数关系时必须用动态规划。笔试中遇到一个题目先判断贪心是否正确靠不靠谱。一个简单的判断标准是选择当前局部最优之后是否会影响后续选择的效果。如果影响那大概率不能用贪心。另外动态规划的题目要学会写状态转移方程。编辑距离的状态转移是dp[i][j] min(dp[i-1][j] 1, dp[i][j-1] 1, dp[i-1][j-1] (s1[i-1] s2[j-1] ? 0 : 1))这道题几乎每年都在实习生笔试里出现不管是字节还是阿里只是换了个业务包装。建议把最长公共子序列、编辑距离、背包三种题型的代码模板背熟笔试现场能省很多思考时间。3.4 位运算与快速幂容易被忽视的送分题网易这套笔试题里还出现了一些和位运算相关的题目。位运算不是NLP的专属考点但NLP算法实习生的笔试里它有奇怪的高频属性。可能因为出题人觉得搞AI的人如果连位运算都搞不定写工程代码容易出问题。常见的位运算考点包括判断一个整数是不是2的幂n 0 (n (n - 1)) 0统计二进制中1的个数n (n - 1) 循环清零最低位的1不使用临时变量交换两个数a ^ b; b ^ a; a ^ b。快速幂是另一个常客。计算a^b mod p如果b很大直接循环乘会超时需要用二分的思想把指数拆成二进制long long fastPow(long long a, long long b, long long p) { long long res 1; a % p; while (b 0) { if (b 1) res res * a % p; a a * a % p; b 1; } return res; }快速幂的思想在NLP里其实也有用武之地比如一些概率计算涉及大量乘法需要取模加速。笔试中遇到这类题直接上模板就行。4. 开放题与场景题没有标准答案的答题思路4.1 设计一个短文本情感分析模块从哪几个维度答开放题里最典型的一道就是“设计一个短文本情感分析模块说明你的技术方案”。这类题没有唯一答案但答题结构决定了你能拿多少分。我的建议是不要只写思路要把一个完整的技术链路铺开数据、特征、模型、评估、上线。数据层面明确训练数据来源标注样本规模正负样本不均衡的问题怎么处理。可以用情感词典扩充样本也可以用远程监督方式通过表情符号打标签。特征层面传统方法用词袋模型、TF-IDF、情感词典得分深度学习方法用word2vec初始化Embedding再进BiLSTM或TextCNN。模型层面对比几个候选模型。朴素贝叶斯简单快速但效果一般TextCNN在小样本短文本上效果很好BiLSTM能捕获长距离依赖但训练较慢BERT如果是2018年那会可以说BERT刚出来理念可以引入可以从预训练模型微调。评估层面除了整体准确率还需要看类别F1特别是负样本的召回率。上线后还要考虑推理延迟、模型更新频率。这种答案结构的好处是阅卷人能够一眼看出你有没有真正做过项目而不是背了几篇博客。4.2 数据稀疏与未登录词从工程角度给方案开放题喜欢追问数据稀疏问题。因为真实业务里用户输入太随意了表情、错别字、中英混搭、网络新词任何一个都是未登录词的重灾区。笔试题里会问一句“集美们冲鸭”这类文本怎么让模型理解你能拿分的关键在于不要只提一个方案而是形成一套组合策略词典层维护领域词典和网络新词词典对未登录词做词典匹配直接标注。切词层采用子词切分方案比如BPE或WordPiece把“冲鸭”切成更细的片段即使整词没出现过片段也能匹配到训练语料。表示层用词向量相似度召回。词表里没有“冲鸭”但“冲鸭”和“加油”的词向量可能距离较近可以通过近邻扩充。模型层用字符级别的Embedding或字向量绕开分词环节。中文按字切分天然不怕词表外词。这样的回答体现了工程落地的层次感比单说“平滑一下”要好得多。我也在复习时发现很多公司开放题问的其实是同一个点你遇到模型效果不好时怎么排查这个问题本质上就是在考察你对数据、特征、模型三个环节的掌控力。4.3 一些进阶算法名词被考到的概率从我当时收集到的一些笔试反馈来看题目中偶尔会出现粒子群算法、模拟退火算法、卡尔曼滤波、KL散度与ELBO、BM25这类偏进阶的名词。它们不一定是主流考点但会出现在多选题的一个选项里或者在开放题中作为可选方案出现。以粒子群算法和模拟退火为例这类元启发式优化算法在NLP里一般用于超参数搜索、特征选择等场景。笔试如果单独考原理常见问法是“模拟退火如何避免陷入局部最优”。核心就两点以一定概率接受更差的解温度随时间下降。粒子群的核心是每个粒子根据自身历史最优和群体历史最优来更新速度与位置。不需要会推导细节但要知道它们属于无梯度优化适合离散或非凸空间。卡尔曼滤波在词性标注、目标跟踪这类时序预测问题里有应用核心是状态预测加观测更新两个步骤。考的概率不高但一旦考到答出“用上一时刻状态预测当前状态再用当前观测修正预测”就能拿大部分分。KL散度和ELBO在变分推断里是核心概念如果你在回答开放题时提到用变分推断近似后验分布会让阅卷人觉得你读过不少机器学习原文。5. 笔试之后的复盘与备考路线建议5.1 时间分配原理、刷题、项目各占多少我自己的备考周期大概是三到四周时间分配可以给大家参考机器学习与NLP基础原理占40%编程刷题占40%项目复盘占20%。这个比例可能和很多人的直觉不一样因为很多人会把时间全花在刷题上。但NLP算法实习生的笔试里基础概念题占了一半以上的分值这些题不刷LeetCode也能答对但背不下来就是拿不到分。刷题部分不建议按照题号顺序刷而是按题型集中突破。我当时的顺序是数组与字符串、排序与查找、链表与树、DP与贪心、图论与字符串匹配。每一类题刷到能在20分钟内写出无bug代码为止。面试笔试不是算法竞赛出题范围有限不需要碰那些超级难的竞赛题。项目复盘也不能忽视。常见问题包括你在这个项目中负责哪部分为什么选这个模型数据怎么处理的遇到bad case怎么分析这些在笔试开放题里不会直接出现但会以场景题的方式隔空考察。把项目里的技术决策梳理清楚开放题自然有东西可写。5.2 我踩过的坑和对你的建议第一多选题目千万不要掉进“理想化”陷阱。很多选项单独看似乎没问题但要结合题目语境判断。比如“word2vec能得到词向量所以它适合解决一词多义问题”这个陈述前半句对后半句错。2018年的word2vec确实不处理多义词每个词只有一个向量这直到后来的ELMo和BERT才被打破。笔试题里很喜欢用这种“半对半错”的选项来筛人。第二编程题先写暴力解再优化AC。在线笔试的判分通常是部分通过制哪怕只过了30%的用例也有分。我见过不少同学一上来憋KMP憋了四十分钟写出来还是错的最后整道题零分。正确策略是先花五分钟写暴力版本确保自己理解了题意再花时间优化到正解。第三开放题答案不要只有一句话。阅卷人快速扫一遍答案时最直观的判断就是有没有分点、有没有流程。哪怕你列的方案不是最优的只要逻辑链完整分数都会比挤牙膏式答案高一档。最后分享一点我在实际复习中的体会NLP算法岗笔试与其说是考察你会不会某个具体算法不如说是考察你面对一个不熟悉的问题时有没有一套稳定的分析框架。这个框架来自对基础原理的反复揣摩也来自大量项目的试错经验。如果你现在准备时间有限可以先把本文提到的几个核心考点过一遍再用几套往年题练手会比漫无目的地刷题更高效。
返回列表