如何通过Gensim实现基于固定窗口的计数型共现词嵌入?
Gensim中实现固定窗口计数型共现词嵌入
Gensim并没有提供开箱即用的固定窗口二元词频共现模型,但可以利用它的基础工具链快速实现这类计数型词嵌入,适配超大规模语料的处理需求,具体步骤如下:
1. 语料预处理
先用Gensim的轻量工具完成分词与清洗,通过迭代式加载避免一次性占用过多内存:
from gensim.utils import simple_preprocess def iter_corpus(file_path): """迭代式读取超大语料文件""" with open(file_path, 'r', encoding='utf-8') as f: for line in f: yield simple_preprocess(line, deacc=True)
2. 构建词汇表与共现矩阵
针对超大语料,用稀疏方式统计固定窗口内的词共现,降低内存消耗:
from collections import defaultdict from gensim.corpora import Dictionary # 生成词汇表,可过滤低频词减少计算量 corpus_iter = iter_corpus("your_large_corpus.txt") vocab = Dictionary(corpus_iter) vocab.filter_extremes(no_below=5) # 过滤出现次数少于5次的词 word2id = vocab.token2id vocab_size = len(vocab) # 初始化共现计数器(用键值对存储稀疏共现) cooccur_counts = defaultdict(int) window_size = 5 # 自定义上下文窗口大小 # 重新遍历语料统计共现 corpus_iter = iter_corpus("your_large_corpus.txt") for sentence in corpus_iter: sent_ids = [word2id[word] for word in sentence if word in word2id] for idx, target_id in enumerate(sent_ids): # 确定当前词的上下文窗口范围 window_start = max(0, idx - window_size) window_end = min(len(sent_ids), idx + window_size + 1) # 遍历上下文词并统计共现(用sorted避免重复计数双向对) for context_id in sent_ids[window_start:idx] + sent_ids[idx+1:window_end]: pair = tuple(sorted((target_id, context_id))) cooccur_counts[pair] += 1
3. 转换为优化后的词嵌入(PPMI)
原始共现矩阵存在高频词偏差,通常转为**正点互信息(PPMI)**作为最终嵌入,提升效果:
import numpy as np from scipy.sparse import csr_matrix # 统计全局词频 corpus_iter = iter_corpus("your_large_corpus.txt") word_freq = np.zeros(vocab_size, dtype=np.int64) for sentence in corpus_iter: for word in sentence: if word in word2id: word_freq[word2id[word]] += 1 total_words = word_freq.sum() # 构建稀疏PPMI矩阵 rows, cols, data = [], [], [] for (i, j), cnt in cooccur_counts.items(): # 计算PMI并取正值得到PPMI pmi = np.log2((cnt * total_words) / (word_freq[i] * word_freq[j])) ppmi = max(pmi, 0.0) if ppmi > 0: rows.extend([i, j]) cols.extend([j, i]) data.extend([ppmi, ppmi]) ppmi_sparse = csr_matrix((data, (rows, cols)), shape=(vocab_size, vocab_size)) # 生成词嵌入字典,每个词对应其PPMI向量 word_embeddings = {vocab[id]: ppmi_sparse[id].toarray().flatten() for id in range(vocab_size)}
4. 持久化与加载
用Gensim的KeyedVectors存储嵌入,方便后续快速调用:
from gensim.models import KeyedVectors # 初始化KeyedVectors并添加向量 kv = KeyedVectors(vector_size=vocab_size) kv.add_vectors([vocab[id] for id in range(vocab_size)], ppmi_sparse.toarray()) # 保存到本地 kv.save("count_based_embeddings.kv") # 加载使用 loaded_emb = KeyedVectors.load("count_based_embeddings.kv") print(loaded_emb["sample_word"])
超大语料适配建议
- 始终用迭代式方式处理语料,避免一次性读入内存;
- 全程使用稀疏矩阵存储共现与PPMI数据;
- 可对语料进行分块处理,逐步累加共现计数,进一步降低内存压力。
内容的提问来源于stack exchange,提问作者la_lo_ca
相关产品推荐
相关产品推荐

