Python实现NMF(非负矩阵分解)

出现背景

  • 数据分布不均,维度大(导致计算效率低下)
  • 难以解释负值的实际意义(e.g.图像数据中不可能有负值的像素点)

分解方法

将一个非负矩阵分解为两个非负矩阵的乘积。

倍增更新规则(2001):
在欧氏距离下,随机初始化,然后不断迭代,直到W(系数矩阵) H(基矩阵)稳定:
注意W在H之后进行更新,更新W时使用的H是更新之后的H
NMP求得的是局部最优解local optima(对应global optima问题),对于局部最优算法,一般考虑以下几点:

  • 是否收敛
  • 收敛速度如何
  • 迭代的终止条件是什么(误差函数,最小化损失函数)

应用

  • 压缩。将原本的矩阵由n*m转换为了(n+m)*r(与聚类的关系:新基是类中心,系数表示归属度)
  • 实际应用:图像识别(机场、太空垃圾、识别星体、机器人识别环境),文本处理(通过NMF发现局部相关性),语音特征提取

实例

对于一个交通流量矩阵Vd,行表示路段,列表示该路段在96个时段内的交通流量。
即对于Vdij 表示第d天路段i在时段j内的交通流量。
其中,Vd的维数 = 路段数 * 时段数。

分解形式:
Vm * h ≈ Cm * r Pr * h

tips:

  • m:路段数量
  • h:时段数量
  • r:交通模式数量(想分几类就把r定为几,对应着PCA中选取了前几个特征向量

分解后得到基本模式矩阵P,系数矩阵C。
对于基本模式矩阵Pr * h

  • 每一行对应一个基本的交通模式(流量随时间变化的模式)
  • Pkj:第k种交通模式时段j内的流量

基本模式矩阵刻画了每一种模式的情况。

对于系数矩阵Cm * r:

  • 每一行表示该路段在基本模式上的投影系数,Cik:路段i在基本模式k上的投影系数
  • 系数矩阵可以代表实际道路交通模式

系数矩阵的列对应三种模式,可以理解为一种道路有三种特征,这三种特征在这个道路上的占比。

import numpy as np
import pandas as pd

data = pd.DataFrame
data = pd.read_csv('20111116.csv',header = None)
data = data.iloc[:,3:]
data = data.values


def train(V, r, k, e):
    m, n = np.shape(V)
    W = np.mat(np.random.random((m, r)))
    H = np.mat(np.random.random((r, n)))
    data = []

    for x in range(k):
        V_pre = W * H
        E = V - V_pre  # 误差
        err = 0.0
        for i in range(m):
            for j in range(n):
                err += E[i, j] * E[i, j]
        data.append(err)
        print(err)
        if err < e:  # e 阈值
            break

        a = W.T * V  # Hkj
        b = W.T * W * H

        for i_1 in range(r):
            for j_1 in range(n):
                if b[i_1, j_1] != 0:
                    H[i_1, j_1] = H[i_1, j_1] * a[i_1, j_1] / b[i_1, j_1]

        c = V * H.T
        d = W * H * H.T
        for i_2 in range(m):
            for j_2 in range(r):
                if d[i_2, j_2] != 0:
                    W[i_2, j_2] = W[i_2, j_2] * c[i_2, j_2] / d[i_2, j_2]

    return W, H, data

W, H ,error= train(data, 4, 100, 1e-5 )

print(W)
print('\n')
print(H)
  • 8
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值