本文用python寻找英文近义词(中文:https://github.com/huyingxi/Synonyms)
使用的都是预训练模型
方法一、nltk+20newsbydate
(运行时下载太慢/失败见下文)
from sklearn.datasets import fetch_20newsgroups
from bs4 import BeautifulSoup
from gensim.models import word2vec
import numpy
import nltk
import re
import os
if os.path.exists(r'sentences.npy'):
# 将预处理后的"词库"从文件中读出,便于调试
numpy_array = numpy.load('sentences.npy', allow_pickle=True)
sentences = numpy_array.tolist()
else:
news = fetch_20newsgroups(subset='all')
X, y = news.data, news.target
print("OK")
# 把段落分解成由句子组成的list(每个句子又被分解成词语)
def news_to_sentences(news):
news_text = BeautifulSoup(news, 'lxml').get_text()
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
raw_sentences = tokenizer.tokenize(news_text)
# 对每个句子进行处理,分解成词语
sentences = []
for sent in raw_sentences:
sentences.append(re.sub('[^a-zA-Z]', ' ', sent.lower().strip()).split())
return sentences
sentences = []
for x in X:
sentences += news_to_sentences(x)
# 将预处理过的"词库"保存到文件中,便于调试
numpy_array = numpy.array(sentences)
numpy.save('sentences.npy', numpy_array)
if os.path.exists(r'word2vec.model'):
model = word2vec.Word2Vec.load('word2vec.model')
else:
num_features = 300
min_word_count = 20
num_workers = 2
context = 5
downsampling = 1e-3
model = word2vec.Word2Vec(sentences, workers=num_workers, size=num_features, min_count=min_word_count,
window=context, sample=downsampling)
model.init_sims(replace=True) # 模型锁定,可以提高模型和后续任务的速度,同时也使得模型不能训练了,read only
model.save('word2vec.model') # 保存模型
# 保存word2vec训练参数便于调试
# model.wv.save_word2vec_format('word2vec_model.bin', binary=True)
# model.wv.load_word2vec_format('word2vec_model.bin', binary=True)
print('词语相似度计算:')
print('morning vs morning:')
print(model.wv.n_similarity('morning', 'morning'))
print('morning vs afternoon:')
print(model.wv.n_similarity('morning', 'afternoon'))
print('morning vs hello:')
print(model.wv.n_similarity('morning', 'hellow'))
print('morning vs shell:')
print(model.wv.n_similarity('morning', 'shell'))
"""
词语相似度计算:
morning vs morning:
1.0
morning vs afternoon:
0.871482091583
morning vs hello:
0.731609166442
morning vs shell:
0.709714434122
"""
print(model.wv.most_similar('sum'))
"""
[('crop', 0.5935108661651611),
('rapid', 0.5862394571304321),
('edges', 0.571550726890564),
('size', 0.5690909028053284),
('acceleration', 0.5680683851242065),
('chopped', 0.5644211769104004),
('depth', 0.5643296837806702),
('chunk', 0.5604238510131836),
('ratio', 0.5565502047538757),
('tube', 0.55369633436203)]
"""
# 以上是用 20newsbydate 和 nltk 的模型,效果很一般
- nltk 的使用:
官网 http://www.nltk.org/data.html
使用官方的 nltk.download() 很慢,可以使用离线下载安装数据
离线下载:
github https://github.com/nltk/nltk_data
百度云 https://pan.baidu.com/s/17ZgkoQeMosWwHNlUvXvTdw 密码:lxmh
下载下来的文件夹包括 chunkers, grammars, misc, sentiment, taggers, corpora, help, models, stemmers, tokenizers 十个文件夹
在以下目录创建文件夹 nltk_data (以下为默认文件夹,可以装在 nltk.download() 时出现的那些文件夹中的任何一个)
windows C:\nltk_data
mac /usr/local/share/nltk_data
Unix /usr/share/nltk_data
把下载好的文件放到 nltk_data 中即可
- 20newsbydate 数据集的下载
https://ndownloader.figshare.com/files/5975967 (14 MB)
在报错中点击或者在文件夹中找到
../anaconda3/lib/python3.7/site-packages/sklearn/datasets/twenty_newsgroups.py
找到 _download_20newsgroups 函数,把开头部分改成如下
def _download_20newsgroups(target_dir, cache_path):
"""Download the 20 newsgroups data and stored it as a zipped pickle."""
train_path = os.path.join(target_dir, TRAIN_FOLDER)
test_path = os.path.join(target_dir, TEST_FOLDER)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
"""
logger.info("Downloading dataset from %s (14 MB)", ARCHIVE.url)
archive_path = _fetch_remote(ARCHIVE, dirname=target_dir)
"""
archive_path = r'你的下载文件路径' # /Users/a123/scikit_learn_data/20news_home/20news-bydate.tar.gz
logger.debug("Decompressing %s", archive_path)
tarfile.open(archive_path, "r:gz").extractall(path=target_dir)
os.remove(archive_path)
.....
由于使用的数据较小,模型效果一般,有些完全就是字符串匹配,长得像的相似度就高
方法二、gensim glove 转 word2vec 加载预训练模型
glove 和 word2vec 是两个很好的把词语用向量表示的库
在 https://github.com/RaRe-Technologies/gensim-data 有更多预训练模型
在 Model 那里,各种大小都有
这里我使用的是 https://nlp.stanford.edu/projects/glove/ 中的 glove.6B.zip,迅雷下了半个小时
以下代码来自https://radimrehurek.com/gensim/scripts/glove2word2vec.html
要使用的库
from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
from gensim.scripts.glove2word2vec import glove2word2vec
在命令行下看看 tmp_file 的值,就是转换后文件的存放位置
glove_file = datapath('/你的下载路径/glove.6B.300d.txt')
# 输出文件
tmp_file = get_tmpfile("word2vec_300d.txt")
# 这里的 tmp_file 是一个字符串,是存放转换文件的路径
# 转换完成后就来这里找转换后的txt文件
开始转换
# 开始转换
print(glove2word2vec(glove_file, tmp_file))
# 打印出来是(400000, 300)
转换完成后,就可以只用转换后文件用 word2vec 加载模型
其中的 tmp_file 可以是你自己的存放了转换后文件的位置
# 转换的文件就是在glove下载的txt这个文件的最开头,加上两个数
# 第一个数指明一共有多少个向量,第二个数指明每个向量有多少维,就能直接用word2vec的load函数加载了
model = KeyedVectors.load_word2vec_format(tmp_file)
到此就已经完成模型的加载了,试一下效果
查找两个词语之间的相似度
model.similarity('dog','cat')
Out[71]: 0.68167466
model.similarity('cut','cat')
Out[72]: 0.082896836
model.similarity('people','person')
Out[73]: 0.5712259
model.similarity('people','apple')
Out[74]: 0.14102192
查找一个词的近义词
model.most_similar('funny')
Out[69]:
[('hilarious', 0.7324165105819702),
('amusing', 0.6964851021766663),
('witty', 0.6262085437774658),
('humorous', 0.6112722754478455),
('fun', 0.6088972091674805),
('laugh', 0.6085041761398315),
('humor', 0.6043205261230469),
('wonderfully', 0.6033899784088135),
('silly', 0.6012822389602661),
('joke', 0.588691771030426)]
在给定的列表中找指定词最相近的词语
model.most_similar_to_given('funny', ['interesting', 'dog', 'such'])
Out[66]: 'interesting'
效果还不错
模型的保存与加载(保存成model会比较大,但是读起来快)
model.save('glove2word2vev.model')
model = KeyedVectors.load('glove2word2vev.model')
关于其他保存形式和更多word2vec的方法可以看
https://blog.youkuaiyun.com/HUSTHY/article/details/103164934