介绍词向量word2evc概念,及CBOW和Skip-gram的算法实现( 五 )


corpus=f.read().strip("n")
f.close()
returncorpus
corpus=load_text8()
#打印前500个字符 , 简要看一下这个语料的样子
print(corpus[:500])
#对语料进行预处理(分词)
defdata_preprocess(corpus):
#由于英文单词出现在句首的时候经常要大写 , 所以我们把所有英文字符都转换为小写 ,
#以便对语料进行归一化处理(Applevsapple等)
corpus=corpus.strip().lower()
corpus=corpus.split("")
returncorpus
corpus=data_preprocess(corpus)
print(corpus[:50])
在经过切词后 , 需要对语料进行统计 , 为每个词构造ID 。 一般来说 , 可以根据每个词在语料中出现的频次构造ID , 频次越高 , ID越小 , 便于对词典进行管理 。 代码如下:
defbuild_dict(corpus):
#首先统计每个不同词的频率(出现的次数) , 使用一个词典记录
word_freq_dict=dict()
forwordincorpus:
ifwordnotinword_freq_dict:
word_freq_dict[word]=0
word_freq_dict[word]+=1
#将这个词典中的词 , 按照出现次数排序 , 出现次数越高 , 排序越靠前
#一般来说 , 出现频率高的高频词往往是:I , the , you这种代词 , 而出现频率低的词 , 往往是一些名词 , 如:nlp
word_freq_dict=sorted(word_freq_dict.items(),key=lambdax:x[1],reverse=True)
#构造3个不同的词典 , 分别存储 ,
#每个词到id的映射关系:word2id_dict
#每个id出现的频率:word2id_freq
#每个id到词的映射关系:id2word_dict
word2id_dict=dict()
word2id_freq=dict()
id2word_dict=dict()
#按照频率 , 从高到低 , 开始遍历每个单词 , 并为这个单词构造一个独一无二的id
forword,freqinword_freq_dict:
curr_id=len(word2id_dict)
word2id_dict[word]=curr_id
word2id_freq[word2id_dict[word]]=freq
id2word_dict[curr_id]=word
returnword2id_freq,word2id_dict,id2word_dict
word2id_freq,word2id_dict,id2word_dict=build_dict(corpus)
vocab_size=len(word2id_freq)
print("therearetotoally%ddifferentwordsinthecorpus"%vocab_size)
for_,(word,word_id)inzip(range(50),word2id_dict.items()):
print("word%s,itsid%d,itswordfreq%d"%(word,word_id,word2id_freq[word_id]))
得到word2id词典后 , 还需要进一步处理原始语料 , 把每个词替换成对应的ID , 便于神经网络进行处理 , 代码如下:
#
把语料转换为id序列
defconvert_corpus_to_id(corpus,word2id_dict):
#使用一个循环 , 将语料中的每个词替换成对应的id , 以便于神经网络进行处理
corpus=[word2id_dict[word]forwordincorpus]
介绍词向量word2evc概念,及CBOW和Skip-gram的算法实现】returncorpus
corpus=convert_corpus_to_id(corpus,word2id_dict)
print("%dtokensinthecorpus"%len(corpus))
print(corpus[:50])
接下来 , 需要使用二次采样法处理原始文本 。 二次采样法的主要思想是降低高频词在语料中出现的频次 。 方法是将随机将高频的词抛弃 , 频率越高 , 被抛弃的概率就越大;频率越低 , 被抛弃的概率就越小 。 标点符号或冠词这样的高频词就会被抛弃 , 从而优化整个词表的词向量训练效果 , 代码如下:
#
使用二次采样算法(subsampling)处理语料 , 强化训练效果
defsubsampling(corpus,word2id_freq):
#这个discard函数决定了一个词会不会被替换 , 这个函数是具有随机性的 , 每次调用结果不同
#如果一个词的频率很大 , 那么它被遗弃的概率就很大
defdiscard(word_id):
returnrandom.uniform(0,1)<1-math.sqrt(
1e-4/word2id_freq[word_id]*len(corpus))
corpus=[wordforwordincorpusifnotdiscard(word)]
returncorpus
corpus=subsampling(corpus,word2id_freq)