吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2324|回复: 6
收起左侧

[Python 转载] 基于pytorch 自己训练文本词向量

[复制链接]
ljl9090 发表于 2021-9-30 17:55
如今的NLP自然语言处理,大多以及抛弃TF-IDF词频逆文档处理模型,而是通过训练word2vec词向量模型;
目前开源的词向量模型数据集公认较好的是腾讯词向量,不过该数据集超过16G,一般配置可能都无法打开使用,
因此可以根据实际需求自行训练需要的词向量模型,这里提供一种训练词向量的一个实例,不过语料库一定要多,效果更好。
结果图片如下:

词向量结果(此处选择5维,一般为300维)
大王==>[-1.1550105810165405, -2.516174077987671, -4.601747035980225, 5.313472270965576, -2.1049396991729736]
罪名==>[1.0574508905410767, -0.9783875346183777, 0.11272682249546051, 7.612886905670166, -1.8402687311172485]
女魔头==>[1.8196024894714355, 1.9293181896209717, -7.641926288604736, -0.9055428504943848, -0.0346614345908165]
以怨==>[-0.009275288321077824, -1.6428550481796265, 1.7217854261398315, 3.149597644805908, -0.4327169954776764]
良苦==>[1.7958626747131348, 0.6769101023674011, -0.739103376865387, 0.684821367263794, 0.908489465713501]
扇求==>[-0.5084913372993469, -5.254477024078369, -4.2640275955200195, -3.659550666809082, -2.7392685413360596]
大理==>[-1.827543020248413, 2.1979267597198486, 1.2208789587020874, 3.172173261642456, -0.9367401599884033]
并立==>[-1.6337153911590576, 4.030898571014404, 2.178544044494629, 3.914534568786621, -0.7697797417640686]
穿帘==>[1.7714473009109497, -4.029304027557373, 0.5541706085205078, 0.3680380880832672, -8.209785461425781]
云南==>[1.742133378982544, 0.08090668171644211, -1.776845932006836, -4.484336853027344, -3.677159070968628]
天龙八部==>[0.36176109313964844, 5.17064094543457, -0.059911321848630905, 0.32547205686569214, 2.093536853790283]
文斗==>[-2.192509651184082, 0.4625106155872345, 1.490928053855896, -1.5388060808181763, -3.8620612621307373]
普通==>[-0.038421038538217545, 1.416630744934082, -1.1946618556976318, 2.9260082244873047, 5.175168037414551]

代码:

import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as Data
import jieba
dtype = torch.FloatTensor
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
np.random.seed(123)

1.初步整理训练数据 ()

注:语料库尽可能的大,尽可能包含实验或者项目的所有文档,对话,等各种文本资料(此处主要体现训练的过程,以及设备的限制(gpu:GTX1060))

docments = ["重庆工商大学统计学院重庆理工大学",
"山村赘婿李子安偶得西周方士传承,大惰随身炉傍身,医、卜、星、相样样精通,要风得龙卷,要雨发大水。软饭也是饭,但得讲究个吃法。李子安吃软饭,那姿势讲究可就大了",
"私生子文斗奸臣,武斗胡人。内忧外患的双重打击,让南宋大厦摇摇欲坠",
"买哪里看小说免费上万能的淘宝!优享品质,惊喜价格!",
"《天龙八部》一书以北宋、辽、西夏、大理并立的历史为宏大背景,将儒释道、琴棋书画等中国传统文化融会贯通其中,书中人物繁多,个性鲜明,情节离奇,尽显芸芸众生百态。丐帮帮主乔峰与大理国王子段誉、少林弟子虚竹结为兄弟。他身为大宋武林第一大帮帮主,发现自己竟是契丹人,虽受尽中原武林人士唾弃而不肯以怨报怨;他身为辽国南院大王,却甘愿背上叛族罪名,最终以悲壮的自杀来阻止辽国发兵攻宋,不愧为顶天立地的大英雄",
"这是金庸先生最后一部武侠小说,也是登峰造极之作!小说讲的是一个从小在扬州妓院长大的小孩韦小宝,他以不会任何武功之姿态闯江湖各大帮会、周旋皇帝朝臣之间并奉旨远征云南、俄罗斯之故事,书中充满精彩绝倒的对白及逆思考的事件!金庸先生将韦小宝的个人经历与历史密密切合,大玩历史哈哈镜的手法,令人赞叹,几乎信以为真,而小宝的做人方法及毫不留情的揭出人生各阶层黑暗面这种做法,使得这部书成了不是武侠小说的武侠小说,到了无剑胜有剑的境地。韦小宝是个最最普通的人,好像也就是在你我身边的那些人一样。",
"连夕阳照进来,都变成一种不吉祥的死灰色",
"《云海玉弓缘》是梁氏武侠天山系列最出名的两部小说之一(另一部是《白发魔女传》),故事发生在清朝中期。主要是厉胜男向魔头孟神通复仇并借此成为另一个“女魔头”的故事",
"灯火阑珊,暗香浮动,伊人何处?露白葭苍,曾是旧时行路。清梦已随潮咽尽,怅望家山云树。恨鸿爪还留,盟鸥非旧,又西飞去。记宝扇求诗,香巾索字,见笑当年崔护。燕子穿帘,早入王堂谢户。凌波微步姗姗远,肠断江郎别浦。怕桃叶桃根,他年重见,此心良苦",
]
word_cuts = jieba.lcut(" ".join(docments))

停用词处理 (根据需求整理停用词)

stop_lst = [u'的',u'\u3000',r'“',r'”',u'…',u'!',u'?',u':',u'\n',u',',"还","看",";",";", "但","让","个","也","要","安","星",u'随着', u'对于', u'对',u'等',u'。',' ',u' ',u'、',u'?',u'在',u'了',"我","你","他","她","它"]
word_sequence = [word for word in word_cuts if word not in stop_lst]
vocab = list(set(word_sequence))
word2idx = {w:i for i,w in enumerate(vocab) if w}

2.参数设置

epochs = 200  #根据训练的实际情况自行调整
batch_size = 16
embedding_size = 5  # 每次词语5维向量表示 (可以自行设置,通常工业界设置为300维,或150维)
C = 2 # 前后几个词语预测
voc_size = len(vocab) #词向量大小(即词语总数)

3.通过skip 模型 整理训练数据

skip_grams: [[c1,w11],[c1,w12],[c1,w13],[c1,w14],[c2,w21],...]

skip_grams = []
for idx in range(C, len(word_sequence) - C):
center = word2idx[word_sequence[idx]] # center word
context_idx = list(range(idx - C, idx)) + list(range(idx + 1, idx + C + 1)) # context word idx
context = [word2idx[word_sequence[i]] for i in context_idx]
for w in context:
skip_grams.append([center, w])

print(skip_grams[:2])

def make_data(skip_grams):
input_data = []
output_data = []
for i in range(len(skip_grams)):
input_data.append(np.eye(voc_size)[skip_grams[i][0]]) # central word
output_data.append(skip_grams[i][1]) # background word
return input_data, output_data

4.整理最终需要训练的数据

input_data, output_data = make_data(skip_grams)
input_data, output_data = torch.Tensor(input_data), torch.LongTensor(output_data)
dataset = Data.TensorDataset(input_data, output_data)
loader = Data.DataLoader(dataset, batch_size, True)

5.构建网络结构 Model
class Word2Vec(nn.Module):
def init(self):
super(Word2Vec, self).init()

    # W and V is not Traspose relationship
    self.W = nn.Parameter(torch.randn(voc_size, embedding_size).type(dtype))
    self.V = nn.Parameter(torch.randn(embedding_size, voc_size).type(dtype))

def forward(self, X):
    # X : [batch_size, voc_size] one-hot
    # torch.mm only for 2 dim matrix, but torch.matmul can use to any dim
    hidden_layer = torch.matmul(X, self.W) # hidden_layer : [batch_size, embedding_size]
    output_layer = torch.matmul(hidden_layer, self.V) # output_layer : [batch_size, voc_size]
    return output_layer

model = Word2Vec().to(device)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = optim.Adam(model.parameters(), lr=1e-3)

6.正式训练

for epoch in range(epochs):
for i, (batch_x, batch_y) in enumerate(loader):
batch_x = batch_x.to(device)
batch_y = batch_y.to(device)

print('batch_x:',batch_x)

    #print('batch_y:',batch_y)
    pred = model(batch_x)
    loss = criterion(pred, batch_y)
    if (epoch + 1) % 100 == 0:
        print(epoch + 1, i, loss.item())

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

7.可视化展示,直观查看训练结果 (可选步骤,训练数据太大,图中效果不明显)

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(10,8))
for i, label in enumerate(vocab):
W, WT = model.parameters()
x,y = float(W[i][1]), float(W[i][2])
plt.scatter(x, y)
plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
if i > 50:
break
plt.show()

查询训练结果  len(docments)* embedding_size

W, WT = model.parameters()
word_vec = {voc:w for voc,w in zip(vocab,W.tolist())}
for name,words in word_vec.items():
print("{}==>{}".format(name,words))

免费评分

参与人数 1热心值 +1 收起 理由
netspirit + 1 鼓励转贴优秀软件安全工具和文档!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zyy22664488 发表于 2021-9-30 20:06
感谢分享
苏晓宇c 发表于 2021-9-30 20:26
现在做词向量不是都用BERT、Transformer....之类的吗
chunhwa 发表于 2021-9-30 22:51
HumorsMrLin 发表于 2021-10-1 00:05
感谢分享学习经历
 楼主| ljl9090 发表于 2021-10-1 17:25
苏晓宇c 发表于 2021-9-30 20:26
现在做词向量不是都用BERT、Transformer....之类的吗

主要BERT,Transformer尤其GPT2,GPT3出现后,个人机器基本无法跑,(当然Bert,Transformer目前应用都是微调)
当然如果你能跑腾讯的词向量了, 你的算力也可以做很多事情了;
主要考虑个人机器可以玩一玩
SUYULIN96 发表于 2021-10-2 06:10
感谢分享学习一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 11:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表