# 解决高频词误导计算结果
# 如果一个词与很多次共现,降低权重,反之,提高权重
# 点互信息 PMI
# 最大似然估计,MLE
# PPMI 最大(pmi(w,c),0)
# V 表示词表,C表示全部的上下文
import math
import numpy as np
M = np.array([[0, 2, 1, 1, 1, 1, 1, 2, 1, 3],
[2, 0, 1, 1, 1, 0, 0, 1, 1, 2],
[1, 1, 0, 1, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[2, 1, 0, 0, 0, 1, 1, 0, 1, 2],
[1, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[3, 2, 1, 1, 1, 1, 1, 2, 1, 0]])
# PPMI
def pmi(M, positive=True):
col_totals = M.sum(axis=0)# 列
row_totals = M.sum(axis=1)# 行
total = col_totals.sum()# 总
# np.outer(a,b)计算矩阵的外积,也就是把a当做列向量,b当做行向量,得到一个n*m的矩阵
#3*2=6 3*3=9,4*2=8,4*3=12 就是a中每个元素与b中元素相乘。
expected = np.outer(row_totals, col_totals) / total # 行,列,行*列得到一个矩阵,之后除以总的,得到分母
M = M / expected # 得到M
# 我感觉应该加上log2
# M = math.log(M, 2)
# Silence distracting warnings about log(0):
# 用于浮点错误处理的上下文管理器. 使用errstate的实例作为上下文管理器允许该上下文中的语句以已知的错误处理行为执行。进入上下文后,错误处理设置为seterr和seterrcall ,并在退出时重置为之前的状态。
with np.errstate(divide='ignore'):
M = np.log(M)
# numpy.isinf(array [,out]):逐个测试是否为+ ve或-ve无限,是否将结果作为布尔数组返回。
M[np.isinf(M)] = 0.0 # log(0) = 0
if positive:
M[M < 0] = 0.0
return M
M_pmi = pmi(M)
# print(M_pmi)
# 打印结果保留两位小数
np.set_printoptions(precision=2)
print(M_pmi)
# https://mp.weixin.qq.com/s?__biz=MzU0MDQ1NjAzNg==&mid=2247521822&idx=1&sn=fd6d53b380f4f9a5d97ddbade30b31ad&chksm=fb3a3315cc4dba03c36f7e9575a309b9a99211aaedafd5c872940c7666f4bfa0cb55c299d8d1&scene=27
U, s, Vh = np.linalg.svd(M_pmi)
print(U)
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
# 字体显示器
plt.rcParams['axes.unicode_minus']=False #让坐标中显示负号
words = ["我", "喜欢", "自然", "语言", "处理", "爱", "深度", "学习", "机器", "。"]
# 为什么要这么写呢
# 前两维对应的二维向量坐标
# 后面的表示上下文的向量表示
for i in range(len(words)):
plt.text(U[i, 0], U[i, 1], words[i])
print(words[i])
print(U[i, 0]) # 横坐标值
print(U[i, 1]) # 纵坐标值
plt.xlim(-0.5, -0.1)
plt.ylim(-0.5, 0.4)
# 保存下来
# plt.savefig('svd.pdf')
plt.show()
车_自然语言处理_SVD_书的代码有问题,这是修改的
最新推荐文章于 2024-09-20 23:31:36 发布