前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >复现经典:《统计学习方法》​第17章 潜在语义分析

复现经典:《统计学习方法》​第17章 潜在语义分析

作者头像
黄博的机器学习圈子
发布2020-06-09 14:41:03
5710
发布2020-06-09 14:41:03
举报

第17章 潜在语义分析

本文是李航老师的《统计学习方法》一书的代码复现。作者:黄海广 备注:代码都可以在github中下载。我将陆续将代码发布在公众号“机器学习初学者”,可以在这个专辑在线阅读。

1.单词向量空间模型通过单词的向量表示文本的语义内容。以单词-文本矩阵

X

为输入,其中每一行对应一个单词,每一列对应一个文本,每一个元素表示单词在文本中的频数或权值(如TF-IDF)

X = \left[ \begin{array} { c c c c } { x _ { 11 } } & { x _ { 12 } } & { \cdots } & { x _ { 1 n } } \\ { x _ { 21 } } & { x _ { 22 } } & { \cdots } & { x _ { 2 n } } \\ { \vdots } & { \vdots } & { } & { \vdots } \\ { x _ { m 1 } } & { x _ { m 2 } } & { \cdots } & { x _ { m n } } \end{array} \right]

单词向量空间模型认为,这个矩阵的每一列向量是单词向量,表示一个文本,两个单词向量的内积或标准化内积表示文本之间的语义相似度。

2.话题向量空间模型通过话题的向量表示文本的语义内容。假设有话题文本矩阵

Y = \left[ \begin{array} { c c c c } { y _ { 11 } } & { y _ { 12 } } & { \cdots } & { y _ { 1 n } } \\ { y _ { 21 } } & { y _ { 22 } } & { \cdots } & { y _ { 2 n } } \\ { \vdots } & { \vdots } & { } & { \vdots } \\ { y _ { k 1 } } & { y _ { k 2 } } & { \cdots } & { y _ { k n } } \end{array} \right]
Y = \left[ \begin{array} { c c c c } { y _ { 11 } } & { y _ { 12 } } & { \cdots } & { y _ { 1 n } } \ { y _ { 21 } } & { y _ { 22 } } & { \cdots } & { y _ { 2 n } } \ { \vdots } & { \vdots } & { } & { \vdots } \ { y _ { k 1 } } & { y _ { k 2 } } & { \cdots } & { y _ { k n } } \end{array} \right]

其中每一行对应一个话题,每一列对应一个文本每一个元素表示话题在文本中的权值。话题向量空间模型认为,这个矩阵的每一列向量是话题向量,表示一个文本,两个话题向量的内积或标准化内积表示文本之间的语义相似度。假设有单词话题矩阵

T
T = \left[ \begin{array} { c c c c } { t _ { 11 } } & { t _ { 12 } } & { \cdots } & { t _ { 1 k } } \\ { t _ { 21 } } & { t _ { 22 } } & { \cdots } & { t _ { 2 k } } \\ { \vdots } & { \vdots } & { } & { \vdots } \\ { t _ { m 1 } } & { t _ { m 2 } } & { \cdots } & { t _ { m k } } \end{array} \right]

其中每一行对应一个单词,每一列对应一个话题,每一个元素表示单词在话题中的权值。

给定一个单词文本矩阵

X
X = \left[ \begin{array} { c c c c } { x _ { 11 } } & { x _ { 12 } } & { \cdots } & { x _ { 1 n } } \\ { x _ { 21 } } & { x _ { 22 } } & { \cdots } & { x _ { 2 n } } \\ { \vdots } & { \vdots } & { } & { \vdots } \\ { x _ { m 1 } } & { x _ { m 2 } } & { \cdots } & { x _ { m n } } \end{array} \right]

LSA 是一种无监督学习方法,主要用于文本的话题分析,其特点是通过矩阵分解发现文本与单词之间的基于话题的语义关系。也称为潜在语义索引(Latent semantic indexing, LSI)。

LSA 使用的是非概率的话题分析模型。将文本集合表示为单词-文本矩阵,对单词-文本矩阵进行奇异值分解,从而得到话题向量空间,以及文本在话题向量空间的表示。

非负矩阵分解(non-negative matrix factorization, NMF)是另一种矩阵的因子分解方法,其特点是分解的矩阵非负。

单词向量空间

word vector space model

给定一个文本,用一个向量表示该文本的”语义“, 向量的每一维对应一个单词,其数值为该单词在该文本中出现的频数或权值;基本假设是文本中所有单词的出现情况表示了文本的语义内容,文本集合中的每个文本都表示为一个向量,存在于一个向量空间;向量空间的度量,如内积或标准化内积表示文本之间的相似度

X = \begin{bmatrix} x_{11} & x_{12}& x_{1n}& \\ x_{21}& x_{22}& x_{2n}& \\ \vdots & \vdots & \vdots & \\ x_{m1}& x_{m2}& x_{mn}& \end{bmatrix}

话题向量空间

1. 话题向量空间

X = \begin{bmatrix} x_{11} & x_{12}& x_{1n}& \\ x_{21}& x_{22}& x_{2n}& \\ \vdots & \vdots & \vdots & \\ x_{m1}& x_{m2}& x_{mn}& \end{bmatrix}

假设所有文本共含有k个话题。假设每个话题由一个定义在单词集合w上的m维向量表示,称为话题向量,即:

t_{l} = \begin{bmatrix} t_{1l}\\ t_{2l}\\ \vdots \\ t_{ml}\end{bmatrix}, l=1,2,...,k

3. 从单词向量空间到话题向量空间的线性变换

图例 17.1

代码语言:javascript
复制
import numpy as np
from sklearn.decomposition import TruncatedSVD
代码语言:javascript
复制
X = [[2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 1, 0], [0, 0, 2, 3], [0, 0, 0, 1], [1, 2, 2, 1]]
X = np.asarray(X);X
代码语言:javascript
复制
array([[2, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 2, 3],
       [0, 0, 0, 1],
       [1, 2, 2, 1]])
代码语言:javascript
复制
# 奇异值分解
U,sigma,VT=np.linalg.svd(X)
代码语言:javascript
复制
U
代码语言:javascript
复制
array([[-7.84368672e-02, -2.84423033e-01,  8.94427191e-01,
        -2.15138396e-01, -6.45002451e-02, -2.50012770e-01],
       [-1.56873734e-01, -5.68846066e-01, -4.47213595e-01,
        -4.30276793e-01, -1.29000490e-01, -5.00025540e-01],
       [-1.42622354e-01,  1.37930417e-02, -1.25029761e-16,
         6.53519444e-01,  3.88575115e-01, -6.33553733e-01],
       [-7.28804669e-01,  5.53499910e-01, -2.24565656e-16,
        -1.56161345e-01, -3.23288048e-01, -1.83248673e-01],
       [-1.47853320e-01,  1.75304609e-01,  8.49795536e-18,
        -4.87733411e-01,  8.40863653e-01,  4.97204799e-02],
       [-6.29190197e-01, -5.08166890e-01, -1.60733896e-16,
         2.81459486e-01,  1.29000490e-01,  5.00025540e-01]])
代码语言:javascript
复制
sigma
代码语言:javascript
复制
array([4.47696617, 2.7519661 , 2.        , 1.17620428])
代码语言:javascript
复制
VT
代码语言:javascript
复制
array([[-1.75579600e-01, -3.51159201e-01, -6.38515454e-01,
        -6.61934313e-01],
       [-3.91361272e-01, -7.82722545e-01,  3.79579831e-02,
         4.82432341e-01],
       [ 8.94427191e-01, -4.47213595e-01, -2.23998094e-16,
         5.45344065e-17],
       [-1.26523351e-01, -2.53046702e-01,  7.68672366e-01,
        -5.73674125e-01]])
代码语言:javascript
复制
# 截断奇异值分解

svd = TruncatedSVD(n_components=3, n_iter=7, random_state=42)
svd.fit(X)  
代码语言:javascript
复制
TruncatedSVD(algorithm='randomized', n_components=3, n_iter=7, random_state=42,
             tol=0.0)
代码语言:javascript
复制
print(svd.explained_variance_ratio_)
代码语言:javascript
复制
[0.39945801 0.34585056 0.18861789]
代码语言:javascript
复制
print(svd.explained_variance_ratio_.sum())
代码语言:javascript
复制
0.933926460028446
代码语言:javascript
复制
print(svd.singular_values_)
代码语言:javascript
复制
[4.47696617 2.7519661  2.        ]
非负矩阵分解
代码语言:javascript
复制
def inverse_transform(W, H):
    # 重构
    return W.dot(H)

def loss(X, X_):
    #计算重构误差
    return ((X - X_) * (X - X_)).sum()
代码语言:javascript
复制
# 算法 17.1

class MyNMF:
    def fit(self, X, k, t):
        m, n = X.shape
        
        W = np.random.rand(m, k)
        W = W/W.sum(axis=0)
        
        H = np.random.rand(k, n)
        
        i = 1
        while i < t:
            
            W = W * X.dot(H.T) / W.dot(H).dot(H.T)
            
            H = H * (W.T).dot(X) / (W.T).dot(W).dot(H)
            
            i += 1
            
        return W, H
代码语言:javascript
复制
model = MyNMF()
W, H = model.fit(X, 3, 200)
代码语言:javascript
复制
W
代码语言:javascript
复制
array([[0.00000000e+00, 4.27327705e-01, 6.30117924e-27],
       [5.11680721e-97, 8.57828102e-01, 0.00000000e+00],
       [2.97520805e-88, 2.39454414e-18, 4.36332453e-01],
       [2.15653741e+00, 3.38756557e-21, 8.38350315e-01],
       [7.36106818e-01, 1.00339294e-54, 8.72892573e-38],
       [6.78344810e-01, 1.07009504e+00, 8.57259947e-01]])
代码语言:javascript
复制
H
代码语言:javascript
复制
array([[7.14647214e-10, 1.01233436e-03, 3.76097657e-02, 1.35755597e+00],
       [9.30509415e-01, 1.86788842e+00, 1.16682319e-02, 4.54479182e-03],
       [4.95440453e-03, 6.18432747e-04, 2.28890170e+00, 8.61836630e-02]])
代码语言:javascript
复制
# 重构
X_ = inverse_transform(W, H);X_
代码语言:javascript
复制
array([[3.97632453e-01, 7.98200474e-01, 4.98615876e-03, 1.94211546e-03],
       [7.98217125e-01, 1.60232718e+00, 1.00093372e-02, 3.89865014e-03],
       [2.16176748e-03, 2.69842277e-04, 9.98722093e-01, 3.76047290e-02],
       [4.15352814e-03, 2.70160021e-03, 2.00000833e+00, 2.99987233e+00],
       [5.26056687e-10, 7.45186228e-04, 2.76848049e-02, 9.99306203e-01],
       [9.99980721e-01, 2.00003500e+00, 2.00018226e+00, 9.99636205e-01]])
代码语言:javascript
复制
# 重构误差

loss(X, X_)
代码语言:javascript
复制
4.002356735601103

使用 sklearn 计算

代码语言:javascript
复制
from sklearn.decomposition import NMF
model = NMF(n_components=3, init='random', max_iter=200, random_state=0)
W = model.fit_transform(X)
H = model.components_
代码语言:javascript
复制
W
代码语言:javascript
复制
array([[0.        , 0.53849498, 0.        ],
       [0.        , 1.07698996, 0.        ],
       [0.69891361, 0.        , 0.        ],
       [1.39782972, 0.        , 1.97173859],
       [0.        , 0.        , 0.65783848],
       [1.39783002, 1.34623756, 0.65573258]])
代码语言:javascript
复制
H
代码语言:javascript
复制
array([[0.00000000e+00, 0.00000000e+00, 1.43078959e+00, 1.71761682e-03],
       [7.42810976e-01, 1.48562195e+00, 0.00000000e+00, 3.30264644e-04],
       [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.52030365e+00]])
代码语言:javascript
复制
X__ = inverse_transform(W, H);X__
代码语言:javascript
复制
array([[3.99999983e-01, 7.99999966e-01, 0.00000000e+00, 1.77845853e-04],
       [7.99999966e-01, 1.59999993e+00, 0.00000000e+00, 3.55691707e-04],
       [0.00000000e+00, 0.00000000e+00, 9.99998311e-01, 1.20046577e-03],
       [0.00000000e+00, 0.00000000e+00, 2.00000021e+00, 3.00004230e+00],
       [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00011424e+00],
       [1.00000003e+00, 2.00000007e+00, 2.00000064e+00, 9.99758185e-01]])
代码语言:javascript
复制
loss(X, X__)
代码语言:javascript
复制
4.000001672582457

本章代码来源:https://github.com/hktxt/Learn-Statistical-Learning-Method

下载地址

https://github.com/fengdu78/lihang-code

参考资料:

[1] 《统计学习方法》: https://baike.baidu.com/item/统计学习方法/10430179

[2] 黄海广: https://github.com/fengdu78

[3] github: https://github.com/fengdu78/lihang-code

[4] wzyonggege: https://github.com/wzyonggege/statistical-learning-method

[5] WenDesi: https://github.com/WenDesi/lihang_book_algorithm

[6] 火烫火烫的: https://blog.csdn.net/tudaodiaozhale

[7] hktxt: https://github.com/hktxt/Learn-Statistical-Learning-Method

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习初学者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第17章 潜在语义分析
    • 单词向量空间
      • 话题向量空间
        • 图例 17.1
        • 使用 sklearn 计算
      • 下载地址
        • 参考资料:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档