集体智慧编程第十章寻找独立特征:在数据集未明显标注的情况下,寻找数据集的潜在特征,比如SVD分解U,V矩阵都存在隐空间。
1. NMF
从数据中提取重要特征的技术被称为非负矩阵分解(NMF)。
假设我们手上有一个对多篇文章进行单词计数信息统计的文章矩阵。我们将这个矩阵分解为两个更小的矩阵,使得二者相乘几乎完全等于原来的矩阵,这两个矩阵分别是特征矩阵和权重矩阵。假设原矩阵R(10 *1000) = M(10 *K) x N(K*1000)
1.1 NMF的特征矩阵
在特征矩阵中,每一行对应一个特征,每个单词对应一列。矩阵中的数字代表了某个单词相对于某个特征的重要程度。这里N矩阵即为特征矩阵。
1.2 权重矩阵
该矩阵的每一行对应一篇文章,每一列对应一个特征,矩阵中的数字代表了当前特征对于当前文章的重要程度。这里M矩阵即为特征矩阵。
1.3 求解特征矩阵和权重矩阵
# -*- coding: utf-8 -*-
"""
非负矩阵分解用于 - 主题模型
使用了一种很奇特的算法: 乘法更新法则恢复原矩阵
"""
import numpy as np
np.random.seed(1)
def _cal_diff(matrix, recover):
"""
计算重构矩阵与原矩阵之间的误差
recover:
重构矩阵
"""
return abs(matrix - recover).sum()
def factorize(m, fea_num = 6, _iter = 1000):
"""
对矩阵进行分解, 重构
m:
一行代表一篇文章, 一列代表一个单词;
fea_num:
为当前matrix寻找feature的个数;
该算法的核心 - 四个矩阵
hn = w' * m
hd = w' * w * feature
"""
if not isinstance(m, np.matrix):
m = np.matrix(m)
print("请确保输入m是一个行为文章, 列为单词的矩阵.")
# 1. 随机初始化权重矩阵和特征矩阵
weight = np.matrix(np.random.random((m.shape[0], fea_num)))
feature = np.matrix(np.random.random((fea_num, m.shape[1])))
# 2. 循环更新矩阵
for i in range(_iter):
# 2.1 计算重构矩阵和原矩阵的误差
lose = _cal_diff(m, weight * feature)
if i % 10 == 0: print("\n原矩阵与重构矩阵之间的lose = {0}".format(lose))
if lose <= 1e-3: return weight, feature
# 2.2 更新特征矩阵
hn = weight.T * m; hd = weight.T * weight * feature
feature = np.matrix(np.array(feature) * np.array(hn) / np.array(hd))
# 2.3 更新权重矩阵
wn = m * feature.T; wd = weight * feature * feature.T
weight = np.matrix(np.array(weight) * np.array(wn) / np.array(wd))
return weight, feature
2. NMF文本挖掘的意义
通过NMF分解,我们可以为文章寻找多个较为重要的主题,同时给出每个主题的关键词。