非负矩阵分解的两种方法简析

一、使用非负最小二乘法

Non-negative matrix factorisation using non-negative least squares

问题

给定一个矩阵\(A\),将其分解成两个非负的因子:

\[ A_{M \times N} \approx W_{M \times K} \times H_{K \times N}, such that \space W_{M \times K} \geq 0 \space and \space H_{K \times N} \geq 0\]

解法

我们的解决方法包含两个步骤。首先,在 A 给定的情况下固定 W 然后求解 H。接下来固定 H 来求解 W。迭代的重复这个过程,求解的方法就是最小二乘法,所以这种方法也叫做交替最小二乘法(ALS)。但是我们的问题有特殊性,那就是我们将 W 和 H 约束位非负的,所以我们用非负最小二乘(NNLS)来代替最小二乘。

代码示例

import numpy as np
from scipy.optimize import nnls

M, N = 20, 10
K = 4

np.random.seed(2019)
A_orig = np.abs(np.random.uniform(low=0.0, high=1.0, size=(M,N)))

A = A_orig.copy()
# 在实际问题中常会出现 A 中有缺失值的情况,特别是在协同过滤的问题中
A[0, 0] = np.NAN
A[3, 1] = np.NAN
A[6, 3] = np.NAN
A[3, 6] = np.NAN

W = np.abs(np.random.uniform(low=0, high=1, size=(M, K)))
H = np.abs(np.random.uniform(low=0, high=1, size=(K, N)))

def cost(A, W, H):
    # 计算代价函数时忽略 A 中缺失的元素
    mask = ~np.isnan(A)
    WH = np.dot(W, H)
    WH_mask = WH[mask] # Now WH_mask is a vector, only include the non-nan values
    A_mask = A[mask]
    A_WH_mask = A_mask-WH_mask
    return np.linalg.norm(A_WH_mask, 2)

num_iter = 1000

for i in range(num_iter):
    if i%2 ==0:
        # 固定 W 求解 H
        for j in range(N): # 注意 H 是 一列一列的求
            mask_rows = ~np.isnan(A[:,j])
            H[:,j] = nnls(W[mask_rows], A[:,j][mask_rows])[0]
    else:
        # 固定 H 求解 W
        for j in range(M): # W 是一行一行的求
            mask_rows = ~np.isnan(A[j,:])
            W[j,:] = nnls(H.T[mask_rows], A[j,:][mask_rows])[0]
    if i%100 == 0:
        print(i,cost(A,W,H))

二、使用TensorFlow

https://nipunbatra.github.io/blog/2017/nnmf-tensorflow.html

主要是利用梯度下降的原理

代码示例

import tensorflow as tf
import numpy as np

np.random.seed(2019)

A = np.array([[np.nan, 4, 5, 2],
              [4, 4, np.nan, 3],
              [5, 5, 4, 4]], dtype=np.float32).T # 4 users,3 movies

# Boolean mask for computing cost only on non-missing value
tf_mask = tf.Variable(~np.isnan(A))

shape = A.shape
A = tf.constant(A)

# latent factors
rank = 3

H = tf.Variable(np.random.randn(rank,shape[1]).astype(np.float32))
W = tf.Variable(np.random.randn(shape[0],rank).astype(np.float32))

WH = tf.matmul(W,H)

# Define cost on Frobenius norm
cost = tf.reduce_sum(tf.pow(tf.boolean_mask(A,tf_mask)                            - tf.boolean_mask(WH,tf_mask),2))

learning_rate = 0.001
steps=1000
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
init = tf.global_variables_initializer()

# Clipping operation. This ensure that W and H learnt are non-negative
clip_W = W.assign(tf.maximum(tf.zeros_like(W),W))
clip_H = H.assign(tf.maximum(tf.zeros_like(H),H))
clip = tf.group(clip_W,clip_H)

steps = 1000
with tf.Session() as sess:
    sess.run(init)
    for i in range(steps):
        sess.run(train_step)
        sess.run(clip)
        if i%100==0:
            print("Cost: ",sess.run(cost))
    learnt_W = sess.run(W)
    learnt_H = sess.run(H)

原文地址:https://www.cnblogs.com/ZeroTensor/p/10262704.html

时间: 2024-10-10 14:44:12

非负矩阵分解的两种方法简析的相关文章

NMath矩阵分解的两种方式

概述:本教程为您介绍.Net唯一的数学与统计学运算库NMath,实现矩阵分解的两种方法. Nmath中包括用于构造和操作矩阵QR和奇异值分解的分解类.QR分解如下表示: 1 AP=QR 其中P是一个可置换矩阵,Q是正交的,且R为上梯形.矩阵A的奇异值分解(SVD)的形式表示为: 1 A=USV* 其中U和V是正交的,S是对角的,和V *表示一个真正的矩阵V或一个复杂的矩阵V的条目沿对角线S的共轭转置的奇异值. 接下来带来一个矩阵分解类的实例,下面代码示例为从FloatMatrix创建FloatQ

CSS实现自适应不同大小屏幕的背景大图的两种方法(转自简书)

CSS实现自适应不同大小屏幕的背景大图的两种方法 一张清晰漂亮的背景图片能给网页加分不少,设计师也经常会给页面的背景使用大图,我们既不想图片因为不同分辨率图片变形,也不希望当在大屏的情况下,背景有一块露白,简而言之,就是实现能自适应屏幕大小又不会变形的背景大图,而且背景图片不会随着滚动条滚动而滚动. 用CSS实现真的很简单很简单,下面我们来看一下第一种方法具体的代码: HTML代码: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <m

Linux网络性能优化方法简析

Linux网络性能优化方法简析 2010-12-20 10:56 赵军 IBMDW 字号:T | T 性能问题永远是永恒的主题之一,而Linux在网络性能方面的优势则显而易见,这篇文章是对于Linux内核中提升网络性能的一些优化方法的简析,以让我们去后台看看魔术师表演用的盒子,同时也看看内核极客们是怎样灵活的,渐进的去解决这些实际的问题. AD:2014WOT全球软件技术峰会北京站 课程视频发布 对于网络的行为,可以简单划分为 3 条路径:1) 发送路径,2) 转发路径,3) 接收路径,而网络性

pdf文件怎么修改 修改PDF文件的两种方法

都说PDF格式的文件不能修改,我就呵呵了!不管你们信不信,反正我是不信.因为我会修改PDF文件,并且方法还不止一种.想知道我是怎么修改PDF文件的吗?下面我就告诉大家修改PDF文件的两种方法. 方法一 1.方法一就是将PDF文件转换成一种可容易编辑的文档,如:word.excel.ppt等格式,然后再进行编辑,编辑好后再将其转换成PDF格式,是不是很简单!具体是该如何转换的,下面有详细教程. 2.下载一个PDF转换器,并将它安装在电脑上.工具最好是支持双向转换的那种,如:http://www.x

Android中使用Gson解析JSON数据的两种方法

Json是一种类似于XML的通用数据交换格式,具有比XML更高的传输效率;本文将介绍两种方法解析JSON数据,需要的朋友可以参考下 Json是一种类似于XML的通用数据交换格式,具有比XML更高的传输效率. 从结构上看,所有的数据(data)最终都可以分解成三种类型: 第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独的词. 第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组

一、查看Linux内核版本命令(两种方法):

一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [[email protected]CentOS home]# cat /proc/versionLinux version 2.6.32-431.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Nov 22 03:15:09 UTC 2013 2.uname -a [

利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

要想提取车牌号,首先你要定位车牌区域嘛,本文分别两种方法用,即颜色和形态学的方法,对车牌区域进行判定.说得是两种方法,其实两种方法并无多大的区别,只是有一步的判断标准不一样而已,你看了下面整理出的的思路就知道两者的区别真的很小了. 方法一:利用颜色提取车牌区域的思路: ①求得原图像的sobel边缘sobelMat ②在HSV空间内利用车牌颜色阈值对图像进行二值化处理,得到图像bw_blue→ ③由下面的判别标准得到图像bw_blue_edge for (int k = 1; k != heigh

ios图片拉伸两种方法

ios图片拉伸两种方法 UIImage *image = [UIImage imageNamed:@"qq"]; 第一种: // 左端盖宽度 NSInteger leftCapWidth = image.size.width * 0.5f; // 顶端盖高度 NSInteger topCapHeight = image.size.height * 0.5f; // 重新赋值 image = [image stretchableImageWithLeftCapWidth:leftCapW

Android第五期 - 更新自己的apk本地与网络两种方法

首先是本地: ParseXmlService部分: package com.szy.update; import java.io.InputStream; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element