Python机器学习(一):绪论
一、什么是机器学习?
生活中,人们常常会基于生活经验,来判断未知的事物,而类似地
- 机器学习是基于过去,预测未来
- 机器学习是让机器具备寻找一个函数的能力,根据该函数 f(x),输入 x,得到想要的结果 y,并将该函数运用在各种领域
- 如图所示,输入一段音频信号,得到翻译结果;输入一张图片,得到图片内容;输入一种场景,得到最优解…
(图摘自李宏毅机器学习课程)
机器学习的概念建立在人工智能之上,人类传统解决问题的方法就是找到一种函数/流程,根据函数/流程来对问题进行求解,但现实中有许多人类无法解决的问题(有些问题很难建立一种标准的函数/流程),于是,我们通过机器来寻找这种函数
二、机器学习算法分类
1.监督学习(Supervised Learning)
监督学习就是从带标签的训练数据中学习得到模型,并用模型对新样本的标签进行预测,它包含以下模型:
- 分类(Classification)
标签为有限集合,即标签的类别是有限的或离散的
应用:垃圾邮件检测;图像识别;从症状到疾病的医学诊断 - 回归(Regression)
标签为实数值,是连续的数值
应用:预测股票价格;自动导航中的加速度与方向盘角度 - 主要算法:
K-近邻算法(KNN)
贝叶斯分类器
线性回归
逻辑回归
支持向量机(SVM)
决策树和随机森林
神经网络
集成学习
2.无监督学习(Unsupervised Learning)
无监督学习就是对无标签的训练数据进行分析,发现其结构或分布规律,它包含以下模型:
- 聚类(Clustering)
将一批无标签样本划分成多个类,保证同一类之间尽量相似
应用:自然语言处理(NLP)的文本分析 - 数据降维(Dimensionality Deduction)
将n维空间中的向量映射到更低维的m维空间中
应用:数据可视化;图像压缩 - 主要算法:
聚类算法
K-均值算法(K-means)
DBSCAN
分层聚类分析(HCA)
异常检测和新颖性检测
单类SVM
孤立森林
可视化和降维
主成分分析(PCA)
核主成分分析
局部线性嵌入(LLE)
t-分布随机近邻嵌入(t-SNE)
关联规则学习
Apriori
Eclat
3.半监督学习(Semi-Supervised Learning-SSL)
通常为数据打标签是非常耗时和昂贵的,你往往会有很多未标记的数据而很少有已标记的数据,而半监督学习算法可以处理部分已标记的数据
大多数半监督学习算法是无监督学习算法和有监督学习算法的结合,例如:深度信念网络 (DBN)
4.强化学习(Reinforcement Learning)
通过与环境的交互进行奖励学习的一系列行动,让智能体根据当前状态从与环境的交互中学习获得策略,产生行动获得奖励
- 目标:让智能体在特定环境中能采取回报最大化的行为
应用:自动驾驶
5.其他算法
- 模型选择(Model Selection)
参数和模型的比较、验证和选择
算法:网格搜索;交叉验证;度量…
应用:通过参数调优提高精度 - 预处理(Preprocessing)
特征提取和归一化
算法:预处理,特征提取…
应用:转换输入数据,如文本,用于机器学习算法
三、机器学习相关问题
1.建立机器学习模型的一般流程
1.1 Training 训练
- Function with Unknown Parameters 实例化,建立参数未知的模型
y = b + w x 1 y = b + wx_1 y=b+wx1,其中 x 1 x_1 x1 为已知数据, w w w 为权重, b b b 为偏差
当我们向模型输入已知数据 x 1 x_1 x1 时,模型就会输出 y y y,我们想让模型输出的 y y y 尽可能地逼近真实值 y 1 y_1 y1
同时,我们还想让所有的数据 { x 0 , x 1 , . . . , x n } \{x_0, x_1, ..., x_n\} {x0,x1,...,xn} 分别输入到模型中时,相应得到的结果都接近数据的真实值 { y 0 , y 1 , . . . , y n } \{y_0, y_1, ..., y_n\} {y0,y1,...,yn},这样就说明建立的模型的性能为优,其中,这些数据称为训练集
但是,如何建立这个模型呢? - Define Loss from Training Data 定义模型的训练数据损失
想要得到这个模型,我们就需要确定 b , w b, w b,w 的取值,如何确定呢?
定义损失函数 L o s s = L ( b , w ) Loss = L(b, w) Loss=L(b,w),Loss用来衡量当一个模型采用 ( b , w ) (b, w) (b,w) 组合来建立时,模型性能的好坏
当Loss越大时,模型的性能越差;当Loss越小时,模型的性能越好
针对不同模型的Loss函数的定义会有所不同 - Optimization 最优解
我们需要找到一组 ( b , w ) (b, w) (b,w) 来建立的模型,使模型的Loss最小,则找到了最优解——即将模型的性能最优化
方法:Gradient Descent 梯度下降
在选择不同的 ( b , w ) (b, w) (b,w) 组合时,可以得到不同的Loss值,由 L o s s = L ( b , w ) Loss = L(b, w) Loss=L(b,w) 可以构成一张三维图,为了找到Loss最小的 ( b , w ) (b, w) (b,w) 组合,我们利用了梯度的概念:如图,在标量场中,某点的梯度是一个矢量,其大小为具有最大增长率的方向导数,其方向为增长率最大的方向,则梯度的负方向就是Loss在该点上下降最快的方向
我们沿着梯度的负方向来不断修改 ( b , w ) (b, w) (b,w) 组合,使得Loss逐渐变小,至于每次修改多少取决于该点的梯度大小或自定义大小,称为 learning rate——学习速率,据此,我们很容易找到Loss的极小值点,这种方法我们称为梯度下降法
某 点 的 梯 度 : ▽ u = a b ∂ u ∂ b + a w ∂ u ∂ w 某点的梯度:▽u={\bf a_b}\frac{\partial u}{\partial b}+{\bf a_w}\frac{\partial u}{\partial w} 某点的梯度:▽u=ab∂b∂u+aw∂w∂u
梯度下降法可能会陷入局部最优解,即Loss的局部最小值,而我们需要找到全局最小值,此时的 ( b , w ) (b, w) (b,w) 组合才能使Loss最小,使模型达到最优性能,不过,局部最优解其实是个假问题,在机器学习中,我们需要面对的难题并非局部最优解
1.2 testing 测试
一般我们会将所拥有的数据分为: 75 % 75\% 75% 的训练集和 25 % 25\% 25% 的测试集,前者用于训练,而后者则用于测试模型的性能
如果模型对数据的预测性能不足,则称为欠拟合;如果模型在训练集上表现很好,而在测试集中表现不佳,则称为过拟合
泛化性: 模型对任意集合的预测效果都很好,则称为泛化性强
2.机器学习的主要挑战
- 训练数据的数量不足
- 训练数据不具代表性,如:数据冗余、数据噪声
- 低质量数据
- 无关特征
- 欠拟合训练数据
模型无法抓住数据的全部特征和规律 - 过拟合训练数据
模型对现有信息量来说过于复杂,导致模型在训练集上表现很好,而在实际测试时表现很差(泛化精度低) - 等…
四、软件环境
1.软件平台
我们将使用 Anaconda 进行包管理,在 Jupyter Lab 上进行代码编写
2.所需的Python库
#导入所需要的库
import pandas as pd
import numpy as np
import sklearn
import matplotlib as mlp
import scipy
import graphviz
其中,前五个库是 Anaconda 自带的,而 graphviz 需要安装,这个库可以帮助我们绘制决策树
在这之前,为了加快下载的速度,我们需要为 Anaconda 换源,更换为国内的镜像源
在 cmd 窗口中输入以下指令即可换源成功,这里更换为清华大学镜像源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
接着,还要修改一下生成的.condarc文件,防止更新再次使用默认的国外源,输入以下指令:
conda config --show-sources
出来的第一行就是配置文件的位置
使用记事本打开该配置文件,将 - defaults
删掉即可
为了使 Anaconda 保持较新的版本,我们需要更新一下 Anaconda,打开 Anaconda Prompt 终端
依次执行下面命令(这里是对 base 虚拟环境进行更新):
conda update conda
conda update anaconda
使用 conda 安装 graphviz 库
conda install graphviz
conda install python-graphviz
安装好后,输入以下命令查看 graphviz 的版本
dot -version
显示以下信息即下载成功
此时, Jupyter Lab 还不能导入 graphviz,还需要用 pip 安装 graphviz:
pip install graphviz
最后,尝试在 Jupyter Lab 上导入 graphviz,并查看版本
五、熟悉sklearn库
1.sklearn自带的数据集
import sklearn.datasets
在 JupyterLab 中导入 sklearn.datasets
包,并对 load 使用 Tab 键,发现sklearn自带了大量可供使用的数据集
我们可以进入sklearn的中文社区,查看这些数据集的详细信息:scikit-learn中文社区:查找关键词【sklearn.datasets.load…】
这里就sklearn中文社区列出了一些数据集的解释,方便调用:
方法 | 功能 |
---|---|
sklearn.datasets.load_boston | 加载并返回波士顿房价数据集(回归) |
sklearn.datasets.load_breast_cancer | 加载并返回乳腺癌数据集(分类) |
sklearn.datasets.load_diabetes | 加载并返回糖尿病数据集(回归) |
sklearn.datasets.load_digits | 加载并返回数字数据集,每个数据点都是一个8x8的数字图像(分类) |
sklearn.datasets.load_files | 加载带有类别作为子文件夹名称的文本文件 |
sklearn.datasets.load_iris | 加载并返回鸢尾花数据集(多分类) |
sklearn.datasets.load_linnerud | 加载并返回linnerud物理锻炼数据集(多输出回归任务) |
sklearn.datasets.load_wine | 加载并返回葡萄酒数据集(分类) |
例如: 我们以导入 load_wine 葡萄酒数据集为例
这里只能截取一部分
可以看到其包含了大量的数据,其中标签为
{
0
、
1
、
2
}
\{0、1、2\}
{0、1、2},显然这是一个三分类数据集
其中数据 data 为
178
×
13
178\times13
178×13 的数组
我们查看一下葡萄酒数据集的属性/特征名:
翻译过来就是:
feature_name = ['酒精', '苹果酸', '灰', '灰的碱性', '镁',
'总酚', '类黄酮', '非黄烷类酚类', '花青素',
'颜色强度', '色调', 'od280/od315稀释葡萄酒', '脯氨酸']
查看分类标签的名字,指定了很简单的三个名字
实际上,它们分别是:
target_names = ["琴酒", "雪莉", "贝尔摩德"]
2.划分数据集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y,**options)
随机将数据集按指定比例划分为训练集和测试集
X, y
分别位数据集 (data) 和标签 (target) ,允许输入 列表、numpy数组、稀疏矩阵、DataFrame
test_size
、train_size
如果为 [0.0, 1.0] 之间的 float 类型,则表示 测试集或训练集 占原数据集的百分比
如果为 int 类型,则表示数据集中要划分为 测试集或训练集 的数量
如果其一为 None,则分别表示为对方的补集;若两个都为 None,则按 0.75 和 0.25 分配训练集和测试集
random_state
随机数种子,int 类型
X_train, X_test, y_train, y_test
返回值:训练集数据,测试集数据,训练集标签,测试集标签
例如: 导入 load_wine 葡萄酒数据集,并划分
# 导入相关库
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
# 加载并返回葡萄酒数据集
wine = load_wine()
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(wine.data, wine.target, test_size=0.3)
# 打印划分情况
print("wine.data.shape:{}, X_train.shape:{}, X_test.shape{}".format(wine.data.shape, X_train.shape, X_test.shape))
输出结果: