数据挖掘(七)
数据挖掘(七)
文章目录
- 数据挖掘(七)
- 加载数据集
- 用现有模型进行分类
- 构建网络
- 寻找子图
- 连通分支
社交网络具有很高的商业价值,比如QQ、微信等拥有大量活跃用户的应用,通过投放广告可以获得不菲的收入。对于网站来说,如果想要提高用户留存率,我们要有用户感兴趣的人或内容。很多事物都可以用图来表示,我们可以使用连通分支把大图分为有意义的小图。根据相似度,把大数据集分为几个子集。
加载数据集
本文根据社交网络用户的好友信息,向他们推荐好友。如果两个用户有共同的好友,那么这两个人相似度很高,值得向彼此推荐。我们可以通过微博等开发者平台获取社交网络数据,寻找喜欢同一个话题的用户,从中选一部分,再获取这些人的好友列表。有了这些数据后,就能根据两个用户共同拥有的好友数量,计算他们的相似度。
用现有模型进行分类
- 首先需要保存朴素贝叶斯分类模型,我们可以使用joblib库保存模型,将模型输出到指定目录。
import os
import json
import joblib
import numpy as np
from sklearn.base import TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction import DictVectorizer
from sklearn.naive_bayes import BernoulliNB
from nltk import word_tokenizeclass NLTKBOW(TransformerMixin):def fit(self, X, y=None):return selfdef transform(self, X):return [{word:True for word in word_tokenize(document)} for document in X]data_folder = os.path.join(os.getcwd(), 'data_mining', 'twitter')
input_filename = os.path.join(data_folder, 'python_tweets.json')
class_filename = os.path.join(data_folder, 'python_classes.json')
output_filename = os.path.join(data_folder, 'python_context.pkl')
tweets = []
classes = []
with open(input_filename) as inf:for line in inf:if len(line.strip()) == 0:continuetweets.append(json.loads(line)['text'])
with open(class_filename) as inf:classes = json.load(inf)
tweet_list = np.array(tweets)
class_list = np.array(classes)
pipeline = Pipeline([('词袋模型转换', NLTKBOW()), ('字典列表转矩阵', DictVectorizer()), ('朴素贝叶斯分类器', BernoulliNB())])
model = pipeline.fit(tweet_list, class_list)
joblib.dump(model, output_filename)
- 加载模型,然后重建NLTKBOW类,因为这是个定制的类,无法直接用joblib加载。我们使用joblib的load方法加载模型,然后调用模型的predict函数预测消息是否与编程语言相关。
import os
import json
import joblib
import numpy as np
from sklearn.base import TransformerMixin
from nltk import word_tokenizeclass NLTKBOW(TransformerMixin):def fit(self, X, y=None):return selfdef transform(self, X):return [{word:True for word in word_tokenize(document)} for document in X]tweets = []
data_folder = os.path.join(os.getcwd(), 'data_mining', 'twitter')
input_filename = os.path.join(data_folder, 'python_tweets.json')
with open(input_filename) as inf:for line in inf:if len(line.strip()) == 0:continuetweets.append(json.loads(line)['text'])
tweet_list = np.array(tweets)
model_filename = os.path.join(data_folder, 'python_context.pkl')
# 加载模型
context_classifier = joblib.load(model_filename)
# 如果第i条消息与编程语言相关,那么y_pred中的第i项为1,否则为0
y_pred = context_classifier.predict(tweet_list)
print(y_pred)
构建网络
- 获取每个用户的好友,好友的定义可以是用户正在关注的人。从初始用户出发,找到每个人的好友保存起来,删除没有好友的孤家寡人。对于这些人,无法按照既定逻辑向他们推荐好友,也许可以从他们发表的消息以及关注他们的人那里发现有用的线索。考虑到要根据共同的好友向用户推荐他们可能感兴趣的人,因此就查找有共同好友的人,找到现有用户的好友,从他们中间找出在现有用户中间有更多好友的人。我们需要统计这些用户的好友数量,遍历所有用户的好友列表,统计每个好友的出现次数。计算完成后,根据好友数量的字典进行排序,找到在当前用户中,关系网最大、最密集的人。
- 我们通过获取用户列表和他们的好友列表,使用这些存在的好友关系的数据就可以构建一张图。图是由一组顶点和边组成。顶点通常表示对象比如用户,边表示用户A是用户B的好友。由于顶点的顺序是有特殊含义,该图称为有向图,因为用户A是用户B的好友并不代表用户B是用户A的好友。我们可以使用NetworkX库实现图关系的可视化,draw函数可以为创建好的图绘制图像。
# 使用NetworkX创建有向图
import networkx as nx
G = nx.DiGraph()
# nodes_for_adding是可迭代的集合,把核心用户作为顶点添加到图中
G.add_nodes_from(nodes_for_adding)
- 计算两个列表之间的相似度有多种方法。比如两个用户来说,可以统计他们好友列表中共同好友数量。然而好友更多的用户,共同好友数量通常也更多。于是可以再除以他们拥有的不同好友的数量实现数据的规范化,得到的正是杰卡德相似系数。该系数总是在0到1之间,代表两者重合的比例。计算杰卡德相似系数时,需要用两个集合交集的元素数量除以两个集合并集的元素数量。
def compute_similarity(friends1, friends2):return len(friends1 & friends2)/len(friends1 | friends2)
寻找子图
利用相似度函数求出每个用户与其他用户之间的相似度,根据相似度进行排序,找出与当前用户最相似的,把他推荐给当前用户。我们也可以找出批量相似度很大的用户,可以把这些用户组成一个群,向他们定向投放广告。找出这些相似用户群的任务叫做聚类分析。聚类分析缺乏一个事实标准,评价结果时,只好根据经验来看分簇结果是否合乎情理。聚类分析另一个复杂之处在于不能用实现标注好的数据进行训练,只好在使用聚类数学模型的基础上求得近似的分组结果,而不是按照用户所希望的那样将数据分成明确的类别。
连通分支
- 一种最简单的聚类方法就是找到图中的连通分支。一个连通分支是图中由边连接在一起的一组顶点,不要求顶点之间必须两两连接,但是连通分支的任意两个顶点之间至少存在一条路径。连通分支计算时不考虑边的权重,只检查边是否存在。因为不论权重高低,只要有边连接的顶点就会被算到连通分支里,而一个连通分支被看作是一簇具有相似特点的用户,为了保证簇内用户具有较高的相似度,需要事先把权重低的边过滤掉。
# 使用NetworkX提供的函数寻找图中的连通分支,sub_graphs是生成器
sub_graphs = nx.connected_component_subgraphs(G)
# 找出连通分支的总数
n_subgraphs = nx.number_connected_components(G)
- 连通分支查找算法依赖于阈值参数,阈值控制着找到的连通分支数量和大小。我们可以事先确定什么样的结果才是令人满意的,再根据理想中的结果来寻找选取参数的准则。作为一般性规则,它应该能够使得同一连通分支内的个体尽可能相似,不同簇内的个体尽可能不相似。轮廓系数是对这两点的量化方法,计算公式如下,a是簇内距离,表示与簇内其他个体之间的平均距离。b为簇间距离,也就是与最近簇内各个个体之间的平均距离。总轮廓系数为每个个体轮廓系数的均值。总轮廓系数接近最大值1时,表示每个簇内的个体相似度很高,不同簇之间距离较远。
s = b − a m a x ( a , b ) s = \frac{b - a}{max(a, b)} s=max(a,b)b−a
- scikit-learn库提供了计算轮廓系数的函数,函数接收的是距离矩阵,轮廓系数的定义要求至少由两个顶点才能计算距离。
from sklearn.metrics import silhouette_score