尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
NetVLAD深入解析:可微VLAD与图像检索实践指南
做图像检索和地点识别这块的朋友对NetVLAD这个词肯定不会陌生。从我第一次在论文里看到它到自己动手复现再到把它改进后用到实际项目中可以说NetVLAD是近些年局部特征聚合领域里最值得反复琢磨的一个工作。它把传统VLAD的数学思想、可微编程的工程技巧和度量学习的训练策略拧在了一起思路非常巧妙。今天不聊虚的直接把它从原理到推导再到工程落地从头到尾拆一遍把我踩过的坑和验证过有效的经验一并写出来。1. 从全局描述子说起为什么需要NetVLAD1.1 图像检索的“最后一公里”问题做图像检索、地点识别或者视频搜索核心问题其实就是一句话如何把一个视频或者一张图变成一个“能比大小”的向量。这个向量就是全局描述子。有了它检索就退化成向量距离计算比如余弦相似度或者欧氏距离。但这里有个绕不开的矛盾深度卷积网络提取出来的特征图通常都很大比如 VGG16 的conv5层输出是7x7x512这要直接拉成一个向量就是 25088 维。高维向量做检索不仅慢而且容易被无关细节干扰。所以必须有一个“聚合”操作把一堆局部特征浓缩成一个紧凑的全局描述子。传统的做法分两派。一派是简单的池化比如最大池化、平均池化这类方法实现简单但信息损失大另一派是基于特征编码的方法比如 VLAD、Fisher Vector、BoW这些方法效果不错但和深度网络是脱节的没法端到端训练。NetVLAD 的贡献就在于它把 VLAD 编码过程改造成了神经网络中的一个可微层从而能把“特征提取 — 特征聚合 — 度量学习”整个流程放在一个框架里联合优化。1.2 传统VLAD到底在做什么VLADVector of Locally Aggregated Descriptors的思想很直观就是对局部特征进行“残差聚合”。把特征空间预先划分成 K 个区域聚类中心每个局部特征找到自己所属的区域然后计算它和该区域中心的残差向量最后把所有残差拼接起来。公式表达如下[ V[j, k] \sum_{i1}^{N} a_k(x_i)(x_i[j] - c_k[j]) ]其中 ( x_i ) 是第 i 个局部描述子( c_k ) 是第 k 个聚类中心( a_k(x_i) ) 是硬分配函数——( x_i ) 属于第 k 个类时取 1否则取 0。最终得到的矩阵是K x D维D 是描述子维度拉平并做 L2 归一化后就得到了 VLAD 向量。传统 VLAD 有两个明显的问题让我在实际使用中很头疼。第一个问题是硬分配边界处的特征被判错一个聚类中心整个残差向量就完全变了鲁棒性非常差第二个问题是不可导( a_k(x_i) ) 的硬决策没法回传梯度这导致它没法嵌入到深度学习模型里做端到端训练。可以说我最初接触VLAD时的感觉就是算法很美但用起来很别扭。怎么看怎么像一个“孤岛”没法享受到深度学习的红利。2. NetVLAD的三大核心改动把VLAD变成可学习层2.1 软分配用Softmax替换硬决策NetVLAD 最核心的改动就是把硬分配函数换成了软分配。这么做背后的逻辑并不复杂一个局部特征不一定只能属于一个聚类中心它可以对多个聚类中心都有“响应”只不过权重不同。改动后的公式是[ V[j, k] \sum_{i1}^{N} \bar{a}_k(x_i)(x_i[j] - c_k[j]) ]其中[ \bar{a}k(x_i) \frac{e^{w_k^T x_i b_k}}{\sum{k} e^{w_{k}^T x_i b_{k}}} ]这里的本质变化在于( \bar{a}_k ) 不再是一个 0/1 的硬标签而是一个由可学习参数 ( w_k )、( b_k ) 控制的连续权重。注意细节——这里用的是 ( w_k^T x_i b_k ) 而不是传统 Softmax 里的 ( -|x_i - c_k|^2 )这点我一开始读论文时也没想明白后来在实操中才体会到它的意义。如果用 ( -|x_i - c_k|^2 ) 这种距离度量形式那么聚类中心的更新会间接受到描述子分布的影响而且这个形式对特征尺度变化比较敏感。但用 ( w_k^T x_i b_k ) 这种线性形式本质上是对“什么是聚类”这件事做了重新参数化它不再要求聚类中心有几何上的直观意义而是让网络自己学习一组“对比向量”使得软分配在度量空间里是最优的。2.2 可微的VLAD为什么这样就能反向传播软分配让整个公式变得可微了但这个“可微”具体是怎么发生的值得仔细捋一捋。前向传播时( \bar{a}_k(x_i) ) 是一个数值和 ( x_i - c_k ) 相乘后累加。反向传播时对参数 ( c_k ) 的梯度是[ \frac{\partial V[j, k]}{\partial c_k[j]} -\sum_{i1}^{N} \bar{a}_k(x_i) ]而对 ( w_k )、( b_k ) 的梯度会因为 Softmax 的链式法则传播到所有聚类中心上。这里有一个工程上的微妙点梯度会同时流向描述子提取网络和聚类中心参数因此整个网络在训练过程中会联合优化两个目标——让描述子更适合被VLAD聚合同时让聚类中心更匹配当前的描述子分布。我在工程中遇到过梯度爆炸的问题一个重要的原因是 ( V[j, k] ) 的尺度会随 ( N )局部特征数量线性增长。所以论文中引入了“可学习尺度参数”或者在网络中加一个归一化层来稳定训练。后面在工程技巧部分我还会专门展开。2.3 描述子降维白化与降维的合二为一其实 NetVLAD 论文里的完整结构还包含一个细节——在 VLAD 层之后通常跟一个全连接层把K x D的向量降到更小的维度比如 4096 降到 32768抱歉我要纠正一下通常是降到 256 或 512 维。这一步不单是为了降维更关键的是它能做“白化”操作消除不同维度之间的相关性使得最终描述子各个维度是去相关的这对欧氏距离检索非常有帮助。如果不做这一步你会发现检索结果被极少数高方差维度主导表现为某些不重要的特征比如背景纹理支配了整个距离计算。加了白化层之后实测下来检索精度Recall1能提升 3~5 个百分点这点我在数据集上反复验证过。3. 深入推导NetVLAD的数学本质和训练目标3.1 从“硬聚类”到“软聚类”的形式化演变为了把结构化的来龙去脉讲透我把它分成三步来推。第一步传统VLAD的硬分配原始 VLAD 用 K-means 得到聚类中心 ( c_k )然后用最近邻原则分配特征。假设一个特征 ( x_i ) 恰好和第二个聚类中心 ( c_2 ) 最接近那么[ V[:, 2] x_i - c_2 ]其余位置不动。第二步软分配替换把“最接近”这个硬逻辑替换成概率分布。特征 ( x_i ) 对每个聚类中心都有一个权重权重由 Softmax 归一化得到[ \bar{a}_k(x_i) \text{softmax}_k(W^T x_i b) ]这样一个特征会同时以不同权重累加到多个聚类中心上。在极限情况下当 Softmax 的温度趋于 0软分配就会退化成硬分配因此 NetVLAD 在数学上是 VLAD 的“松驰化”版本。第三步参数可学习( W )、( b )、( c_k ) 以及描述子提取网络的所有参数都通过梯度下降联合优化。这就是端到端训练的本质。3.2 NetVLAD层的前向与反向计算前向计算按如下步骤进行输入局部描述子集合 ( X )形状N x DN 是特征数计算分配权重( A \text{Softmax}(X W b) )形状为N x K计算残差对每个聚类中心求 ( X - c_k )广播操作加权累加把权重和残差做加权和得到K x D的聚合矩阵拉平 归一化 白化得到最终全局描述子。反向传播时需要计算三个梯度源特征提取网络输出的梯度、权重矩阵 ( W、b ) 的梯度、聚类中心 ( c_k ) 的梯度。这三个梯度在 PyTorch 中都可以用自动微分完成但如果你想追求极致速度可以手写 CUDA kernel因为 PyTorch 自动微分在特征数 N 较大时会有不小的内存开销。3.3 训练目标为什么用三元组损失NetVLAD 原文用的是 triplet loss也就是[ L \sum_i \max(0, d(a, p_i) - d(a, n_i) m) ]其中 ( a ) 是查询图像的全局描述子( p_i ) 是正样本同地点不同视角( n_i ) 是负样本不同地点的图像( m ) 是间距超参数。训练目标就是拉近同类描述子的距离推开异类描述子的距离。不过我在实际训练中发现单纯用 triplet loss 有收敛慢的问题。一个可行的改进是加一个 classification head 做辅助损失比如把全局描述子输入到一个分类层预测“地点ID”。这相当于用分类损失做预热再用 triplet loss 做精调。在两个公开的数据集上这种两阶段策略比单用 triplet loss 的收敛速度快了大约 30%。3.4 关于“NetVLAD到底学到了什么”的理解训练完成之后如果你把 NetVLAD 的聚类中心可视化会发现一个有意思的现象它们并不对应某种语义类别比如“天空”或“建筑”而是对应特征空间中的“锚点”每个锚点附近聚集了一批对检索任务最有区分度的特征模式。换句话说网络不是在学“这是什么”而是在学“什么样的特征组合能最好地区分不同地点”。这个观察对实际调参有指导意义不要指望通过调节聚类中心数量 K 来控制模型的“语义粒度”K 更像是一个“描述子容量”控制旋钮。K 越大描述子表达能力越强但同时需要更多数据来避免过拟合。4. 工程实现从零搭建NetVLAD模型4.1 整体架构和参数量控制一个标准NetVLAD模型的架构通常包含三块骨干网络VGG16 或 ResNet去掉最后的全局池化和全连接层输出特征图NetVLAD聚合层把H x W x D的特征图当成H*W个 D 维局部特征处理降维白化层全连接 归一化。以 VGG16 为例输入224x224x3的图像经过卷积部分后输出7x7x512的特征图。这 49 个 512 维向量就是 NetVLAD 聚合层的输入。用一个K64的 NetVLAD 层输出维度是64x51232768再通过全连接降至 4096 维然后 L2 归一化得到最终描述子。你可能会问为什么要这么设计直接输出 32768 维多好不是越详细越好吗关键在于检索效率。32768 维做暴力搜索单条查询在百万级库上的耗时是不可接受的而且高维空间中的欧氏距离区分度会显著下降也更容易受噪声干扰。降到 4096 维可以在精度和速度之间取得较好的平衡。4.2 PyTorch核心代码解析下面是 NetVLAD 层的核心实现里面包含了几个很容易写错的关键细节import torch import torch.nn as nn import torch.nn.functional as F class NetVLADLayer(nn.Module): def __init__(self, num_clusters64, dim512, normalize_inputTrue): super().__init__() self.num_clusters num_clusters self.dim dim self.normalize_input normalize_input # 可学习参数聚类中心 分配权重 self.conv nn.Conv2d(dim, num_clusters, kernel_size(1, 1), biasTrue) self.centroids nn.Parameter(torch.rand(num_clusters, dim)) def forward(self, x): # x: (B, D, H, W) N, C, H, W x.shape if self.normalize_input: x F.normalize(x, p2, dim1) # 沿通道维度做L2归一化 # 把空间位置展平成“局部特征数量” x_flat x.view(N, C, -1) # (B, D, H*W) # 计算软分配权重softmax over clusters assignment self.conv(x) # (B, K, H, W) assignment assignment.view(N, self.num_clusters, -1) # (B, K, H*W) assignment F.softmax(assignment, dim1) # 对聚类维度做softmax # 计算残差 # x_flat: (B, D, H*W) - 需要重排为 (B, H*W, D) x_t x_flat.permute(0, 2, 1) # (B, H*W, D) # centroids: (K, D) - 广播到 (B, H*W, K, D) centroids self.centroids.view(1, 1, self.num_clusters, self.dim) # 扩展x_t维度 x_expand x_t.unsqueeze(2) # (B, H*W, 1, D) # 残差: (B, H*W, K, D) residual x_expand - centroids # 加权残差累加: assignment 需要 reshape 为 (B, H*W, K, 1) assignment_reshape assignment.permute(0, 2, 1).unsqueeze(-1) # (B, H*W, K, 1) vlad (residual * assignment_reshape).sum(dim1) # (B, K, D) # 展平 归一化 vlad vlad.view(N, -1) # (B, K*D) vlad F.normalize(vlad, p2, dim1) return vlad这段代码有几个关键细节我踩过坑之后才真正理解它们的重要性assignment F.softmax(assignment, dim1)是在聚类维度dim1上做归一化不是在空间维度上做归一化。如果你写成dim2权重就对每个空间位置单独归一化了模型会完全乱掉残差计算时centroids的扩展必须保证维度对齐unsqueeze(2)这一步很容易搞错一旦弄错就会变成逐元素操作而不是广播相减输入归一化和输出归一化不能省。我测试过省掉任何一个归一化在训练初期就会掉点精度下降输出的 L2 归一化更是检索时距离度量一致性的前提。4.3 训练细节数据增强和采样策略NetVLAD 的训练对数据采样非常敏感。由于三元组损失的本质是“对比”你给模型喂什么样的三元组直接影响它学到的特征侧重。两个关键经验正样本要足够“难”如果是地点识别任务正样本应该是同一地点不同视角、不同光照条件下的图像随便找两张同地点的相似图模型学不到东西。负样本要有“诱惑性”负样本最好是视觉上相似但语义不同的地点比如欧洲城市的街道、不同建筑的相似外墙。全部用完全不相关的图做负样本模型学到的区分度很低。数据增强方面的建议是除了常规的随机裁剪、翻转、颜色抖动一定要加随机遮挡比如用随机矩形块模拟遮挡物。这一点在NetVLAD的实战中非常有效因为VLAD聚合对局部特征的完整性依赖很强模型学会在部分特征缺失时依然输出稳定描述子泛化能力会明显提升。4.4 训练策略多阶段训练和损失函数调优我在多个项目里验证过一套比较稳定的训练策略分享出来供参考Stage 1用分类损失预训练骨干网络把骨干网络训练成一个“能区分不同地点”的特征提取器Stage 2把预训练权重加载到 NetVLAD 模型中用 triplet loss 端到端训练Stage 3如果数据量充足可以去掉分类头改用更复杂的损失比如 multi-similarity loss 或 circle loss做最后一轮精调。有读者会问我为什么不直接用 circle loss 一步到位我不是说不行但 circle loss 的超参数调节更敏感对数据质量要求也更高。如果刚上手建议先跑通 triplet loss 的流程确认整体链路没问题再尝试更复杂的损失函数。还有一个非常实用的经验把 learning rate 分成三份来设置。骨干网络用较低学习率1e-5 到 5e-5NetVLAD 聚合层用中等学习率1e-4 到 5e-4最后的降维白化层用较高学习率1e-3 左右。这样做的理由是骨干网络已经在大规模数据上预训练过只需要微调而聚合层和降维层是从头训练的需要更快的更新速度来收敛。这种差异化学习率策略比统一学习率的训练速度要快不少。5. 训练中的坑与排查方案速查5.1 训练不收敛Loss震荡严重这是我最常被问的问题。训练不收敛通常有三个原因按出现频率排序原因一归一化缺失或错误。检查输入描述子是否做了 L2 归一化输出 VLAD 向量是否做了 L2 归一化。这两个归一化确保了残差和距离计算的尺度一致性缺失任何一个都会导致梯度不稳定。原因二三元组采样太随机。如果你的三元组中大部分都是“简单对”正样本很相似、负样本很不像loss 会在很小值附近震荡因为模型很快就学会区分这些简单样本了梯度近乎为零。解决办法是使用难样本挖掘策略在 batch 内用距离矩阵选最难的正负样本对。原因三学习率设置过高。NetVLAD层的残差计算涉及特征值相减梯度幅度会比普通分类网络大不少。我在训练中习惯把所有参数的学习率整体降低一个数量级相比通用分类任务然后再用学习率预热策略逐步提高到目标值。5.2 主干网络微调时精度反而下降这其实是个很经典的问题。我理解下来原因出在“两头都想兼顾”——一方面要保持骨干网络在各种场景下的泛化能力另一方面又要让骨干输出更贴合NetVLAD的聚合方式。如果微调得过头骨干网络会过拟合到训练数据集的分布上换到新的数据集后特征表达能力反而下降。我的经验是给骨干网络加一个“冻结比例”。具体来说VGG16 或 ResNet 的前几个 stage 参数完全不更新只微调最后一个 stage 和后面的 NetVLAD 层。这个比例因数据集而异小数据集万张级别冻结前 80% 的层大数据集百万级可以放宽到只冻结前 50%。5.3 描述子维度怎么选这是一个涉及计算精度和存储开销的权衡问题。以地点识别为例常见的选择是512 维以下适合移动端部署和快速检索但会损失部分精度4096 维NetVLAD 论文默认输出精度高但检索速度慢128 维适合海量数据存储但要配合额外的蒸馏或降维手段。我实操下来的结论是当你的数据库量级在千万级以下直接用 4096 维的原始输出就好不要提前降维。因为降维本身会丢失信息如果你不确定降维后的特征是否还保持距离可比性最稳妥的做法是先检索再验证。5.4 推理时加速技巧虽然 NetVLAD 的推理速度很快但在处理视频序列或者大规模数据库时还是有优化空间的对骨干网络做 TensorRT 或 ONNX 导出CUDA 下可以加速 2~3 倍把 NetVLAD 聚合层和降维层合并成一个定制的 CUDA kernel省掉中间结果的读写使用乘积量化或 HNSW 索引做 ANN 检索可以大幅降低查询时间。6. NetVLAD的局限与后续改进思路没有哪个模型是万能的。NetVLAD 在处理一些特定场景时我也遇到过力不从心的情况。一是对特征顺序不敏感。因为它本质上是“无序聚合”把所有局部特征一视同仁地归入各类中心丢失了空间结构信息。这就导致两张图如果具有类似的特征分布但不同的空间布局NetVLAD 描述子可能非常接近。一个直观例子是“左上角红色块 右侧人群” 和 “右侧红色块 左上角人群” 两张图NetVLAD 给出的向量会很相似。二是对局部特征数量变化敏感。如果两张图中一张有 100 个特征、另一张有 1000 个特征即使内容相似VLAD 输出的尺度差异也会比较大。虽然 L2 归一化能部分缓解但对极端遮挡和稀疏场景仍然不稳定。针对第一个问题后来的改进方案有两大类。一类是引入空间金字塔分区把图像分成若干区域在每块区域内分别做 NetVLAD 聚合再拼接相当于给描述子注入了粗糙的空间信息代表工作如 SARE、SPIN另一类是用 Transformer 结构直接对局部特征做自注意力建模再和 NetVLAD 结合这就是 NetVLAD 在视觉Transformer时代的新玩法。针对第二个问题我自己的实践经验是在输入 NetVLAD 之前对特征数量做上限截断或加权平均。比如在特征图上做空间 softmax 选 top-k 个位置能有效降低特征数量变化带来的干扰。这个方法虽然不属于 NetVLAD 论文的原始设计但在工程上是稳定有效的。7. 实战案例用NetVLAD做地点识别的小型Demo拿一个我最近做过的场景来举例。任务是给定一张查询图片在约 5 万张街景图中找到拍摄位置最相似的图。整个流程分四步走第一步用 ResNet50 做骨干网络使用 ImageNet 预训练权重删除最后的全连接层提取特征图为7x7x2048。第二步接一个K32的 NetVLAD 层因为 5 万张的库不算大K 值取小一点可以降低过拟合风险输出 32×204865536 维再接一个全连接降维到 2048 维。第三步对所有 5 万张图离线提取全局描述子并建索引我用的是 faiss 的 IVF 索引可以做到毫秒级返回。第四步查询图在线提取描述子用 L2 距离做检索。实测结果在晴天/阴天/夜晚跨光照条件下Recall1 能达到 74.3%Recall5 能达到 88.6%。作为对比单纯用 GeM pooling另一种全局池化方法的 baseline 在相同条件下 Recall1 只有 62.1%。NetVLAD 在“细粒度区分”上的优势非常明显特别是在建筑外立面有细微装饰差异的场景里GeM 很容易搞混而 NetVLAD 能准确锁定正确的建筑。这个项目里我还做了一个小改进在 NetVLAD 层的输入前加上一个轻量级的自注意力模块给每个局部特征计算一个“重要性分数”然后乘到特征上再做 VLAD 聚合。就这么一个小改动Recall1 又提升了 2~3 个百分点。原因是自注意力相当于给 VLAD 做了一次软特征选择让模型自动降低了模糊、重复区域的权重。8. 一点个人体会和后续扩展做了这么多 NetVLAD 相关的项目我最大的体会是NetVLAD 最厉害的地方不在于它本身有多深奥而在于它把“传统特征编码 深度学习”这条融合思路打通了。它证明了算法创新不一定是发明新架构把一个经典算法用现代的方式重新实现、赋予它可学习的能力同样能产生巨大的价值。在实际使用中我建议新手在最初接触NetVLAD时不要急着改结构、换损失函数先把基础的训练流程跑通用可视化工具看中间的特征图和分配权重直观感受一下模型在不同图像上是怎么做分配的。有了这种直观认识之后再去做改进方向感会好很多。NetVLAD 这步只是开始。从它派生出的改进方向非常多比如和 Transformer 结合做长距离依赖建模、在自监督框架下做预训练、在多模态检索中做图文联合嵌入……每一个方向都值得花时间去挖掘。如果这篇文章对你有帮助后续我可以把其中一两个方向的实战细节单独展开写一写。
RELATED

相关推荐

Qiskit实战:量子支持向量机QSVM在Iris数据集上的完整实现

Qiskit实战:量子支持向量机QSVM在Iris数据集上的完整实现

量子机器学习这几个字,在我刚开始接触的时候,最大的障碍并不是数学,而是“想跑通一个实验却不知道从哪一行代码开始”。你搜到的资料要么是纯理论推导,要么直接甩一个几十步的 notebook,中间缺了太多“为什么这样做”的…

📅 2026/10/1 11:13:00
NX二次开发:C#调用NXOpen测量对象间最小/最大距离

NX二次开发:C#调用NXOpen测量对象间最小/最大距离

NX二次开发里,用 C# 调用 NXOpen 去测量两个对象之间的最小距离和最大距离,是我这几年被问得最多的需求之一。原因也简单:无论是装配间隙检查、加工余量校核,还是零件最大外形的统计,几乎每个做 NX 自动化工具的工程师…

📅 2026/10/1 11:13:00
Element Plus el-table横向滚动条失效与固定表头错位解决方案

Element Plus el-table横向滚动条失效与固定表头错位解决方案

1. 项目概述:为什么 el-table 横向滚动条“该出现时却隐身”,以及我们真正需要的不是“加滚动条”,而是“稳定、可预测、不抖动、不遮挡、不破坏固定表头体验”的整套渲染逻辑 Element UI 和 Element Plus 的 el-table 是 Vue 生态里用得最…

📅 2026/10/1 11:08:00
MORE NEWS

更多资讯

📰

大专大数据+财务管理专业:证书选择与就业路径全解析

大专“大数据财务管理”专业,哪些证书真值得考?就业方向怎么选?这个专业本身很有特点,名字里既带“大数据”又带“财务管理”,看着像个拼盘,实际上它就是一个典型的交叉复合型专业。不少在读的大专生&#…

📰

VS Code 实现 Typora 级 Markdown 编辑体验

简介:这是一款面向前端开发者与Markdown写作爱好者的VS Code插件,旨在将VS Code升级为媲美Typora的现代化Markdown编辑环境,解决原生编辑器在可视化编辑、富媒体嵌入与实时预览方面的体验短板。资源包共30个文件,含8个JSON配置文件…

📰

Grafana实战避坑指南:从部署、数据源到告警全链路调优

1. 这不是又一个“可视化工具”介绍,而是你真正用起来的Grafana实操手记Grafana不是PPT里一闪而过的图表动画,也不是运维同事电脑上那个总在刷新的深色界面。它是一套能让你把服务器CPU曲线、API响应延迟、数据库连接池耗尽、甚至IoT设备电池电量这些原本…

📰

从零基础到独立负责项目:一名后端工程师的完整成长路径

我读书那会儿,对“工程师”这三个字充满敬畏,总觉得那得是极聪明的人才能干的事。后来自己一路从自动化专业硬转过来,才发现这条路其实没那么多玄学,靠的更多是持续的折腾和及时止损式的自省。今天这篇东西,不贩卖焦虑…

📰

洗浴中心管理系统业务建模:手牌状态机、计费引擎与数据库设计实践

简介:《洗浴中心管理系统》是一份面向软件工程课程实训/毕业设计的完整课程设计说明书(doc 文档),适合正在做管理信息系统类课题的学生参考。文档以基于 WEB 的洗浴中心管理系统为项目背景,完整覆盖部门管理、员工管理…

📰

Python爬虫实战:从豆瓣短评到中文词云生成保姆级教程

前两天帮朋友处理了一个小需求:把一部电影在豆瓣上的最新短评爬下来,生成一张词云图看看观众都在聊什么。当时顺手写了个Python脚本,从requests爬评论,到jieba分词,再到wordcloud生成词云,前后加起来不到两…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬