本文的多国语言版: 日本語, Português, Türkçe, Français, , العَرَبِيَّة, Español (México), Español (España) 或 Polski
你是否也曾听人们谈起机器学习但是只有一个朦胧的概念? 你是否厌倦了在同事的高谈阔论中颓然欲睡? 此诚求变之机
本教程适合所有对机器学习感到好奇, 却不知从何下手的读者我想应该有很多人试着读了维基百科页面, 然后愈发迷惘沉沦, 盼望着有人能够提供一个 high-level 的解释, 那你找对地方了
我们的目标是让所有人都能读懂这就难免有些泛泛而谈但是无妨, 但凡本文能让一个人真正对机器学习感兴趣, 那么目的就算达到了
什么是机器学习?
机器学习的核心思想是创造一种普适的算法, 它能从数据中挖掘出有趣的东西, 而不需要针对某个问题去写代码你需要做的只是把数据投喂给普适算法, 然后它会在数据上建立自己的逻辑
比如说有一种算法, 叫分类算法, 它可以把数据分到不同的组别当中一个识别手写数字的分类算法, 也可以用作判断垃圾邮件, 而无需修改一行代码算法是同一个算法, 只是输入了不同的训练数据, 便有了不同的分类逻辑
机器学习是个筐, 什么普适算法都往里装
两种机器学习算法
机器学习主要分为两类有监督学习和无监督学习, 区别很简单, 却很关键
有监督学习
想想你是一家房产中介你的业务正在增长, 所以雇了一帮实习销售来助拳那么问题来了身经百战的你, 一眼就看穿一栋房子价值几何, 但是实习生可没有这样丰富的人生经验, 所以摸不准行情
为了辅助实习生(以便解放自己度个假), 你决定做个小程序, 基于面积周边环境相似房产成交价等等, 来预估本地的房价
所以你把 3 个月来本市的每一笔交易都拿小本本记了下来对每处房产都整理了一大堆细节房间数面积周边环境等等, 当然最重要的是, 最终成交价:
有了训练数据, 我们就想搞个程序去预估其他的房价:
这就是有监督学习你是知道每处房产到底卖多少的, 换言之, 问题的答案是已知的, 逻辑是可以反推的
为了开发小程序, 把每处房产的训练数据导进机器学习算法里, 算法试图摸索出其中的数学规律
这有点像是去掉了符号的算术题答案:
根据上图, 你能否推算出这些题目的原貌呢? 显然, 我们需要对这些数字动点手脚, 以使等式成立
在有监督学习中, 我们做的实际上就是让电脑代替人来让等式成立一旦你学会了解决某一类问题, 那么这类问题里的任何子问题都就迎刃而解了!
无监督学习
回到最开始那个卖房地产的例子如果我们不知道具体每处房产的价格可咋整? 即使仅知道面积位置等信息, 你也依然可以搞点动静出来, 这就叫无监督学习
这就好比有人给你一张纸, 上面写着一串数字, 然后说我也不知道啥意思, 你可以猜猜这是什么套路好运!
这些数据我们能做什么呢? 对于新手来讲, 可以得到一个算法, 从数据中自动辨识出细分的市场定位可能你会发现, 当地大学附近的购房者偏好多卧室的小房子, 而郊区的购房者则倾向于大套三了解到不同类型消费者的存在可以指导市场行为
另一个可以做的就是自动识别出那些少有相似点的特异房产可能这些特异房产是豪华公馆, 那么就可以调配最好的销售人员专门负责这些大买卖
后文主要专注于有监督学习, 但并非因为无监督学习的作用小或者趣味少实际上无监督学习的重要性与日俱增且发展迅速, 因为不需要事先对正确答案对应的数据加标签
注: 还有很多其他种类的机器学习算法, 不过建议从这些基础算法入手
哎哟不错, 但是真的有可能学习到真实的房价吗?
作为一个人类, 你的大脑可以面对各种形势, 并且在无明确指导的情况下自主学习如何应对如果你卖了很久的房子, 就会慢慢地对房价对销售策略对观察客户等问题产生一种感觉强人工智能研究的目的就在于让计算机掌握这种能力
但是当前的机器学习算法还没那么厉害它们只能对很具体有限的问题生效或许这里的学习更应该定义为基于样本数据得出解决具体问题的等式
不幸的是, 让机器基于样本数据得出解决具体问题的等式不是个好名字, 所以我们还是回到了机器学习
当然如果你在 50 年后, 强人工智能都普及了时候看到本文, 会觉得全文都很古典别看了, 让你的机器人给你拿个包子吃, 未来人类
放码过来!
然, 上面例子里的预测房价程序应该怎么写呢? 思考一秒, 然后接着看
如果你对机器学习一无所知, 可能会尝试依照预测房价的基本规律, 写出如下代码:
- [amalthea_exercise lang="python" executable="false" writable="false"]
- [amalthea_sample_code]
- def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
- price = 0
- # 这一片的均价是 200 美元一平米
- price_per_sqft = 200
- if neighborhood == "hipsterton":
- # 有的区更贵
- price_per_sqft = 400
- elif neighborhood == "skid row":
- # 有的区便宜
- price_per_sqft = 100
- # 根据基准价和面积预测实际价格
- price = price_per_sqft * sqft
- # 根据房间数调整预测
- if num_of_bedrooms == 0:
- # 公寓稍微便宜点
- price = price20000
- else:
- # 卧室多的房子贵
- price = price + (num_of_bedrooms * 1000)
- return price[/amalthea_sample_code]
- [/amalthea_exercise]
如果顺着写上几个小时, 或许也能得到一个能跑的程序但势必存在隐患, 而且无法应对价格变化
如果计算机能自己发现如何应用这些方程, 那岂不是好得多? 只要能得到正确的数字, 谁管具体方程是什么呢?
- [amalthea_exercise lang="python" executable="false" writable="false"]
- [amalthea_sample_code]
- def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = 贾维斯, 帮我算一下
- return price
- [/amalthea_sample_code]
- [/amalthea_exercise]
这个问题可以想象成: 价格是道炖菜, 配方是卧室数量, 面积和周边环境如果你能算出每种成分对最终价格的影响是多少, 或许那就是配方搅合最终价格的确切权重
这可以使原程序 (满是 if/else) 变得简单如下:
- [amalthea_exercise lang="python" executable="false" writable="false"]
- [amalthea_sample_code]
- def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
- price = 0
- # 加少许配方 1
- price += num_of_bedrooms * .841231951398213
- # 加大把配方 2
- price += sqft * 1231.1231231
- # 适量的配方 3
- price += neighborhood * 2.3242341421
- # 最后来点盐
- price += 201.23432095
- return price
- [/amalthea_sample_code]
- [/amalthea_exercise]
注意这些奇妙深刻的加粗数字. 841231951398213 1231.12312312.3242341421 和 201.23432095, 这就是我们的权重只要我们能找到准确的权重, 那就可以预测房价了
一个比较粗暴的权重计算方法大致如下:
第一步:
把所有权重都设为 1.0:
- [amalthea_exercise lang="python" executable="false" writable="false"]
- [amalthea_sample_code]
- def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
- price = 0
- # 加少许配方 1
- price += num_of_bedrooms * 1.0
- # 加大把配方 2
- price += sqft * 1.0
- # 适量的配方 3
- price += neighborhood * 1.0
- # 最后来点盐
- price += 1.0
- return price
- [/amalthea_sample_code]
- [/amalthea_exercise]
第 2 步:
把每个房产的参数代入公式, 计算预测结果和实际价格的误差:
比如第一个房子实际卖了 $250,000, 但是你的方程却预测的是 $178,000, 但这一个房子就少了 $72,000
现在把每个房子对应误差的平方加起来, 比方你有 500 单交易, 那么误差的平方和就有 $86,123,373, 可谓谬以千里再把平方和除以 500 得到平均每个房子的误差, 这一平均误差值就是方程的代价(即最小二乘法, 平方是为了防止误差正负相抵)
如果我们能通过调整权重将代价降为零, 那方程就完美了这表示在所有例子中, 方程都准确无误地基于输入数据猜中了房价这就是我们的目标尝试不同的权重, 让代价尽量低
第 3 步:
不断地重复第 2 步, 尝试每一种可能的权重值组合哪个组合能让代价最接近于 0 就选哪一组找到那一组权重, 就解决了问题!
脑洞时间
挺简单的对吧? 回想一下刚才的所做, 拿到一些数据, 填进三个普适的简单的步骤里, 然后得到一个能猜房价的方程 Zillow(美国房价预测网站)面临着严重的威胁!
但是有这么几个激动人心的事实:
过去 40 年里, 很多领域 (如语言学 / 翻译学) 的研究已经表明, 搅合数字炖菜 (作者自己打的比方) 的普适性学习算法已经超越了那些, 由真人尝试自己发现显式规律的人方法机器学习的暴力方法最终击败了人类专家
刚才得出的方程其实是很笨的它并不知道平方米和卧室到底是什么, 它只知道搅拌多少数字可以得到正确答案
你大概并不知道为什么某一组权重就是好的, 而只是写了一个自己都不明白的方程, 但却证明是好用的
假设我们不用平方米和卧室数这些参数, 而是读入一个数列比方说每个数字代表的是从车顶上拍的照片的某一像素的亮度, 然后我们预测的结果也不是房价了, 而是方向盘转过的角度这就是一个人自动驾驶的风方程了?
疯了, 对吧?
第 3 步的尝试每个数字
当然你不可能真的尝试每一种可能权重组合来寻找最优解, 实际情况是永远尝试不完
为了避免这一情况, 数学家们发现了很多机智办法来尽快找到一个不错的结果以下就是其中一种:
第一, 写一个能够代表上面第 2 步的方程:
然后用机器学习界的黑话 (暂时可以忽略) 重新写一遍:
这个等式代表了在当前的权重组合下, 我们的价格预测有多么离谱
如果把房间数和平方米所有可能权重值可视化, 可以得到类似下图的图像:
这个图里的蓝色最低点就是代价的最低点方程误差最小处, 最高点即是最离谱的情况所以如果我们找到一组权重值, 使得方程对应最低点, 那就是答案!
所以我们只需要以下山的方式来调整权重, 逼近最低点如果每一次微小的调整都向着最低点进发, 那迟早能够到达
函数的导数就是切线的斜率, 换句话说, 这告诉我们哪条路可以下山
因此如果计算代价函数对每个权重的偏微分, 然后再从权重里减去这个值, 这可以让我们离谷底更近重复执行, 最终我们会到达谷底并获得权重的最优解(如果没看懂, 不要担心, 继续看)
这是一种寻找方程最佳权重方式的高度概括, 叫作批梯度下降 (batch gradient descent) 如果你对此感兴趣, 不要害怕, 了解更多细节
当你使用机器学习库来解决实际问题的时候, 这些都会自动完成, 但是了解究竟发生了什么还是很有用的
还略过了什么?
上述的三步算法即是多变量线性回归, 针对一条穿过房产数据的直线来进行预测目标等式, 并用这一等式去猜测此前未曾见过的房屋价格, 解决实际问题的时候这非常行之有效
但是以上方法或许只对特别简单的例子好使, 并非万金油其中一个原因就是房价不总是简单到能用一条连续直线来代表
好在另有很多方法解决, 很多机器学习算法可以处理非线性数据 (如神经网络 或 有核 的支持向量机) 同样也有算法是以更加聪明的方式使用线性回归以拟合更复杂的直线但不论哪一方法, 最根本的思想都是找到最佳的权重
并且我忽略了过拟合问题对于已有的原始数据, 找到一组很棒的权重值不难, 但是却有可能对训练集以外新的房子不适用有很多方法可以避免这一现象(如正则化和使用交叉验证数据集), 这是成功应用机器学习算法的关键命题
尽管基本概念很简单, 但是要用机器学习取得有用的结果, 还是需要技巧和经验的不过这些技巧是每一个开发者, 都能够学会的!
机器学习是魔法吗?
看到机器学习技术如此轻易就解决了看起来非常困难的问题(如手写识别), 你可能会感觉只要有足够多的数据, 什么问题都不是问题了导入数据, 然后等着计算机变出一个适合数据的式子!
但需要记住的事, 机器学习要想生效, 必须满足一个条件, 就是目标问题对已有数据确实是可解的
比如建立一个模型, 根据房子里种的植物种类预测房价, 这肯定不管用因为房里的植物和售价本来就没有关系, 不管再怎么试, 计算机还是无法找出这种关系
所以如果一位人类专家不能用数据解决某个问题, 计算机也不行相反, 计算机的优势在于, 对于人类能解决的问题, 计算机可以更快地完成
如何学习更多机器学习
在我看来, 机器学习目前最大的问题在于其主要还是存在于学术界, 对于广大只是想稍微了解而并非想成为专家的人们, 通俗易懂的材料还是不够丰富, 当然这一情况已经在好转
吴恩达的 Machine Learning class on Coursera 相当惊艳, 我强烈推荐从这里开始对于 CS 专业的人, 只要还记得一丁点数学, 就可以学
你也可以通过下载安装 Scikit-learn, 来自己尝试海量的机器学习算法, 这是一个提供黑盒版标准算法的 Python 框架
来源: https://juejin.im/post/5aa23feef265da239e4dabe8