2021-05-31

12句话入门机器学习

这是一篇关于机器学习工具包Scikit-learn的入门级读物。对于程序员来说,机器学习的重要性毋庸赘言。也许你还没有开始,也许曾经失败过,都没有关系,你将在这里找到或者重拾自信。只要粗通Python,略知NumPy,认真读完这21句话,逐行敲完示例代码,就可以由此进入*的王国。

  1. 机器学习有四种用途:分类、聚类、回归和降维。
    理解了这句话,就意味着学会了机器学习。迷茫的时候,在心里默念这句话,就会找到前进的方向。更严格一点,机器学习的目的只有三个:分类、聚类和回归,降维不过是达成目标的手段之一。

  2. 分类和聚类都是对个体样本归类,看起来很相似,实则相去甚远——前者属于有监督的学习,后者属于无监督的学习。
    分类是基于经验的,而经验来自过往的数据,这意味着分类需要训练;聚类则是基于当前全部样本的特征,不依赖经验,自然也就无需训练。举个例子:让你从一堆水果中挑出苹果、橘子和香蕉,这是分类;让你将画在纸上的若干个图案分组,分组规则由你决定,这是聚类。

  3. 从字面上看,分类和回归看上去风马牛不相及,其实二者是亲兄弟,使用的算法几乎完全重合。
    分类是对个体样本做出定性判定,回归是对个体样本做出定量判定,二者同属于有监督的学习,都是基于经验的。举个例子:有经验的老师预测某学生考试及格或不及格,这是分类;预测某学生能考多少分,这是回归;不管是预测是否及格还是预测考多少分,老师的经验数据和思考方法是相同的,只是最后的表述不同而已。

  4. 传统的软件开发,代码是重点,而对于机器学习,数据是重点。
    在训练机器学习模型时,数据的质量和数量都会影响训练结果的准确性和有效性。因此,无论是学习还是应用机器学习模型解决问题,前提都是要有足够多且足够好的数据集。

  5. 数据集通常是指由若干个样本数据组成的二维数组,数组的每一行表示一个样本的数据。
    举个例子:用性别、年龄、身高(米)、体重(千克)、职业、年薪(万元)、不动产(万元)、有价证券(万元)等信息组成的一维数组表示一位征婚者的数据,下面的二维数组就是一个婚介机构收集到的征婚者数据集。

import numpy as np
members = np.array([
[‘男’, ‘25’, 185, 80, ‘程序员’, 35, 200, 30],
[‘女’, ‘23’, 170, 55, ‘公务员’, 15, 0, 80],
[‘男’, ‘30’, 180, 82, ‘律师’, 60, 260, 300],
[‘女’, ‘27’, 168, 52, ‘记者’, 20, 180, 150]
])
1
2
3
4
5
6
7

  1. 数据集的列,也被称为特征维或特征列。
    上面的征婚者数据集共有性别、年龄、身高(米)、体重(千克)、职业、年薪(万元)、不动产(万元)、有价证券(万元)等8列,也可以说这个数据集有8个特征维或特征列。

  2. 所谓降维,并非是将数据集从二维变成一维,而是减少数据集的特征维。
    征婚者的个人信息远不止上面所列出的这8项,还可以加上生日、业余爱好、喜欢的颜色、爱吃的食物等等。不过,要是将所有的个人信息都加入到数据集中,不但会增加数据保存和处理的难度和成本,对于择偶者来说,也会因为信息量太多而分散了注意力,以至于忽略了最重要的信息。降维就是从数据集中剔除对结果无影响或影响甚微的特征列。

  3. 标准化是对样本集的每个特征列减去该特征列的平均值进行中心化,再除以标准差进行缩放。
    满分为100分的考试中,你如果得了90分,这自然是一个好成绩。不过要是和其他同学比的话,就未必是了:假如其他同学都是满分,那90分就是最差的一个。数据标准化的意义在于反映个体数据偏离所有样本平均值的程度。下面是对征婚者数据集中有价证券特征列标准化后的结果。

security = np.float32((members[:,-1])) # 提取有价证券特征列数据
security
array([ 30., 80., 300., 150.], dtype=float32)

(security - security.mean())/security.std() # 减去均值再除以标准差
array([-1.081241, -0.5897678, 1.5727142, 0.09829464], dtype=float32)
1
2
3
4
5

  1. 归一化是对样本集的每个特征列减去该特征列的最小值进行中心化,再除以极差(最大值最小值之差)进行缩放。
    归一化处理类似于标准化,结果收敛于[0,1]区间内。下面是对征婚者数据集中有价证券特征列归一化后的结果。

security = np.float32((members[:,-1])) # 提取有价证券特征列数据
security
array([ 30., 80., 300., 150.], dtype=float32)

(security - security.min())/(security.max() - security.min()) # 减去最小值再除以极差
array([0., 0.18518518, 1., 0.44444445], dtype=float32)
1
2
3
4
5

  1. 机器学习模型只能处理数值数据,因此需要将性别、职业等非数值数据变成整数,这个过程被称为特征编码。
    征婚者数据集中,对于性别特征列,可以用0表示女性,用1表示男性,或者反过来也没有问题。不过这个方法不适用于职业特征列的编码,因为不同职业之间原本是无序的,如果用这个方法编码,就会产生2比1更接近3的问题。此时通行的做法是使用独热码(one-of-K):若有n个不同的职业,就用n位二进制数字表示,每个数字只有1位为1其余为0。此时,职业特征列将从1个扩展为n个。下面使用Scikit-learn的独热码编码器对性别和职业两列做特征编码,生成6个特征列(性别2列,职业4列)。该编码器位于preprocessing子模块中。

from sklearn import preprocessing as pp
X = [
[‘男’, ‘程序员’],
[‘女’, ‘公务员’],
[‘男’, ‘律师’, ],
[‘女’, ‘记者’, ]
]

ohe = pp.OneHotEncoder().fit(X)
ohe.transform(X).toarray()
array([[0., 1., 0., 0., 1., 0.],
[1., 0., 1., 0., 0., 0.],
[0., 1., 0., 1., 0., 0.],
[1., 0., 0., 0., 0., 1.]])
1
2
3
4
5
6
7
8
9
10
11
12
13

  1. Scikit-learn的数据集子模块datasets提供了若干数据集:函数名以load 开头的是模块内置的小型数据集;函数名以fetch开头,是需要从外部数据源下载的大型数据集。
    datasets.load_boston([return_X_y]) :加载波士顿房价数据集
    datasets.load_breast_cancer([return_X_y]) :加载威斯康星州乳腺癌数据集
    datasets.load_diabetes([return_X_y]) :加载糖尿病数据集
    datasets.load_digits([n_class, return_X_y]) :加载数字数据集
    datasets.load_iris([return_X_y]) :加载鸢尾花数据集。
    datasets.load_linnerud([return_X_y]) :加载体能训练数据集
    datasets.load_wine([return_X_y]) :加载葡萄酒数据集
    datasets.fetch_20newsgroups([data_home, …]) :加载新闻文本分类数据集
    datasets.fetch_20newsgroups_vectorized([…]) :加载新闻文本向量化数据集
    datasets.fetch_california_housing([…]) :加载加利福尼亚住房数据集
    datasets.fetch_covtype([data_home, …]) :加载森林植被数据集
    datasets.fetch_kddcup99([subset, data_home, …]) :加载网络入侵检测数据集
    datasets.fetch_lfw_pairs([subset, …]) :加载人脸(成对)数据集
    datasets.fetch_lfw_people([data_home, …]) :加载人脸(带标签)数据集
    datasets.fetch_olivetti_faces([data_home, …]) :加载 Olivetti 人脸数据集
    datasets.fetch_rcv1([data_home, subset, …]):加载路透社英文新闻文本分类数据集
    datasets.fetch_species_distributions([…]) :加载物种分布数据集
  2. 每个二维的数据集对应着一个一维的标签集,用于标识每个样本的所属类别或属性值。通常数据集用大写字母X表示,标签集用小写字母y表示。
    下面的代码从数据集子模块datasets中提取了鸢尾花数据集——这是用来演示分类模型的最常用的数据集。鸢尾花数据集X共有150个样本,每个样本有4个特征列,分别是花萼的长度和宽度、花瓣的长度和宽度。这些样本共有3种类型,分别用整数0、1、2表示,所有样本的类型标签组成标签集y,这是一个一维数组。

from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
X.shape # 数据集X有150个样本,4个特征列
(150, 4)

y.shape # 标签集y的每一个标签和数据集X的每一个样本一一对应
(150,)

X[0], y[0]
(array([5.1, 3.5, 1.4, 0.2]), 0)
1
2
3
4
5
6
7
8
加载数据时,如果指定return_X_y参数为False(默认值),则可以查看标签的名字。

iris = load_iris()
iris.target_names # 查看标签的名字
array([‘setosa’, ‘versicolor’, ‘virginica’], dtype=’<U10’)

X = iris.data
y = iris.target
1
2
3
4
5

  1. 模型训练时,通常会将数据集和标签集分成两部分:一部分用于训练,一部分用于测试。
    分割数据集是一项非常重要的工作,不同的分割方法对于模型训练的结果有不同的影响。 Scikit-learn提供了很多种数据集分割方法,train_test_split是其中最简单的一种,可以根据指定的比例随机抽取测试集。train_test_split函数位于模型加粗样式
上一篇:2021-04-16:SDK细碎知识点,平台(未完成)


下一篇:SQLServer基础:TOP、OFFSET-FETCH、SET ROWCOUNT用法笔记