推荐系统里的那些算法—— TF-IDF(附python代码)
    基于UGC(user Generate Content)的推荐
 
- 用户用标签来描述对物品的看法,所以用户生成标签(UGC)是联系用户和物品的纽带,也是反应用户兴趣的重要数据源。
- 一个用户标签行为的数据集一般由一个三元组(用户,物品,标签)的集合表示,其中一条记录 (u, i, b)表示用户u给物品i打上了标签b.
- 一个最简单的算法 
  - 统计每个用户最常用的标签
- 对于每个标签,统计被打过这个标签次数最多的物品
- 对于一个用户,首先找到他常用的标签,然后找到具有这些标签的最热门的物品,推荐给他
- 所以用户u对物品i的兴趣公式为
        
         
          
           
            p
           
           
            (
           
           
            u
           
           
            ,
           
           
            i
           
           
            )
           
           
            =
           
           
            ∑
           
           
            
             n
            
            
             
              u
             
             
              ,
             
             
              b
             
            
           
           
            ×
           
           
            
             n
            
            
             
              b
             
             
              ,
             
             
              i
             
            
           
          
          
           p(u,i)=\sum n_{u,b}\times n_{b,i}
          
         
        p(u,i)=∑nu,b×nb,i其中,
       
        
         
          
           
            n
           
           
            
             u
            
            
             ,
            
            
             b
            
           
          
         
         
          n_{u,b}
         
        
       nu,b是用户u打过标签b的次数,
       
        
         
          
           
            n
           
           
            
             b
            
            
             ,
            
            
             i
            
           
          
         
         
          n_{b,i}
         
        
       nb,i是物品i被打过标签b的次数。
 
TF-IDF
 
- 词频-逆文档频率(Term Frequency-Inverse Document Frequency,TF-IDF)是一种用于资讯检索与文本挖掘的常用加权技术。
- TF-IDF是一种统计方法,用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
      
       
        
         
          T
         
         
          F
         
         
          I
         
         
          D
         
         
          F
         
         
          =
         
         
          T
         
         
          F
         
         
          ×
         
         
          I
         
         
          D
         
         
          F
         
        
        
         TFIDF=TF\times IDF
        
       
      TFIDF=TF×IDF
- TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
- TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。
- 词频(Term Frequency,TF) 
  - 指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数的归一化,以防止偏向更长的文件。(同一个词语在长文件里可能会比短文件有更离的词数,而不管该词语重要与否。)
        
         
          
           
            T
           
           
            
             F
            
            
             
              i
             
             
              ,
             
             
              j
             
            
           
           
            =
           
           
            
             
              n
             
             
              
               i
              
              
               ,
              
              
               j
              
             
            
            
             
              n
             
             
              
               ∗
              
              
               ,
              
              
               j
              
             
            
           
          
          
           TF_{i,j}=\frac {n_{i,j}}{n_{*,j}}
          
         
        TFi,j=n∗,jni,j其中
       
        
         
          
           T
          
          
           
            F
           
           
            
             i
            
            
             ,
            
            
             j
            
           
          
         
         
          TF_{i,j}
         
        
       TFi,j,表示词语i在文档j 中出现的频率,
       
        
         
          
           
            n
           
           
            
             i
            
            
             ,
            
            
             j
            
           
          
         
         
          n_{i,j}
         
        
       ni,j表示i在j 中出现的次数,
       
        
         
          
           
            n
           
           
            
             ∗
            
            
             ,
            
            
             j
            
           
          
         
         
          n_{*,j}
         
        
       n∗,j表示文档j的总词数
 
- 逆向文件频率(Inverse Document Frequency,IDF) 
  - 是一个词语普遍重要性的度量,某一特定词语的 IDF,可以由总文档数目除以包含该词语之文档的数目,再将得到的商取对数得到。
        
         
          
           
            I
           
           
            D
           
           
            
             F
            
            
             i
            
           
           
            =
           
           
            l
           
           
            o
           
           
            
             g
            
            
           
           
            
             
              N
             
             
              +
             
             
              1
             
            
            
             
              
               N
              
              
               i
              
             
             
              +
             
             
              1
             
            
           
          
          
           IDF_i=log_{} {\frac {N+1}{N_i+1}}
          
         
        IDFi=logNi+1N+1其中
       
        
         
          
           I
          
          
           D
          
          
           
            F
           
           
            i
           
          
         
         
          IDF_i
         
        
       IDFi,表示词语i在文档集中的逆文档频率,N表示文档集中的文档总数,
       
        
         
          
           
            N
           
           
            i
           
          
         
         
          N_i
         
        
       Ni表示文档集中包含了词语i的文档数。
 
TF-IDF基于UGC推荐的改进
 
- 为了避免热门标签和热门物品获得更多的权重,我们需要对“热门“进行惩罚借鉴TF-IDF的思想,以一个物品的所有标签作为“文档”,标签作为“词语”,从而计算标签的“词频”(在物品所有标签中的频率)和"逆文档频率”(在其它物品标签中普遍出现的频率)
- 由于“物品i的所有标签” 
     
      
       
        
         
          n
         
         
          
           ∗
          
          
           ,
          
          
           i
          
         
        
       
       
        n_{*,i}
       
      
     n∗,i应该对标签权重没有影响,而“所有标签总数”对于所有标签是一定的,所以这两项可以略去。在简单算法的基础上,直接加入对热门标签和热门物品的惩罚项:
      
       
        
         
          p
         
         
          (
         
         
          u
         
         
          ,
         
         
          i
         
         
          )
         
         
          =
         
         
          
           ∑
          
          
           b
          
         
         
          
           
            n
           
           
            
             u
            
            
             ,
            
            
             b
            
           
          
          
           
            l
           
           
            o
           
           
            
             g
            
            
             
              1
             
             
              +
             
             
              
               n
              
              
               b
              
              
               
                (
               
               
                u
               
               
                )
               
              
             
            
           
          
         
         
          
           
            l
           
           
            o
           
           
            
             g
            
            
             
              n
             
             
              
               b
              
              
               ,
              
              
               i
              
             
            
           
          
          
           
            l
           
           
            o
           
           
            
             g
            
            
             
              1
             
             
              +
             
             
              
               n
              
              
               i
              
              
               
                (
               
               
                u
               
               
                )
               
              
             
            
           
          
         
        
        
         p(u,i)=\sum _b\frac {n_{u,b}}{log_{1+n_b^{(u)}}}\frac{log_{n_{b,i}}}{log_{1+n_i^{(u)}}}
        
       
      p(u,i)=b∑log1+nb(u)nu,blog1+ni(u)lognb,i
 其中,
     
      
       
        
         
          n
         
         
          b
         
         
          
           (
          
          
           u
          
          
           )
          
         
        
       
       
        n_b^{(u)}
       
      
     nb(u)记录了标签b被多少个不同的用户使用过,
     
      
       
        
         
          n
         
         
          i
         
         
          
           (
          
          
           u
          
          
           )
          
         
        
       
       
        n_i^{(u)}
       
      
     ni(u)记录了物品i被多少个不同的用户打过标签
import pandas as pd
import numpy as np
import math
wordA = "xxx"
wordB = "yyy "
sepA = wordA.split(" ")
sepB = wordB.split(" ")
setA = set(sepA)
setB = set(sepB)
union = setA.union(setB)
dictA = dict.fromkeys(setA,0)
dictB = dict.fromkeys(setA,0)
for word in dictA:
    dictA[word] += 1
    
for word in dictB:
    dictB[word] += 1
pd.DataFrame([dictA,dictB])
def computeTF(dict,set):
    tfdict = {}
    setcount = len(set)
    for word,count in dict.items():
        tfdict[word] = count / setcount
    return tfdict
tfA = computeTF(dictA,setA)
tfB = computeTF(dictB,setB)
def computeIDF(dictlist):
    
    idfDict = dict.fromkeys(dictlist[0],0)
    N = len(dictlist)
    for Dict in dictlist:
        for word,count in Dict.items():
            if count > 0:
                idfDict[word] += 1
    
    for word ,ni in idfDict.items():
        idfDict[word] = math.log10((N+1)/(ni+1))
    return idfDict
idfs = computeIDF([dictA,dictB])
def computeTFIDF(tf,idfs):
    tfidf = {}
    for word,tfval in tf.items():
        tfidf[word] = tfval * idfs[word]
    return tfidf
tfidfA = computeTFIDF(tfA,idfs)
tfidfB = computeTFIDF(tfB,idfs)
pd.DataFrame([tfidfA,tfidfB])