自然语言处理之新闻分类(五)使用gensim训练词向量

本文深入解析gensim库中的Word2Vec模型,涵盖模型原理、参数设置及应用场景。gensim封装了如tf-idf、Word2Vec、doc2vec等模型,Word2Vec通过CBOW和Skip-Gram两种方法训练词向量,可用于计算词间相似度及预测词义关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

gensim的介绍

在自然语言处理中,应该都听过gensim。gensim中封装了包括了tf-idf,Word2Vec , doc2vec等模型,Word2Vec 采用了CBOW(Continuous Bag-Of-Words,连续词袋模型)和Skip-Gram两种方法。
其实使用gensim中的Word2Vec 思想很简单,就是使用大量已分词的文本作为输入,然后用一个稠密向量来表示每个词作为映射的输出。
我们这里假设每一个词的向量长度为300,一共有10000个词,那么其中的矩阵就是[10000 ,300]的矩阵。这个矩阵就是来表示词向量。

Word2Vec 词向量的前期准备

在进行训练前,我们需要先准备用来训练的数据,比方说进行切词处理,大小写转换等,这里面可以会删去一些停用词。然后就可以利用这一些数据进行转换,最后来获取我们前面所说的计算机所能够接收的词向量。并且在后续对其做一些简单的操作,比如:

model['python']  

然后我们可以计算一下两个词之间的余弦距离

model.similarity('woman', 'king')

也可以计算余弦距离最接近“word”的10个词,或topn个词

model.most_similar("word")
model.similar_by_word('贪污', topn =100) 最接近的100个词

除了计算两个词之间的相似度,也可以计算不同集合之间的相似度。但是要注意,当出现某个词语不在这个训练集合中的时候,会报错

list_sim1 =  model.n_similarity(list1, list2)

训练模型

在我们使用gensim.models.Word2Vec(sentences)建立词向量模型了之后,就相当于遍历完一次语料库并建立词典,以及搭建好了一个空模型架构;当输入了数据之后进行训练、保存,我们就可以得出模型来预测了。
这里使用Word2Vec 实际是会对数据进行两次迭代。第一次是为了构建模型的结构,之后第二次迭代则是为了后面的训练。

gensim训练时的参数设置

gensim中的每个参数都会影响训练的速度和精度。
1.sentences 第一个参数是预处理后的训练语料库。是可迭代列表,但是对于较大的语料库,可以考虑直接从磁盘/网络传输句子的迭代。
2.sg=1是skip-gram算法,对低频词敏感;默认sg=0为CBOW算法。
size(int) 是输出词向量的维数,默认值是100。这个维度的取值与我们的语料的大小相关,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。值太小会导致词映射因为冲突而影响结果,值太大则会耗内存并使算法计算变慢,一般值取为100到200之间,不过见的比较多的也有300维的。
3.window(int)是一个句子中当前单词和预测单词之间的最大距离,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。windows越大所需要枚举的预测此越多,计算的时间越长。
4.min_count 忽略所有频率低于此值的单词。默认值为5。
5.workers表示训练词向量时使用的线程数,默认是当前运行机器的处理器核数。

训练完毕,我们保存完模型之后就可以用来进行模型的预测了:

model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)
[('queen', 0.50882536)]
model.doesnt_match("breakfast cereal dinner lunch";.split())
'cereal'
model.similarity('woman', 'man')
0.73723527
model.most_similar(['man'])
'''
[(u'woman', 0.5686948895454407),
 (u'girl', 0.4957364797592163),
 (u'young', 0.4457539916038513),
 (u'luckiest', 0.4420626759529114),
 (u'serpent', 0.42716869711875916),
 (u'girls', 0.42680859565734863),
 (u'smokes', 0.4265017509460449),
 (u'creature', 0.4227582812309265),
 (u'robot', 0.417464017868042),
 (u'mortal', 0.41728296875953674)]
 '''

但是,需要强调的是,训练集上表现的好也不意味着 Word2Vec 在真实应用中就会表现的很好,还是需要观看应用场景的。

最后附上代码

import logging
import random
import numpy as np
import torch
import pandas as pd
from gensim.models.word2vec import Word2Vec


logging.basicConfig(level=logging.INFO, format='%(asctime)-15s %(levelname)s: %(message)s')

seed = 777
random.seed(seed)
np.random.seed(seed)
torch.cuda.manual_seed(seed)
torch.manual_seed(seed)

fold_num = 10
data_file = 'train_set.csv'

def all_data2fold(fold_num, num=10000):
    fold_data = []
    f = pd.read_csv(data_file, sep='\t', encoding='UTF-8')
    texts = f['text'].tolist()[:num]
    labels = f['label'].tolist()[:num]

    total = len(labels)

    index = list(range(total))
    np.random.shuffle(index)

    all_texts = []
    all_labels = []
    for i in index:
        all_texts.append(texts[i])
        all_labels.append(labels[i])

    label2id = {}
    for i in range(total):
        label = str(all_labels[i])
        if label not in label2id:
            label2id[label] = [i]
        else:
            label2id[label].append(i)

    all_index = [[] for _ in range(fold_num)]
    for label, data in label2id.items():
        # print(label, len(data))
        batch_size = int(len(data) / fold_num)
        other = len(data) - batch_size * fold_num
        for i in range(fold_num):
            cur_batch_size = batch_size + 1 if i < other else batch_size
            # print(cur_batch_size)
            batch_data = [data[i * batch_size + b] for b in range(cur_batch_size)]
            all_index[i].extend(batch_data)

    batch_size = int(total / fold_num)
    other_texts = []
    other_labels = []
    other_num = 0
    start = 0
    for fold in range(fold_num):
        num = len(all_index[fold])
        texts = [all_texts[i] for i in all_index[fold]]
        labels = [all_labels[i] for i in all_index[fold]]

        if num > batch_size:
            fold_texts = texts[:batch_size]
            other_texts.extend(texts[batch_size:])
            fold_labels = labels[:batch_size]
            other_labels.extend(labels[batch_size:])
            other_num += num - batch_size
        elif num < batch_size:
            end = start + batch_size - num
            fold_texts = texts + other_texts[start: end]
            fold_labels = labels + other_labels[start: end]
            start = end
        else:
            fold_texts = texts
            fold_labels = labels

        assert batch_size == len(fold_labels)
        index = list(range(batch_size))
        np.random.shuffle(index)

        shuffle_fold_texts = []
        shuffle_fold_labels = []
        for i in index:
            shuffle_fold_texts.append(fold_texts[i])
            shuffle_fold_labels.append(fold_labels[i])

        data = {'label': shuffle_fold_labels, 'text': shuffle_fold_texts}
        fold_data.append(data)

    logging.info("Fold lens %s", str([len(data['label']) for data in fold_data]))

    return fold_data


fold_data = all_data2fold(10)
fold_id = 9

train_texts = []
for i in range(0, fold_id):
    data = fold_data[i]
    train_texts.extend(data['text'])

logging.info('Total %d docs.' % len(train_texts))
logging.info('Start training...')

num_features = 100
num_workers = 8

train_texts = list(map(lambda x: list(x.split()), train_texts))
model = Word2Vec(train_texts, workers=num_workers, size=num_features)
model.init_sims(replace=True)

model.save("./word2vec.bin")
model = Word2Vec.load("./word2vec.bin")
model.wv.save_word2vec_format('./word2vec.txt', binary=False)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值