小科普:机器学习是啥?怎么分,怎么学,怎么用?

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

人工智能的概念太大了,今天给大家唠会儿机器学习(其实它也很大)。

有朋友就问了:啥玩意机器学习、深度学习的,你自己能区分吗?

一、机器学习与深度学习之辨

我举个便于理解的例子,如果把人工智能比作考古,那么机器学习可以算作器物鉴定,深度学习则是用仪器去鉴定。

机器学习是人工智能技术里的一个分类。类比到考古学,除了研究器物外,还有遗迹、文化等。

提起器物鉴定,比如评价一个花瓶,我们首先想到古董专家去看它的颜色、形状、纹理。然后用食指戳一下眼镜框,说这件藏品是清朝仿的宋代。机器学习也是这样,对于一项研究,首先需要手动提取数据的特征

比如预测糖尿病人身体状况和血糖的关系。需要先找专家给出意见,比如身高、体重可能是因素。至于老婆和你是不是一个姓,这没关系。

哎,需要先把关键特征提取出来,然后再让机器去学习。

时代在发展,科技在进步。到后来,器物年代的鉴定方便了。找一个仪器,嘀~,一测物体碳元素的半衰期,很容易就能获取年代。这个就是深度学习,它自己会从原始数据中找需要的信息。

还是糖尿病预测那个例子,你把病人每天的生活录像交给深度学习,它自己会从里面去找。

那你说,用高科技仪器去检测物体,是不是也属于器物鉴定的范围。因此,深度学习属于机器学习

既然它们是从属关系了,干嘛我们还要区分着说?诶,这就像问你是集团员工还是子公司员工的区别。

  • 老机器学习算法,需要人工定义特征,易于理解、可解释,硬件消耗低,小规模数据量效果好。例如车牌识别、人脸识别。

  • 新深度学习算法,可自主学习特征,模型复杂,消耗高,难以解释,大规模的高级任务效果好。例如ChatGPT聊天机器人。

他们各有优劣,都有生存空间,就像是电钻和钉子的差别,主要看你想花多少钱干什么事。

二、机器学习算法与普通逻辑算法之辨

又有一个朋友问:我多写几个ifelse,我的程序能叫"机器学习"吗?两者的区别又是什么?

这位朋友是一名具有15年经验的Java开发。他提出了这个问题。在他看来,ChatGPT不过就是一个能处理数据的接口,接收参数,然后给出返回值。在具备大量对话样本的情况下,他也能用Java语言通过随机拼装的方式来实现。

我说相信他,肯定了他。但是我现在遇到一个难题,请他用逻辑代码实现一下。

我想请他用逻辑代码实现一个语音转文字。我说"旺财?",程序能识别出来是"旺财"两个字,而且还得带着疑问的语气。

他摇了摇头,若有所思。我问是不是疑问语气不好实现。他回答说,不是,旺财也很难。

他说,这不像是电商购物,你买了商品,我就往库里插入一条数据。你退货了,我就改变一下订单状态。而语音识别这个,参数是一组声波值。每个人的数据不同,甚至同一个人用不同语气,数据也不一样,参数完全不确定,没法写代码

我说,虽然我们不知道怎么写逻辑,但是我说"旺财",你是能听懂的 。不止你,大家都能听出来。这说明,这段语音肯定是有规律的。这个规律已经被大脑找到了。因此,得用一个类似于大脑的程序才能实现它。这个程序的参数不是写死的,需要随着运行而改变并优化,直到找到这个规律,这就是机器学习算法

再举一个例子。如果要区分下图所示的两种样本,你采用逻辑代码的方式,可以实现。

但是,如果样本变成如下这样。原来代码的判断条件就失效了。

而机器学习算法,它并不关心ifelse,它会适应新数据,代码不用变,参数会自己变。

说的有点玄乎了!我能学会吗?

三、机器学习入门利器 sklearn

sklearn全称为scikit-learn。它是一个机器学习库,里面提供了许多用于数据预处理、特征工程、模型选择和评估等任务的函数和类,也包含了各种常见的算法。

随机说一下这里面的聚类算法。

聚类算法可以自动将一组数据划分为不同的组

比如老板给你一组数据,是广场上所有的人,让你分组。你可以分为男人和女人,可以分为老人和孩子,可以有很多种维度来分。

聚类算法是预置的,不用训练就可以用。

有人又问了:你不是说,机器学习得训练吗?怎么现在又不用了?

是呀,机器学习的门类很广。聚类是机器学习里的一种无监督学习方法,它不需要事先标记好训练样本。它能看到数据后,临时去分析。

比如下面这个图,将一堆数据进行分析,它按照是不是在一个圈里进行了聚类。

你可以思考一下,普通逻辑代码该如何实现。

上面那种聚类叫光谱聚类 。除此之外还有密度聚类(基于密度)、K-means聚类(基于距离)、层次聚类(基于树形)......看你的需求。

好了,机器学习的天地很广阔,单靠我这一篇文章也说不全。下面我们就来一个项目案例,加深印象。

如果你跟着敲一遍,可以对外说自己搞过机器学习项目。

四、实战:投票回归器实现疾病进展预测

看名字很吓人,其实碰不到烧脑的内容,全是调框架里的类。我主要是想给大家展示一下,机器学习的实现流程。

从新闻中我们经常会听到,科学家用AI预测癌症。怎么预测呢?就是先找一批人,获取他们的关键信息,比如是不是抽烟,每天喝多少酒,几天生一次气......这些作为输入。然后,他是否患有癌症作为输出。之后,让机器学习其中的联系。

医生可能知道喝酒有患癌的几率,但是他不知道每项具体影响多少,他也无法根据一个人的情况,预测出来是否患有疾病。但是,机器学习通过大量样本数据的计算,可以找到里面的规律

这就是机器学习做预测的场景。注意,前面那个关键信息的提取,很重要。

4.1 调研与处理数据集

谷歌研究院曾经给地图部门,提供过一项关于目的地好不好停车的预测服务。

预测一个地方好不好停车,因素太多了。我们采用常识可以判断,商场在节假日不好停车,体育场在有重大赛事时不好停车,学校在有考试时不好停车。

但实际上,也跟天气、位置、是否收费、停车位的数量等诸多因素有关。

一开始,他们在某地收集实时的指标和好不好停车的结果。后来他们发现"好不好停车"这是个主观问题,于是改为收集"找到停车位花了几分钟?"。这是个客观问题。就这样,他们通过雇人的方式(谷歌竟然走外包),在25个典型城市,收集了10万组地面实况数据。

通过机器学习的训练和验证,他们发现,模型的预测依然不准确。就算他们结合了实时地图的流量,也会有很多误判的情况。于是观察发现,很多用户吃午饭的时候,会沿着饭店绕圈,虽然道路很畅通,但确实不好停车

因此,他们便将这一项数据加入到特征中。下面是它预测某地不同时段的停车难度。

这个功能,现在依然在完善和更新。

从这里,我们可以看出,机器学习对训练数据有较高的要求。垃圾数据可能会训练出垃圾模型

我这里有一组优质数据集,很专业,我们可以直接用。它对442名糖尿病患者做了一个收集,内容是他们的10项身体指标,以及1年以后的血糖指数。

序号 名称 数值示例
1 AGE 年龄 59
2 SEX 性别 2
3 BMI 体重指数 32.1
4 BP 平均血压 101
5 S1 血清总胆固醇 157
6 S2 低密度脂蛋白 93.2
7 S3 高密度脂蛋白 38
8 S4 总胆固醇/HDL 4
9 S5 血清甘油三酯 4.8598
10 S6 血糖水平 87
输出 Y 一年后血糖 151

下面是全部数据的样例,很壮观:

OK,下面我们通过机器学习去训练这批数据。训练完成之后,再用这个模型,去预测一名新患者一年后血糖的情况。如果数据真的像"旺财"的发音一样有规律,那么这个新患者的预测值也会是真的。

接下来,开始动代码了。

你需要保证你有一个Python环境,最好是3.6及其以上版本。

然后,安装sklearn。

pip install -U scikit-learn

4.2 预处理数据

虽然有了上面的数据集,但是对于机器学习来说,还是没法用。

为啥?你不是说这个数据集很专业吗?!

深度学习可以直接用,但是机器学习你得做预处理。

首先,这一行11个数,总共442行,你得分开输入输出吧。前10个是指标,是原因x。最后1个是输出,是结果y

数据集的地址是 www4.stat.ncsu.edu/~boos/var.s...

下载之后,复制到你写程序的同级目录,命名为diabetes.txt

我们先读入数据做拆分。

4.2.1 拆分输入输出

python 复制代码
import numpy as np
datasets = np.loadtxt("diabetes.txt")
X = datasets[:, :10]  # 取前10个数据作为输入
y = datasets[:, -1]  # 取最后1个数据作为输出

numpy可以直接加载txt格式的文件。我们打印一下datasets.shape,它会输出(442, 11)。也就是说,有422行数据,每行11列数值。

随后,将数组中前10个赋值给X, 倒数第1个赋值给y。这样就完成了输入和输出的切分。

X的数值如下,422行,每行10个数:

lua 复制代码
array([[59.    ,  2.    , 32.1   , ...,  4.    ,  4.8598, 87.    ],
       ...,
       [36.    ,  1.    , 19.6   , ...,  3.    ,  4.5951, 92.    ]])

y的数值如下,只有1行,共422个数:

scss 复制代码
array([151.,  75., 141., 206., 135.,  97., 138.,  63., 110., 310., 101.,
        ...
        66., 173.,  72.,  49.,  64.,  48., 178., 104., 132.,220.,  57.])

那么,现在可以开始机器学习了吧?

还是不行!

4.2.1 标准化与归一化

兄台,请先放下你手里的刀,咱们有话慢慢说!

不行的原因,不在于那1项输出,而是这10项输入。

先看下面的表格。

输入指标 张三 李四 数据集上下限
AGE 年龄 59 19 19~79
BMI 体重指数 32.1 19.2 18~42
BP 平均血压 101 87 62~133
S1 血清总胆固醇 157 124 97~301
S5 血清甘油三酯 4.8598 4.1744 3.2581~6.107

悟性很高的你,估计已经明白了。有些数据,比如血压,增加2个单位,无关痛痒。但是,像表格里的最后一项,增加2个单位,可能就是天上、地下的区别。

机器学习会观察数据间的差异与联系。同一项指标的数值还具有可比性。但是不同指标之间的数值却无法对比,因为他们不在同一个维度上。这就像穷人和富人对于500块钱的区别。对穷人来说,这可能是半个月生活费。对富人来说,买不了一双鞋垫。

如果这样的数据交给机器学习算法的话,那么对于数字敏感的它们,会优待大额数值,那些0.30.6的区别,在3300的体系下,基本就被忽略掉了。但实际上,它们可能都很关键,甚至更关键。

因此,需要找一种方案,将它们变为同一起跑线,还不能改变它们的差异与分布。这是为了使不同特征之间的数据具有可比性,这项操作在算法中,叫做数据预处理

常用的处理有归一化,就是捏着它们的最大值与最小值,将它们等比压缩到是[0, 1]或者[-1, 1]的区间范围内。[3, 300]如果被压缩成[0.01, 1],那么他们仍然是百倍的关系,而且也能与0.30.6一起比较了。

还有一种处理方式叫标准化,它主要从标准方差的角度,在保留了数据的分布形状下去处理数据。提到方差一词,我就不讲了,因为你不爱听。

对于上面的数据,我们该如何处理呢?我是这么做的:

python 复制代码
X_mean = np.mean(X, axis=0) # 求每列的平均值
X_centered = X - X_mean # 求均值差
# 对数据依照方差进行缩放
std = np.std(X_centered, axis=0) # 求标准差
scaled_X = X_centered * std # 每个数乘以标准差
scale = np.sqrt(np.sum(scaled_X**2, axis=0))
scaled_X = scaled_X/scale # 缩放

首先通过np.mean(X, axis=0)针对每一列分别获得平均数。也就是这批数据中的平均年龄、平均体重指数等。

然后,让每个人的指标都减去这个平均数。这就将原始数据的大正数,转化为绕着平均值上下浮动的正负数。

就像下面这样:

上面只演示了一组数据,其他9组数据都是这样处理。这样做不但可以将数据变小,而且还能保留他们之间的差异

后面的代码是对整体数据做平衡,通过方差进行缩放。最终我们看到,虽然身高体重、年龄的数值都不一样,但是打印一下scaled_X发现,整体上"贫富"差距不是很大了。

lua 复制代码
array([[ 0.03807591,  0.05068012,  0.06169621, ..., -0.00259226,
         0.01990749, -0.01764613],
       ...,
       [-0.04547248, -0.04464164, -0.0730303 , ..., -0.03949338,
        -0.00422151,  0.00306441]])

到这一步,基本上预处理算是结束了。下面就该选模型去训练了。

4.3 训练与预测

我们现在手头上有两组数据,一个是预处理过的scaled_X,另一个是结果y

下面我们开始训练:

python 复制代码
from sklearn.ensemble import RandomForestRegressor
reg_rf = RandomForestRegressor(random_state=1)
reg_rf.fit(scaled_X, y)

上面就是全部的训练代码。没错,就是3行!

我经常说,如果你不是立志做一个科学家,只是想做应用解决问题。其实人工智能真的没有多难,都是调用框架

RandomForestRegressorsklearn的一个类,叫随机森林回归器

回归器是一种机器学习模型,它能找到输入变量和输出变量之间的关系,并根据这个关系对新的输入进行预测。

随机森林是一种解决回归问题的算法。它会构建多棵决策树,然后引入了随机性,包括对训练样本的随机采样和对特征的随机选择。这样能够降低过拟合的风险,也能保持较高的预测准确性。

对于随机森林算法,如果还是不够形象,我画一张图你就明白了。

其实生活中,我们经常用随机森林。上面图已经很形象了,对于一件事的判断,它会有好多棵决策树。通过哪棵树都能做出最终判断 。就像相亲,可以看家庭,可以看人品,可以看长相。我们只了解对方的部分信息就能有结论 ,当然全部知道更好。这就是决策森林算法,它会故意地丢掉部分信息,这样可以避免过拟合(首富喜欢吃火龙果,因此吃火龙果的就是首富)。

上面代码中reg_rf.fit(scaled_X, y)是用随机森林回归器对Xy做了训练。

接下来,进行预测。

假设我们有这么一组数据,这是一名新患者的指标。

AGE, SEX, BMI, BP, S1, S2, S3, S4, S5, S6
49, 1, 31.1, 110, 154, 95.2, 33, 4, 4.6692, 97

我们如何进行预测呢?代码如下:

python 复制代码
x_new = [[49, 1, 31.1, 110, 154, 95.2, 33, 4, 4.6692, 97]]
scaled_x_new = (x_new - X_mean) * std/scale
pred_rf = reg_rf.predict(scaled_x_new)

首先,依然需要将原始数据做预处理。也就是减去平均值,根据方差做缩放。

然后,调用回归器的predict方法,即可得到预测结果。这里的结果是array([213.26])。看来,这个位患者一年后的血糖情况不是很乐观,建议及早干预。

它预测的靠不靠谱?我是说随机森林算法靠不靠谱,万一它把重要的特征忽略掉了怎么办?

4.4 投票回归预测

投票回归,可以融合多个算法,综合多个预测结果进行判断,类似投票的形式,因此叫投票回归。

它的用法如下:

python 复制代码
# 随机森林回归、梯度提升回归、线性回归......
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.linear_model import LinearRegression
# 投票回归器
from sklearn.ensemble import VotingRegressor

# 各个回归器分别训练
reg1 = GradientBoostingRegressor(random_state=1)
reg1.fit(scaled_X, y)
reg2 = RandomForestRegressor(random_state=1)
reg2.fit(scaled_X, y)
reg3 = LinearRegression()
reg3.fit(scaled_X, y)

# 投票回归器训练
reg = VotingRegressor([('gb', reg1), ('rf', reg2), ('lr', reg3)])
reg.fit(scaled_X, y)

# 投票回归器预测
pred = reg.predict(scaled_x_new)

流程相信大家都看懂了。

解决回归问题有很多种算法,除了随机森林,还有梯度提升回归、线性回归、多项式回归......反正不要钱,多结合几种,可能会更稳妥一些。

我们对比一下各个算法回归器与最终投票器的效果。

我取了15组数据分别进行预测并画了一个图。五角星是投票器的预测结果,其他形状是各家算法的预测结果。

我们看到,就算是各个回归算法,他们的预测结果虽然略有差别,但是大体也是接近的。而投票器,则更偏向于"少数服从多数"。

以上示例,包含数据集,GitHub地址:github.com/hlwgy/juejj...

五、总结

传统机器学习算法,是一种轻量级的AI解决方案,适用于处理样本特征相对固定的简单任务。这很像老专家抱着大花瓶进行鉴定。你得真懂行,不然很难去提取其中的特征。因此,建议做这类任务,带一个行业专家。

另外,对于研究的事物,需要有规律。有人问,用机器学习去预测双色球行吗?

双色球不是一种因果回归,它属于随机抽取,每一次都相当于从0开始,没有任何规律可言。因此,无法通过机器学习去准确地预测。

你就是做再多的训练,其实效果也就是下面这几句(1到33选6个红球,1到16选1个蓝球):

python 复制代码
import random
red_balls = random.sample(range(1, 34), 6)
blue_ball = random.randint(1, 17)
red_balls, blue_ball = sorted(red_balls), blue_ball
print(red_balls,  blue_ball)
# [4, 6, 16, 18, 19, 27] 15

幸运的朋友,[4, 6, 16, 18, 19, 27] 15送给你了,去吧!

我是掘金@TF男孩,一个善于挖掘传统知识的程序员。

相关推荐
huapiaoy1 分钟前
Redis中数据类型的使用(hash和list)
redis·算法·哈希算法
冷白白14 分钟前
【C++】C++对象初探及友元
c语言·开发语言·c++·算法
鹤上听雷22 分钟前
【AGC005D】~K Perm Counting(计数抽象成图)
算法
一叶祇秋35 分钟前
Leetcode - 周赛417
算法·leetcode·职场和发展
可惜已不在35 分钟前
AI 搜索引擎工具集合
人工智能·ai
Landy_Jay39 分钟前
深度学习:基于MindSpore实现CycleGAN壁画修复
人工智能·深度学习
武昌库里写JAVA40 分钟前
【Java】Java面试题笔试
c语言·开发语言·数据结构·算法·二维数组
ya888g40 分钟前
GESP C++四级样题卷
java·c++·算法
Funny_AI_LAB1 小时前
MetaAI最新开源Llama3.2亮点及使用指南
算法·计算机视觉·语言模型·llama·facebook
NuyoahC1 小时前
算法笔记(十一)——优先级队列(堆)
c++·笔记·算法·优先级队列