什么是机器学习
机器学习是一门能够让编程计算机从数据中学习的计算机科学(和艺术)。
工程化定义:
一个计算机程序在完成任务T之后,获得经验E,其表现效果为P,如果任务T的性能表现,也就是用以衡量的P,随着E的增加而增加,可以称之为机器学习。
为什么要使用机器学习
1.通过机器学习算法可以简化那些现有解决方案需要大量手动调整或者规则列表超长的问题的代码,并且提升执行表现;
- 比如用传统编程技术编写垃圾邮件过滤器
2.解决传统技术手段根本无法解决的复杂问题;
- 语音识别问题
3.在环境波动中适应新的数据;
- 新写法的垃圾邮件
4.从复杂问题和海量数据中获得洞见。
- 通过研究训练效果优秀的学习算法的数据,了解人类没有发现的数据中的关联性或新趋势
机器学习系统的种类
监督/无监督学习
标准:是否在人类的监督下训练
监督学习
分类问题:
垃圾邮件过滤
回归问题:
汽车价格预测
房价预测
重要的监督学习算法:
- K-近邻算法(KNN)
- 线性回归(LR)
- 逻辑回归(LR)
- 支持向量机(SVM)
- 决策树和随机森林(DT RF)
- 一部分神经网络(NN)
无监督学习(异常检测:比如信用卡欺诈,又或者从数据集中移除异常值)
聚类算法(比如,检测相似访客的分组)
- K-平均算法(K-means)
- 层次聚类分析(HCA)
- 最大期望算法(EM)
可视化和降维(可视化,便于人理解数据怎么组织)(降维,用来做特征提取,减小数据所占空间,提高速度,有可能提高性能)
- 主成分分析(PCA)
- 核主成分分析(Kernel PCA)
- 局部线性嵌入(LLE)
- t-分布领域嵌入算法(t-SNE)
关联规则学习(发现数据属性间的联系:比如超市的商品)
- Apriori
- Eclat
半监督学习
- 大量未标记数据和少量已标记数据
- 大多数半监督算法采用无监督和监督算法结合
- 深度信念网络(DBN)基于一种互相叠加的非监督组件(受限玻尔兹曼机),然后用监督学习进行微调
强化学习
学习系统,又称为智能体,能够观察环境,作出选择,执行操作,并获得回报,或者以负面回报的形式获得惩罚。
- 比如:AlphaGo
批量学习和线上学习
标准:是否能从导入的数据流进行持续学习
批量学习
必须使用所有的可用数据进行训练,一般采用离线学习的方式,即先训练系统,然后将其投入生产环境,这时候学习过程停止,只是将所学的应用处理。只是每次更新数据的时候,重新训练的成本较大。
线上学习
又称为增量学习,持续接收数据流,并同时对数据流的变化做出快速或自主的反应,可以解决超大数据集的训练问题。
需要指出的是,整个训练通常也是离线完成的,“在线学习”具有歧义性,称为增量学习更合适。
基于实例学习与基于模型的学习
是将新的数据和已知的数据进行匹配,还是对训练数据进行模式检测,进而建立预测模型。根据如何泛化来分类。
基于实例的学习
将所有的训练数据全部记住,然后根据某种相似度度量方式将其泛化到新的实例
基于模型的学习
构建符合训练数据特征的模型,然后根据模型来预测
案例
- 任务:根据人均GDP预测人民生活满意度的例子
- 模型选择:猜测数据符合线性函数
- 度量模型的性能表现:定义实用函数(模型有多好)或者代价函数(模型有多坏)
人均GDP与生活满意度表
人均GDP与生活满意度数据图
尽管数据有噪声(即,部分随机),看起来生活满意度是随着人均GDP的增长线性提高的。所以,你决定生活满意度建模为人均GDP的线性函数。这一步称作模型选择:你选一个生活满意度的线性模型,只有一个属性,人均GDP。
这个模型有两个参数θ0和θ1。通过调整这两个参数,你可以使你的模型表示任何线性函数。
在使用模型之前,你需要确定θ0和θ1。如何能知道哪个值可以使模型的性能最佳呢?
要回答这个问题,你需要指定性能的量度。你可以定义一个实用函数(或拟合函数)用来测量模型是否够好,或者你可以定义一个代价函数来测量模型有多差。对于线性回归问题,人们一般是用代价函数测量线性模型的预测值和训练样本的距离差,目标是使距离差最小。
接下来就是线性回归算法,你用训练样本训练算法,算法找到使线性模型最拟合数据的参数。这称作模型训练。在我们的例子中,算法得到的参数值是θ0=4.85和θ1=4.91×10–5。
最后,可以准备运行模型进行预测了。例如,假如你想知道塞浦路斯人有多幸福,但OECD没有它的数据。幸运的是,你可以用模型进行预测:查询塞浦路斯的人均GDP,为22587美元,然后应用模型得到生活满意度,后者的值在4.85 + 22,587 × 4.91 × 10-5 = 5.96左右。
以下将展示加载数据、准备、创建散点图的Python代码,然后训练线性模型并进行预测。
# 样例:根据人均GDP预测人民生活满意度
# 线性模型
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn
from sklearn.linear_model import LinearRegression
from sklearn.neighbors import KNeighborsRegressor
%matplotlib inline
np.random.seed(42) # 随机种子
# 加载数据
oecd_bli = pd.read_csv("./datasets/lifesat/oecd_bli_2015.csv", thousands=',')
gdp_per_capita = pd.read_csv("./datasets/lifesat/gdp_per_capita.csv",thousands=',',delimiter='\t',
encoding='latin1', na_values='n/a')
oecd_bli.head() # 默认5行
LOCATION | Country | INDICATOR | Indicator | MEASURE | Measure | INEQUALITY | Inequality | Unit Code | Unit | PowerCode Code | PowerCode | Reference Period Code | Reference Period | Value | Flag Codes | Flags | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | AUS | Australia | HO_BASE | Dwellings without basic facilities | L | Value | TOT | Total | PC | Percentage | 0 | units | NaN | NaN | 1.1 | E | Estimated value |
1 | AUT | Austria | HO_BASE | Dwellings without basic facilities | L | Value | TOT | Total | PC | Percentage | 0 | units | NaN | NaN | 1.0 | NaN | NaN |
2 | BEL | Belgium | HO_BASE | Dwellings without basic facilities | L | Value | TOT | Total | PC | Percentage | 0 | units | NaN | NaN | 2.0 | NaN | NaN |
3 | CAN | Canada | HO_BASE | Dwellings without basic facilities | L | Value | TOT | Total | PC | Percentage | 0 | units | NaN | NaN | 0.2 | NaN | NaN |
4 | CZE | Czech Republic | HO_BASE | Dwellings without basic facilities | L | Value | TOT | Total | PC | Percentage | 0 | units | NaN | NaN | 0.9 | NaN | NaN |
gdp_per_capita[:5]
Country | Subject Descriptor | Units | Scale | Country/Series-specific Notes | 2015 | Estimates Start After | |
---|---|---|---|---|---|---|---|
0 | Afghanistan | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 599.994 | 2013.0 |
1 | Albania | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 3995.383 | 2010.0 |
2 | Algeria | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 4318.135 | 2014.0 |
3 | Angola | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 4100.315 | 2014.0 |
4 | Antigua and Barbuda | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 14414.302 | 2011.0 |
# 数据预处理
def prepare_country_stats(oecd_bli, gdp_per_capita):
oecd_bli = oecd_bli[oecd_bli["INEQUALITY"]=="TOT"]
oecd_bli = oecd_bli.pivot(index="Country", columns="Indicator", values="Value")
gdp_per_capita.rename(columns={"2015": "GDP per capita"}, inplace=True)
gdp_per_capita.set_index("Country", inplace=True)
full_country_stats = pd.merge(left=oecd_bli, right=gdp_per_capita, left_index=True, right_index=True)
full_country_stats.sort_values(by="GDP per capita", inplace=True)
remove_indices = [0, 1, 6, 8, 33, 34, 35]
keep_indices = list(set(range(36)) - set(remove_indices))
return full_country_stats[["GDP per capita", "Life satisfaction"]].iloc[keep_indices]
# 准备数据
country_stats = prepare_country_stats(oecd_bli, gdp_per_capita)
X = np.c_[country_stats["GDP per capita"]]
y = np.c_[country_stats["Life satisfaction"]]
country_stats.head()
GDP per capita | Life satisfaction | |
---|---|---|
Country | ||
Russia | 9054.914 | 6.0 |
Turkey | 9437.372 | 5.6 |
Hungary | 12239.894 | 4.9 |
Poland | 12495.334 | 5.8 |
Slovak Republic | 15991.736 | 6.1 |
# 可视化数据
country_stats.plot(kind='scatter', x="GDP per capita", y='Life satisfaction')
plt.show()
# 定义线性模型
lin_reg_model = LinearRegression()
# 训练模型
lin_reg_model.fit(X, y)
# 对塞浦路斯进行预测
X_new = [[22587]] # 塞浦路斯的人均GDP
print(lin_reg_model.predict(X_new))
[[5.96242338]]
# 定义k近邻模型,并训练和预测
clf = KNeighborsRegressor(n_neighbors=3)
clf.fit(X, y)
X_new = [[22587]]
print(clf.predict(X_new))
[[5.76666667]]
如果一切顺利,模型就可以作出好的预测。如果不能,可能需要使用更多的属性(就业率、健康、空气污染等等),获取更多更好的训练数据,或选择一个更好的模型(比如,多项式回归模型)。
总结一下:
- 研究数据;
- 选择模型;
- 用训练数据进行训练(即,学习算法搜寻模型参数值,使代价函数最小);
- 最后,使用模型对新案例进行预测(这称作推断),但愿这个模型推广效果不差。
机器学习的主要挑战
训练数据的数量不足
目前大部分机器学习算法都需要大量的数据才能正常工作(除非重用现有模型的某些部分)。
数据的不合理有效性
2001年,微软有研究员表明,截然不同的机器学习算法(包括最简单的算法)在自然语言歧义消除这个复杂问题的表现上,几乎完全一致
这些数据表明,和算法开发上,数据的建设尤为重要。
训练数据不具代表性
就如之前的根据人均GDP预测人民生活满意度任务为例,如果有部分数据缺失,则会是模型的预测不准确。
采样偏差
采样偏差是使训练数据不具代表性的重要原因,一个著名的案例是1936年,兰登对决罗斯福。
其次,还有一种特殊类型的采样偏差,叫做无反应偏差。
质量差的数据
如果训练数据满是错误、异常值和噪声,系统将更难检测到底层模式,更不可能会表现更好,所以很有必要花时间处理训练数据。
- 如果一些实例是明显的异常值,最好删掉它们或尝试手工修改错误;
- 如果一些实例缺少特征(比如,你的5%的顾客没有说明年龄),你必须决定是否忽略这个属性、忽略这些实例、填入缺失值(比如,年龄中位数),或者训练一个含有这个特征的模型和一个不含有这个特征的模型,等等。
无关特征
正所谓:垃圾入,垃圾出。只有在训练数据包含足够相关特征、非相关特征不多的情况下,才能进行学习。机器学习项目成功的关键之一是用好的特征进行训练。这个过程称作特征工程,包括:
- 特征选择:选取最有用的特征进行训练;
- 特征提取:将现有的特征进行组合,产生更有用的特征(比如,降维);
- 收集新数据创建新特征。
过拟合训练数据
还是以人均GDP预测人民生活满意度为例。
如果我们采用高阶多项式,固然可以获得在训练数据上表现好得多的模型,但显然,也是一点用都没有的。
警告:过拟合发生在相对于训练数据的量和噪声,模型过于复杂的情况。可能的解决方案有:
- 简化模型,可以通过选择一个参数更少的模型(比如使用线性模型,而不是高阶多项式模型)、减少训练数据的属性数、或限制一下模型;
- 收集更多的训练数据;
- 减小训练数据的噪声(比如,修改数据错误和去除异常值)。
欠拟合训练数据
与过拟合相反,产生的原因是对于训练数据来说,模型过于简单,比如用线性模型预测幸福值,就属于拟合不足,因为实际情况显然比这要复杂的多。
解决方式:
- 选择一个更强大的模型,带有更多参数;
- 用更好的特征训练学习算法(特征工程);
- 减小对模型的限制(比如,减小正规化超参数)。
回顾
- 机器学习是让机器通过学习数据对某些任务做得更好,而不使用确定的代码规则;
- 有许多不同类型的机器学习系统:监督或非监督,批量或线上,基于实例或基于模型,等等;
- 在机器学习项目中,训练集来收集数据,然后对学习算法进行训练。如果算法是基于模型的,就调节一些参数,让模型拟合到训练集(即,对训练集本身作出好的预测),然后希望它对新样本也能有好预测。如果算法是基于实例的,就是用记忆学习样本,然后用相似度推广到新实例;
- 如果训练集太小、数据没有代表性、含有噪声、或掺有不相关的特征(垃圾进,垃圾出),系统的性能不会好。最后,模型不能太简单(会发生欠拟合)或太复杂(会发生过拟合)。
测试和验证
了解一个模型对于新场景的泛化能力1唯一方法就是,让模型真实的取处理新场景。
测试集
做法之一是将模型部署到新场景,然后监控它的输出。但这样如果模型效果不好,用和肯定会抱怨,所以这显然不是最好的办法。
更好的选择是将数据分割成两部分:训练集和测试集。顾名思义,训练集用来训练模型,测试集用来测试模型,应对新场景的误差率称为泛化误差。通过测试集来评估模型,就可以得到对这个误差的评估。这个评估可以知道模型在处理新场景的能力如何。 如果训练误差很低(模型对于训练集很少出错),但是泛化误差很高,那说明模型对于训练数据存在过度拟合。
通常采用2/8定律,20%用于测试,80%用于训练。
交叉验证
评估一个模型,可以采用测试集,那么对于多个模型呢?(比如线性模型和多项式模型)
这时候,千万不要用测试集去验证,这样仍然会出现过拟合。正确的做法是交叉验证,通过将训练机分成若干个互补的子集,然后将多个模型,在这些子集的不同组合进行训练,再用剩下的子集进行验证,从而选定最好的模型,最后再用测试集来测试泛化误差。
没有免费午餐公理
模型是观察的简化,这个简化是丢弃了那些不大可能泛化到新实例上的多余细节。要确定舍弃什么数据、保留什么数据,必须要做假设。例如,线性模型的假设是数据基本上是线性的,实例和模型直线间的距离只是噪音,可以放心忽略。
1996年,David Wolpert提到,如果没有对数据做出假设,那么就没有理由更偏好于哪个模型,那么想要知道哪个模型最好的方式,就是对所有模型进行评估。但实际上是不可能的,所以需要对数据做出一些合理的假设。
例如,对于简单任务,你可能是用不同程度的正规化评估线性模型,对于复杂问题,你可能要评估几个神经网络模型。