Word2Vec基本实践

news2024/11/16 7:23:05

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 系列文章目录
  • 前言
  • 一、使用SkipGram 模型
    • 1. 构建实验语料库
    • 2. 生成Skip-Gram训练数据
    • 3. 对Skip-Gram数据进行One-Hot编码
    • 4. 定义Skip-Gram模型
    • 5. 训练Skip-Gram模型
    • 6. 输出Skip-Gram词向量
  • 二、使用CBOW 模型
    • 1. 构建实验语料库
    • 2. 生成CBOW训练数据
    • 3. CBOW数据进行One-Hot编码
    • 4. 定义CBOW模型
    • 5. 训练CBOW模型
    • 6. 输出CBOW词向量


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用SkipGram 模型

1. 构建实验语料库

# 定义一个句子列表,后面会用这些句子来训练CBOW和Skip-Gram模型
sentences = ["Kage is Teacher", "Mazong is Boss", "Niuzong is Boss",
             "Xiaobing is Student", "Xiaoxue is Student",]
# 将所有句子连接在一起,然后用空格分隔成词汇
words = ' '.join(sentences).split()
# 构建词汇表,去除重复的词
word_list = list(set(words))
# 创建一个字典,将每个词汇映射到一个唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)}
# 创建一个字典,将每个索引映射到对应的词汇
idx_to_word = {idx: word for idx, word in enumerate(word_list)}
voc_size = len(word_list) # 计算词汇表的大小
print("词汇表:", word_list) # 输出词汇表
print("词汇到索引的字典:", word_to_idx) # 输出词汇到索引的字典
print("索引到词汇的字典:", idx_to_word) # 输出索引到词汇的字典
print("词汇表大小:", voc_size) # 输出词汇表大小

2. 生成Skip-Gram训练数据

# 生成Skip-Gram训练数据
def create_skipgram_dataset(sentences, window_size=2):
    data = []
    for sentence in sentences:
        sentence = sentence.split()  # 将句子分割成单词列表
        for idx, word in enumerate(sentence):  # 遍历单词及其索引
            # 获取相邻的单词,将当前单词前后各N个单词作为相邻单词
            for neighbor in sentence[max(idx - window_size, 0): 
                        min(idx + window_size + 1, len(sentence))]:
                if neighbor != word:  # 排除当前单词本身
                    # 将相邻单词与当前单词作为一组训练数据
                    data.append((neighbor, word))
    return data
# 使用函数创建Skip-Gram训练数据
skipgram_data = create_skipgram_dataset(sentences)
# 打印未编码的Skip-Gram数据样例
print("Skip-Gram数据样例(未编码):", skipgram_data)

3. 对Skip-Gram数据进行One-Hot编码

# 定义One-Hot编码函数
import torch # 导入torch库
def one_hot_encoding(word, word_to_idx):
    # 创建一个全为0的张量,长度与词汇表大小相同
    tensor = torch.zeros(len(word_to_idx))  
    tensor[word_to_idx[word]] = 1  # 将对应词汇的索引位置置为1
    return tensor  # 返回生成的One-Hot向量

# 展示One-Hot编码前后的数据
word_example = "Teacher"
print("One-Hot编码前的单词:", word_example)
print("One-Hot编码后的向量:", one_hot_encoding(word_example, word_to_idx))

# 展示编码后的Skip-Gram数据样例
print("Skip-Gram数据样例(已编码):", [(one_hot_encoding(context, word_to_idx), 
          word_to_idx[target]) for context, target in skipgram_data[:3]])

4. 定义Skip-Gram模型

# 定义Skip-Gram模型
import torch.nn as nn # 导入neural network
class SkipGram(nn.Module):
    def __init__(self, voc_size, embedding_size):
        super(SkipGram, self).__init__()
        # 从词汇表大小到嵌入大小的线性层(权重矩阵)
        self.input_to_hidden = nn.Linear(voc_size, embedding_size, bias=False)  
        # 从嵌入大小到词汇表大小的线性层(权重矩阵)
        self.hidden_to_output = nn.Linear(embedding_size, voc_size, bias=False)  

    def forward(self, X): # X : [batch_size, voc_size]        
         # 生成隐藏层:[batch_size, embedding_size]
        hidden_layer = self.input_to_hidden(X) 
        # 生成输出层:[batch_size, voc_size]
        output_layer = self.hidden_to_output(hidden_layer)  
        return output_layer
    
embedding_size = 2 # 设定嵌入层的大小,这里选择2是为了方便展示
skipgram_model = SkipGram(voc_size,embedding_size)  # 实例化SkipGram模型
print("Skip-Gram模型:", skipgram_model)


##建立skipgram模型--使用nn.embedding层替代线性层

import torch.nn as nn
class SkipGram(nn.Module):
    def __init__(self,voc_size,embeding_size):
        super(SkipGram,self).__init__()
        self.input_to_hidden=nn.Embedding(voc_size,embeding_size)
        self.hidden_to_output=nn.Linear(embeding_size,voc_size,bias=False)
        
    def forward(self,X):
        hidden_layer=self.input_to_hidden(X)
        output_layer=self.hidden_to_output(hidden_layer)
        
        return output_layer
        
voc_size=len(words_list)
skipgram_model=SkipGram(voc_size,embeding_size=2)

5. 训练Skip-Gram模型

# 训练Skip-Gram模型
learning_rate = 0.001 # 设置学习速率
epochs = 1000 # 设置训练轮次
criterion = nn.CrossEntropyLoss()  # 定义交叉熵损失函数
import torch.optim as optim # 导入随机梯度下降优化器
optimizer = optim.SGD(skipgram_model.parameters(), lr=learning_rate)  

# 开始训练循环
loss_values = []  # 用于存储每轮的平均损失值
for epoch in range(epochs):
    loss_sum = 0 # 初始化损失值
    for context, target in skipgram_data:        
        X = one_hot_encoding(target, word_to_idx).float().unsqueeze(0) # 将中心词转换为One-Hot向量   
        y_true = torch.tensor([word_to_idx[context]], dtype=torch.long) # 将周围词转换为索引值   
        y_pred = skipgram_model(X)  # 计算预测值
        loss = criterion(y_pred, y_true)  # 计算损失
        loss_sum += loss.item() # 累积损失
        optimizer.zero_grad()  # 清空梯度
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
    if (epoch+1) % 100 == 0: # 输出每100轮的损失,并记录损失
        print(f"Epoch: {epoch+1}, Loss: {loss_sum/len(skipgram_data)}")  
        loss_values.append(loss_sum / len(skipgram_data))

# 绘制训练损失曲线
import matplotlib.pyplot as plt # 导入matplotlib
plt.plot(range(1, epochs//100 + 1), loss_values) # 绘图
plt.title('Training Loss') # 图题
plt.xlabel('Epochs') # X轴Label
plt.ylabel('Loss') # Y轴Label
plt.show() # 显示图

6. 输出Skip-Gram词向量

# 输出Skip-Gram习得的词嵌入
print("\nSkip-Gram词嵌入:")
for word, idx in word_to_idx.items(): # 输出每个单词的嵌入向量
    print(f"{word}: \
    {skipgram_model.input_to_hidden.weight[:, idx].detach().numpy()}")  


plt.rcParams["font.family"]=['SimHei'] # 用来设定字体样式
plt.rcParams['font.sans-serif']=['SimHei'] # 用来设定无衬线字体样式
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号
# 绘制二维词向量图
fig, ax = plt.subplots() 
for word, idx in word_to_idx.items():
    vec = skipgram_model.input_to_hidden.weight[:, \
            idx].detach().numpy() # 获取每个单词的嵌入向量
    ax.scatter(vec[0], vec[1]) # 在图中绘制嵌入向量的点
    ax.annotate(word, (vec[0], vec[1]), fontsize=12) # 点旁添加单词标签
plt.title('2维词嵌入') # 图题
plt.xlabel('向量维度1') # X轴Label
plt.ylabel('向量维度2') # Y轴Label
plt.show() # 显示图

二、使用CBOW 模型

1. 构建实验语料库

# 定义一个句子列表,后面会用这些句子来训练CBOW和CBOW模型
sentences = ["Kage is Teacher", "Mazong is Boss", "Niuzong is Boss",
             "Xiaobing is Student", "Xiaoxue is Student",]
# 将所有句子连接在一起,然后用空格分隔成词汇
words = ' '.join(sentences).split()
# 构建词汇表,去除重复的词
word_list = list(set(words))
# 创建一个字典,将每个词汇映射到一个唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)}
# 创建一个字典,将每个索引映射到对应的词汇
idx_to_word = {idx: word for idx, word in enumerate(word_list)}
voc_size = len(word_list) # 计算词汇表的大小
print("词汇表:", word_list) # 输出词汇表
print("词汇到索引的字典:", word_to_idx) # 输出词汇到索引的字典
print("索引到词汇的字典:", idx_to_word) # 输出索引到词汇的字典
print("词汇表大小:", voc_size) # 输出词汇表大小

2. 生成CBOW训练数据

# 生成CBOW训练数据
def create_cbow_dataset(sentences, window_size=2):
    data = []
    for sentence in sentences:
        sentence = sentence.split()  # 将句子分割成单词列表
        for idx, word in enumerate(sentence):  # 遍历单词及其索引
            # 获取上下文词汇,将当前单词前后各window_size个单词作为上下文词汇
            context_words = sentence[max(idx - window_size, 0):idx] \
                + sentence[idx + 1:min(idx + window_size + 1, len(sentence))]
            # 将当前单词与上下文词汇作为一组训练数据
            data.append((word, context_words))
    return data

# 使用函数创建CBOW训练数据
cbow_data = create_cbow_dataset(sentences)
# 打印未编码的CBOW数据样例(前三个)
print("CBOW数据样例(未编码):", cbow_data[:3])

3. CBOW数据进行One-Hot编码

# 定义One-Hot编码函数
import torch # 导入torch库
def one_hot_encoding(word, word_to_idx):
    # 创建一个全为0的张量,长度与词汇表大小相同
    tensor = torch.zeros(len(word_to_idx))  
    tensor[word_to_idx[word]] = 1  # 将对应词汇的索引位置置为1
    return tensor  # 返回生成的One-Hot向量

# 展示One-Hot编码前后的数据
word_example = "Teacher"
print("One-Hot编码前的单词:", word_example)
print("One-Hot编码后的向量:", one_hot_encoding(word_example, word_to_idx))

# 展示编码后的CBOW数据样例
# 展示编码后的CBOW数据样例
print("CBOW数据样例(已编码):", [(one_hot_encoding(target, word_to_idx), 
                          [one_hot_encoding(context, word_to_idx) for context in context_words]) 
                         for target, context_words in cbow_data[:3]])

4. 定义CBOW模型

# 定义CBOW模型
import torch.nn as nn # 导入neural network# 定义CBOW模型
class CBOW(nn.Module):
    def __init__(self, voc_size, embedding_size):
        super(CBOW, self).__init__()
        # 从词汇表大小到嵌入大小的线性层(权重矩阵)
        self.input_to_hidden = nn.Linear(voc_size, 
                                         embedding_size, bias=False)  
        # 从嵌入大小到词汇表大小的线性层(权重矩阵)
        self.hidden_to_output = nn.Linear(embedding_size, 
                                          voc_size, bias=False)  

    def forward(self, X): # X: [num_context_words, voc_size]
        
        # 生成嵌入:[num_context_words, embedding_size]
        embeddings = self.input_to_hidden(X)  
        # 计算隐藏层,求嵌入的均值:[embedding_size]
        hidden_layer = torch.mean(embeddings, dim=0)  
        # 生成输出层:[1, voc_size]
        output_layer = self.hidden_to_output(hidden_layer.unsqueeze(0)) 
        return output_layer
    
embedding_size = 2 # 设定嵌入层的大小,这里选择2是为了方便展示
cbow_model = CBOW(voc_size,embedding_size)  # 实例化cbow模型
print("CBOW模型:", cbow_model)

5. 训练CBOW模型

# 训练CBOW模型
learning_rate = 0.001 # 设置学习速率
epochs = 1000 # 设置训练轮次
criterion = nn.CrossEntropyLoss()  # 定义交叉熵损失函数
import torch.optim as optim # 导入随机梯度下降优化器
optimizer = optim.SGD(cbow_model.parameters(), lr=learning_rate)  

# 开始训练循环
loss_values = []  # 用于存储每轮的平均损失值
for epoch in range(epochs):
    loss_sum = 0
    for target, context_words in cbow_data:
        # 将上下文词转换为One-hot向量并堆叠
        X = torch.stack([one_hot_encoding(word, word_to_idx) for word in context_words]).float() 
        y_true = torch.tensor([word_to_idx[target]], dtype=torch.long)  # 将目标词转换为索引值
        y_pred = cbow_model(X)  # 计算预测值
        loss = criterion(y_pred, y_true)  # 计算损失
        loss_sum += loss.item()
        optimizer.zero_grad()  # 清空梯度
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
        
    if (epoch+1) % 100 == 0: # 输出每100轮的损失,并记录损失
        print(f"Epoch: {epoch+1}, Loss: {loss_sum/len(cbow_data)}")  
        loss_values.append(loss_sum / len(cbow_data))
# 绘制训练损失曲线
import matplotlib.pyplot as plt # 导入matplotlib
plt.plot(range(1, epochs//100 + 1), loss_values) # 绘图
plt.title('Training Loss') # 图题
plt.xlabel('Epochs') # X轴Label
plt.ylabel('Loss') # Y轴Label
plt.show() # 显示图

6. 输出CBOW词向量

# 输出CBOW习得的词嵌入
print("\nCBOW词嵌入:")
for word, idx in word_to_idx.items(): # 输出每个单词的嵌入向量
    print(f"{word}: \
    {cbow_model.input_to_hidden.weight[:, idx].detach().numpy()}")  
plt.rcParams["font.family"]=['SimHei'] # 用来设定字体样式
plt.rcParams['font.sans-serif']=['SimHei'] # 用来设定无衬线字体样式
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号
# 绘制二维词向量图
fig, ax = plt.subplots() 
for word, idx in word_to_idx.items():
    vec = cbow_model.input_to_hidden.weight[:, \
            idx].detach().numpy() # 获取每个单词的嵌入向量
    ax.scatter(vec[0], vec[1]) # 在图中绘制嵌入向量的点
    ax.annotate(word, (vec[0], vec[1]), fontsize=12) # 点旁添加单词标签
plt.title('2维词嵌入') # 图题
plt.xlabel('向量维度1') # X轴Label
plt.ylabel('向量维度2') # Y轴Label
plt.show() # 显示图

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPF三方UI库全局应用MessageBox样式(.NET6版本)

一、问题场景 使用HandyControl简写HC 作为基础UI组件库时,希望系统中所有的MessageBox 样式都使用HC的MessageBox,常规操作如下: 在对应的xxxx.cs 顶部使用using 指定特定类的命名空间。 using MessageBox HandyControl.Controls.Message…

Elasticseach RestClient Api

Elasticsearch RestclientApi基础用法 查询 索引库 初始化 添加依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>创建链接 package com…

今日分享丨点亮这四个技能,你也可以成为可视化专家

引言 以大数据、人工智能等为代表的新质生产力时代已悄然而至&#xff0c;央企、国企逐步意识到数据资源展示对于经营管理的重要性和紧迫性。数据可视化成为连接用户与数据的桥梁&#xff0c;藉由设计师的巧手&#xff0c;把复杂抽象的数据以基于管理需求&#xff0c;转化为直…

PyTorch -- RNN 快速实践

RNN Layer torch.nn.RNN(input_size,hidden_size,num_layers,batch_first) input_size: 输入的编码维度hidden_size: 隐含层的维数num_layers: 隐含层的层数batch_first: True 指定输入的参数顺序为&#xff1a; x&#xff1a;[batch, seq_len, input_size]h0&#xff1a;[batc…

探究C语言函数栈帧的创建和销毁

引言 在C语言程序中&#xff0c;每当一个函数被调用时&#xff0c;系统都会在栈上为该函数分配一块内存空间&#xff0c;这块内存空间就被称为栈帧。 栈帧中包含了函数执行所需的所有信息&#xff0c;如局部变量、参数、返回地址等。栈帧的创建和销毁是函数调用的核心部分&am…

【华为HCIA数通网络工程师真题-数据通信与网络基础】

文章目录 选择题判断题 选择题 1、在 VRP 平台上&#xff0c;可以通过下面哪种方式访向上条历史命令&#xff1f; 上光标 &#xff08;ctrlU 为自定义快捷键&#xff0c;ctrlP 为显示历史缓存区的前一条命令&#xff0c;左光标为移动光标&#xff09; 2、主机 A &#xff08;1…

TensorRT-常见问题

1、ModelImporter.cpp:779: ERROR: builtin_op_importers.cpp:3608 In function importResize:[8] Assertion failed: scales.is_weights() && "Resize scales must be an initializer!"解决方法&#xff1a;将TensorRT版本升到可以匹配cuda版本的最高版本&a…

多态性(Java)

本篇学习面向对象语言的第三个特性——多态。 目录 1、多态的概念 2、继承多态实现条件 3、重写 4、重新与重载的区别&#xff1a; 5、向上转移和向下转型 5、1向上转型&#xff1a; 5、2 向下转型 1、多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态…

Servlet实践操作

Servlet运行原理 Tomcat 的代码内置了 main 方法&#xff0c;当我们启动 Tomcat 的时候&#xff0c;就是从 Tomcat 的 main 方法开始执行的 被 WebServlet 注解修饰的类会在 Tomcat 启动的时候就被获取并集中管理 Tomcat 通过反射这样的语法机制来创建被 WebServlet 注解修饰…

Day 27:2596. 检查骑士巡视方案

Leetcode 2596. 检查骑士巡视方案 骑士在一张 n x n 的棋盘上巡视。在 **有效 **的巡视方案中&#xff0c;骑士会从棋盘的 左上角 出发&#xff0c;并且访问棋盘上的每个格子 恰好一次 。 给你一个 n x n 的整数矩阵 grid &#xff0c;由范围 [0, n * n - 1] 内的不同整数组成&…

超神级!Markdown最详细教程,程序员的福音

超神级&#xff01;Markdown最详细教程&#xff0c;程序员的福音Markdown最详细教程&#xff0c;关于Markdown的语法和使用就先讲到这里&#xff0c;如果喜欢&#xff0c;请关注“IT技术馆”。馆长会更新​最实用的技术&#xff01;https://mp.weixin.qq.com/s/fNzhLFyYRd3skG-…

linux环境编程基础学习

Shell编程&#xff1a; 相对的chmod -x xx.sh可以移除权限 想获取变量的值要掏点dollar&#xff08;&#xff04;&#xff09; 多位的话要加个花括号 运算&#xff1a;expr 运算时左右两边必须要加空格 *号多个含义必须加转义符 双引号可以加反单&#xff0c;但是发过来就不行 …

containerd手动配置容器网络

containerd手动配置容器网络 机器详情nerdctl启动一个不带网络的容器获取容器ID、PID与network namespace路径准备bridge插件的执行配置文件通过下面的命令调用bridge插件准备tuning插件文件执行下面的命令调用tuning插件准备portmap插件文件执行下面的命令调用portmap插件删除…

算法竞赛数论杂题

menji 和 gcd 题目&#xff1a; 一开始以为是只有l不确定&#xff0c;r是确定的&#xff0c;这样的话我们可以枚举r的所有约数&#xff0c;然后对其每个约数x进行判断&#xff0c;判断是否满足题意&#xff0c;具体做法是先让l % x如果 0则该约数可行&#xff0c;如果不可行…

文件扫描工具都有哪些?职场大佬都在用的文本提取工具大盘点~

回想起刚毕业初入职场那阵子&#xff0c;领导让帮忙把纸质文件扫描提取为文本时&#xff0c;还只会傻乎乎地一点点操作&#xff0c;属实是费劲得很&#xff01; 好在后面受朋友安利&#xff0c;找到了4个能够快速实现文件扫描文字提取的方法&#xff0c;这才让我的办公效率蹭蹭…

[SCAU 课程设计参考] 活动管理程序

(仅供参考!!!!!!) 废话不多说&#xff0c;直接上代码&#xff01;(但是量有点多&#xff0c;放前面影响观感&#xff0c;所以还是先不放了&#xff0c;文章末尾有链接) 题目的要求: 提要:我的设计只是一个参考&#xff0c;当时还是大一的时候写的&#xff0c;代码比较青涩&a…

[学习笔记]-MyBatis-Plus简介

简介 Mybatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 简言之就是对单表的增删改查有了很好的封装。基本不用再单独写sql语句了。目前此类…

微博舆情分析系统可以继续完善的基于python 前端vue

微博舆情分析系统可以继续完善的&#xff0c;前后端分离&#xff0c;前端基于vue 后端基于python的flask可以说是非常的简洁&#xff0c;支持实时更新数据。界面如图 主要工作点体现在后端实时更新数据跟数据的处理方面上&#xff0c;后续有空会用hadoop来处理海量数据真…

数据库 | 试卷四

1.数据库系统的特点是 数据共享、减少数据冗余、数据独立、避免了数据不一致和加强了数据保护 2.关系模型的数据结构是二维表结构 3.聚簇索引 cluster index 4. 这里B&#xff0c;C都是主属性&#xff0c;所以B->C不是非主属性对码的部分函数依赖 候选键&#xff08;AC&a…

Jlink下载固件到RAM区

Jlink下载固件到RAM区 准备批处理搜索exe批处理调用jlink批处理准备jlink脚本 调用执行 环境&#xff1a;J-Flash V7.96g 平台&#xff1a;arm cortex-m3 准备批处理 搜索exe批处理 find_file.bat echo off:: 自动识别脚本名和路径 set "SCRIPT_DIR%~dp0" set &qu…