自然语言处理:Word2Vec

每种动物都有自己的语言,机器也是!自然语言处理(NLP)就是在机器语言和人类语言之间沟通的桥梁。

NLP通常有情感分析、文本挖掘、信息抽取、信息检索、问答/对话系统(聊天机器人)、语音识别、机器翻译等应用。

最近大火的ChatGPT(Chat Generative Pre-trained Transformer)则是人工智能研究实验室OpenAI新推出的人工智能技术驱动的自然语言处理工具。主要通过使用TransFormer神经网络架构使得ChatGPT具有聊天互动的能力,可以根据特定聊天场景进行交流,还具备撰写邮件、脚本、文案、翻译、代码等不同类型文字的功能。

最近几篇推文我将从Word2Vec→Transformer→BERT出发,从简单到复杂尝试NLP的一些工作。

(BERT与GPT的模型简介可以参考这篇文章:http://t.csdn.cn/c8ZVD

ChatGPT问答对话系统(图源:自截)

本篇推文为Word2Vec的实现

1.什么是词向量

在自然语言处理任务中,首先需要考虑词如何在计算机中表示,通常有两种表示方式[1]。

1.离散表示(one-hot representation)

1.1 将每个词表示为一个长向量(维度为词表大小),向量中只有一个维度的值为1,其余为0。

例如:

建筑 [0, 0, 0, 0, 1, 0, 0, ……]

景观 [0, 0, 0, 1, 0, 0, 0, ……]

语料库中的每个词都有一个索引,但以这种方式表示,词与词之间无任何关系,同时当词数比较多时,会导致特征空间十分大;

1.2 Bag of Words 表示

将每个单词在语料库中出现的次数加到one-hot编码中,此方法仍未考虑单词的顺序及语义信息。

2.分布式表示(distribution representation)

将词通过词嵌入(word embedding)转换为一种分布式表示,即词向量。

比如我们将词汇表里的词用"Royalty",“Masculinity”, "Femininity"和"Age"4个维度来表示,King这个词对应的词向量可能是[0.99,0.99,0.05,0.7]。大致可以理解为国王为具有王权的男性,这样就从原来非常稀疏的one hot产生的词向量转变成了现在的稠密向量,大大节约了内存和减少了计算量。

在实际情况中,我们需要自定词向量的维度[2]。

以GloVe词向量为例,glove.6B.50d.txt中,每个词有50维:

of: 0.70853 0.57088 -0.4716 0.18048 0.54449 0.72603 0.18157 -0.52393 0.10381 -0.17566 0.078852 -0.36216 -0.11829 -0.83336 0.11917 -0.16605 0.061555 -0.012719 -0.56623 0.013616 0.22851 -0.14396 -0.067549 -0.38157 -0.23698 -1.7037 -0.86692 -0.26704 -0.2589 0.1767 3.8676 -0.1613 -0.13273 -0.68881 0.18444 0.0052464 -0.33874 -0.078956 0.24185 0.36576 -0.34727 0.28483 0.075693 -0.062178 -0.38988 0.22902 -0.21617 -0.22562 -0.093918 -0.80375

glove.6B.100d.txt中,每个词有100维:

of: -0.1529 -0.24279 0.89837 0.16996 0.53516 0.48784 -0.58826 -0.17982 -1.3581 0.42541 0.15377 0.24215 0.13474 0.41193 0.67043 -0.56418 0.42985 -0.012183 -0.11677 0.31781 0.054177 -0.054273 0.35516 -0.30241 0.31434 -0.33846 0.71715 -0.26855 -0.15837 -0.47467 0.051581 -0.33252 0.15003 -0.1299 -0.54617 -0.37843 0.64261 0.82187 -0.080006 0.078479 -0.96976 -0.57741 0.56491 -0.39873 -0.057099 0.19743 0.065706 -0.48092 -0.20125 -0.40834 0.39456 -0.02642 -0.11838 1.012 -0.53171 -2.7474 -0.042981 -0.74849 1.7574 0.59085 0.04885 0.78267 0.38497 0.42097 0.67882 0.10337 0.6328 -0.026595 0.58647 -0.44332 0.33057 -0.12022 -0.55645 0.073611 0.20915 0.43395 -0.012761 0.089874 -1.7991 0.084808 0.77112 0.63105 -0.90685 0.60326 -1.7515 0.18596 -0.50687 -0.70203 0.66578 -0.81304 0.18712 -0.018488 -0.26757 0.727 -0.59363 -0.34839 -0.56094 -0.591 1.0039 0.20664

有了用Distributed Representation表示的词向量,我们就可以较容易的分析词之间的关系了,比如我们将词的维度降维到2维,有一个有趣的研究表明,用下图的词向量表示我们的词时,我们可以发现:

图1 有趣的词向量(图源:CSDN 前行的zhu)

2.词向量的表示

Word2Vec文章介绍了两个词向量模型:连续词袋模型(Continuous Bag-of-Words,简称CBOW) 与和跳字模型(Skip-Gram)。对于在语义上有意义的表示,它们的训练依赖于条件概率,条件概率可以被看作是使用语料库中⼀些词来预测另⼀些单词。由于是不带标签的数据,因此跳元模型和连续词袋都是自监督模型。

对二者的讲解资料十分多,详细了解推荐在此查看:http://t.csdn.cn/zkciu

3.Word2Vec的代码实现

我们使用Penn Tree Bank(PTB)数据集进行实验,该语料库取⾃“华尔街⽇报”的文章,分为训练集、验证集和测试集。

3.1 文本预处理

%matplotlib inline
import math
import os
import random
import torch
from d2l import torch as d2l
import collections
from torch import nn

将文本作为字符串加载到内存中并将字符串拆分为词元(如单词和字符)

d2l.DATA_HUB['ptb'] = (d2l.DATA_URL + 'ptb.zip','319d85e578af0cdc590547f26231e4e31cdf1e42')def read_ptb():"""将PTB数据集加载到文本行的列表中"""data_dir = d2l.download_extract('ptb')with open(os.path.join(data_dir, 'ptb.train.txt')) as f:raw_text = f.read()return [line.split() for line in raw_text.split('\n')]  #进行分词操作def count_corpus(tokens):if len(tokens)==0 or isinstance(tokens[0],list):tokens=[token for line in tokens for token in line]print(tokens)return collections.Counter(tokens)

构建词表,其中出现次数少于10次的任何单词都将由“<unk>”词元替换。

class Vocab:def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens=[]if reserved_tokens is None:reserved_tokens=[]counter=count_corpus(tokens)self._token_freqs=sorted(counter.items(), key=lambda x: x[1], reverse=True)self.idx_to_token=['<unk>']+reserved_tokensself.token_to_idx={token:idx for idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:if freq<min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token]=len(self.idx_to_token)-1def __len__(self):return len(self.idx_to_token)def __getitem__(self,tokens):if not isinstance(tokens,(list,tuple)):return self.token_to_idx.get(tokens,self.unk)return [self.__getitem__(token) for token in tokens]def to_tokens(self,indices):if not isinstance(indices,(list, tuple)):return self.idx_to_token[indices]return [self.idx_to_token[index] for index in indices]def unk(self):return 0def token_freqs(self):return self._token_freqsdef count_corpus(tokens):if len(tokens)==0 or isinstance(tokens[0],list):tokens=[token for line in tokens for token in line]return collections.Counter(tokens)sentences = read_ptb()
vocab=Vocab(sentences,min_freq=10)  
subsampled, counter=subsample(sentences,vocab)

下采样,将高频词wi“a”、“the”、“of”等进行丢弃,其被丢弃的概率为:

def subsample(sentences,vocab):sentences=[[token for token in line if vocab[token]!=vocab.unk] for line in sentences]counter=count_corpus(sentences)# print(counter)num_tokens=sum(counter.values())# print(num_tokens)def keep(token):return(random.uniform(0,1)<math.sqrt(1e-4/counter[token]*num_tokens))return([[token for token in line if keep(token)] for line in sentences],counter)

提取中心词和上下文词,随机采样1到max_window_size之间的整数作为上下⽂窗⼝。对于任⼀中⼼词,与其距离不超过采样上下⽂窗⼝⼤⼩的词为其上下⽂词。

def get_centers_and_contexts(corpus, max_window_size):centers,contexts=[],[]for line in corpus:# print(line)if len(line)<2:continuecenters+=linefor i in range(len(line)):window_size=random.randint(1,max_window_size)indices=list(range(max(0,i-window_size),min(len(line),i+1+window_size)))indices.remove(i)contexts.append([line[idx] for idx in indices])return centers,contexts

整合代码:读取PTB数据集并返回数据迭代器和词表。

#@save
def load_data_ptb(batch_size, max_window_size, num_noise_words):"""下载PTB数据集,然后将其加载到内存中"""num_workers = d2l.get_dataloader_workers()sentences = read_ptb()vocab = Vocab(sentences, min_freq=10)subsampled, counter = subsample(sentences, vocab)corpus = [vocab[line] for line in subsampled]all_centers, all_contexts = get_centers_and_contexts(corpus, max_window_size)all_negatives = get_negatives(all_contexts, vocab, counter, num_noise_words)class PTBDataset(torch.utils.data.Dataset):def __init__(self, centers, contexts, negatives):assert len(centers) == len(contexts) == len(negatives)self.centers = centersself.contexts = contextsself.negatives = negativesdef __getitem__(self, index):return (self.centers[index], self.contexts[index],self.negatives[index])def __len__(self):return len(self.centers)dataset = PTBDataset(all_centers, all_contexts, all_negatives)data_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True,collate_fn=batchify, num_workers=num_workers)return data_iter, vocab

3.2 预训练word2vec

在前向传播中,跳元语法模型的输入包括形状为(批量大小,1)的中心词索引center和形状为(批量大小,max_len)的上下文与噪声词索引contexts_and_negatives。这两个变量首先通过嵌入层从词元索引转换成向量,然后它们的批量矩阵相乘返回形状为(批量大小,1,max_len)的输出。输出中的每个元素是中心词向量和上下文或噪声词向量的点积。

def skip_gram(center,contexts_and_negtives,embed_v,embed_u):v=embed_v(center)u=embed_u(contexts_and_negtives)pred=torch.bmm(v,u.permute(0,2,1))return pred

计算⼆元交叉熵损失

class SigmoidBCELoss(nn.Module):# 带掩码的二元交叉熵损失def __init__(self):super().__init__()def forward(self, inputs, target, mask=None):out = nn.functional.binary_cross_entropy_with_logits(inputs, target, weight=mask, reduction="none")return out.mean(dim=1)loss = SigmoidBCELoss()

初始化模型参数

data_iter,vocab=d2l.load_data_ptb(512,5,5)
embed_size=100
net=nn.Sequential(nn.Embedding(num_embeddings=len(vocab),embedding_dim=embed_size),nn.Embedding(num_embeddings=len(vocab),embedding_dim=embed_size))

定义训练阶段代码

def train(net,data_iter,lr,num_epochs,device=d2l.try_gpu()):def init_weights(m):if type(m)==nn.Embedding:nn.init.xavier_uniform_(m.weight)net.apply(init_weights)net=net.to(device)optimizer=torch.optim.Adam(net.parameters(),lr=lr)animator=d2l.Animator(xlabel='epoch',ylabel='loss',xlim=[1,num_epochs])metric=d2l.Accumulator(2)for epoch in range(num_epochs):timer,num_batches=d2l.Timer(),len(data_iter)for i, batch in enumerate(data_iter):optimizer.zero_grad()center,context_negative,mask,label=[data.to(device) for data in batch]pred=skip_gram(center,context_negative,net[0],net[1])l=(loss(pred.reshape(label.shape).float(),label.float(),mask)/mask.sum(axis=1)*mask.shape[1])l.sum().backward()optimizer.step()metric.add(l.sum(),l.numel())if (i+1)%(num_batches//5)==0 or i==num_batches-1:animator.add(epoch+(i+1)/num_batches,(metric[0]/metric[1]))print(f'loss{metric[0]/metric[1]:.3f},'f'{metric[1]/timer.stop():.1f} tokens/sec on {str(device)}')

开始训练

lr,num_epochs=0.002,100
train(net,data_iter,lr,num_epochs)

实验结果如下图

3.3 应用词嵌入

使⽤训练好模型中词向量的余弦相似度来从词表中找到与输⼊单词语义最相似的单词,十分神奇!

def get_similar_tokens(query_token, k, embed):W = embed.weight.datax = W[vocab[query_token]]# 计算余弦相似性。增加1e-9以获得数值稳定性cos = torch.mv(W, x) / torch.sqrt(torch.sum(W * W, dim=1) *torch.sum(x * x) + 1e-9)topk = torch.topk(cos, k=k+1)[1].cpu().numpy().astype('int32')for i in topk[1:]: # 删除输入词print(f'cosine sim={float(cos[i]):.3f}: {vocab.to_tokens(i)}')get_similar_tokens('tour', 3, net[0])

例如,我们查找与“chip”相近的词,余弦相似度最高的前三个词为:

cosine sim=0.386: machine

cosine sim=0.383: computer

cosine sim=0.371: equipment

与“university”相近的词,余弦相似度最高的前三个词为:

cosine sim=0.460: graduate

cosine sim=0.408: school

cosine sim=0.440: professor

与“money”相近的词,余弦相似度最高的前三个词为:

cosine sim=0.454: funds

cosine sim=0.408: rely

cosine sim=0.406: investors

·未完待续·

[1] http://t.csdn.cn/69pp9

[2] http://t.csdn.cn/3a7bb

本文的学习基于李沐老师的《动手学深度学习》:

https://zh-v2.d2l.ai/chapter_preface/index.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37727.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

周鸿祎:ChatGPT可能两三年内产生自我意识;字节加入大模型之战;Ubuntu下一版本默认不再支持Flatpak| 极客头条...

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 苏宓 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&#xf…

chatGPT在线网页写论文

帮我写一篇关于秦始皇对于中国的影响论文 秦始皇&#xff0c;即嬴政&#xff0c;是中国历史上的伟大统治者之一。他在位期间统一了中国各个诸侯国&#xff0c;建立了秦朝&#xff0c;并为中国历史上的统一奠定了基础。秦始皇对于中国的影响是深远而持久的&#xff0c;不仅在政…

如何加速大模型开发?技术方案拆解来了:昇思MindSpore技术一览

随着ChatGPT爆火出圈&#xff0c;狂飙之势从22年底持续到23年初&#xff0c;与以往的技术突破不同的是&#xff0c;此次的大模型不仅被技术界关注&#xff0c;而且备受投资界、产业界和大众消费者的追捧&#xff0c;使它成为历史上最快月活过亿的现象级应用&#xff0c;继而引发…

Python项目:基于爬虫+Flask实现招聘岗位数据分析与可视化

在 基于爬虫Flask实现豆瓣电影Top250数据分析 的基础上,进一步实战,开发出本项目 基于爬虫Flask实现的招聘岗位数据分析与可视化,干货多多,也学到了很多的东西。 文章目录 1、项目简介:2、成果展示:3、后台展示4、项目总结: 1、项目简介: 项目主要是对招聘网站 51job 上的招聘信…

微信小程序输入框字数限制以及计算

wxml代码如下: <textarea class"textarea-bg font_s33 font_c31" id"information" maxlength150 placeholder"请输入遇到的问题或建议" name"information" value"{{information}}"bindinput"getDataBindTap"&…

百度推出可24时直播带货的AI数字人

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 前几天我还说做直播太内卷&#xff0c;运营成本太高了呢&#xff0c;今天百度就推出了AI数字人&#xff0c;同时推出了曦灵数字人直播平台。它最大的特色功能就是&#xff1a; (1)有基础文本&#…

从开店营销到智能化私域运营,有赞发布人工智能引擎Jarvis

“以往在私域发起一场营销活动&#xff0c;从活动策划&#xff0c;到历史数据分析&#xff0c;再到内容排期&#xff0c;整个策划阶段往往需要一周以上的时间&#xff0c;而现在通过营销画布&#xff08;MA&#xff09;以及其中内嵌的人工智能能力&#xff0c;只需要30分钟不到…

小度助手和它背后的百度AI野望

乾明 发自 凹非寺量子位 报道 | 公众号 QbitAI 百度最近的一则高管晋升通告&#xff0c;反映出小度助手对百度的重要性不断提高。 最新一季财报刚结束&#xff0c;李彦宏一封内部信&#xff0c;将“小度助手”&#xff08;DuerOS&#xff09;负责人景鲲&#xff0c;晋升为公司副…

2023 最新 抖音AI换脸表情包小程序变现玩法项目

单条视频变现1万 普通人也能轻松玩转 表情包小程序变现在抖音的玩法一直越来越好&#xff0c;最近新出的AI换脸表情包玩法更有意思&#xff0c;可以预见的是这是一个有红利期的&#xff0c;短平快的项目&#xff0c;刚开始大家都会特别感兴趣&#xff0c;都会把自己的脸换到视…

【DuerOS开发日记】1.据说小度在等待帅的人把它唤醒

目录 【Minecode|开发日记】1.据说小度在等待帅的人把它唤醒 【Minecode|开发日记】2.打造属于自己的小度(1)&#xff1a;使用PythonSDK 【Minecode|开发日记】3.打造属于自己的小度(2)&#xff1a;小白小白&#xff01;——唤醒词替换 &#xff08;未完持更&#xff09; 写在前…

小度科技独立背后,百度开始和大家分享AI大蛋糕

9月的最后一天&#xff0c;小度放了个大招&#xff1a;智能生活事业群组&#xff08;SLG&#xff09;业务完成独立融资协议签署。 据悉&#xff0c;该轮融资战略领投方为百度资本及CPE领投&#xff0c; 跟投方为IDG资本。 一、小度科技独立&#xff0c;估值达200亿元 小度独…

李彦宏发布小度在家“解锁”中国家庭市场,被称作AI性价比之王

个人移动设备火了之后&#xff0c;差不多所有硬件相关行业都瞄准了下一个目标&#xff1a;家庭。 这一瞄&#xff0c;就是好多年过去了啊...... 无论是打着互联网旗号的各种大屏硬件&#xff0c;还是各种各样千奇百怪的“智能设备”。但几年的时间里&#xff0c;这些东西陆续进…

使用大型语言模(LLM)构建系统(三):思维链推理

今天我学习了DeepLearning.AI的 Building Systems with LLM 的在线课程&#xff0c;我想和大家一起分享一下该门课程的一些主要内容。 下面是我们访问大型语言模(LLM)的主要代码&#xff1a; import openai#您的openai的api key openai.api_key YOUR-OPENAI-API-KEY def get_…

某跨境出口电商APP参数解密

工具 jadxfrida-15.1.1charlespostman包名&#xff08;Y29tLmRoZ2F0ZS5idXllcm1vYg&#xff09; 抓包 使用postman测试发现以上参数只需要sign和deviceId两个参数&#xff1b; 看sign参数位数猜测可能是MD5&#xff0c;deviceId的形式类似于uuid4&#xff08;此处只是猜测&am…

海外跨境电商商城源码-进出口电商平台网站-多语言多商户平台

欢迎探讨&#xff0c;名片交流 一、海外跨境电商系统源码包括以下几个部分&#xff1a; 前端&#xff1a;React框架、Bootstrap 后端&#xff1a;Node.js&#xff0c;Express框架、NoSQL数据库 支付系统&#xff1a;Stripe、PayPal等主流支付平台 物流系统&#xff1a;DHL…

黑白照片上色变彩色?狂飙大嫂竟美成这样?人工智能太可怕了(11)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 如何利用人工智能API&#xff0c;给黑白图片上色。 智能识别黑白图像内容并填充色彩&#xff0c;使黑白图像变得鲜活。 我…

开发任务拆分方法

一、背景 任务总和应该能反馈为完成某个目标需要做的所有工作总量。WBS中也讲了很多分解的原则、标准和方法&#xff0c;但是在实际工作中&#xff0c;做任务拆分时候往往只看到了关键任务而忽略了其他细节&#xff0c;或者任务粒度过大&#xff0c;导致任务长时间处于执行中状…

多图详解WBS任务分解法

专业项目管理知识请点击下方关注项目管理精英 更多推荐 一位项目经理的深刻反思 项目经理如何正确使用鱼骨图&#xff1f; 从助理到总监&#xff0c;项目经理的成长之路 一图了解通俗易懂的项目管理 免责声明&#xff1a; 本公众号部分分享的资料来自网络收集和整理&am…

任务分解的五个步骤

近期有不少新同事入职&#xff0c;深感任务分解能力对职场新手太过重要&#xff0c;旧文再次分享。 以下正文&#xff1a; 写OKR&#xff08;Objectives and Key Results&#xff0c;是一套明确和跟踪目标及其完成情况的管理工具和方法&#xff09;深层次的问题就是掌握任务定…

使用腾讯tapd工具,进行创建迭代任务、任务拆解、、制定整体发布计划、多维度甘特图进度把控

举例操作1、创建迭代---》每一个项目可以有多个迭代任务&#xff0c;一般一个迭代任务时间安排可以保持在2周&#xff0c;敏捷开发2、创建任务 ---》创建任务时一定要关联迭代&#xff0c;这样后面甘特图才会将多维度项目进度才会展示出来 3、甘特图进度管理 视图切换有一下…