专栏首页机器学习初学者精选文章复现经典:《统计学习方法》​第17章 潜在语义分析

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

第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

import numpy as np
from sklearn.decomposition import TruncatedSVD
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
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]])
# 奇异值分解
U,sigma,VT=np.linalg.svd(X)
U
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]])
sigma
array([4.47696617, 2.7519661 , 2.        , 1.17620428])
VT
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]])
# 截断奇异值分解

svd = TruncatedSVD(n_components=3, n_iter=7, random_state=42)
svd.fit(X)  
TruncatedSVD(algorithm='randomized', n_components=3, n_iter=7, random_state=42,
             tol=0.0)
print(svd.explained_variance_ratio_)
[0.39945801 0.34585056 0.18861789]
print(svd.explained_variance_ratio_.sum())
0.933926460028446
print(svd.singular_values_)
[4.47696617 2.7519661  2.        ]

非负矩阵分解

def inverse_transform(W, H):
    # 重构
    return W.dot(H)

def loss(X, X_):
    #计算重构误差
    return ((X - X_) * (X - X_)).sum()
# 算法 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
model = MyNMF()
W, H = model.fit(X, 3, 200)
W
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]])
H
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]])
# 重构
X_ = inverse_transform(W, H);X_
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]])
# 重构误差

loss(X, X_)
4.002356735601103

使用 sklearn 计算

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_
W
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]])
H
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]])
X__ = inverse_transform(W, H);X__
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]])
loss(X, X__)
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

本文分享自微信公众号 - 机器学习初学者(ai-start-com),作者:机器学习初学者

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 复现经典:《统计学习方法》第15章 奇异值分解

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

    黄博的机器学习圈子
  • Github标星2.3k+!这个仓库提供了靠谱的入门人工智能的路线及资料!

    Github上有一个仓库(标星2300+),很大程度上解决了这个问题,不但提供了学习路线,为初学者指明了学习的方向,而且所有代码和数据集都提供了下载方式。

    黄博的机器学习圈子
  • 推荐五篇论文| 轻量级的Transformer; 对比学习;ResNeSt;Shortcut Learning等

    Transform已经在自然语言处理(例如机器翻译,问题解答)中无处不在;但是,要实现高性能,它需要大量的计算,这使其不适合受硬件资源和电池严格限制的移动应用程...

    黄博的机器学习圈子
  • 丢给你个环形队列玩玩

    假设我需要处理10000个字节的数据,就是串口一次性会发过来10000个字节,然后单片机每次取10个字节处理,然后处理1000次就处理完了

    杨奉武
  • 重叠时间段问题优化算法详解

    这是一个实际业务需求中的问题。某一直播业务表中记录了如下格式的用户进出直播间日志数据:

    用户1148526
  • pytorch基础知识-维度变换-(上)

    维度变换是pytorch中的重要操作,尤其是在图片处理中。本文对pytorch中的维度变换进行讲解。

    用户6719124
  • 一个有趣的时间段重叠问题

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.n...

    用户1148526
  • pytorch基础知识:张量(下)

    其中一维标量主要用于Bias(偏差)中,如在构建神经元中多组数据导入到一个神经元中,由激活函数激活输出一个数值,则该神经元主要使用bias功能。线性层输入(Li...

    用户6719124
  • MySQL中InnoDB引擎对索引的扩展

    MySQL中,使用InnoDB引擎的每个表,创建的普通索引(即非主键索引),都会同时保存主键的值。

    数据和云
  • AkShare-中国宏观-国房景气指数

    国房景气指数是全国房地产开发业综合景气指数的简称。它是对房地产业发展变化趋势和变化程度的量化反映,由8个分类指数合成运算出综合指数,并用百分制表示。其中,综合...

    AkShare

扫码关注云+社区

领取腾讯云代金券