赞
踩
前面提到,物品画像的特征标签主要都是指的如电影的导演、演员、图书的作者、出版社等结构话的数据,也就是他们的特征提取,尤其是体征向量的计算是比较简单的,如直接给作品的分类定义0或者1的状态。但另外一些特征,比如电影的内容简介、电影的影评、图书的摘要等文本数据,这些被称为非结构化数据,首先他们本应该也属于物品的一个特征标签,但是这样的特征标签进行量化时,也就是计算它的特征向量时是很难去定义的。
因此这时就需要借助一些自然语言处理、信息检索等技术,将如用户的文本评论或其他文本内容信息的非结构化数据进行量化处理,从而实现更加完善的物品画像/用户画像。TF-IDF算法便是其中一种在自然语言处理领域中应用比较广泛的一种算法。可用来提取目标文档中,并得到关键词用于计算对于目标文档的权重,并将这些权重组合到一起得到特征向量。
TF-IDF算法原理
TF-IDF自然语言处理领域中计算文档中词或短语的权值的方法,是词频(Term Frequency,TF)和逆转文档频率(Inverse Document Frequency,IDF)的乘积。TF指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被正规化,以防止它偏向长的文件(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否)。IDF是一个词语普遍重要性的度量,某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
TF-IDF算法基于一个这样的假设:若一个词语在目标文档中出现的频率高而在其他文档中出现的频率低,那么这个词语就可以用来区分出目标文档。这个假设需要掌握的有两点:
因此,TF-IDF算法的计算可以分为词频(Term Frequency,TF)和逆转文档频率(Inverse Document Frequency,IDF)两部分,由TF和IDF的乘积来设置文档词语的权重。
TF指的是一个词语在文档中的出现频率。假设文档集包含的文档数为
N
N
N,文档集中包含关键词
k
i
k_i
ki的文档数为
n
i
n_i
ni,
f
i
j
f_{ij}
fij表示关键词
k
i
k_i
ki在文档
d
j
d_j
dj中出现的次数,
f
d
j
f_{dj}
fdj表示文档
d
j
d_j
dj中出现的词语总数,
k
i
k_i
ki在文档dj中的词频
T
F
i
j
TF_{ij}
TFij定义为:
T
F
i
j
=
f
i
j
f
d
j
TF_{ij}=\frac {f_{ij}}{f_{dj}}
TFij=fdjfij。并且注意,这个数字通常会被正规化,以防止它偏向长的文件(指同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否)。
IDF是一个词语普遍重要性的度量。表示某一词语在整个文档集中出现的频率,由它计算的结果取对数得到关键词
k
i
k_i
ki的逆文档频率
I
D
F
i
IDF_i
IDFi:
I
D
F
i
=
l
o
g
N
n
i
IDF_i=log\frac {N}{n_i}
IDFi=logniN
由TF和IDF计算词语的权重为:
w
i
j
=
T
F
i
j
w_{ij}=TF_{ij}
wij=TFij·
I
D
F
i
=
f
i
j
f
d
j
IDF_{i}=\frac {f_{ij}}{f_{dj}}
IDFi=fdjfij·
l
o
g
N
n
i
log\frac {N}{n_i}
logniN
结论:TF-IDF与词语在文档中的出现次数成正比,与该词在整个文档集中的出现次数成反比。
用途:在目标文档中,提取关键词(特征标签)的方法就是将该文档所有词语的TF-IDF计算出来并进行对比,取其中TF-IDF值最大的k个数组成目标文档的特征向量用以表示文档。
注意:文档中存在的停用词(Stop Words),如“是”、“的”之类的,对于文档的中心思想表达没有意义的词,在分词时需要先过滤掉再计算其他词语的TF-IDF值。
import pandas as pd import numpy as np ''' - 利用tags.csv中每部电影的标签作为电影的候选关键词 - 利用TF·IDF计算每部电影的标签的tfidf值,选取TOP-N个关键词作为电影画像标签 - 并将电影的分类词直接作为每部电影的画像标签 ''' def get_movie_dataset(): # 加载基于所有电影的标签 # all-tags.csv来自ml-latest数据集中 # 由于ml-latest-small中标签数据太多,因此借助其来扩充 _tags = pd.read_csv("datasets/ml-latest-small/all-tags.csv", usecols=range(1, 3)).dropna() tags = _tags.groupby("movieId").agg(list) # 加载电影列表数据集 movies = pd.read_csv("ml-latest-small/movies.csv", index_col="movieId") # 将类别词分开 movies["genres"] = movies["genres"].apply(lambda x: x.split("|")) # 为每部电影匹配对应的标签数据,如果没有将会是NAN movies_index = set(movies.index) & set(tags.index) new_tags = tags.loc[list(movies_index)] ret = movies.join(new_tags) # 构建电影数据集,包含电影Id、电影名称、类别、标签四个字段 # 如果电影没有标签数据,那么就替换为空列表 # map(fun,可迭代对象) movie_dataset = pd.DataFrame( map( lambda x: (x[0], x[1], x[2], x[2]+x[3]) if x[3] is not np.nan else (x[0], x[1], x[2], []), ret.itertuples()) , columns=["movieId", "title", "genres","tags"] ) movie_dataset.set_index("movieId", inplace=True) return movie_dataset movie_dataset = get_movie_dataset() print(movie_dataset)
from gensim.models import TfidfModel import pandas as pd import numpy as np from pprint import pprint # ...... def create_movie_profile(movie_dataset): ''' 使用tfidf,分析提取topn关键词 :param movie_dataset: :return: ''' dataset = movie_dataset["tags"].values from gensim.corpora import Dictionary # 根据数据集建立词袋,并统计词频,将所有词放入一个词典,使用索引进行获取 dct = Dictionary(dataset) # 根据将每条数据,返回对应的词索引和词频 corpus = [dct.doc2bow(line) for line in dataset] # 训练TF-IDF模型,即计算TF-IDF值 model = TfidfModel(corpus) movie_profile = {} for i, mid in enumerate(movie_dataset.index): # 根据每条数据返回,向量 vector = model[corpus[i]] # 按照TF-IDF值得到top-n的关键词 movie_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30] # 根据关键词提取对应的名称 movie_profile[mid] = dict(map(lambda x:(dct[x[0]], x[1]), movie_tags)) return movie_profile movie_dataset = get_movie_dataset() pprint(create_movie_profile(movie_dataset))
from gensim.models import TfidfModel import pandas as pd import numpy as np from pprint import pprint # ...... def create_movie_profile(movie_dataset): ''' 使用tfidf,分析提取topn关键词 :param movie_dataset: :return: ''' dataset = movie_dataset["tags"].values from gensim.corpora import Dictionary # 根据数据集建立词袋,并统计词频,将所有词放入一个词典,使用索引进行获取 dct = Dictionary(dataset) # 根据将每条数据,返回对应的词索引和词频 corpus = [dct.doc2bow(line) for line in dataset] # 训练TF-IDF模型,即计算TF-IDF值 model = TfidfModel(corpus) _movie_profile = [] for i, data in enumerate(movie_dataset.itertuples()): mid = data[0] title = data[1] genres = data[2] vector = model[corpus[i]] movie_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30] topN_tags_weights = dict(map(lambda x: (dct[x[0]], x[1]), movie_tags)) # 将类别词的添加进去,并设置权重值为1.0 for g in genres: topN_tags_weights[g] = 1.0 topN_tags = [i[0] for i in topN_tags_weights.items()] _movie_profile.append((mid, title, topN_tags, topN_tags_weights)) movie_profile = pd.DataFrame(_movie_profile, columns=["movieId", "title", "profile", "weights"]) movie_profile.set_index("movieId", inplace=True) return movie_profile movie_dataset = get_movie_dataset() pprint(create_movie_profile(movie_dataset))
def create_inverted_table(movie_profile):
inverted_table = {}
for mid, weights in movie_profile["weights"].iteritems():
for tag, weight in weights.items():
#到inverted_table dict 用tag作为Key去取值 如果取不到就返回[]
_ = inverted_table.get(tag, [])
_.append((mid, weight))
inverted_table.setdefault(tag, _)
return inverted_table
inverted_table = create_inverted_table(movie_profile)
pprint(inverted_table)
用户画像构建步骤:
相关代码
import pandas as pd import numpy as np from gensim.models import TfidfModel from functools import reduce import collections from pprint import pprint # ...... ''' user profile画像建立: 1. 提取用户观看列表 2. 根据观看列表和物品画像为用户匹配关键词,并统计词频 3. 根据词频排序,最多保留TOP-k个词,这里K设为100,作为用户的标签 ''' def create_user_profile(): watch_record = pd.read_csv("ml-latest-small/ratings.csv", usecols=range(2), dtype={"userId":np.int32, "movieId": np.int32}) watch_record = watch_record.groupby("userId").agg(list) # print(watch_record) movie_dataset = get_movie_dataset() movie_profile = create_movie_profile(movie_dataset) user_profile = {} for uid, mids in watch_record.itertuples(): record_movie_prifole = movie_profile.loc[list(mids)] counter = collections.Counter(reduce(lambda x, y: list(x)+list(y), record_movie_prifole["profile"].values)) # 兴趣词 interest_words = counter.most_common(50) maxcount = interest_words[0][1] interest_words = [(w,round(c/maxcount, 4)) for w,c in interest_words] user_profile[uid] = interest_words return user_profile user_profile = create_user_profile() pprint(user_profile)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。