本文内容
- 介绍豆瓣影评数据集
- 构造语料训练 Word2Vec 模型
- 获取数据 cntext2.x & Word2Vec 模型文件
一、豆瓣影评数据集
1.1 数据集介绍
数据集: douba-movie-1000w
数据源: 豆瓣电影
记录数:
- 电影 10269 部
- 影评 10310989 条
体积: 1.35G
该数据集正好弥补下国内公开电影数据集的空缺, 数据已经过初步清洗,可用于推荐系统、情感分析、知识图谱、新闻传播学、社会学文化变迁等多个领域(或主题)。
1.2 读取数据
下载 douba-movie-1000w.zip 解压后,可以看到数据集中有一个 all_movies_with_id.csv 文件。
import pandas as pd
df = pd.read_csv('all_movies_with_id.csv')
df
1.3 所含字段
for col in df.columns:
print(f' - {col}')
Run
- ID
- Movie_Name 电影名
- Score 豆瓣电影评分(1-10)
- Review_People 评论者人数
- Star_Distribution 评论评分分布(1-5, 含多个数值,数值以%间隔)
- Craw_Date 爬虫运行日期
- Username 豆瓣评论者用户名
- Date 影评日期
- Star 影评评分(1-5)
- Comment 影评内容
- Comment_Distribution 影评评分分布
- Like 影评获得的喜欢数
二、 构造语料&训练Word2Vec
2.1 构造语料
将字段 Comment 中所有文本汇总到 douban-movie-1000w.txt,
import pandas as pd
# 读取数据,只读取字段sign
df = pd.read_csv('all_movies_with_id.csv', usecols=['sign'])
# 将sign列中的所有文本汇总到douban-movie-1000w.txt
with open('douban-movie-1000w.txt', 'w', encoding='utf-8') as f:
text = '\n'.join(df['Comment'].fillna(''))
f.write(text)
# 删除df和text变量,释放内存
del df
del text
2.2 配置cntext2.1.6
将 cntext-2.1.6-py3-none-any.whl 放置于桌面,打开 cmd (苹果电脑打开terminal), 输入cd desktop
cd desktop
之后在 cmd (苹果电脑打开terminal) 中使用 pip3 安装
pip3 install cntext-2.1.6-py3-none-any.whl
文末有 cntext-2.1.6-py3-none-any.whl 获取方式
2.3 训练Word2Vec
# cntext为2.1.6
import cntext as ct
# 训练Word2Vec模型
w2v = ct.Word2Vec(corpus_file='douban-movie-1000w.txt',
vector_size=200,
window_size=15,
min_count=5)
Run
Mac(Linux) System, Enable Parallel Processing
Cache output/douban-movie-1000w_cache.txt Not Found or Empty, Preprocessing Corpus
Reading Preprocessed Corpus from output/douban-movie-1000w_cache.txt
Start Training Word2Vec
Word2Vec Training Cost 2965 s.
Output Saved To: output/douban-movie-1000w.200.15.txt
经过半个小时的训练, 得到
- 模型文件 output/douban-movie-1000w-Word2Vec.200.15.txt
- 模型文件 output/douban-movie-1000w-Word2Vec.200.15.bin
- 缓存文件 output/douban-movie-1000w_cache.txt
其中模型文件有 txt 和 bin 两种格式, 信息量完全等同。 txt 可以用记事本打开查看, 而 bin 则是二进制文件, 体积更小。 已训练好的模型, 因 bin 格式体积更小, 便于分享。
2.4 评估模型
使用近义法和类比法, 判断模型的表现。详情可查看文档
ct.evaluate_similarity(w2v_model)
ct.evaluate_analogy(w2v_model)
Run
近义测试: similarity.txt
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/cntext/model/evaluate_data/similarity.txt
评估结果:
+----------+------------+----------------------------+
| 发现词语 | 未发现词语 | Spearman's Rank Coeficient |
+----------+------------+----------------------------+
| 459 | 78 | 0.43 |
+----------+------------+----------------------------+
类比测试: analogy.txt
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/cntext/model/evaluate_data/analogy.txt
Processing Analogy Test: 100%|██████████████| 1198/1198 [00:11<00:00, 99.91it/s]
评估结果:
+--------------------+----------+------------+------------+----------+
| Category | 发现词语 | 未发现词语 | 准确率 (%) | 平均排名 |
+--------------------+----------+------------+------------+----------+
| CapitalOfCountries | 615 | 62 | 39.02 | 2.98 |
| CityInProvince | 175 | 0 | 28.57 | 4.74 |
| FamilyRelationship | 272 | 0 | 92.65 | 1.48 |
| SocialScience | 8 | 62 | 25.00 | 6.00 |
+--------------------+----------+------------+------------+----------+
近义测试: Spearman’s Rank Coeficient系数取值[-1, 1], 取值越大, 说明模型表现越好。
类比测试:
- CapitalOfCountries 豆瓣影评语料在此项表现尚可,可能目前电影库中有一定比例的外国素材。
- CityInProvince 豆瓣影评语料在此项表现较差,不太可能是中国素材太少,可能大多数省市以类似汉东省的形式出现。这是我的猜测。 人民网留言板语料Word2Vec中,该项准确率100%。
- FamilyRelationship 豆瓣影评体现的是电影相关内容,而电影永远的主题是人性, 内容少不了家长里短,七大姑八大姨,所以此项准确率高达92.65%。 以年报MD&A为例,此处准确率只有10%。
- SocialScience 豆瓣影评语料在此项表现一般, 应该是语料中常见的社会科学词语提及较少。
整体而言,语料训练的效果很不错,抓住了数据场景的独特性语义。
四、使用Word2Vec
4.1 导入Word2Vec模型文件
import cntext as ct
# 导入模型,请注意路径。
# 「当前代码」 与 「output」 同处于一个文件夹内
dm_w2v = ct.load_w2v('output/douban-movie-1000w-Word2Vec.200.15.txt')
# dm_w2v = ct.load_w2v('output/douban-movie-1000w-Word2Vec.200.15.bin')
dm_w2v
Run
Loading output/douban-movie-1000w-Word2Vec.200.15.txt...
<gensim.models.keyedvectors.KeyedVectors at 0x314193830>
4.2 KeyedVectors的操作方法(或属性)
方法 | 描述 |
---|---|
KeyedVectors.index_to_key | 获取词汇表中的所有单词。 |
KeyedVectors.key_to_index | 获取单词到索引的映射。 |
KeyedVectors.vector_size | 获取GloVe模型中任意词向量的维度。 |
KeyedVectors.get_vector(word) | 获取给定单词的词向量。 |
KeyedVectors.similar_by_word(word, topn=10) | 获取某词语最相似的10个近义词。 |
KeyedVectors.similar_by_vector(vector, topn=10) | 获取词向量最相似的10个近义词。 |
4.3 查看词表
查看词表所有单词
dm_w2v.index_to_key
Run
['电影',
'一个',
'没有',
'喜欢',
...
'跟着',
'意识',
'态度',
...]
为了方便查看, 这里只展示部分数据。
4.4 词表映射
查看单词到索引的映射
dm_w2v.key_to_index
Run
{'电影': 0,
'一个': 1,
'没有': 2,
...
'跟着': 997,
'意识': 998,
'态度': 999,
...}
4.5 向量维度数
print(f'词表有 {len(dm_w2v.key_to_index)} 个词')
print(f'向量是 {dm_w2v.vector_size} 维')
Run
词表有 426646 个词
向量是 200 维
4.6 获取词向量
dm_w2v.get_vector('给力')
Run
array([-1.24090052e+00, -6.79377019e-01, 1.42518425e+00, -1.46615291e+00,
-9.53197628e-02, 6.50456071e-01, -2.97696137e+00, 2.20916629e+00,
6.12876177e-01, 1.63172066e+00, 4.91760701e-01, -9
......
......
-1.42494082e+00, 2.49131727e+00, -6.27597034e-01, -7.91438043e-01,
-4.54898655e-01, 1.37747681e+00, -4.20672953e-01, -1.53694853e-01,
1.04936564e+00, 2.18786263e+00, -8.07472587e-01, -8.32003877e-02],
dtype=float32)
4.7 近义词
根据词语查看近义词
# 近义词
dm_w2v.similar_by_word('给力', topn=10)
Run
[('相当给力', 0.6180022358894348),
('太给力', 0.6019443273544312),
('带劲', 0.5840415954589844),
('不给力', 0.5774183869361877),
('过瘾', 0.5616626739501953),
('牛叉', 0.553788959980011),
('出彩', 0.5414286851882935),
('精彩', 0.5332293510437012),
('看得过瘾', 0.5250197649002075),
('大赞', 0.5205727219581604)]
根据向量查找最相似的近义词
word_vector = dm_w2v.get_vector('给力')
dm_w2v.similar_by_vector(word_vector, topn=10)
Run
[('给力', 1.0),
('相当给力', 0.6180021166801453),
('太给力', 0.6019443273544312),
('带劲', 0.5840415954589844),
('不给力', 0.5774183869361877),
('过瘾', 0.5616626739501953),
('牛叉', 0.5537890195846558),
('出彩', 0.5414287447929382),
('精彩', 0.5332292914390564),
('看得过瘾', 0.5250197649002075)]
4.8 计算多个词的中心向量
我们可以计算「宇宙」、「飞船」、「战争」的宇宙语义向量(中心向量)。 并试图寻找中心向量 universe_vector 的最相似的10个词。
# 几个词语构建的宇宙语义向量
universe_vector = ct.semantic_centroid(wv=dm_w2v,
words=['宇宙', '飞船', '战争'])
dm_w2v.similar_by_vector(universe_vector, topn=20)
Run
[('宇宙', 0.7568532228469849),
('星系', 0.7090039253234863),
('飞船', 0.7080673575401306),
('人类文明', 0.6973789930343628),
('战舰', 0.6890057325363159),
('母舰', 0.6864359974861145),
('星球', 0.6799622774124146),
('卫星', 0.6799139976501465),
('星际', 0.6789332032203674),
('空间站', 0.6780815124511719),
('地球', 0.6769616603851318),
('外太空', 0.6683873534202576),
('核战', 0.6669113039970398),
('外星飞船', 0.6592534780502319),
('木星', 0.6586896777153015),
('能源', 0.6562989950180054),
('战争', 0.6556441187858582),
('巨兽', 0.6544537544250488),
('月球', 0.6525537967681885),
('一艘', 0.6521110534667969)]
语义捕捉的很准哦。
4.9 概念轴
男性概念向量由多个男性词的向量加总求均值得到,女性概念向量算法类似。当性质或方向明显相反的两个概念向量相减, 得到的新的向量,我们可以称之为概念轴向量Concept Axis。常见的概念轴,
- 尺寸(大, 小)
- 湿度(干燥,潮湿)
- 性别(男, 女)
- 财富(富裕, 贫穷)
- 等
其实任意概念的向量也可看做概念轴,即该概念向量与0向量相减。只不过两组性质方向相反的方式得到的概念轴, 在语义上更稳定。
import cntext as ct
import numpy as np
# 定义词语列表
phy_words = ['游泳', '跑步', '篮球', '羽毛球', '马拉松', '马术', '徒步']
rich_words = [
'富裕', '财富', '金钱', '豪宅', '豪车',
'奢侈品', '投资', '股票', '基金', '黄金',
'钻石', '游艇', '私人飞机', '企业家', '富豪',
'成功', '繁荣', '奢华', '贵族', '高收入'
]
poor_words = [
'贫穷', '贫困', '饥饿', '失业', '低收入',
'简陋', '破旧', '乞丐', '流浪', '欠债',
'破产', '困境', '艰难', '挣扎', '匮乏',
'落后', '无助', '绝望', '赤贫', '温饱'
]
phy_project_on_fortune = ct.sematic_projection(wv = dm_w2v,
words = phy_words,
c_words1 =poor_words,
c_words2 =rich_words)
phy_project_on_fortune
Run
[('跑步', -1.82),
('徒步', -0.82),
('游泳', -0.19),
('羽毛球', 0.57),
('马拉松', 0.62),
('马术', 1.15),
('篮球', 4.0)]
计算结果中, 数值越大越接近于c_words2, 越小越接近于c_words1 。 可以看到在财富概念轴向量上的投影, 篮球不太准,但是其他几项基本上看出运动的贫富性。
4.10 类比 king-man + woman ~ queen
每个词是高维向量空间中的一个点, 两个点可以组成有方向的向量,而向量可以比较方向。这里是推理过程,受限于数据,公式不一定完全成立, 但是思维可以类比。
这两个词相减,按感觉应该得到的是性别方向,雄性->雌性。
gender_direction_1 = vector(man)-vector(woman)
gender_direction_2 = vector(king)-vector(queen)
那两个性别方向应该近似,即 gender_direction_1 约等于 gender_direction_2 ,将其看做等式就得到如下公式:
vector(理应近似queen) = vector(king)-vector(men)+vector(women)
现在我们检查三个语义向量计算出的新的向量是否有与queen相关的语义信息。
def semactic_vector(wv, words):
vector = ct.semantic_centroid(wv=wv,
words=words)
return vector
men_vector = semactic_vector(dm_w2v, ['男', '男孩', '男人', '他', '父亲', '爸爸', '爷爷'])
women_vector = semactic_vector(dm_w2v, ['女', '女孩', '女人', '她', '母亲', '妈妈', '奶奶'])
king_vector = semactic_vector(dm_w2v, ['国王', '皇帝', '帝王', '大帝'])
# 假设 king- queen 约等于 man -woman
# result 近似等于 king - queen + women
result_vector = king_vector - men_vector + women_vector
# 现在检查 result_vector 的语义应该与queen相关
dm_w2v.similar_by_vector(result_vector, topn=20)
Run
[('皇帝', 0.8448051810264587),
('王后', 0.8056979179382324),
('国王', 0.8004385232925415),
('帝王', 0.7693961262702942),
('君主', 0.7663125991821289),
('皇后', 0.7614380717277527),
('太后', 0.7463700175285339),
('妃子', 0.7433678507804871),
('君王', 0.7407413125038147),
('皇子', 0.7380139231681824),
('王位', 0.7319545745849609),
('皇上', 0.7215542197227478),
('登基', 0.7210745215415955),
('大臣', 0.714862048625946),
('伊丽莎白一世', 0.702217698097229),
('王朝', 0.7000151872634888),
('宫女', 0.6997070908546448),
('驾崩', 0.6992778182029724),
('王妃', 0.6981185078620911),
('昏君', 0.6974363923072815)]
可以看到三个语义向量四则运算出的 result_vector 与queen仍具有较高的相关性。
五、获取资料
除了本文介绍的这个 1000w 条影评数据集, 大邓还有2个类似的豆瓣影评数据集,影评记录量 212w和442 w 条。 两个数据集下载链接我都公开,感兴趣的可以都下载下来。
- 免费 douba-movie-1000w 链接: https://pan.baidu.com/s/15C0fn7oyYEFvuQtPO8tw8Q?pwd=1g7m 提取码: 1g7m
- 免费 douban-movie-1000w-Word2Vec.200.15.bin
链接: https://pan.baidu.com/s/1fK8LhLmK4_xq-eHzNn42lg?pwd=2hwr 提取码: 2hwr
- 免费 douban-movie-442w 链接: https://pan.baidu.com/s/1T_LPuxEZ_W8xfYcxV7rW5Q?pwd=a683 提取码: a683
- 免费 douban-movie-212w 链接: :https://pan.baidu.com/s/1VBwnOqfMPu_Y48bMlQ4oiw?pwd=t8id
提取码: t8id
- 免费词向量 https://cntext.readthedocs.io/zh-cn/latest/embeddings.html
- 100元 cntext-2.1.6-py3-none-any.whl 如有需要,加微信 ***372335839***, 备注「姓名-学校-专业」
相关内容
- 数据集 | 3394w条豆瓣书评数据集
- 实验 | 使用Stanford Glove代码训练中文语料的GloVe模型
- 可视化 | 人民日报语料反映七十年文化演变
- 词向量 | 使用MD&A2001-2023语料训练Word2Vec模型
- 实验 | 使用Stanford Glove代码训练中文语料的Glove模型