数据挖掘 - 低秩矩阵恢复与非负矩阵分解
2017-09-05 20:32
274 查看
1. 低秩矩阵恢复
低秩矩阵恢复主要应用于推荐算法,对矩阵中的未评分位置进行评分。具体原理推导见这里吧:http://download.csdn.net/download/zk_j1994/9983147
代码:
loss下降过程:
2. 非负矩阵分解
非负矩阵分解与低秩矩阵恢复类似,他们的三个矩阵的元素都要求非负。不同的是低秩矩阵恢复是预测原矩阵中为0的位置;而非负矩阵分解认为原矩阵是完整的。假设原矩阵R(n * m) = M(n*k) x N(k*m);非负矩阵的应用主要有:
2.1 文本挖掘
假设文本矩阵为n * m,即n篇文章,m个单词,其中的元素为单词出现的次数。将矩阵分解之后,k即为特征的个数或者说主题的个数。在M中我们容易得出每篇文章最重要的几个主题;而在N中我们容易得出每个主题最重要的一些单词。
# -*- 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 = 2000):
"""
对矩阵进行分解, 重构
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
if __name__ == "__main__":
# 1. 文本寻找主题
data = [[0, 0, 0, 0, 2, 4, 0, 0, 3, 0, 5],
[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
[3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
[0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
[0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
[0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2]]
weight, feature = factorize(data, 3)
recover = np.mat(weight) * np.mat(feature)
"""
对第0篇文章进行分析:
第0篇文章在7个特征(主题)上的权重weight[0,:] = [0.009, 2.817, 0.589, 0, 0, 0, 0]
我们又容易从feature矩阵中获取每个特征中, 每个单词的重要性。
因此我们可以为第0篇文章选出2个最大的特征, 每个特征我们取3个最重要的单词:
2.817: [第10个单词, 第5个单词, 第8个单词]
0.589: [第4个单词, 第9个单词, 第5个单词]
这两个特征极有可能代表两个不同的主题, 但这篇文章主要和2.817那个特征(主题相关)
"""
# 2. 数据降维
data = [[5, 5, 3, 0, 5, 5, 4, 3, 2, 1, 4, 1, 3, 4, 5],
[5, 0, 4, 0, 4, 4, 3, 2, 1, 2, 4, 4, 3, 4, 0],
[0, 3, 0, 5, 4, 5, 0, 4, 4, 5, 3, 0, 0, 0, 0],
[5, 4, 3, 3, 5, 5, 0, 1, 1, 3, 4, 5, 0, 2, 4],
[5, 4, 3, 3, 5, 5, 3, 3, 3, 4, 5, 0, 5, 2, 4],
[5, 4, 2, 2, 0, 5, 3, 3, 3, 4, 4, 4, 5, 2, 5],
[5, 4, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0],
[5, 4, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[5, 4, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
[5, 4, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]]
# 2.1 sklearn数据压缩
from sklearn.decomposition import NMF
Model = NMF(n_components=2)
W = Model.fit_transform(data)
"""
NMF用于数据降维
weight就是降维结果, 其次NMF还可以用于图像无损压缩等等, 节约存储空间;
"""
# 3. 总结
# 其实文本寻找主题也是一个降维的过程, 将一个含有数千个单词的文章进行维度约简, 留下少量单词代表文章主题
3. 注意
显然K越大,则P,Q矩阵更为复杂,能够更好地拟合原矩阵,但也容易导致过拟合;而K越小,则P,Q更简单,模型更精简。
同时,对于非负矩阵分解而言,k的大小决定了所有文章能生成多少个主题,一般根据经验决定,或者尝试调节k的大小。
参考文献
http://m.blog.csdn.net/winone361/article/details/50705739 https://wenku.baidu.com/view/7bbaf0739b6648d7c1c74687#28 http://blog.csdn.net/google19890102/article/details/51124556
低秩矩阵恢复主要应用于推荐算法,对矩阵中的未评分位置进行评分。具体原理推导见这里吧:http://download.csdn.net/download/zk_j1994/9983147
代码:
# -*- coding: utf-8 -*- """ 基于矩阵分解的推荐算法 1. 使用梯度下降进行迭代更新; """ import numpy as np import matplotlib.pyplot as plt np.random.seed(1) def load_data(): data = [[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5], [0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3], [0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0], [3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0], [5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0], [0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0], [4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1], [0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4], [0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2], [0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0], [1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]] return np.array(data) def gradAscent(data, K, max_iter, alpha, beta): """ 梯度下降更新P, Q矩阵的元素, 使均方误差最小 """ if not isinstance(data, np.matrix): data = np.mat(data) # 初始化P, Q矩阵 n, m = data.shape P = np.mat(np.random.random((n, K))) Q = np.mat(np.random.random((K, m))) print("\nP = \n{0}".format(P)) print("\nQ = \n{0}".format(Q)) loss_list = [] _iter = 0 while _iter < max_iter: # 更新P, Q中的每一个元素 for i in range(n): for j in range(m): if data[i, j] > 0: error = (data[i, j] - P[i, :] * Q[:, j])[0, 0] # (i, j)处的误差 for k in range(K): P[i, k] = P[i, k] + alpha * (2 * error * Q[k, j] - beta * P[i, k]) Q[k, j] = Q[k, j] + alpha * (2 * error * P[i, k] - beta * Q[k, j]) # 计算原矩阵和恢复矩阵之间的误差 loss = 0 for i in range(n): for j in range(m): if data[i, j]> 0: for k in range(K): loss += P[i, k] * Q[k, j] loss = np.sum(abs(data[i, j] - loss)) loss_list.append(loss) if loss <= 1e-3: break _iter += 1 return P, Q, loss_list def draw_loss(loss): plt.plot(range(len(loss)), loss) plt.show() if __name__ == "__main__": data = load_data() P, Q, loss = gradAscent(data, 5, 20000, 0.0002, 0.02) print("\n恢复矩阵 = \n{0}".format(P * Q)) draw_loss(loss)
loss下降过程:
2. 非负矩阵分解
非负矩阵分解与低秩矩阵恢复类似,他们的三个矩阵的元素都要求非负。不同的是低秩矩阵恢复是预测原矩阵中为0的位置;而非负矩阵分解认为原矩阵是完整的。假设原矩阵R(n * m) = M(n*k) x N(k*m);非负矩阵的应用主要有:
2.1 文本挖掘
假设文本矩阵为n * m,即n篇文章,m个单词,其中的元素为单词出现的次数。将矩阵分解之后,k即为特征的个数或者说主题的个数。在M中我们容易得出每篇文章最重要的几个主题;而在N中我们容易得出每个主题最重要的一些单词。
# -*- 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 = 2000):
"""
对矩阵进行分解, 重构
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
if __name__ == "__main__":
# 1. 文本寻找主题
data = [[0, 0, 0, 0, 2, 4, 0, 0, 3, 0, 5],
[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
[3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
[0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
[0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
[0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2]]
weight, feature = factorize(data, 3)
recover = np.mat(weight) * np.mat(feature)
"""
对第0篇文章进行分析:
第0篇文章在7个特征(主题)上的权重weight[0,:] = [0.009, 2.817, 0.589, 0, 0, 0, 0]
我们又容易从feature矩阵中获取每个特征中, 每个单词的重要性。
因此我们可以为第0篇文章选出2个最大的特征, 每个特征我们取3个最重要的单词:
2.817: [第10个单词, 第5个单词, 第8个单词]
0.589: [第4个单词, 第9个单词, 第5个单词]
这两个特征极有可能代表两个不同的主题, 但这篇文章主要和2.817那个特征(主题相关)
"""
# 2. 数据降维
data = [[5, 5, 3, 0, 5, 5, 4, 3, 2, 1, 4, 1, 3, 4, 5],
[5, 0, 4, 0, 4, 4, 3, 2, 1, 2, 4, 4, 3, 4, 0],
[0, 3, 0, 5, 4, 5, 0, 4, 4, 5, 3, 0, 0, 0, 0],
[5, 4, 3, 3, 5, 5, 0, 1, 1, 3, 4, 5, 0, 2, 4],
[5, 4, 3, 3, 5, 5, 3, 3, 3, 4, 5, 0, 5, 2, 4],
[5, 4, 2, 2, 0, 5, 3, 3, 3, 4, 4, 4, 5, 2, 5],
[5, 4, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0],
[5, 4, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[5, 4, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
[5, 4, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]]
# 2.1 sklearn数据压缩
from sklearn.decomposition import NMF
Model = NMF(n_components=2)
W = Model.fit_transform(data)
"""
NMF用于数据降维
weight就是降维结果, 其次NMF还可以用于图像无损压缩等等, 节约存储空间;
"""
# 3. 总结
# 其实文本寻找主题也是一个降维的过程, 将一个含有数千个单词的文章进行维度约简, 留下少量单词代表文章主题
3. 注意
显然K越大,则P,Q矩阵更为复杂,能够更好地拟合原矩阵,但也容易导致过拟合;而K越小,则P,Q更简单,模型更精简。
同时,对于非负矩阵分解而言,k的大小决定了所有文章能生成多少个主题,一般根据经验决定,或者尝试调节k的大小。
参考文献
http://m.blog.csdn.net/winone361/article/details/50705739 https://wenku.baidu.com/view/7bbaf0739b6648d7c1c74687#28 http://blog.csdn.net/google19890102/article/details/51124556
相关文章推荐
- 数据挖掘基础知识-矩阵(分解)
- 数据挖掘算法-矩阵分解在推荐系统中的应用
- MADlib——基于SQL的数据挖掘解决方案(6)——数据转换之矩阵分解
- 数据挖掘基础知识-矩阵(分解)
- 基于评分数据的推荐算法实现:slopeone和矩阵分解
- Oracle数据库利用日志挖掘来恢复误删除的数据
- opencv中SVD分解并恢复重构矩阵
- oracle 基于数据挖掘的不完全恢复
- 数据挖掘中的矩阵基础(1)
- MADlib——基于SQL的数据挖掘解决方案(4)——数据类型之矩阵
- 数据分析、数据挖掘之特征分解、特征分析
- 利用日志挖掘 oracle 不完全恢复 恢复误删除的表/数据/视图等
- 数据降维--低秩恢复
- 数据降维--低秩恢复
- 数据挖掘中的矩阵基础(2)
- 程序员的机器学习入门笔记(三):数据挖掘中矩阵的那些事
- Oracle数据库利用日志挖掘来恢复误删除的数据
- Spark数据挖掘-TF-IDF文档矩阵
- HAWQ + MADlib 玩转数据挖掘之(二)——矩阵
- 通过凸优化的低秩矩阵恢复和完成