数据挖掘-聚类分析
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
获取数据
• from time import sleep
• def get_links(subreddit, token, n_pages=5): • stories = [] • after = None
for page_number in range(n_pages): result={} url = "https://oauth.reddit.com/r/{}limit=100".format(subreddit) headers = {"Authorization": "bearer {}".format(token['access_token']),"User-Agent": USER_AGENT} if after: url += "&after={}".format(after) response = requests.get(url, headers=headers) result = response.json() after = result['data']['after'] sleep(2) stories.extend([(story['data']['title'],story['data']['url'],story['data']['score']) for story in result['data']['children']]) • return stories
聚类分析
理论前提
我聚 们类 使属 用于 聚无 类监 算督 法学 探习 索︐ 隐 藏 在 数 据 里 的 奥 秘 ︒
k-means 算法
经典机器学习算法k-means(k均值)
k-means聚类算法迭代寻找最能够代表数据的聚类质心点。 算法开始时使用从训练数据中随机选取的几个数据点作为质心点。k-means中的k表示寻 找多少个质心点,同时也是算法将会找到的簇的数量。例如,把k设置为3,数据集所有 数据将会被分成3个簇。 k-means算法分为两个步骤:
#如果自行获取数据,请从此处开始
skip_node_types = ["script", "head", "style", etree.Comment] 创建函数,该函数为了从文件中抽取数据 #函数的最后一行,调用getroot()函数,获取到树的根节点,而不是整棵树etree def get_text_from_file(filename): with open(filename, encoding='utf-8') as inf: html_tree = LH.parse(inf) return get_text_from_node(html_tree.getroot())
获取新闻文章
本章将构建一个按照主题为最新的新闻报道分组的系统。你可以运行几周(或更长时间)以了解这段时间 新闻趋势的变化。 系统首先从流行的链接聚合网站reddit寻找新闻报道的链接。reddit存储了大量其他网站的链接,还提供 讨论区。网站收集的链接按照类别进行分类,这些类别被统称为subreddit,比如有电视节目、趣味图片 等类别。本章关注的是新闻这一类链接。本章使用/r/worldnews类别的链接, 但是我们所编写的代码也可以用来抓取其他类别的语料。
• 为每一个数据点分配簇标签,更新各簇的质心点。分簇这一步中,我们为数据集的每个个体设置 一个标签,把它和最近的质心点联系起来。对于距离质心点1最近的个体,我们为它们分配标签 1,距离质心点2最近的个体,分配标签2,以此类推。标签相同的个体属于同一个簇,所有带有 标签1的数据点属于簇1(只是暂时的,数据点所属的簇会随着算法的运行发生变化)。 • 更新环节,计算各簇内所有数据点的均值,更新质心点。
response = requests.get(url) data = response.text with open(fullpath, 'w') as outf: outf.write(data)
如果下载网页时出现问题,跳过问题网站,继续下载下一个网站的网页。上述代码能够完成我们收集到的 95%的网站下载任务,对本章的应用来说足够了,因为我们寻找的是大体趋势而不是做精准研究。
获取数据
我们数据集的每条广播都来自 /r/worldnews栏目的热度列表。上节讲解 了连接reddit网站和抽取广播内容的方法。 我们来创建一个函数,把这两个步骤整合起 来,抽取指定栏目每条广播的标题、链接和 喜欢数。
我们遍历世界新闻栏目,最多一次获取100篇新闻报道。我们还 可以使用分页,reddit最多允许我们读多少页,我们就读多少页。 但是我们这里最多读5页。
实验准备
获取数据集 本次数据来源:数据资源宝库reddit。 已经提供数据集,有兴趣自行上网获得数据的可以看后面获取数据的PPT,没有可以忽略。 【即如果不考虑自行获取数据,跳转到第10页PPT】
相关Python库:
• • • • • • • • os Lxml Numpy collections pandas Hashlib Sklearn matplotlib
• • • • • • • • • • •
获取数据
我们首先需要访问每个链接,下载各个网页,将它们保存到Data文件夹中事先 建好的用于存放原始网页的文件夹raw。后面,我们就要从这些原始网页中获取 有用的信息。先把全部网页都保存下来,比起后面时不时地下载网页方便多了。 首先,指定存放原始网页的目录。 • import os • data_folder = os.path.join(os.path.expanduser("~"), "Data", • "websites", "raw") 后面我们要用MD5散列算法为每篇报道创建一个唯一的文件名,所以先导入hashlib。 • import hashlib 如果所有网页都能成功下载,计数器输出值应该为0: • number_errors = 0 接下来,遍历每一篇新闻报道: • for title, url, score in stories:
获取数据
• except Exceຫໍສະໝຸດ Baidution as e:
number_errors += 1 print(e)
如果错误很多,把上面print(e)那一行改为raise,调用异常中断机制,以便修改问题。 现在,我们原始网页文件夹raw中有很多网页,查看这些网页(用文本编辑器打开),你会发现新闻报道 的内容湮没在HTML、JavaScript、CSS以及其他内容之中。因为我们只对报道本身感兴趣,就需要一种从 不同网站的网页中抽取内容的方法。 获得原始网页后,我们需要找出每个网页中的新闻报道内容。有一些在线资源使用数据挖掘方法来解决 这个问题。 一般来说,很少需要用到这些复杂的算法,当然使用它们能得到更为精确的结果。这也是数据挖掘艺术 的一部分——知道什么时候用,什么时候不用。 首先,获取到raw文件夹中的所有文件名: • filenames = [os.path.join(data_folder, filename) for filename in os.listdir(data_folder)] 接着,创建输出文件夹,新闻报道内容抽取出来后,将保存到该文件夹下。 • text_output_folder = os.path.join(os.path.expanduser("~"), "Data","websites",
lxml包解析HTML文件 scikit-learn实现了k-means 算法,直接从cluster模块导 入
工具根据词语出现在多少 篇文档中,对词语计数进 行加权
实验过程
第一步:提取数据
创建列表,存放这些不可能包含新 闻报道内容的节点。
#如果使用提供数据,请从此处开始,包含以下 data_folder = os.path.join("../", "Data", "websites", "textonly")
获取数据
数据资源宝库reddit 链接聚合网站reddit(www.reddit.com)拥有几亿用户,虽然英文版主 要面向美国。每个用户都可以发布他们感兴趣的网站的链接,同时为该链 接指定标题。 其他用户对其点赞,表示他们喜欢这个链接的内容,也可以投反对票,表 示不喜欢。点赞最高的链接将被移到网页的最上面,没有多少人喜欢的将 不会显示。随着时间的推移,先前发表的链接也将不再显示(根据喜欢数 来定)。 分享的链接被点赞后,用户将会获得叫作karma的积分,这也是为了激励 用户只分享好故事。
获取数据
对报道的标题进行散列操作,作为输出文件名,以保证唯一性。因为reddit网站不要求文章 标题具有唯一性,因此两篇报道可能使用相同的标题,这就会导致数据集中两条数据之间的冲 突。 我们使用MD5算法对报道的URL进行散列操作。现在人们发现MD5也不是绝对可靠的,但是 就我们这么小的数据规模来说不太可能出问题(出现碰撞情况),即使出现这样的问题,也不 用太担心。 • output_filename = hashlib.md5(url.encode()).hexdigest() • fullpath = os.path.join(data_folder, output_filename + ".txt") 接下来下载网页,保存到输出文件夹中。 • try:
使用我们前面获取到的令牌,就可以获取一个栏目的一系列链 接。/r/<subredditname>API端点默认返回所指定栏目的热门 文章。我们会使用/r/chinasubreddit: • subreddit = "worldnews“ • url = "https://oauth.reddit.com/r/{}".format(subreddit) 接下来,需要设置头部,这样才能指定授权令牌,设置独一无 二的用户代理,争取不会被过分限制请求次数。代码如下: • headers = {"Authorization": "bearer {}".format(token['access_token']),"User-Agent": USER_AGENT} • response = requests.get(url, headers=headers) 调用response的json方法,将会得到包含reddit返回信息的一 个Python字典。它包含给定栏目的25条广播,对它们进行遍历, 输出每条广播的标题。广播的相关内容存储在字典键为data的 那一项中。代码如下: • for story in result['data']['children']: • print(story['data']['title'])
"textonly")
实验过程
加载库
无论是否自行获取数据,都应当加载库 MD5散列算法相关库 import os import hashlib from lxml import etree import lxml.html as LH from sklearn.cluster import KMeans from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.pipeline import Pipeline from collections import Counter import matplotlib.pyplot as plt import numpy as np TfidfVectorizer向量化
理论前提
k-means 算法
经典机器学习算法k-means(k均值)
k-means算法会重复上述两个步骤;每次更新质心点时,所有质心点将会小范围移动。这会
轻微改变每个数据点在簇内的位置,从而引发下一次迭代时质心点的变动。这个过程会重复执 行直到条件不再满足时为止。通常是在迭代一定次数后,或者当质心点的整体移动量很小时, 就可以终止算法的运行。有时可以等算法自行终止运行,这表明簇已经相当稳定——数据点所 属的簇不再变动,质心点也不再改变时。 对于k-means算法,寻找新质心点的标准是,最小化每个数据点到最近质心点的距离。 这叫作算法的惯性权重(inertia),任何经过训练的KMeans实例都有该属性。