Embedding理解+代码

article/2025/4/27 20:34:29

目录

  • Embedding
    • 主要思想
  • Word2vec
    • 主要思想
      • 两种模型:
      • 目的:
    • 算法
      • 一、定义超参数
      • 二、将语料库转换one-hot编码表示
      • 三、模型训练
    • 代码手动实现 skip-gram模型
      • 一、数据准备
      • 二、定义超参数
      • 三、定义word2vec模型
        • 数据清洗及生成词汇表
        • 训练模型
      • 四、 获取词向量和相似词
      • 完整代码
  • Item2vec
    • 主要思想
    • 运用
    • 局限性
  • Deepwalk-基础的Graph Embedding算法
    • 主要思想
    • 算法
    • 代码

Embedding

主要思想

把世界万物变成一个向量,让计算机看这个向量,再进行处理
万物都可嵌入

Word2vec

主要思想

就是把每个单词变成一个向量,并且这个向量还保留了单词的语义关系
example:man<->woman,queen<->king
在这里插入图片描述

两种模型:

CBOWSkip-gram(用处广)

目的:

把每个词都用向量表示,同时还保留他们之间语义关系
在这里插入图片描述

算法

一、定义超参数

学习率、训练次数、窗口尺寸、嵌入(embedding)尺寸
以下是窗口为二的滑动窗口
在这里插入图片描述

二、将语料库转换one-hot编码表示

在这里插入图片描述

三、模型训练

1、目标词的one-hot编码传入神经网络模型中训练,最后得到输出结果
在这里插入图片描述
2、训练得到的输出结果运用softmax函数归一化处理
在这里插入图片描述

3、处理后的结果和相邻窗口的单词one-hot编码分别做差得到各自的误差
4、将各自误差相加得到总误差
在这里插入图片描述
5、交叉熵损失函数处理
在这里插入图片描述

6、通过对参数求偏导,梯度下降方法求更新的参数,反向传播更新权重矩阵
7、最终求得更新迭代过后输入层到隐藏层的权重矩阵即为对应词的embedding词向量
在这里插入图片描述

代码手动实现 skip-gram模型

一、数据准备

 #准备语料库text="natural language processing and machine learning is fun and exciting"#分词处理corpus=[[word for word in text.split()]]

二、定义超参数

 #准备超参数settings = {'window_size': 2,  # 窗口大小(目标单词的左边和右边最近的2个单词被视为上下文单词)'n': 10,  # 单词嵌入维度,取决于词汇库大小,也是隐藏层大小'epochs': 50,  # 训练次数'learning_rate': 0.01  # 学习率}

三、定义word2vec模型

class word2vec():
 def __init__(self):self.n = settings['n']self.lr = settings['learning_rate']self.epochs = settings['epochs']self.window = settings['window_size']

数据清洗及生成词汇表

为后续把数据放入神经网络做准备
在函数train_data内部,我们进行以下操作:

self.v_count: 词汇表的长度(注意,词汇表指的就是语料库中不重复的单词的数量)

self.words_list: 在词汇表中的单词组成的列表

self.word_index: 以词汇表中单词为key,索引为value的字典数据

self.index_word: 以索引为key,以词汇表中单词为value的字典数据

for循环给用one-hot表示的每个目标词和其的上下文词添加到train_data中,one-hot编码用的是word2onehot函数。

    def train_data(self,settings,corpus):#先对语料库进行去重,得到去重后的每个词语对应的个数 返回的是一个字典word_counts=defaultdict(int)for row in corpus:for word in row:   #这里的word是二维数组里的单词word_counts[word]+=1# 计算有多少个不同的单词self.v_count = len(word_counts.keys())#去重后单词放入列表self.words_list=list(word_counts.keys())#做成 单词:索引(这里要提出i,word两个参数 所以用enumerate)self.word_index=dict((word,i) for i,word in enumerate(self.words_list))#做成 索引:单词self.index_word = dict((i,word) for i, word in enumerate(self.words_list))#开始存入目标及窗口范围内的词语train_data=[]for sentence in corpus:sent_len = len(sentence)for i, word in enumerate(sentence):w_target=self.word2onehot(sentence[i])#保存窗口范围内的词语w_context=[]for j in range(i-self.window,i+self.window):if j != i and j <= sent_len - 1 and j >= 0:w_context.append(self.word2onehot(sentence[j]))train_data.append([w_target,w_context])#这里就是最终存入神经网络输出层的格式return np.array(train_data)  #定义Onehot函数def word2onehot(self,word):#初始化都是0word_vec=[0 for i in range(0,self.v_count)]#找到传入单词在句子中的索引word_index=self.word_index[word]#将对应位置改为1word_vec[word_index]=1return word_vec

训练模型

    #训练模型def train(self,train_data):#定义权重矩阵self.w1=np.random.uniform(-1,1,(self.v_count,self.n))self.w2=np.random.uniform(-1,1,(self.n,self.v_count))#迭代训练for i in range(self.epochs):self.loss=0for w_t,w_c in train_data:#将目标词语进入前向传递y_pred,h,u=self.forward_pass(w_t)#将窗口误差相加EI=np.sum([np.subtract(y_pred,word) for word in w_c],axis=0)#反向传播self.backprop(EI,h,w_t)#计算误差self.loss += -np.sum([u[word.index(1)] for word in w_c]) + len(w_c) * np.log(np.sum(np.exp(u)))print('Epoch:', i, "Loss:", self.loss)def forward_pass(self,x):h=np.dot(x,self.w1)u=np.dot(h,self.w2)y_c=self.softmax(u)return y_c,h,udef softmax(self,x):e_x=np.exp(x-np.max(x))return e_x/e_x.sum(axis=0)def backprop(self,e,h,x):dl_dw2 = np.outer(h, e)dl_dw1 = np.outer(x, np.dot(self.w2, e.T))self.w1 = self.w1 - (self.lr * dl_dw1)self.w2 = self.w2 - (self.lr * dl_dw2)

四、 获取词向量和相似词

# 获取词向量def word_vec(self, word):w_index = self.word_index[word]v_w = self.w1[w_index]return v_w#获取相似词def vec_sim(self,word,top_n):v_w1=self.word_vec(word)word_sim={}for i in range(self.v_count):v_w2=self.w1[i]theta_sum=np.dot(v_w1,v_w2)theta_den=np.linalg.norm(v_w1)*np.linalg.norm(v_w2)theta=theta_sum/theta_denword=self.index_word[i]word_sim[word]=thetawords_sorted=sorted(word_sim.items(),key=lambda kv:kv[1],reverse=True)for word,sim in words_sorted[:top_n]:print(word,sim)

完整代码

import numpy as np
import math
from collections import defaultdict#定义模型
class word2vec():def __init__(self):self.n = settings['n']self.lr = settings['learning_rate']self.epochs = settings['epochs']self.window = settings['window_size']#定义训练数据函数(一个目标词,以及窗口范围内的词语 把他们都转化为one-hot编码)#清洗数据def train_data(self,settings,corpus):#先对语料库进行去重,得到去重后的每个词语对应的个数 返回的是一个字典word_counts=defaultdict(int)for row in corpus:for word in row:   #这里的word是二维数组里的单词word_counts[word]+=1# 计算有多少个不同的单词self.v_count = len(word_counts.keys())#去重后单词放入列表self.words_list=list(word_counts.keys())#做成 单词:索引(这里要提出i,word两个参数 所以用enumerate)self.word_index=dict((word,i) for i,word in enumerate(self.words_list))#做成 索引:单词self.index_word = dict((i,word) for i, word in enumerate(self.words_list))#开始存入目标及窗口范围内的词语train_data=[]for sentence in corpus:sent_len = len(sentence)for i, word in enumerate(sentence):w_target=self.word2onehot(sentence[i])#保存窗口范围内的词语w_context=[]for j in range(i-self.window,i+self.window):if j != i and j <= sent_len - 1 and j >= 0:w_context.append(self.word2onehot(sentence[j]))train_data.append([w_target,w_context])return np.array(train_data)#定义Onehot函数def word2onehot(self,word):#初始化都是0word_vec=[0 for i in range(0,self.v_count)]#找到传入单词在句子中的索引word_index=self.word_index[word]#将对应位置改为1word_vec[word_index]=1return word_vec#训练模型def train(self,train_data):#定义权重矩阵self.w1=np.random.uniform(-1,1,(self.v_count,self.n))self.w2=np.random.uniform(-1,1,(self.n,self.v_count))#迭代训练for i in range(self.epochs):self.loss=0for w_t,w_c in train_data:#将目标词语进入前向传递y_pred,h,u=self.forward_pass(w_t)#将窗口误差相加EI=np.sum([np.subtract(y_pred,word) for word in w_c],axis=0)#反向传播self.backprop(EI,h,w_t)#计算误差self.loss += -np.sum([u[word.index(1)] for word in w_c]) + len(w_c) * np.log(np.sum(np.exp(u)))print('Epoch:', i, "Loss:", self.loss)def forward_pass(self,x):h=np.dot(x,self.w1)u=np.dot(h,self.w2)y_c=self.softmax(u)return y_c,h,udef softmax(self,x):e_x=np.exp(x-np.max(x))return e_x/e_x.sum(axis=0)def backprop(self,e,h,x):dl_dw2 = np.outer(h, e)dl_dw1 = np.outer(x, np.dot(self.w2, e.T))self.w1 = self.w1 - (self.lr * dl_dw1)self.w2 = self.w2 - (self.lr * dl_dw2)# 获取词向量def word_vec(self, word):w_index = self.word_index[word]v_w = self.w1[w_index]return v_w#获取相似词def vec_sim(self,word,top_n):v_w1=self.word_vec(word)word_sim={}for i in range(self.v_count):v_w2=self.w1[i]theta_sum=np.dot(v_w1,v_w2)theta_den=np.linalg.norm(v_w1)*np.linalg.norm(v_w2)theta=theta_sum/theta_denword=self.index_word[i]word_sim[word]=thetawords_sorted=sorted(word_sim.items(),key=lambda kv:kv[1],reverse=True)for word,sim in words_sorted[:top_n]:print(word,sim)"""
word_counts:  {'natural': 1, 'language': 1, 'processing': 1, 'and': 2, 'machine': 1, 
'learning': 1, 'is': 1, 'fun': 1, 'exciting': 1}
words_list:   ['natural', 'language', 'processing', 'and', 'machine', 'learning', 'is', 'fun', 'exciting']
"""
if __name__ == '__main__':#准备超参数settings = {'window_size': 2,  # 窗口大小(目标单词的左边和右边最近的2个单词被视为上下文单词)'n': 10,  # 单词嵌入维度,取决于词汇库大小,也是隐藏层大小'epochs': 50,  # 训练次数'learning_rate': 0.01  # 学习率}#准备语料库text="natural language processing and machine learning is fun and exciting"#分词处理corpus=[[word for word in text.split()]]# print(corpus)"""[['natural', 'language', 'processing', 'and', 'machine', 'learning', 'is', 'fun', 'and', 'exciting']]"""#模型实例化w2v=word2vec()train_data=w2v.train_data(settings,corpus)w2v.train(train_data)print(w2v.word_vec("machine"))print(w2v.vec_sim("machine",3))

Item2vec

Word2vec诞生后,Embedding思想从自然语言处理领域扩散到了所有机器学习领域。

主要思想

将物品转化为向量,保留物品之间的语义关系

相比于Word2vec利用“词序列”生成词Embedding。Item2vec利用“物品序列”构造物品Embedding。物品之间两两计算cosine相似度即为商品的相似度。

Item2vec摒弃了时间窗口的概念,认为序列中任意两个物品都相关,除此之外模型与skip-gram完全一致

运用

通过矩阵分解产生了用户隐向量和物品隐向量,从Embedding的角度看待矩阵分解,则用户隐向量和物品隐向量就是用户Embedding向量和物品Embedding向量。
item embedding: 利用用户行为序列,采用word2vec思想,生成每个item的Embedding
user embedding:由历史item embedding平均或聚类得到。

局限性

只能利用序列型数据,在处理互联网场景下大量的网络化数据时往往捉襟见肘,由此出现了
Graph Embedding


Deepwalk-基础的Graph Embedding算法

主要思想

解决的是图嵌入问题,把图节点转成n维向量
其中原图中相近的节点,嵌入后依然相近
能够在向量种反映出原图中结构信息,连接信息。
在这里插入图片描述

算法

通过在图里像醉汉一样随机游走,生成一连串随机游走序列,每个序列都类似一句话,其中序列里的每个节点都类似word2vec里的单词。

为何需要随机游走?
图本身非常复杂,我们只能用海量的随机游走序列来捕捉图的信息和模式

可直接套用word2vec种skip-gram方法(中间节点预测相邻节点)可以捕获相邻的关联信息最后迭代优化生成的每个节点的词嵌入向量表。最终能反映出每个节点的相似关系
在这里插入图片描述
在这里插入图片描述

其中word2vec里假设相邻单词是相关的,deepwalk假设在随机游走序列里相邻的节点是相关的

代码

维基百科词条图嵌入
在这里插入图片描述
在这里插入图片描述
通过网站爬取,保存到了tsv文件内构成数据集
在这里插入图片描述

数据集:
https://s3-ap-south-1.amazonaws.com/av-blog-media/wp-content/uploads/2019/11/space_data.zip

#图数据挖掘
import networkx as nx
#数据分析
import pandas as pd
import numpy as np
#随机数
import random
#进度条
from tqdm import tqdm
#降维模块
from sklearn.decomposition import PCA
#word2vec模块
from gensim.models import Word2Vec
import warnings
warnings.filterwarnings('ignore')
#可视化模块
import matplotlib.pyplot as plt
#自然语言处理
from gensim.models import Word2Vec
#降维算法
from sklearn.decomposition import PCA#获取数据
df = pd.read_csv("space_data.tsv",sep='\t')  #分隔符是\t
print(df.head())############################################## 构建无向图 ###################################################
G=nx.from_pandas_edgelist(df,"source","target",edge_attr=True,create_using=nx.Graph())#edge_attr: edge属性的列名称 nx.Graph()无向图
# print(len(G)) #生成的节点数all_nodes=list(G.nodes())  #将无向图的所有节点放入列表中
print(all_nodes)################################ 构建生成随机游走节点序列的函数(输入起始节点和路径长度,生成随机游走序列)###############
def get_randomwalk(node,path_length):random_walk=[node]for i in range(path_length-1):temp=list(G.neighbors(node))           #汇总邻接节点random_node=random.choice(temp)        #随机选择一个邻接节点random_walk.append(random_node)        #将此邻接节点放入列表内node=random_node                       #最后从此邻接节点当作第二次的初始节点return random_walk
# print(get_randomwalk('space exploration',4))###################################### 对每个节点都去做生成随机游走序列 ############################################
gamma=10 #每个节点作为起始节 点生成随机游走序列个数
walk_length=5 #随机游走序列最大长度random_walks=[]
for n in tqdm(all_nodes):   #遍历每个节点for i in range(gamma):  #每个节点作为起始节点生成gamma个随机游走序列random_walks.append(get_randomwalk(n,walk_length))
print(len(random_walks))
# print(random_walks[2])############################################ 训练word2vec模型 #################################################
model=Word2Vec(vector_size=256, #embedding维数window=4,        #窗口宽度sg=1,            #skip-gram模型hs=0,            #不加分层softmaxnegative=10,     #负样本采样alpha=0.03,      #学习率min_alpha=0.0007,#最小学习率seed=14          #随机数种子
)
#用随机游走序列构建词汇表
model.build_vocab(random_walks,progress_per=2)
#训练
model.train(random_walks,total_examples=model.corpus_count,epochs=50,report_delay=1)
#查看某个节点的Embedding
# print(model.wv.get_vector('space exploration'))
#找相似词语
# print(model.wv.similar_by_word('in-space propulsion technologies'))################################# PCA降维可视化 (256维(高维能捕获更丰富的信息)是看不到的只能转化为2维)#################
X=model.wv.vectors
#将Embedding用PCA降维到2维
pca=PCA(n_components=2)
embed_2d=pca.fit_transform(X)
print(embed_2d.shape)plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:,0],embed_2d[:,1])
plt.show()

http://chatgpt.dhexx.cn/article/srUOLNe3.shtml

相关文章

Embedding 基础

一、什么是Embedding 简单来说&#xff0c;Embedding 就是用一个数值向量“表示”一个对象&#xff08;Object&#xff09;的方法&#xff0c;这里说的对象可以是一个词、一个物品&#xff0c;也可以是一部电影等等。一个物品能被向量表示&#xff0c;是因为这个向量跟其他物品…

终于有人把Embedding讲明白了

导读&#xff1a;如果要总结深度学习大获成功的原因&#xff0c;那至少有两样东西必须入选&#xff1a;一样当然是很“深”的神经网络模型&#xff0c;这也是深度学习的“深度”的由来&#xff0c;另一样就是Embedding。 在深度学习中&#xff0c;Embedding是个很重要的概念&am…

计算机网络(二) | 网络编程基础、Socket套接字、UDP和TCP套接字编程

目录 一、网络编程基础1.1 为什么需要网络编程1.2 什么是网络编程1.3 网络编程中的基本概念 二、Socket套接字2.1 概念2.2 分类2.3 Java数据报套接字通信模型2.4 Java流套接字通信模型2.5 UDP数据包套接字编程2.6 TCP流套接字编程 一、网络编程基础 1.1 为什么需要网络编程 丰…

C#编程并实现网络UDP套接字

文章目录 一、UDP介绍二、C#命令行/控制台hello world程序&#xff08;一&#xff09;创建项目&#xff08;二&#xff09;客户端程序&#xff08;三&#xff09;服务端程序&#xff08;四&#xff09;使用wireshark抓包 三、C#Form窗口程序&#xff08;一&#xff09;创建项目…

Linux C语言高级

一、软件包管理及shell命令 1.流行的两种软件包管理机制 1.Deb软件包&#xff1a;由Debian Linux首先提出的软件包管理机制 2.RPM软件包&#xff1a;由Redhat Linux推出的软件包管理机制 2.Debian Linux开发了APT软件包管理器 1.检查和修复软件包依赖关系 2.利用Internet网络帮…

精心收集了60个C语言项目源码,分享给大家

C语言文章更新目录 C/C学习资源&#xff08;百度云盘链接&#xff09; 计算机二级资料&#xff08;过级专用&#xff09; C语言学习路线&#xff08;从入门到实战&#xff09; 编写C语言程序的7个步骤和编程机制 C语言基础-第一个C程序 C语言基础-简单程序分析 VS2019编写简单…

python基于c语言开发_C高级编程:基于模块化设计思想的C语言开发 PDF 超清版

给大家带来的一篇关于C语言相关的电子书资源&#xff0c;介绍了关于C高级编程、模块化、设计思想、C语言开发方面的内容&#xff0c;本书是由机械工业出版社出版&#xff0c;格式为PDF&#xff0c;资源大小80 MB&#xff0c;吉星编写&#xff0c;目前豆瓣、亚马逊、当当、京东等…

【Linux】网络基础+UDP网络套接字编程

只做自己喜欢做的事情&#xff0c;不被社会和时代裹挟着前进&#xff0c;是一件很奢侈的事。 文章目录 一、 网络基础1.局域网和广域网2.协议初识和网络协议分层&#xff08;TCP/IP四层模型&#xff09;3.MAC地址和IP地址&#xff08;子网掩码&#xff0c;路由表&#xff0c;I…

C#使用TCP/UDP协议通信并用Wireshark抓包分析数据

目录 一、Wireshark抓包软件下载安装二、控制台程序使用 UDP 通信1&#xff09;创建新项目2&#xff09;编写代码3&#xff09;编译结果4&#xff09;抓包分析数据 三、Form窗口程序使用 TCP 通信1&#xff09;创建新项目2&#xff09;设计图形界面3&#xff09;编写代码4&…

SimpleFOC之ESP32(九)—— WIFI、UDP和TCP

目录 说明一、网络通信1.1、准备工作1.2、UDP通信1.3、TCP通信 二、硬件准备三、代码参考四、代码演示4.1、WIFI_AP模式UDP通信4.2、WIFI_STA模式TCP client通信 五、UDP通信控制电机5.1、硬件准备5.2、代码演示5.2.1、串口通信更改为UDP通信5.2.2、笔记本连接AP5.2.3、UDP发送…

如何进行网络编程(代码利用UDP socket实现)

目录 一、什么是网络编程&#xff1f; 二、那么在Java中能调用C语言的函数吗&#xff1f; 三、操作系统提供的socket API主要有两类&#xff08;实际上不止两类&#xff09; 1.流套接字&#xff08;底层使用TCP协议&#xff09; TCP协议的特点&#xff1a; 2.数据报套接字…

北斗系统学习—JT808协议用C语言解析

前言&#xff1a; 本人从事于Linux应用开发(音视频应用方向&#xff09;,现在主要是负者AI摄像头的开发&#xff0c;在学音视频的途中&#xff0c;虽然是个小白&#xff0c;但是更愿意把自己所学音视频的一些知识分享给大家&#xff0c;以后每周都会更新哦&#xff01; 本期介绍…

TCP/IP协议(一、自己动手实现udp)

对TCP/IP协议都只是听过&#xff0c;没有仔细研究过&#xff0c;一些知识体系也比较零散&#xff0c;什么三次握手&#xff0c;四次挥手&#xff0c;滑动窗口&#xff0c;零拷贝技术等等&#xff0c;都是知识有这么个东西&#xff0c;而不知道具体是啥&#xff0c;这几天还是根…

【Linux】传输层协议:UDP和TCP

但人不能永远浪漫下去&#xff0c;那会走向自我毁灭的。浪漫都是水字旁&#xff0c;会把人淹死的。人最终还是要进入一个规则体系&#xff0c;所谓&#xff0c;随心所欲不逾矩嘛 文章目录 一、UDP协议1.端口号2.理解UDP报头3.UDP的特点&#xff08;面向数据报&#xff0c;全双…

Linux网络:UDP协议 | TCP协议

文章目录 前言端口号netstat -- pidof UDP协议TCP协议三次握手 四次挥手确认应答(ACK)机制超时重传机制连接管理机制理解TIME_WAIT状态理解 CLOSE_WAIT 状态 滑动窗口流量控制拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结 基于TCP 和 UDP 的应用层协议TCP/UD…

C语言SOCKET编程指南

转载自&#xff1a;http://blog.sina.com.cn/s/blog_79b01f66010163q3.html 这篇文章完全可以作为c语言socket编程指南&#xff0c;无论在任何系统下。感谢作者fenglovel&#xff01; C语言SOCKET编程指南 1、介绍 Socket 编程让你沮丧吗&#xff1f;从man pages中很难得到有…

【socket】从计算机网络基础到socket编程——Windows Linux C语言 + Python实现(TCP+UDP)

一、部分基础知识1.1 计算机网络的体系结构1.11 互联网简介1.12 计算机网络的分类1.13 协议与网络的分层体系结构▶ 协议▶ 网络的分层体系结构 1.14 OSI 七层模型&#xff08;重要&#xff09;▶ OSI 模型的结构▶ OSI 模型各层的功能 1.15 TCP/IP 的体系结构&#xff08;重要…

C语言 C语言基础

C语言 C语言基础 一、简述 对于C语言基础相关方面的表面理解&#xff0c;简单介绍。 二、二进制 生活中常用的是十进制&#xff0c;基数0,1,2,3,4,5,6,7,8,9,。满10进1。 时钟60进制。基数0,1,2...57,58,59。满60进1。60秒为1分钟&#xff0c;60分钟为1小时。 计算机二进制&a…

炼一项专业技能c语言,C语言程序设计_安徽新华电脑专修学院

C语言程序设计&#xff0c;安徽新华电脑专修学院&#xff0c;2013年3月&#xff0c;在安徽省315国际消费者权益日纪念大会暨省消协四届三次理事会会议上&#xff0c;安徽新华电脑专修学院被省消费者协会授予“诚信单位”。 C语言程序设计&#xff0c; 并用c语言进行测试。还有b…

C++中使用UDP Socket发送字节数据

文章目录 参考代码结果展示 参考 这篇文章给的代码也能用 https://blog.csdn.net/qq_36437446/article/details/106446172 CRC代码来自https://blog.csdn.net/huijunma2010/article/details/124151471 在线计算CRC http://www.ip33.com/crc.html 代码 这里的byte是unsigned…