矩阵特征集体智慧编程学习之非负矩阵因式分解

每日一贴,今天的内容关键字为矩阵特征

    大学时我的线性代数老师寿继麟,事先六十多岁带着一副金丝眼镜精力矍铄,传说是我最尊敬的余德鴻副校长的老师。上课的课本是寿老师写的打印出来给大家,很便宜。我虽然不好好学习,但是在好老师的率领下,也不至于学的太差。余校长隔段时光总会给我们上一堂课,虽然没有说过我们什么,但总能让我们羞愧进而耐劳上一段时光。记得他说过这样一个问题,会场人声嘈杂,给你两个麦克风,怎么在一无所知的情况下分离出你想听到的那个人的声音。十年后的今年我才真正开始考虑这个问题,余校长提出的问题,原来寿老师事先就帮我们处理了。

    非负矩阵因式分解,非负是说矩阵的元素都是正数或者零,因式分解就是对矩阵A,寻觅矩阵B和C,使得A=B*C。这样分解有什么用呢?还是为了处理分类的问题。区别人声,也是一个分类问题。分类的问题在之前《集体伶俐编程学习之分类系统》中提到了贝叶斯和费舍尔,在《集体伶俐编程学习之聚类系统》中提到了K-均值聚类,贝叶斯和费舍尔需要事前定义好分类,然后训练模型,K-均值聚类的计算量还是蛮大的。而非负矩阵因式分解可以一次把所有的相关性计算出来,还是很有必要好好学习的。

    矩阵因式分解的目标呢,就是把矩阵B拆分成为两个矩阵相乘,比如矩阵F和矩阵W,这样B=W*F。矩阵的乘法事先寿老师教的很清晰,第一个矩阵(比如W)的列必须于第二个矩阵(比如F)的行数相称才能相乘,乘积矩阵(比如B)的每一个元素的取值,是通过将矩阵W中雷同行的值与矩阵F中雷同列的值相乘,然后将乘积相加所得。(这里我不举例子了,随便Google就有了)。这里将B拆分为F和W的乘积,F代表特征矩阵,W代表权值矩阵,下面具体说说这两个货色。

    F特征矩阵:在该矩阵中,每一个特征对应一行,每一个单词对应一列,矩阵中的数字代表了某个单词相对于某个特征的重要程度;

    W权值矩阵:在改矩阵中,每一行对应一本书,每一列对应一个特征,矩阵中的数字代表了将某个特征应用于某篇文章的程度;

    这样W*F就可以重构出B,一行对应一本书,一列对应一个单词。

    

    通过计算最好的特征矩阵和权值矩阵,算法实验尽可能大地来从新结构文章矩阵。这里我们先定义一种方法来衡量最终结果与幻想结果的接近程度:

def difcost(a,b):
  dif=0
  for i in range(shape(a)[0]):
    for j in range(shape(a)[1]):
      # Euclidean Distance
      dif+=pow(a[i,j]-b[i,j],2)
  return dif

    函数difcost针对两个同样大小的矩阵遍历其中的每一个值,并将两者的间差值的平方累加起来。

    下面我们需要一种方法能够逐渐地更新矩阵,以使本钱函数的计算值逐步降低。《集体伶俐编程学习之优化系统》里的退火法和遗传算法都能满足要求。这里我来学习一种更为的方法,乘法更新矩阵规律。规律的具体道理先不学习,先直接拿来用。有兴趣的看这篇论文《Algorithms for Non-negative Matrix Factorization》

    这个规律发生四个新的更新矩阵:

    hn:转置后的权重矩阵与数据矩阵相乘而来;

    hd:转置后的权重矩阵与原权重矩阵相乘,再与特征矩阵相乘而来;

    wn:数据矩阵与转置后的特征矩阵相乘而来;

    wd:权重矩阵与特征矩阵相乘,再与转置后的特征矩阵相乘而来;

    更新特征矩阵和权重矩阵,我们将特征矩阵中的每一个值与hn中的对应值相乘,并除以hd中的对应值;再将权重矩阵中的每一个值与wn中的对应值相乘,并除以wd中的对应值下面看用python的算法实现:

    

def factorize(v,pc=10,iter=50):
  ic=shape(v)[0]
  fc=shape(v)[1]

  # Initialize the weight and feature matrices with random values
  w=matrix([[random.random() for j in range(pc)] for i in range(ic)])
  h=matrix([[random.random() for i in range(fc)] for i in range(pc)])

  # Perform operation a maximum of iter times
  for i in range(iter):
    wh=w*h
    
    # Calculate the current difference
    cost=difcost(v,wh)
    
    if i%10==0: print cost
    
    # Terminate if the matrix has been fully factorized
    if cost==0: break
    
    # Update feature matrix
    hn=(transpose(w)*v)
    hd=(transpose(w)*w*h)
  
    h=matrix(array(h)*array(hn)/array(hd))

    # Update weights matrix
    wn=(v*transpose(h))
    wd=(w*h*transpose(h))

    w=matrix(array(w)*array(wn)/array(wd))  
    
  return w,h
    每日一道理
即使青春是一枝娇艳的花,但我明白,一枝独放永远不是春天,春天该是万紫千红的世界。 即使青春是一株大地伟岸的树,但我明白,一株独秀永远不是挺拔,成行成排的林木,才是遮风挡沙的绿色长城。即使青春是一叶大海孤高的帆,但我明白,一叶孤帆很难远航,千帆竞发才是大海的壮观。

    参数pc指定我们希望找到的特征数,iter是最多执行次数。

    来看看我机器执行的测试:

    

    测试数据还是用之前的例子:每一行都是一本书,每一列都代表一个词,数组中的数字代表这个词在这本书中涌现的次数或者TF-IDF值:

books = [    
  [2, 3, 3, 12, 13, 12],    
  [3, 3, 1, 13, 12, 11], 
  [1, 10, 3, 5, 11, 13],    
  [13, 12, 11, 1, 3, 3],    
  [12, 13, 12, 3, 2, 2],    
  [5, 11, 13, 3, 1, 10]  
]

    

测试过程:

    

>>> from numpy import *
>>> v=matrix(nnmf.books)
>>> w,f=nnmf.factorize(v,2)
2352.23524582
130.308626905
125.555272626
125.540256481
125.540046063
>>> w
matrix([[ 1.01861466,  0.11646996],
        [ 0.99224682,  0.07461746],
        [ 0.80748193,  0.400123  ],
        [ 0.04713232,  1.2421583 ],
        [ 0.04119911,  1.27694878],
        [ 0.27820173,  1.02855868]])
>>> f
matrix([[  0.21984673,   3.29533888,   0.77713346,  10.7432405 ,
          12.31672543,  12.3422249 ],
        [  8.44995405,  10.06321664,   9.81092778,   0.6161926 ,
           0.65151678,   2.88313112]])
>>> w*f
matrix([[  1.20810496,   4.52874298,   1.93427795,  11.01499022,
          12.62187925,  12.90776943],
        [  0.84865631,   4.02068115,   1.50317469,  10.70592492,
          12.26984613,  12.46166529],
        [  3.5585432 ,   6.68745101,   4.55309905,   8.92152545,
          10.20622012,  11.1197307 ],
        [ 10.50654247,  12.65542508,  12.2233535 ,   1.27176259,
           1.38980281,   4.16302294],
        [ 10.79921601,  12.98597723,  12.56006946,   1.22945829,
           1.33939163,   4.1900994 ],
        [  8.75243536,  11.26737784,  10.30731484,   3.6225783 ,
           4.09665751,   6.39909782]])

    我测试用的特征数选择为2。

    先来看看权值矩阵w:

    book1,特征一显著(1.0),特征二不显著(0.1);

    book2,特征一显著(0.9),特征二不显著(0.0)

    book3,特征一显著(0.8),特征二不显著(0.4);

    book4,特征一不显著(0.0),特征二显著(1.2);

    book5,特征一不显著(0.0),特征二显著(1.2);

    book6,特征一不显著(0.2),特征二显著(1.0);

    再看看特征矩阵:

    特征一:word1不显著(0.2),word2不太显著(3.2),word3不显著(0.7),word4显著(10.7),word5显著(12.3),word6显著(12.3)

    特征二:word1挺显著(8.4),word2显著(10.0),word3显著(9.8),word4不显著(0.6),word5不显著(0.6),word6不显著(2.8)

    

    实现还是很简单的,主要是这类思惟,再次得成论断最NB的还是算法。上次听博士说一年要读100多篇论文,这才是学术研究,这才会发明核心技术。

    

    

文章结束给大家分享下程序员的一些笑话语录: 一条狗在街上闲逛,看见橱窗里一张告示:「招聘程序员。会编程,有团队精神,至少精通两种语言。均等机会。」
  那条狗就进去申请,但是被拒绝了。
  「我不能雇一条狗在公司里做事。」经理说。
  狗不服气,指着告示上「均等机会」几字抗议。
  经理没法,叹了口气,不屑地问道:「你会编程吗?」
  那条狗默默地走到电脑前,编了个程序,运作准确。
  「你有团队精神吗?」经理问。
  那条狗掉头看了看门外,一大群野狗在外面虎视耽耽。
  「我真的不能雇狗做这份工作。」经理气急败坏地说。
  「就算会编程、有团队精神,但是我需要的雇员至少要能精通两种语言。」
  那条狗抬头看着经理说:「喵-噢。」

--------------------------------- 原创文章 By
矩阵和特征
---------------------------------

你可能感兴趣的:(编程)