第一讲 机器会学习么?--介绍学习-----学习总结
机器学习定义:
We define machine learning as a set of methods that can automatically detect patterns in data, and then use the uncovered patterns to predict future data, or to perform other kinds of decision making under uncertainty (such as planning how to collect more data!).
大数据、人工智能、机器学习和深度学习:
机器学习方法的分类:
有监督学习(supervised learning) 数据集中的样本带有标签,有明确目标 回归和分类
数据集中的样本带有标签
目标:找到样本到标签的最佳映射
应用场景:垃圾邮件分类、病理切片分类、客户流失预警、客户风险评估、房价预测等。
典型方法:回归模型:线性回归、岭回归、LASSO和回归样条等 分类模型:逻辑回归、K近邻、决策树、支持向量机等
无监督学习(unsupervised learning) 数据集中的样本没有标签,没有明确目标 聚类、降维、排序、密度估计、关联规则挖掘
根据数据本身的分布特点,挖掘反映数据的内在特性
聚类:将数据集中相似的样本进行分组,使得: 同一组对象之间尽可能相似; 不同组对象之间尽可能不相似。
应用场景: 基因表达水平聚类:根据不同基因表达的时序特征进行聚类,得到基因表达处于信号通路上游还是下游的信息 篮球运动员划分:根据球员相关数据,将其划分到不同类型(或者不同等级)的运动员阵营中 客户分析:把客户细分成不同客户群,每个客户群有相似行为,做到精准营销
例子:
强化学习(reinforcement learning) 智慧决策的过程,通过过程模拟和观察来不断学习、提高决策能力 例如:AlphaGo
数据集:
一般流程:
过度拟合问题:
模型选择:
机器学习的数学结构:
数据也是有数学结构的,没有数学结构我们便无法处理数据。
度量结构:表示数据之间的距离。
网络结构:有些数据本身就有网络结构,如社交网络。如果没有,可以利用度量结构给数据附加一个网络结构。
代数结构:将数据看作向量、矩阵或更高阶的张量。
几何结构:流形、对称性等
度量结构:以文本处理为例
其他距离:
k近邻:
网络结构
PageRank算法
Scikit-learn概览
Scikit-learn
Python用于数据建模的第三方库
实现主要的机器学习、数据挖掘算法 Scikit-learn的
主要功能:
数据集预处理
数据集划分
构建模型
模型提升
模型评估
常用函数:
Scikit-learn主要模块
案例1:使用 KNN 对新闻主题进行自动分类
代码解决:http://cookdata.cn/note/view_static_note/ca759b585803e5a3fb8e0f5053cd010e/
本案例旨在用新闻主题分类这一简单任务演示机器学习的一般流程。具体地,我们使用了一个搜狐新闻数据集。使用 Python 的 jieba 分词工具对中文新闻进行了分词处理。然后使用 Scikit-learn 工具的 K近邻算法构建 KNN 模型。最后对新闻分类的效果进行了简单的分析。
1 数据读取
搜狐中文新闻数据存放在 train_sample_utf8.csv 和 test_sample_utf8.csv 两个文件中,在后面的分析中我们分别当做训练集和测试集来使用。我们首先使用 Pandas
中的 read_csv
函数读取。
import pandas as pd
%matplotlib inline
raw_train = pd.read_csv("./input/train_sample_utf8.csv",encoding="utf8")
raw_test = pd.read_csv("./input/test_sample_utf8.csv",encoding="utf8")
查看两个文件的前五行数据。
raw_train.head(5)
raw_test.head(5)
raw_train.shape
raw_test.shape
可见,训练集包含 5521 条新闻,测试集中包含 3111 条新闻。那么,训练集和测试集中,不同主题的新闻分布如何?我们可以借助 DataFrame
某列的 value_counts
方法完成统计。然后使用 plot
函数进行可视化显示。
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 8))
plt.subplot(1, 2, 1)
raw_train["分类"].value_counts().sort_index().plot(kind="barh",title='训练集新闻主题分布')
plt.subplot(1, 2, 2)
raw_test["分类"].value_counts().sort_index().plot(kind="barh",title='测试集新闻主题分布')
一共包含 12 种主题的新闻,无论是在训练集还是测试集,各个主题的新闻分布较均衡。
2 对新闻内容进行分词
由于新闻为中文,再进一步进行处理之前,我们需要先对新闻内容进行分词。简单来说,分词就是将连在一起的新闻内容中的词进行分割。这里我们使用 Python 中一个著名的中文分析器 jieba
完成这项任务。为了后续方便,我们封装一个 news_cut
函数,它接受的输入为新闻内容,输出为分词后的结果。分词后,词与词之间使用空格进行分隔。
import jieba
def news_cut(text):
return " ".join(list(jieba.cut(text)))
#简单测试下分词效果
test_content = "六月初的一天,来自深圳的中国旅游团游客纷纷拿起相机拍摄新奇刺激的好莱坞环球影城主题公园场景。"
print(news_cut(test_content))
现在利用封装的分词函数,对训练集和测试集中的新闻内容进行分词处理,分词结果保存到对应 DataFrame 对象的 ”分词文章“ 一列。这里我们使用了 Pandas
中的 Series
对象的 map
函数。它能够接受一个函数,对 Series
中的每一个元素作为该函数的输入,然后将函数的输出返回。
raw_train["分词文章"] = raw_train["文章"].map(news_cut)
raw_test["分词文章"] = raw_test["文章"].map(news_cut)
raw_test.head(5)
3 将新闻表示为向量
#加载停用词
stop_words = []
file = open("./input/stopwords.txt")
for line in file:
stop_words.append(line.strip())
file.close()
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(stop_words=stop_words)
X_train = vectorizer.fit_transform(raw_train["分词文章"])
X_test = vectorizer.transform(raw_test["分词文章"])
4 构建 KNN 分类器
使用 sklearn
中 neighbors
模块的 KNeighborsClassifier
类构建一个 KNN 分类器。我们将邻居数 n_neighbors
设置为 5 。使用邻居的标签进行投票时,用预测样本与邻居样本的距离的倒数作为权重。然后使用 fit
方法,在训练集中训练模型。
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5,weights="distance")
knn.fit(X_train, raw_train["分类"])
5 测试集新闻主题预测
模型训练完成后,可以使用 predict
方法对测试集中的样本进行预测,得到预测标签列表 Y_test
。
Y_test = knn.predict(X_test)
6 新闻主题分类效果进行评估
下面使用混淆矩阵来分析模型在测试样本上的表现。混淆矩阵从样本的真实标签和模型预测标签两个维度对测试集样本进行分组统计,然后以矩阵的形式展示。借助混淆矩阵可以很好地分析模型在每一类样本上的分类效果。为了更直观地分析,我们借助 Python 中可视化包 seaborn
提供的 heatmap
函数,将混淆矩阵可视化。
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(9, 7))
## 设置正常显示中文
sns.set(font='SimHei')
## 绘制热力图
ax = sns.heatmap(confusion_matrix(raw_test["分类"].values,Y_test),linewidths=.5,cmap="Greens",
annot=True, fmt='d',xticklabels=knn.classes_, yticklabels=knn.classes_)
ax.set_ylabel('真实')
ax.set_xlabel('预测')
ax.xaxis.set_label_position('top')
ax.xaxis.tick_top()
ax.set_title('混淆矩阵热力图')
这还不是一个完美的新闻主题分类器,这个分类器倾向于将主题预测为"教育"或"文化"。要获得更好的效果,我们可能还需要做很多工作,例如更好的文本预处理和表示,尝试不同的 K 值的效果,甚至利用其它的机器学习算法等。感兴趣的同学可以自己进一步进行尝试。
案例2:使用 PageRank 对全球机场进行排序
代码解决:
http://cookdata.cn/note/view_static_note/c73c2c8ae61485ac923995add62135ba/
PageRank 是谷歌公司起家的算法,在数据科学领域具有重要的地位和作用。PageRank 算法最初提出来用于利用网页之间的链接关系来对网页进行排序,从而优化搜索引擎的效果。如今,我们可以将 PageRank 算法用作网络中节点排序的一般算法。
在本案例中,我们使用一个全球机场之间航线的网络数据集,借助 Python 中的复杂网络分析库 networkx 中实现的 PageRank 算法,完成对全球机场的排序。
1 数据集介绍
文件 ./input/out.opsahl-openflights.csv
中的有向网络包含世界各机场之间的航班。有向边表示从一个机场到另一个机场的飞行航线。这个数据集是从Openflights.org 数据中提取出来的,与 Tore Opsahl 在数据集列表中的网络14c相对应,来源网址为:toreopsahl.com。
利用 networkx
中的 read_edgelist
函数,将网络加载到内存中。注意,由于我们处理的是有向网络,所以需要将 create_using
参数设置为 nx.DiGraph()
。
import networkx as nx
flights_network = nx.read_edgelist("./input/out.opsahl-openflights.csv",create_using=nx.DiGraph())
print("航班数:" + str(len(flights_network.nodes)))
print("航线数:" + str(len(flights_network.edges)))
在这个航线网络中,一共包含 2939 个机场,30501 条航线。下面我们使用 nx.draw
函数,将网络进行可视化。
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(figsize=(24, 16))
pos_flights = nx.kamada_kawai_layout(flights_network) #网络布局
ax.axis("off")
plt.box(False)
nx.draw(flights_network, node_size=30,node_color = "green", edge_color = "#D8D8D8",width=.3, ax=ax)
2 找出最大连通子图
从上图中很容易看出,这个网络不是一个连通图。我们从航线网络中提取出最大连通子图进行进一步分析。 对于有向网络, networkx
中的 weakly_connected_component_subgraphs
函数可以返回网络中的连通子图列表。我们只提取最大连通子图。
largest_component = max(nx.weakly_connected_component_subgraphs(flights_network), key=len)#找出最大连通子图
print("航班数:" + str(len(largest_component.nodes)))
print("航线数:" + str(len(largest_component.edges)))
在最大连通子图中,一共包含 2905 个机场和 30442 条航线。下面将最大连通子图进行可视化。
fig, ax = plt.subplots(figsize=(24, 16))
pos_flights2 = nx.kamada_kawai_layout(largest_component)
ax.axis("off")
plt.box(False)
nx.draw(largest_component, node_size=30,node_color = "green", edge_color = "#D8D8D8",width=.3,pos = pos_flights2, ax=ax)
3 PageRank 算法简介
PageRank算法是由谷歌创始人拉里·佩奇(Larry Page)和谢尔盖·布林(Sergey Brin)所设计出来的谷歌搜索引擎上的页面排序算法,最早作为论文发表于 1998 年。 论文发表之后没多久,佩奇和布林就以此论文为基础创立了谷歌公司。
PageRank是一个迭代算法。 在初始的时候,每个点的PageRank值都设置成1|V|1|V|,其中|V||V|为图中点的数量。 在每一轮的迭代中,每个点 vv 都沿着它的出边往它每个邻居点传递 vv 的 1|N+(v)|1|N+(v)| 的PageRank值。 于是,经过第 t+1t+1 轮迭代之后,每个点 vv 的PageRank值可以表示为
阻尼系数 ββ 用来表示在PageRank迭代过程中一个点沿着出边跳转到下一个点的概率。 (1−β)(1−β) 表示在浏览过程不沿着边跳转,而是在所有点中随机挑选下一个点的概率。 实际试验证明 ββ 被设置成 0.850.85 时 PageRank 的计算结果最符合实际情况。
4 使用 PageRank 算法对机场进行排序
在 networkx
中,使用 pagerank
函数即可计算网络中节点的 PageRank 值。
pr_dict = nx.pagerank(largest_component)
import pandas as pd
pr_df = pd.DataFrame.from_dict(pr_dict,orient="index")
pr_df.columns = ["pr_value"]
pr_df.sort_values(by = "pr_value").head(20)
pr_df.head(20)
5 将节点大小与 PageRank 值关联并可视化
实现一个函数 get_nodesize_pagerank
,将网络中节点的 PageRank 值,映射为网络中节点的大小。
def get_nodesize_pagerank(pagerank, min_size, max_size):
nodesize_list = []
pr_max = max(pagerank.values())
for node, pr in pagerank.items():
nodesize = (max_size - min_size)*pr/pr_max + min_size
nodesize_list.append(nodesize)
return nodesize_list
fig, ax = plt.subplots(figsize=(24, 16))
pos_flights2 = nx.kamada_kawai_layout(largest_component)
ax.axis("off")
plt.box(False)
nx.draw(largest_component, node_size=get_nodesize_pagerank(pr_dict,1,100),node_color = "green", edge_color = "#D8D8D8",width=.3,pos = pos_flights2, ax=ax)