不可思议的Word2Vec之系列四- 不一样的“相似”

简介:

I. 相似度的定义

当用Word2Vec得到词向量后,一般我们会用余弦相似度来比较两个词的相似程度,定义为

cos(x,y)=xy|x|×|y|cos⁡(x,y)=x⋅y|x|×|y|

有了这个相似度概念,我们既可以比较任意两个词之间的相似度,也可以找出跟给定词最相近的词语。这在gensim的Word2Vec中,由most_similar函数实现。

等等!我们很快给出了相似度的计算公式,可是我们居然还没有“定义”相似!连相似都没有定义,怎么就得到了评估相似度的数学公式了呢?

要注意,这不是一个可以随意忽略的问题。很多时候我们都不知道我们干的是什么,就直接去干了。好比上一篇文章说到提取关键词,相信很多人都未曾想过,什么是关键词,难道就仅仅说关键词就是很“关键”的词?而如果想到,关键词就是用来估计文章大概讲什么的,这样我们就得到一种很自然的关键词定义

keywords=argmaxwsp(s|w)keywords=arg⁡maxw∈s⁡p(s|w)

进而可以用各种方法对它建模。

回到本文的主题来,相似度怎么定义呢?答案是:看场景定义所需要的相似。

那么,通过余弦相似度给出的相似,又是什么情况呢?事实上,Word2Vec本质上来说,还是使用上下文的平均分布描述当前词(因为Word2Vec是不考虑词序的),而余弦值与向量模长没关系,因此它描述的是“相对一致”。那么,余弦相似度大,事实上意味着这两个词经常跟同一批词搭配,或者更粗糙讲,那就是在同一句话中,两个词具有可替换性。比如,“广州”最相近的词语是“东莞”、“深圳”,那是因为很多场景下,直接将矩阵中的“广州”直接换成“东莞”、“深圳”,这个句子还是合理的(是句子本身的合理,但这个句子不一定是事实,比如“广州是广东的省会”,变成“东莞是广东的省会”,这个句子是合理的,但是这个句子并非是事实)。

>>> s = u'广州'

>>> pd.Series(model.most_similar(s))
0 (东莞, 0.840889930725)
1 (深圳, 0.799216389656)
2 (佛山, 0.786817014217)
3 (惠州, 0.779960155487)
4 (珠海, 0.735232532024)
5 (厦门, 0.725090026855)
6 (武汉, 0.724122405052)
7 (汕头, 0.719602525234)
8 (增城, 0.713532149792)
9 (上海, 0.710560560226)

II. 相关:另一种相似

前面已经说了,相似度的定义事实上要看场景的,余弦相似度只是其中之一。有时候我们会觉得“东莞”和“广州”压根就没联系,对于“老广州”来说,“白云山”、“白云机场”、“广州塔”这些词才是跟“广州”最相似的,这种场景也是很常见的,比如做旅游的推荐,旅游来到广州后,自然是希望输入“广州”后,自动输出来“白云山”、“白云机场”、“广州塔”这些广州相关的词语,而不是输出“东莞”、“深圳”这些词语。

这种“相似”,准确来说是“相关”,应该怎么描述呢?答案是互信息,定义为

logp(x,y)p(x)p(y)=logp(y|x)logp(y)log⁡p(x,y)p(x)p(y)=log⁡p(y|x)−log⁡p(y)

互信息越大,说明 x,yx,y两个词经常一起出现。

这样,在给定词xx的情况下,我们就可以找出经常跟词xx一起出现的词,这个也完全可以由Word2Vec中的Skip-Gram+Huffman Softmax模型来完成。代码如下

import numpy as np
import gensim
model = gensim.models.word2vec.Word2Vec.load('word2vec_wx')

def predict_proba(oword, iword):
    iword_vec = model[iword]
    oword = model.wv.vocab[oword]
    oword_l = model.syn1[oword.point].T
    dot = np.dot(iword_vec, oword_l)
    lprob = -sum(np.logaddexp(0, -dot) + oword.code*dot) 
    return lprob

from collections import Counter
def relative_words(word):
    r = {i:predict_proba(i, word)-np.log(j.count) for i,j in model.wv.vocab.iteritems()}
    return Counter(r).most_common()

这时候,“广州”的相关词为

>>> s = u'广州'

>>> w = relative_words(s)

>>> pd.Series(w)
0 (福中路, -17.390365773)
1 (OHG, -17.4582544641)
2 (林寨镇, -17.6119545612)
3 (坪山街道, -17.6462214199)
4 (东圃镇, -17.6648893759)
5 (西翼, -17.6796614955)
6 (北京西, -17.6898282385)
7 (⇋, -17.6950761384)
8 (K1019, -17.7259853233)
9 (景泰街道, -17.7292421556)
10 (PSW3, -17.7296432222)
11 (广州铁路职业技术学院, -17.732288911)
12 (13A06, -17.7382891287)
13 (5872, -17.7404719442)
14 (13816217517, -17.7650583156)
15 (未遂案, -17.7713452536)
16 (增城市, -17.7713832873)
17 (第十甫路, -17.7727940473)
18 (广州白云机场, -17.7897457043)
19 (Faust, -17.7956389314)
20 (国家档案馆, -17.7971039916)
21 (w0766fc, -17.8051687721)
22 (K1020, -17.8106548248)
23 (陈宝琛, -17.8427718407)
24 (jinriGD, -17.8647825023)
25 (3602114109100031646, -17.8729896156)

可以发现,得到的结果基本上都是跟广州紧密相关的。当然,有时候我们稍微强调一下高频词,因此,可以考虑将互信息公式修改为

logp(x,y)p(x)pα(y)=logp(y|x)αlogp(y)log⁡p(x,y)p(x)pα(y)=log⁡p(y|x)−αlog⁡p(y)

其中 αα是一个略小于1的常数。如果取 α=0.9α=0.9,那么有

from collections import Counter
def relative_words(word):
    r = {i:predict_proba(i, word)-0.9*np.log(j.count) for i,j in model.wv.vocab.iteritems()}
    return Counter(r).most_common()

结果重新排列如下:

>>> s = u'广州'

>>> w = relative_words(s)

>>> pd.Series(w)
0 (福中路, -16.8342976099)
1 (北京西, -16.9316053191)
2 (OHG, -16.9532688634)
3 (西翼, -17.0521852934)
4 (增城市, -17.0523156839)
5 (广州白云机场, -17.0557270208)
6 (林寨镇, -17.0867272184)
7 (⇋, -17.1061883426)
8 (坪山街道, -17.1485480457)
9 (5872, -17.1627067119)
10 (东圃镇, -17.192150594)
11 (PSW3, -17.2013228493)
12 (Faust, -17.2178736991)
13 (红粉, -17.2191157626)
14 (国家档案馆, -17.2218467278)
15 (未遂案, -17.2220391092)
16 (景泰街道, -17.2336594498)
17 (光孝寺, -17.2781121397)
18 (国际货运代理, -17.2810157155)
19 (第十甫路, -17.2837591345)
20 (广州铁路职业技术学院, -17.2953441257)
21 (芳村, -17.301106775)
22 (检测院, -17.3041253252)
23 (K1019, -17.3085465963)
24 (陈宝琛, -17.3134413583)
25 (林和西, -17.3150577006)

相对来说,后面这个结果更加可读一点。另外的一些结果,展示如下:

>>> s = u'飞机'
>>> w = relative_words(s)
>>> pd.Series(w)
0 (澳门国际机场, -16.5502216186)
1 (HawkT1, -16.6055740672)
2 (架飞机, -16.6105400944)
3 (地勤人员, -16.6764712234)
4 (美陆军, -16.6781627384)
5 (SU200, -16.6842796275)
6 (起降, -16.6910345896)
7 (上海浦东国际机场, -16.7040362134)
8 (备降, -16.7232609719)
9 (第一架, -16.7304077856)

>>> pd.Series(model.most_similar(s))
0 (起飞, 0.771412968636)
1 (客机, 0.758365988731)
2 (直升机, 0.755871891975)
3 (一架, 0.749522089958)
4 (起降, 0.726713418961)
5 (降落, 0.723304390907)
6 (架飞机, 0.722024559975)
7 (飞行, 0.700125515461)
8 (波音, 0.697083711624)
9 (喷气式飞机, 0.696866035461)

>>> s = u'自行车'
>>> w = relative_words(s)
>>> pd.Series(w)
0 (骑, -16.4410312554)
1 (放风筝, -16.6607225423)
2 (助力车, -16.8390451582)
3 (自行车, -16.900188791)
4 (三轮车, -17.1053629907)
5 (租赁点, -17.1599389605)
6 (电动车, -17.2038996636)
7 (助动车, -17.2523149342)
8 (多辆, -17.2629832083)
9 (CRV, -17.2856425014)

>>> pd.Series(model.most_similar(s))
0 (摩托车, 0.737690329552)
1 (骑, 0.721182465553)
2 (滑板车, 0.7102201581)
3 (电动车, 0.700758457184)
4 (山地车, 0.687280654907)
5 (骑行, 0.666575074196)
6 (单车, 0.651858925819)
7 (骑单车, 0.650207400322)
8 (助力车, 0.635745406151)
9 (三轮车, 0.630989730358)

大家可以自己尝试。要说明的是:很遗憾,Huffman Softmax虽然在训练阶段加速计算,但在预测阶段,当需要遍历一遍词典时,事实上它比原生的Softmax还要慢,所以这并不是一个高效率的方案。

III. 究竟做了啥

根据前面两部分,我们可以看到,“相似”一般有两种情景:1、经常跟同一批词语搭配出现;2、经常一起出现。这两种情景,我们都可以认为是词语之间的相似,适用于不同的需求。

比如,在做多义词的词义推断时,比如star是“恒星”还是“明星”,就可以利用互信息。我们可以事先找到star意思为“恒星”的时候的语料,找出与star互信息比较大的的词语,这些词语可能有sun、planet、earth,类似地,可以找到star为“明星”的时候的语料,找出与star互信息比较大的词语,这些词语可能有entertainment、movie等。到了新的语境,我们就可以根据上下文,来推断究竟是哪个词义。

总而言之,需要明确自己的需求,然后再考虑对应的方法。

目录
相关文章
|
13天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
13天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
12天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1550 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
14天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
14天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1996 15
|
8天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
|
18天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1693 4
|
12天前
|
人工智能 安全 JavaScript
DeepSeek Harness开源Agent运行框架实战:4种安装方式、WebUI启动、插件管理与排坑全流程
随着AI Agent技术快速发展,单纯依靠大模型对话能力,很难完成复杂的自动化任务。模型需要具备读取本地文件、执行脚本、访问网页、操作文件系统、拆分复杂任务并分步执行的能力。DeepSeek Harness,简称DSH,是开源的AI Agent执行运行框架,遵循“Agent = 大模型 + Harness执行底座”的设计理念,为大模型提供一套安全可控的工具调用、任务编排、沙箱执行与插件扩展能力。它提供Web可视化界面与完整命令行工具,支持插件化扩展,能够让大模型自主拆解复杂需求,调用各类工具分步完成目标,无论是本地电脑调试,还是部署在云服务器上长期运行智能体任务都十分合适。本文为从0到1完整保
921 0
|
14天前
|
缓存 JSON API
阿里云千问Qwen3.8‑Max深度解析:核心能力、订阅计费规则、API接入配置与生产落地完整教程
Qwen3.8‑Max作为千问系列新一代MoE架构旗舰基座,总参数量达到2.4万亿,激活参数950亿,是面向复杂专业任务、长周期智能体、工程级代码开发、多模态深度解析的高阶大模型,原生支持文本、图像、视频多模态输入,最大上下文窗口达到百万Token,最大输出Token支持131072,内置深度思考推理链路,在编程、科研、法律金融专业分析、长视频文档解析、自主Agent任务等场景能力表现突出。很多开发者在项目前期直接接入该旗舰模型,却对模型能力边界、多种计费模式、订阅套餐权益、API参数配置、上下文缓存优化缺乏完整认知,出现成本失控、接口报错、长文本信息丢失、深度思考模式额外消耗大量Token等
1005 3