hello大家好我是小白
这是一个理论结合实作的机器学习课程
实作的部分我们会用Python来完成
所以如果你还没有学过Python的话
可以先去看我的Python课程
理论的部分因为这不是一堂数学课
所以里面不会有太艰深的数学大家也不用担心
好那我们就废话不多说直接开始吧
hello大家好我是小白
非常欢迎您来到这个课程
首先先跟大家厘清几个观念
第一个是什么是人工智慧AI
AI的全写是artificial intelligence
大家应该常常听到人工智慧吧
那究竟什么是人工智慧呢
人工智慧或者你可以叫他人工智能
用简单的一句话来说
就是我们希望机器可以跟人类一样拥有智慧
一旦机器有了智慧
他就可以帮我们处理很多繁杂的事情啦
好接着什么是机器学习ML
ML 的全写是machine learning
我们刚刚说人工智慧
是我们希望机器可以拥有智慧
那要怎么样让机器拥有智慧呢
其中一个方法就是透过让机器去学习
好现在问题来了
要怎么样让机器去学习呢
我们可以先想一下人类是怎么样学习的
人类是不是可以透过过去的历史
跟过往的经验来做学习嘛
对机器来说也是一样啊
机器的过去历史跟过往经验
其实就是过去储存下来的资料嘛
所以机器学习呢
我们用简单的一句话来说
就是从过去储存下来的资料中去找出规则
OK 机器学习用简单的一句话来说
就是从资料中去找出规则
好接着什么是深度学习DL
DL 的全写是deep learning
其实深度学习呢它就是机器学习的其中一招
我们刚刚说机器学习
他是从资料中去找出规则
那要从资料中找出规则有很多种方法
其中的一个方法呢就是深度学习
那深度学习这个方法
他是透过模仿人类大脑的一个类神经网路
来从资料中去找出规则OK
那至于什么是类神经网路呢
之后的课程还会再跟大家做介绍
好所以我们总结一下刚刚说的人工智慧
机器学习还有深度学习
我们可以用这一张图来做一个表示
人工智慧是我们最终想要达成的目标
我们想要机器跟人类一样拥有智慧
那他就可以帮我们处理很多繁杂的事情
那要怎么样实现人工智慧呢
其中一个方法就是透过让机器去学习
那机器学习呢
用简单的一句话来说
就是从资料中去找出规则
要从资料中找出规则有很多种方法
其中一个很厉害的方法就是透过深度学习
那深度学习这个方法呢
它就是透过模仿大脑的一个类神经网路
去达成从资料中找出规则
OK 所以呢这个是人工智慧
机器学习还有深度学习他们三者间的关系
接下来我们来了解一下机器是如何学习的
之前已经提过了
机器学习就相当于是从资料中去找出规则
那接着我们进一步来探讨
机器或者说电脑是怎么样从资料中找出规则的呢
其实只要透过一些数学的技巧搭配程式
就可以达成让机器从资料中找出规则了
好那接着我们就直接来看一下
机器学习的过程大概长什么样子
假设现在我们的手上有一些图片的资料
这些图片是狗跟猫的图片
我们想要让机器从这些图片的资料中学会
如何分辨狗跟猫OK
也就是说我们想要让机器从这些资料中
里面去找出分辨狗跟猫的规则
那我们可以怎么做呢
大家可以先想一下人类是怎么样学会分辨狗跟猫的
假设今天你要教一个小朋友
这个小朋友他完全不知道什么是猫什么是狗
你要教会他如何分辨
一开始你可能拿了一张图片
问小朋友说这只是猫还是狗呢
可以看到小朋友的眼神相当的茫然
因为他跟本不知道你在说什么他只想赶快睡觉
于是呢他随便乱回答他说这只是狗
显然的他答错了
这时候身为老师的我们呢就给他一个叉叉
并且告诉这个小朋友长这个样子的动物是猫哦
接着我们又拿了一张图片问小朋友
这只是猫还是狗呢
可以看到相较于上一次的茫然
这一次小朋友的眼神透露出了一点点的自信
他回答说这只是猫
相当的可惜他又答错了
身为老师的我们又给他打了一个叉叉
并且告诉小朋友长这个样子的动物是狗哦
就这样经过不断的看照片然后让小朋友作答
看照片让小朋友作答
只要小朋友他答错了我们就请他修正
久而久之小朋友看多了猫跟狗的图片
他大概也会知道猫长什么样子狗长什么样子了
所以你再问他这只是猫还是狗
可以看到他就非常坚定非常自信的告诉你这只是狗
同样的这样子的学习方式
一样可以套用到机器身上
我们可以输入一张图片到机器里面
或者说输入一张图片到电脑里面
并且问他这只是猫还是狗呢
输入到电脑里面以后就会触发一些程式
那这些程式的背后其实就是在使用一些数学的技巧
这边的数学技巧搭配程式
我们也可以把它叫做模型model
所以呢这边我们可以这样子说
我们可以把一张图片输入到模型里面
并且问他这只是猫还是狗呢
那一开始的时候这个模型跟一个无知的小孩是一样的
他并不会知道什么是猫什么是狗
所以呢他随便乱猜这只是狗
显然他答错了
我们这时候就要给他一个叉叉
并且告诉他长这个样子的是猫哦
请他修正一下模型长这个样子的是猫哦
接着我们又拿了另外一张图片
输入到机器里面输入到模型里面
并且问他是猫还是狗呢
这次他回答是猫
显然的又答错了一样给他打一个叉叉
并且告诉他长这个样子的是狗请他修正一下模型
一样就经过这样子不断的训练
不断的给机器看很多猫跟狗的图片
如果他答错了就请他修正
直到最后这个模型他有了一定的正确率之后
我们就说这个模型训练完成了
可以看到最后我们输入一张狗的图片
这个模型告诉你这一只是狗
那训练好机器之后或者说训练好这个模型之后
假设未来你有一张新的图片
你想要问他是猫还是狗
你就可以把它输入到模型里面
他就会告诉你这一只是狗
接着再来看一个列子
假设现在我们的手上有一些房屋买卖的资料
这些资料是房屋的坪数跟他相对应的出售价格
一样我们想要让机器从这些资料中去找出规则
找出坪数跟他相对应的出售价格之间的规则
也就是说
我们想要由坪数去推测出售的价格应该是多少
那这样子的话我们就可以说坪数叫做特征feature
价格叫做标签label
我们由坪数去推测价格是多少
所以坪数叫做特征价格叫做标签
接着训练的过程就跟刚刚大同小异
我们可以把坪数也就是特征输入到模型里面
那模型一开始是无知的
所以呢他会随便乱猜测
假设他猜测400万
我们就看一下我们手上的资料
我们手上的资料写说这个50坪的房子
他出售的价格是500万
也就是我们的标签是500万
那显然跟他的猜测是有一段距离的
所以这时候呢我们就告诉这个模型
这个房子他出售价格是500万哦请你修正一下
接着一样输入下一笔资料66坪
然后到模型里面他推测900万
我们再看一下手上的资料是650万标签是650万
所以呢一样再修正一下模型
就这样不断不断的修正
不断不断的看资料
直到最后模型的预测跟我们真实的资料
也就是标签误差值不大的时候
我们就说这个模型训练完成了
那模型训练完成之后
假设你有一个房子想要卖它是72坪
你不知道他应该卖多少
你就可以把72坪这个特征输入到模型里面
让他预测一下应该可以卖多少钱
那讲到这边你可能就有疑问啦
一栋房子的价格
应该不是单单看它有几坪就可以决定的吧
我们可能还要看它的位置看它的格局等等的综合因素
才有办法评估一栋房子值多少钱
没有错所以你可以把资料收集的更完整一点
除了坪数以外我们现在还收集了他的位置还有房间的数目
所以现在机器就是要由坪数、位置跟房间的数目
去推测出售的价格应该是多少
那现在我们就会说坪数、位置还有房间叫做特征
价格呢一样是标签
因为我们是由坪数、位置跟房间来推测价格
所以这3个是特征价格是标签
学习的过程就跟刚刚一样大同小异
我们输入特征坪数、位置还有房间的数目到模型里面
那模型一开始是无知的所以他会随便乱推测
假设一开始推测400万
我们看一下手上的资料也就是标签
标签是500万所以呢请模型修正一下
接着再输入第二笔资料
一样请模型推测他推测900万
看一下标签是650万再请模型修正一下
就这样不断不断的训练
直到模型的误差值到了一定的范围内
我们就说这个模型训练完成了
一样未来如果你有一间房子
它是72坪在华盛顿有6个房间想要卖
你想要推测他应该可以卖多少钱
就可以输入到这个模型里面
他推估说可以卖730万
这个大概就是机器学习的过程
接下来我们就直接来实作喽
这堂课我们要使用的是colab
colab是Google免费提供的python撰写环境
它可以让我们在浏览器上面
非常快速简单的撰写python程式
但因为是Google提供的
所以呢你要先办一个Google帐号并且登录
登录好之后呢在这边可以看到9个点
点进来找到云端硬碟
我们在左上角可以看到一个新增
然后点选这里的更多
如果在这里你已经找得到Google colab的话就点选它
找不到我们就点选连接更多应用程式
好我们在这里可以找到colab 点进来
然后点选安装
点选安装他可能会叫你登录一下
那你就登录
好登录好安装好之后呢
我们就点选确定完成
OK 接着我们再到新增这里更多
可以看到多了一个Google colab 就点进来
点进来之后可以看到
他就帮我们创建了一个可以撰写Python的环境
首先呢我们先看到左上角
左上角这边是档案的名称
你可以把它做修改
假设我把它改成环境建置
OK 这样就修改过来了
接着因为我个人比较习惯背景是黑色的
所以呢我到工具这边找到设定
那这边有一个网站里面的主题
我们选到Dark
然后点选储存背景就会变成黑色的
当然你也可以自己设定你喜欢的颜色
那在编辑器这边呢
你也可以设定文字的大小啊间距等等的
就留给大家自己来玩
那我们在撰写程式之前呢要先做连线的动作
我们可以到右上角这边找到一个连线点下去
那他就会分配一些资源给我们做使用
等他一下
好连线好之后呢
我们可以看到中间这一块
中间这一块呢就是我们可以撰写程式的地方
首先我们到这个格子里面
就可以直接输入程式码啦
假设我输入print 87
那我把它放大一点大家看的比较清楚
好print 87打完之后
这边有一个执行的按钮点下去
那他就会开始执行了
执行的结果呢就会显示在下面
在colab里面程式码是可以分成一块一块的
我们可以把滑鼠放到这个格子的上面一点点
可以看到它就跳出了一个加程式码或者是加文字
放到下面一点点一样会跳出来
假设我点选加程式码
哎它就多出了一个格子
那一样我们就可以在这个格子里面撰写python程式
假设我写print 88 按下执行
可以看到执行的结果就会显示在下面
那我们来看一下如果我点选加文字
他就跳出一个可以撰写文字的格子
假设我写一个你好我好大家好
这边除了撰写文字以外
你也可以选择一些字体啊字形等等的
可以看到这边就多了一个文字的格子
OK 我们可以加很多程式码的格子
也可以加很多文字的格子
那如果你不想要的话这边可以把它删掉
有一个垃圾桶的符号点下去就删掉了
删掉删掉删掉OK
那colab呢它还有一个重点
就是它可以提供免费的GPU跟TPU给我们使用
那GPU跟TPU呢是在运算上面可以帮我们加速很多
我们可以在上面这边找到编辑
然后有一个笔记本设定
可以看到这边有一个硬体加速
你就可以选择GPU或者是TPU
那在之后的课堂呢我们也会使用到GPU来做加速
所以假设这边我选择GPU 然后按下储存
你可以看到他就帮我们重新做连线分配
一样要等他一下
他连线好之后
会问我们说要不要删除先前的执行阶段
假设我这边就先按取消
好连线上gpu之后
我们想要看一下他给我们使用的gpu是哪一张的话
我们可以在程式码的格子里面打上
!nvidia-smi 按下执行
可以看到他现在给我们使用的GPU
是这一张特斯拉T4 OK
好那这样子呢我们的环境建置就完成啦
第一个要跟大家介绍的数学技巧
叫做简单线性回归
英文是simple linear regression
可以看到它的名字前面有简单这两个字
所以可想而知呢它很简单
大家不用太担心
我们先来描述一下今天遇到的状况
假设今天你是一间新创公司的老板
你想要聘顾你的第一个员工
但是呢你不太确定应该要给他多少薪水
于是你就到市场上去
收集了一些同职位的人的资料
那这些资料是他们工作的年资跟对应的薪水
那我们把这边的这些资料呢
把它用图表画出来会长这样
x轴是年资y轴是月薪
这里的每一个叉叉
就表示你收集到的每一笔资料
那从这张图我们不难看出来
年资跟月薪是成一个正比关系的
也就是年资越高的人月薪也会越高
好那现在问题来了
你是一间新创公司的老板
你想要聘顾你的第一个员工
你的第一个员工来了
他告诉你他的年资是两年半也就是2.5
那请问你应该开多少薪水给他呢
这时候就可以使用到简单线性回归啦
由于年资跟月薪是成一个正比的关系
所以这些资料我们大概可以使用
一条直线来做表示
简单线性回归
就是把资料用一条最适合的直线来做表示
假设现在我们已经找到了这条最适合的直线
那我们就可以把2.5这个年资
带到这条直线里面去
看一下大概可以给这位员工多少薪水
带进去之后呢
可以看到我们大概可以给这位员工51K的薪水
那现在问题就会变成
要怎么样找出这条最适合的直线呢
我们先来看一下
一条直线在数学上可以怎么样做表示
我们可以写y=w*x+b来表示一条直线
那把这条式子套用到现在这个例子里面
y就会等于月薪x就会等于年资
所以呢现在的问题就变成
我们要找出一个最适合的w 跟最适合的b
来表示这些资料
我们要找出一个最适合的w 跟最适合的b
来表示这条直线
好那我们就直接来实作看看
不同的w跟不同的b
会产生怎么样的直线呢
首先我们先把资料读取进来
我们可以使用Pandas这个模组
来做读取的动作
这边我把它叫做pd
Pandas这个模组
是一个非常好用的资料处理工具
在colab里面我们不需要特别安装它
因为预设已经安装好了
所以我们可以直接引入做使用
接着我们要使用的资料
它的网址呢你可以在课程档案里面找到
我把它用一个变数来做表示
这边特别注意我们要读取的这个档案
它是一个CSV档
所以呢我们可以使用Pandas
它底下的read CSV来做读取的动作
我们只要把网址写到参数里面它就可以做读取了
这边我一样用一个变数来做表示
我们直接把读取的结果把它显示出来看看
执行
这就是我们要使用的资料
年资跟他对应的薪水
总共有0-32 也就是33笔资料
我们想要用一条直线来表示这一些资料
一条直线我们说过了
在数学里面可以写成y等于w乘以x加上b
那在我们这个例子里面呢
我们是想要用年资去预测薪水
所以年资就会是x 薪水就会是y
我们先把x跟y把它分离出来
我们想要去取得years experience这一列
那想要去取得这一列的话
可以在后面写上中括号years experience
这样他就会把那一列分离出来x
y也是一样
我想要去取得salary这一列
那我把它显示出来看看x跟y
好没有问题
接着呢我们先把这些资料对应的图把它画出来看看
我在另外开一个格子
要画图的话可以使用一个非常好用的套件叫做matplotlib
我们使用它底下的pyplot
我把它叫做plt
一样matplotlib这个套件在colab里面预设也是安装好的
所以我们可以直接引入做使用
我可以使用它底下的scatter 来把图画出来
我们只要把刚刚分离出来的x跟y
把它传进去它就会帮我们把图画出来了
然后最后我要把它显示出来要写一个show
执行
可以看到他就把我们的资料用一个点的方式
一点一点的把它显示出来
那如果你想要改变这个点的样式
假设我想要把它改成叉叉我想要改变它的颜色
那我这边我可以另外再加一些参数
我可以再写一个marker等于
原本的标记是圈圈嘛
我想要把它变成叉叉那我可以写上x
然后我也想要改变颜色我可以设定color
想要把它变成红色我写Red 好执行
可以看到标记就变成红色的叉叉
至于这边还可以有什么标记还可以是什么颜色
大家有兴趣的话就留给你自己去研究
这边我可以再帮图加上一个标题
我可以设定它的title
假设我的标题是年资对应他的薪水
好我们执行
可以看到好像出了一点错误
在标题的这个部分呢它出现了4个框框
会发生这个错误的原因是因为
matplotlib它预设是不支援中文的
如果我们想要显示中文的话
可以自己加入中文的字体
好那就来加入一下
首先我们要先去下载一个中文的字体
这边我在另外新建一格来做下载的动作
我们可以使用wget这个工具来做下载
只不过预设在colab里面是没有安装它的
所以我们要先安装
想要在colab里面安装套件安装模组
可以输入惊叹号后面一样pip install你想要安装的东西
安装好之后引入他
接着我们就可以使用他底下的download
来做下载的动作
只要在参数里面写上你想要下载的东西
他的网址就可以了
那这个网址呢一样在课程档案里面都可以找得到
这个就是我们要下载的字体
好直接执行
它会先安装接着引入下载
下载完成
我们来看一下
在左边可以找到一个档案打开来
这就是我们刚刚下载的字体
它叫Chinesefont.ttf
好这边我先把它关起来
下载好字体之后呢
我们就可以把它加入到matplotlib里面啦
要加入字体的话
我们额外再引入matplotlib 我把它叫做mpl
然后再从matplotlib它底下的font_manager
引入fontManager
那这边都引入完之后呢
就可以先用fontManager它底下的addfont来加入字体
我们刚刚下载的字体叫做Chinesefont.ttf
所以我们就在这里写上Chinesefon.ttf
加入字体之后呢我们还要设定现在要使用这一个字体
那要设定要使用这个字体
我们可以用mpl它底下的rc来设定一些东西
我们要设定的是字体所以第一个参数写上font
第二个参数就指定要使用的字体是Chinesefont
好那这样子就应该没问题了
我们先把字体加入进来
再设定要使用这个字体
再执行一次
可以看到现在中文就可以正常的显示了
这里除了设定图表的标题以外
我们也可以设定图表的x轴跟y轴标签
要设定x轴标签的话我们可以使用
x label 来做设定
那我们的x轴是年资
所以呢我写上年资
再来是y轴
y轴的话就是y label
y轴是月薪
那它的单位是千
所以呢我们写上月薪
括弧千再执行一次
可以看到现在x轴跟y轴的标签都上去了年资跟月薪
接着我们来把直线把它画出来
这边我在另外新增一格
刚刚已经提到了在数学上一条直线可以写成y=w*x+b
那特别注意我们是想要用x的值去预测y
所以呢这个y跟我们这个y是不一样的
这个y是预测的值
那这个y呢是真实的数据
所以呢我们回到下面
我们就可以用x去乘以一个w加上b
来表示我们预测的y
所以呢我把它叫做y_pred表示预测的y
那现在呢
假设一开始我先把w设定成0 b也设定成0
我们先来看看w=0 b=0画出来的直线会长什么样子
要画直线的话我们可以用plt它底下的plot来画
第一个参数就写上x的值
第二个参数就写上y的值
那这次呢我们的y值是y_pred预测的结果
一样要把它显示出来要写上show
OK 我们执行看看
可以看到这就是
w等于0 b等于0的时候画出来的直线
那我也可以把它的颜色改一下
假设我把它的color 把它设定成蓝色blue
这个颜色我觉得不错
接着呢我把上面的这些资料
把这些叉叉也把它画进来
我就把这里的这些都复制过来
复制在这里好再执行一次
那这个就是我们的预测线
这些呢是真实的资料
我们的目标呢就是要找出一条最能表示这些资料的直线
那现在这条直线是w=0 b=0的结果
所以呢我们要找出一个最适合的w跟b来表示这一些资料
那在这之前我们可以再帮图表加上一些图例
我们这一个plot 是画直线嘛
那scatter是画这些叉叉
我们可以在它的后面再加上一个label
这个图例呢是预测线
然后一样在画叉叉这边呢
我们也可以再加上一个label
它呢是真实数据
加上这个label之后
我们可以在这边再写上plot.legend
它就会把图例显示出来
好我们执行
可以看到这边图列就显示出来了
这条直线呢是预测线
然后这些叉叉是真实数据
我们先把这边的这些呢把它写成一个函式
这样子呢好让我们带入不同的w跟b
我把它叫做plot_pred
然后它可以传入w跟b
把这些把它做缩排
我们就来试试看带入不同的w跟b
画出来的结果会长怎么样
这边我们就可以呼叫plot_pred
假设我一样先带入0跟0 执行一次
可以看到跟刚刚的结果是一样的
假设我把b的值做修改
我把它改成10 再执行一次
可以看到这个线呢看起来好像没有变
但实际上是有变的
是因为我们现在x轴跟y轴的这个值呢
x轴跟y轴的值我们没有固定
所以图会看起来好像没有变
所以这边我们先把x轴跟y轴的值做一个固定
要做固定的话呢这边我们可以这样子写
plt.xlim 我们设定它的最大跟最小的范围
x轴的话是0-10左右嘛这边还有多一点
所以我把它设定0-12
这边我们可以这样子写哦
在里面写上一个这个列表
然后呢设定它的最小跟最大值
然后y的值呢也是一样
我们设定他的最大跟最小
这边的话因为有可能到负数
所以呢我让他最小是-60好了
最大的话就让他到到140
好那我们再执行一次
可以看到现在呢x轴跟y轴的值就会是固定的
再执行一次
x轴跟y轴的值就会是固定的
y轴呢是-60到140 那x轴是0到12
我们再试一次0跟0的结果
0跟0的结果这一条直线是在y等于0的这个地方
那如果我把b的值把它带入改成10再执行一次
可以看到这条直线呢它就往上了
所以呢由此可知b的值是控制这条直线它的上或下
如果把它改成40
它就更往上了
那如果是-30呢执行
可以看到它就往下
那现在我们试试看改动w的值
本来是0嘛我把它改成10看看
可以看到这条线呢它变斜了
往上斜上去了
那如果改成20呢
就会更斜
如果我改成负数-10
可以看到它就会往下掉下去往下斜
正数的话就是往上斜
负数的话就是往下斜
这边我试试看-5
好可以看到它是这样子的一条线
那这边因为已经超出边界了所以我们看不到
接着我们来把这张图变成动态的
这样就可以不用一直手动调整w跟b的值
想要在colab里面新增一些互动元件的话
我们可以使用ipywidgets这个工具
这里我引入它里面的interact
好那我就可以这样做使用
在第一个参数写上函式的名称
然后我们想要动态调整的是w跟b的值嘛
也就是这个函式要传入的两个参数
这边我就可以设定w的值
我希望它的范围假设是-100到100之间然后它的间距是1
再来设定b的值
一样假设我希望它是-100然后到100之间一样是间距1
我们直接执行看看
可以看到这边就会多了互动元件
预设值呢w跟b都是0 我可以做调整
我把w往上加8的时候呢这个直线会长这样
然后把b往上加
好它会慢慢往上移动接着再加
大家都可以自己去玩玩看
调整不同的w跟不同b的值
看一下这条直线会长什么样子
好那就留给大家自己去玩啦
在看完了不同的w跟b 会产生什么样子的直线之后
接着我们的问题就会变成
怎么样是最适合这些资料的直线呢
我们总要定义一下吧
总要帮每一条线评个分数吧
我们先来看一组相对简单的资料
如果我一样是想要用一条直线来表示这些资料的话
假设今天我是用这条直线
那这条直线它是w等于0 b等于0的结果
那我们总要帮这条直线
跟这些资料的适合程度评个分数吧
或者你可以说
把这条直线跟这些资料的吻合程度评个分数吧
那我们要怎么样帮这条直线评个分数呢
非常的简单
我们只要去计算这些真实的资料
跟这条线的距离加总是多少就可以了
因为如果这些资料跟这条线越吻合的话
那这些资料跟这条线的距离就会越小嘛
所以呢我们只要把每一条线
跟这些真实资料的距离计算出来
接着再从中找出最小的那一个
那一条线就会是最适合这些资料的直线
我们直接来实际操作一次
以现在这个例子来说
总共有三个资料点
分别在1,1 2,2跟3,3的位置
我们想要用这一条直线来表示这些资料
这条直线是w等于0 b等于0的结果
然后我们想要帮这条直线
跟这些资料的适合程度去评一个分数
要怎么评分呢
我们可以用这些资料跟这条直线的距离加总
去当做评分的依据
这个点的话1-0所以它跟线的距离是1
那这个点的话2-0距离是2 这边3-0是3
所以呢我们的式子会写成这样
大家可能会看到这边我除了1-0之外
我还把它做了平方
这边会做平方的原因
是因为它可以方便我们计算
因为在往后呢你可能会出现负数
那直接做平方就可以把负数的问题解决了
所以以这个例子来说的话
1减0的平方2减0的平方3减0的平方
最后距离的加总
应该说距离平方的加总就会是14
我们再看另外一条线
假设我们想要用这一条线来表示这些资料
那这条线是w等于2 b等于0的结果
我们一样计算他们的距离
那这边的这个点呢它一样是1嘛
所以这边就是1减掉2 1减2的平方
然后这边是2减掉4 2减4的平方
3减掉6的平方
可以看到这边就会出现负数了嘛
如果我们没有平方的话这边就会出现负数
所以这边一样计算完之后做加总
一样是14
好再看下一条线
可以看到这条线相当的吻合
它是w等于1 b等于0的结果
那样计算距离
可以发现每一个呢都是一样的值
所以计算出来距离就会是0
以这三条线来说的话
我们就会说这一条线w等于1 b等于0的这条线
是最适合这些资料的直线
接着根据不同的w或b 产生出来的分数
或者说产生出来的距离平方加总
我们可以把它写成一个函数
这个函数就叫做cost function
中文的话是成本函数
以我们这个例子来说
cost function可以写成这个样子
它是拿真实的数据去减掉预测值然后做平方
也就是我们去计算真实的数据
跟那条直线的距离平方那就会是cost
也就是我们刚刚所说的评分
好回到原本的例子
我们想要找出一条最适合这些资料的直线
那我们就需要帮直线评个分数
也就是计算这边的cost
我们先假设现在所有的直线
它的b都等于0的情况下
我们去看看不同的w 对应的cost会是多少
我们就一个一个点的带入
先带入一个w等于-10几然后它的cost会在这里
接着带入第二个第三个
一路带入带入带入
最后我们带入很多很多个点之后
我们会发现其实这个cost function也就是成本函数
它会是一个这样子的抛物线
这是b等于0的情况
那如果b不等于0 w跟b所对应的cost又会长什么样子呢
我们来看一下
这边我用不同视角的3D图来给大家看
这里是w的值这里是b的值
然后z轴呢是cost的值
可以看到它的图形会长这个样子
这个红点呢是Cost最低的点
我们再看另外两个不同的角度
好从这两个角度我们可以看得到
这个红点的地方我刚刚说了是Cost最低的地方
我们可以看到
大概在w等于10几的地方
然后b等于20几的地方
会产生一个cost最低的点
那这也就是我们的目标嘛
我们的目标就是要找出一条最适合的直线
找出一条最适合的直线
就是要找出一个最适合的w跟b
最适合的w跟b 所产生出来的那一条直线
跟所有真实资料的距离平方加总就会是最小的
也就是这边的cost最小的地方
这边都理解了之后
接着我们就直接来实作cost function
这边我另外开了一个新的colab档案
来做cost function的实作
一开始呢一样要先读取资料
读取资料的做法跟之前都是一样的
所以我直接复制
好贴上执行
资料读取好之后呢
接着我们就来实作cost function
再开一格
我们的cost function
是拿真实资料去减掉预测值的平方嘛
所以呢这边我们可以这样子写
先把预测值把它算出来
我叫它y pred
它会等于w 去乘以x 加上b嘛
那这边的w跟b现在都还不知道
所以我先假设w等于10 然后b等于0好了
计算出预测值之后我们就可以拿真实资料
真实资料就是y去减掉预测值y Pred
然后我们要做它的平方
所以我把它括号起来然后做平方
这边呢就叫做cost
好那我们直接把这个cost 把它显示出来看看
可以看到总共显示出了33个值
那这33个值呢就是真实资料去减掉预测值
然后做平方的结果
也就是我们的距离平方
如果我们想要把这些距离平方的值做加总的话
只要在后面写上.sum()
好把它显示出来看看
可以看到这就是加总的结果
距离平方的加总
如果觉得这边的值太大的话
通常我们还会把它做一个平均
我们总共有33笔资料嘛
所以我们这边就会除以33
但是呢这边这样子写比较好
我们去算这个x的长度
那x的长度就是33嘛
所以呢这边除以33
这个就是距离平方的平均
接着我们来把这边计算cost的动作写成一个函式
这样好让我们带入不同的w跟b的值
好再开一格
这边我就把它叫做compute cost
然后它要传入我们的资料
x跟y以及预测的线它的w跟b的值
计算的方式呢都跟这边是一样的
我直接贴过来
我们要先去做预测值嘛
预测值就是w乘以x加上b
然后呢去计算cost
再做加总之后取平均
我就让最后cost的值等于加总之后再取平均的结果
最后呢我们再把这个cost把它做回传
我们来试试看带入不同的w跟b
会产生什么样子的结果
这边就来呼叫看看
xy就是这边的真实资料然后w
我们刚刚是带10跟0嘛w跟b
一样我试试看10跟0 执行
他说compute cost is not define 哦这边还没执行
要先执行再执行这里
他回传的值就是602点多少
跟刚刚是一样的
如果这边我带入的是10 再执行一次
可以看到这次的cost就是227点多少多少
那大家可以自己去带入
看看不同的w跟b 产生的cost会是多少
接着我们来试试看
在固定b等于0的情况下
然后让w等于-100到100之间
然后我们来看看它的cost会是多少
这边我先定义一个cost 让它是一个列表
然后来存放w从-100到100之间cost的值
好那这里呢
我们就可以用一个for回圈去做计算
我让w让它是从range -100 然后到100之间
这边我要写101
它就会产生一个类似
从-100到100之间的一个列表
然后我们就要去计算cost
这边的函式直接拿来做
使用xy 然后固定b等于0的情况下
让他一直带入w的值
这边就叫做cost
然后呢再把它append到我们的costs这个列表里面
最后我把它显示出来看看执行
这边呢这一些总共从w等于..
哇非常的多
从w等于-100到100之间总共有201个值
它的cost
我先把它关掉
接着我们来把不同的w对应的cost
把它画成一张图来看看
这边就引入我们的绘图工具matplotlib它底下的pyplot
我把它叫做PLT
接着我们就可以使用scatter
来把每一个资料点把它画出来
我们把每一个w跟对应的cost 把它画出来
那我们这边的w呢就是从-100到100之间
跟它对应的cost
把它显示出来执行
可以看到从-100~100之间总共会有201个点嘛
那201个点呢画出来就长这样密密麻麻的
这边我们除了这样画以外
也可以直接把它连成一条线
把它连成一个抛物线
这里就使用plot 一样传入w跟对应的cost
再执行这条抛物线就做连线了
这里我边帮他加个标题还有标签
这一个呢是cost function在b等于0 然后w从-100~100之间
再设定他的xlabel
xlabel就是w的值
然后ylabel cost
执行看看
可以看到标题还有x轴y轴的标签都上来了
接着我们把b的值也考虑进来
让b的值也是从-100到100
我们来看看cost会是多少
这边我引入一个在做矩阵运算非常好用的工具numpy
我把它叫做NP
现在w跟b都是-100到100之间
我们可以用NP底下的arange
那这个arange的用法
基本上跟我们上面的这个range是差不多的
我想要创建一个-100到100之间的一个矩阵然后间隔是1
我们可以这样子写
那这边我就把它叫做ws 因为有很多个w
b也是一样我把它叫做bs
接着我再创建一个二维的矩阵
这边我可以用NP点zeros
来创建一个里面全部都是0的矩阵
第一个维度让它是201 第二个也是201
因为我们现在这边w的值总共有201个b的值也是201个
这个矩阵就是要存放不同的w跟不同的b
它们对应到的cost
所以我把它叫做costs
接着就可以来做计算了
我先用一个for回圈去跑过所有的ws里面的值
接着再用一个for回圈去跑过所有的bs里面的值
然后我们就可以计算他们的cost
要计算cost的话我们上面已经写好函式了
直接拿下来用
在这边直接复制下来
好那xy是真实资料
然后这边把wb传进来就会计算出cost
我们就可以把它存放到costs这个矩阵里面
这边的话我们在另外设定义个i 一开始等于0
然后这里也设定义个j等于0
那这里i跟j的值呢就会等于这个cost
然后这边让j让它加1
最后这边呢i让它加1
这样子计算完之后
就会把所有的w跟所有的b
他们的组合所对应的cost 把它储存起来了
储存在这个costs里面
把它显示出来看看执行
他说numpy has no attribute
这边多写了一个r
好再执行一次
他需要一点时间等他一下
长这个样子是一个二维的矩阵
那里面的每一个值呢
就代表了一个相对应的w跟b 所计算出来的cost
再来我们就来把同时考虑w跟b 所计算出来的cost
它的图把它画出来看看
因为要同时考虑到w跟b的值
所以我们会画一个3D的图
要创建一个3D的图我们可以写plt.axes
然后设定它的projection=3D 我把它叫做AX
然后我们先把它显示出来看看
执行
可以看到就创建了一个3D图
不过现在里面什么东西都没有
那我们可以看到这个图的边边是有点灰色的感觉
我不想要他是灰色的
我也可以做一个设定
我可以用ax.xaxis.set_pane_color来设定颜色
我想要它是白色的
我这边可以写一个rgb的值
白色的就让它是0 0 0
好执行看看
他说没有attribute
这边写反了
好可以看到这个x轴这一面呢
就会变成白色的
那同样的我把它用到y轴跟z轴
这边就直接复制
只要把这里改成y跟z
好再执行一次
这样就会都是白色的看起来舒服许多
再来我们把w跟b所对应的cost 把它画成一个曲面图
这边我们可以用它底下的plot_surface
然后就可以把我们刚刚所创建的w值跟b的值
也就是ws跟bs这两个矩阵把它传进来
最后是我们储存的cost
好那这边特别注意
其实呢我们不是单单传入WS跟BS这两个一维矩阵就可以了
他要的是这两个一维矩阵所产生的一个二维网格
那我们要产生这个二维网格的话
我们可以使用numpy它底下的mesh grid
然后呢这边特别注意第一个我们先传入BS
第二个再传入WS
那他就会把它做成一个二维的网格回传给我们
我就把它叫做
b grid w grid
大家想要详细了解这个二维网格是什么东西
他是怎么运作的话
可以看一下这个网址
他解释的非常详细
这边我就不赘述了
大家如果感兴趣的话我把网址放在下方
可以自己去研究一下
这边我们就要改成传入w grid跟b grid
好这样没问题我们执行
可以看到这个曲面图就显示出来了
我们再帮这个图增加一些标题还有标签
这边的话我们可以写ax.set_title
这边特别注意我们前面要多加一个set
跟前面不一样前面是直接写title就可以了
这边呢要特别多加一个set
title呢我们就让它是wb所产生的cost
那就是对应的cost
这边会使用到中文
使用到中文的话一样我们就要把中文字体加入
所以呢我一样回到之前的这个档案里面
中文加入是在这个地方
前面还要做下载嘛这边先做下载
我就直接贴过来
这边是下载好先执行它
接着呢就是把它加入进来
这边是加入进来
好我把它贴到这里
先做下载然后再把字体加入
这边title设定好之后
接着我们设定xy跟z轴的标签
那这边一样要加上set xlabel
x轴的标签呢就是w
然后再设定它的..
这边我直接用复制
设定它的y轴标签y轴标签就是b
然后再是z轴z轴就是cost
好那我们把它再把它显示出来一次
可以看到这个就是w
然后b 然后他们对应的cost是z轴
这边如果我们想要把这个图旋转一下也是可以的
如果想要旋转的话
可以在这边设定一个view init
它可以传入两个参数
第一个参数是上下的旋转角度
第二个参数是左右的旋转角度
假设第一个我写45 第二个我写-120 再执行一次
可以看到现在图呢它就转成这样
这边是w 这边是b 然后呢这个是cost
好那这个旋转的角度
大家也可以自己去玩玩看
接着我觉得这个曲面的颜色不太好看
我想要把它做个修改
那可以在这里再多设定一个参数叫做cmap
我把它设定成spectral r
好我们执行看看
可以看到现在颜色就好看的许多
至于这边还可以设定成什么其他的颜色
就留给大家自己去研究哦
我觉得这个颜色不错
然后我们还可以再多设定一个不透明度的值
那不透明度呢叫做Alpha Alpha
我让他等于0.7
执行看看
可以看到现在他就多了一个透明的感觉
看起来就更舒服了
接着如果我们想要让这个图更好看的话
我还可以再帮他加一个边框
我可以写plot wireframe
然后一样传入这前三个参数
接着我设定边框的颜色是黑色
好我们执行看看
可以看到现在多加了这个边框
但是呢有点太黑了
一样我们可以设定它的透明度Alpha
假设我让它的透明度是0.1就好了
再执行
可以看到这样就非常的舒服非常的好看
接着我们来把cost最低的那一个点把它找出来
要找出cost最低的那一个点
我们可以用numpy它底下的min
然后呢去找我们整个cost
我把它印出来看看
最低的cost是多少呢
最低的cost是32.69多
那如果我们想要知道32.69多这个cost
它对应的w跟b是多少的话
我们可以这样子做
可以用np.where 去找出它的位置
找出所有的cost当中等于最低的这个cost
它的位置它的索引在哪里
那因为这个costs它是一个二维的矩阵
所以它会回传两个值也就是两个索引
我把它叫做w index跟b index
好那我们就可以把这两个值把它印出来看看
执行
可以看到它找出来的索引在109跟129的地方
我们还要从所有w的矩阵中去找出这个索引所对应的w值
b的部分也是一样
好那我们再执行一次
可以看到对应的值呢
对应的w值是9 然后b是29
也就是说当w等于9 b等于29的时候会有最小的cost
那这边我们就可以这样子写
当w等于这个值并且b等于这个值的时候
会有最小cost
那最小的cost呢就可以从costs这一个二维矩阵中去取值
要取的值就是这两个索引所对应的那一个值
好我们再执行一次
他就说啦
当w等于9 b等于29的时候会有最小cost
那最小的cost是36.69多
最后呢我们还可以把这个
最小的cost的那一个点把它画出来
那要把它画出来的话我们就可以用scatter
第一个值呢就传入w的值然后再是b的值
再是z轴也就是我们cost的值
好执行
可以看到最小的cost的那个点呢就在这里
那我可以把它的颜色改一下
设定它的color等于红色
然后呢我想要让它大一点
设定它的SS就是大小
我让它是40 好再执行一次
可以看到这样就舒服了许多
最后的最后我想要再把这张图调整的大一点
那我可以到最上面这边来设定
我可以写plt点figure
然后设定它的figsize
他可以设定两个值
这两个值呢分别代表图的宽度跟高度
假设我一开始是5跟5好了
看看他会长什么样子
感觉还是有一点小我再把它变大一点
7跟7 来看看
这样看起来舒服许多了
好那这边其他的参数像是旋转角度啊
图的大小或是颜色等等的
大家都可以自己去做调整
那这就是我们cost function的实作
在看完了cost function之后
接着我们的问题就会变成
怎么样有效率的去找出最佳的w跟b呢
最佳的w跟b 也就是对应到cost最低的那一个点
从我们上一个实作不难看出来
我们是用一个暴力破解的方法
我穷举了w从-100到100之间的所有值
然后去看它的cost是多少
再从中找出最低的那一个点
这边考虑的w跟b也是一样
我穷举了w跟b 从-100到100之间的所有组合它对应的cost
然后再从中找出它的最低点
但是呢这不是一个好的办法
我们必须要有效率的找出最佳的w跟b
那有效率的找出w跟b
这边可以使用一个方法
叫做gradient descent 中文是梯度下降
那大家也不用把它想的太困难
其实梯度下降呢就是根据斜率去改变参数
以我们这个例子来说参数就是w跟b
所以呢就是根据斜率去改变w跟b的值
我们就直接来看看gradient descent是怎么样运作的
以这个当做例子
我们先假设b等于0 只考虑w的情况下
要怎么样找出一个最佳的w
它可以让cost的值最低呢
首先我们要先去设定一个初始的w值
那这个初始的w值可以随机设定
假设我设定在这里
大概等于-75的地方
接着我们可以透过微分的方式
计算出这一点的切线斜率
我们可以透过微分的方式
计算出这一点的切线斜率
那这边大家要特别注意
当我们在使用gradient descent的时候
其实我们是不知道这条蓝色的线的
我们是不知道这条蓝色的抛物线的
这条抛物线是经过我们暴力穷举才得到的
所以呢你并不会知道最低点在这里
那我们重新描述一下现在这个问题
大概可以比喻成这个样子
今天你被蒙着眼睛丢到一个地方
在这个地方你只能往前走或往后走
那你的目标呢是要走到最低点的地方
不过幸运的是你可以透过某种方法
去计算出你目前所处的位置他前后的陡峭程度
接着呢你就可以根据这个陡峭程度
去找出往下走的路
回到原本的例子一样
在这个点的时候
你可以透过微分的方式
去计算出他的切线斜率
这个切线斜率也就相当于是陡峭程度
然后呢我们就可以根据这个斜率
去找出往下走的路
好这边我简单的带一下
这个斜率是怎么样算出来的
首先呢我们要先设定好cost function长什么样子
那以我们这个例子cost function长这样
我们是拿真实数据去减掉预测值然后做平方
那以数学来表示的话
就是拿y去减掉ypred 然后做平方
这个ypred呢又可以表示成w乘以x加上b
因为我们是想要以一条直线来表示资料嘛
所以这边是w乘以x加上b
接着在这个例子里面b是等于0的
所以呢我们可以直接把它省略掉
然后呢我们只要把它对w做微分
就可以得到切线斜率了
那做微分之后会长这样
详细的微分过程我就不做给大家看了
大家有兴趣的话可以自己去研究
那实际上如果你完全不知道什么是微分也没关系
因为有很多工具都可以帮我们自动的做计算
好这边微分完之后
如果我们想要知道w等于-75的时候
它的切线斜率会是多少
那我们就把-75带进来
这里的x跟y呢都是我们的真实资料
一样带进来就可以算出来
切线斜率是多少了
在我们知道了斜率之后
就相当于是知道了这里的陡峭程度
那知道了这里的陡峭程度之后
我们就可以往下走啦
要怎么往下走呢
我们可以让w去减掉斜率去乘以一个学习率
那这个学习率是什么我等等再跟大家解释
我们先看前面的w去减掉斜率
以这个例子来说现在w大概等于-75
然后呢切线斜率很明显的是一个负数
所以我们让w去减掉一个负数
也就是会加上一个值嘛
所以呢加上一个值之后他就会往前了
接着我们就一直重复这样子的动作
再去计算这一点的切线斜率
那一样我们把数字带进来就可以找到斜率了
找到斜率之后再带到下面这一条式子
一样现在呢w大概等于-60的地方
显然可以看得到这个斜率还是负的
我们再让w去减掉一个负数
那就是加上一个值嘛
所以它就会往前
我们就一直不断重复这样子的动作
计算斜率更新w
计算斜率更新w 我们来看一看
计算斜率更新w 计算斜率更新
然后再来一直不断重复
直到最后我们快要接近最低点或是在最低点的时候
这边的切线斜率就会相当接近0 OK
这边的切线斜率就会相当接近0
那相当接近0之后
我们让w去减掉一个接近0的值
也就相当于w是没有更新
那我们就找到最低点啦
这大概就是gradient descent的运作过程
接着呢我们来看一下这个学习率是什么东西
学习率它的英文是learning rate
那其实讲简单一点呢
学习率就是我们往下走的步伐大小
好回到刚刚的例子
一样一开始我们先找一个初始的w
然后呢就可以计算它的切线斜率
计算完切线斜率之后要往下的话
我们可以让w的值去减掉斜率乘以一个学习率
那这个学习率呢就是你要设定一个数值
这个学习率是多少你要自己去决定
我们来看一下这里是拿斜率去乘以学习率
如果你的学习率越大的话这边就会越大嘛
有可能是正的越大也有可能是负的越大
那我们拿w去减掉一个越大的值w的变化就会越大
也就是说它的步伐会越大
反过来如果你的学习率越小的话
这边相乘之后就会比较小
然后我们拿w去减掉一个比较小的值
w的变化就会比较小
也就是步伐会比较小
好那我们就来看一下
不同的学习率会有什么样子的结果
先来看学习率如果是大的话
那他的步伐就会相对比较大OK比较大
好 看到这边你可能会有一个疑问
就是他的步伐是不是渐渐在变小
没有错
他是渐渐在变小
即便我们的学习率都是保持一样的
他的步伐也会慢慢变小
为什么呢
因为这边的斜率也会变
他在这边的斜率是比较大的
然后呢在越靠近最低点的地方斜率就会越小
所以他这里呢步伐也会变小
接着我们来看
如果学习率是比较小的话会长什么样子呢
那他的步伐呢就会比较小
我把两张图放在一起比较一下会比较清楚
左边呢是学习率大的右边呢是学习率小的
可以看到左边他的步伐就比较大
右边呢就比较小
讲到这边你可能就会说
那我们肯定是把学习率设定成很大啊
因为设定成很大
他往下走的速度才会快嘛
这样我们才可以越快到达最低点
这是一个非常好的问题
但是呢我们的学习率也有可能会过大
过大的话会长什么样子呢
我们来看一下
你第一步就走到这里了
接着第二步
你不是走到最低点哦
你是直接跨过去跨到了对面
那我们再来看第三步呢
第三步他又跨回来了
你就会这样一直不断的跨过去又跨过来跨过去又跨过来
永远都没有办法走到最低点
因为你的步伐太大了跟本没有办法走到最低点
这是学习率过大的问题
我们再来看一下如果学习率过小的话会怎么样呢
你的每一步都很小很小很小很小
很小到你走到天荒地老也一样没有办法走到最低点
所以呢学习率你不能太大也不能太小
要找到一个最适中的值
那要怎么样找到最适中的值呢
我们可以透过不断的实验跟测试去找到它
好那这就是学习率
接着我们再回到原本的gradient descent
刚刚的例子都是只有在考虑w的情况下
如果我们现在连b也要考虑的话
那这个gradient descent会怎么运作呢
基本上都是一样的
首先呢你要先去设定一个随机的初始w跟b的值
那这边你看到的这个图呢
也是我们经过穷举之后才得到的
所以呢你并不会知道这个最低点在这里
那我们就直接套用到比喻里面
今天呢你一样莫名其妙被带到了一个地方
然后蒙上了眼罩
这个地方呢有点类似一个峡谷的地形
那你的目标一样是要找到这个峡谷的最低点
不过这次跟上次不一样的是
你除了可以前后走以外你也可以左右走
你一样可以透过某种方法得知你前后的陡峭程度
还有左右的陡峭程度
那你就可以透过陡峭程度去找到往下走的路了嘛
这边跟刚刚一样陡峭程度就代表斜率
所以呢这里就是计算w方向的斜率
那这边呢就是计算b方向的斜率
要计算斜率的话
一样我们可以对cost function做微分
以这个例子来说cost function长这样
是用真实数据去减掉预测值然后做平方
也就是y减掉y pred然后做平方
其中这边的y pred呢
我们还可以拆解成w乘以x加上b
接着对w作微分就可以得到w方向的斜率
那如果对b作微分呢就可以得到b方向的斜率
做完微分之后结果会是这样
w方向的斜率长这个样子
b方向的斜率长这个样子
一样如果我们想要知道
这个点它的斜率是多少
那我们就把数值带进去就可以了
把这边的w带进去把这边的b带进去
然后x跟y呢也是我们有的数据了
那就可以计算出这边的w方向斜率跟b方向斜率
接着呢我们就可以来更新w跟b的值啦
也就是我们可以往下走了
要更新w 我们就拿w去减掉w方向的斜率去乘以学习率
那要更新b呢就是拿b去减掉b方向的斜率乘以学习率
这样子呢就可以往下走了
到这个点之后
一样我们再重新计算一次w方向的斜率跟b方向的斜率
计算完之后呢就可以做更新
那我们就可以慢慢的往前走往前走走到最低点的地方
那我们是蒙着眼睛在走
要怎么样判断自己是不是在最低点的呢
一样当你越靠近最低点的时候
w方向跟b方向的斜率就会越小
然后你又让w跟b 去减掉一个很小的值
那它就相当于没有怎么样变
我们就可以借此来判断
现在自己的位置大概在哪里
学习率的部分
一样你要自己去设定一个值
这个值不能太大也不能太小
如果你的学习率设定的过大的话
那他的步伐就会非常的大
大到有可能永远没有办法到最低点的地方
反之学习率如果过小的话
你的步伐就会非常的小
小到你走到天荒地老可能也走不到最低点的地方
这就是我们的gradient descent 它的运作过程
接着我们就直接来试做看看啦
好那我们就来实作gradient descent啦
首先一样要先读取资料
读取资料的动作跟之前都是一样的
所以我直接用复制的
接着我们刚刚说了gradient descent
就是去计算斜率然后更新参数
要计算w方向的斜率
我们可以把cost function对w作微分
反正要计算b方向的斜率
我们可以把cost function对b作微分
我们就来计算一下
我们把cost function对w作微分
它的结果是这样2乘以x 然后再乘以
w乘以x加上b去减掉y
这个呢是把cost function对w作微分的结果
那如果我们把cost function对b作微分的话
其实呢差别就只是这边少乘了一个x
那w方向的斜率我就叫它w gradient
那b方向的呢我就叫它b gradient
现在如果我想要知道
当w等于10 b也等于10的时候
它w方向跟b方向的斜率是多少呢
那我就先设定w等于10 b也等于10
我们先来看w方向的好执行
我们可以看到它总共产生了33个值
因为我们总共有33笔资料嘛
你每一笔资料带进去都会产生一个斜率
这边我们就把它做平均
要做平均的话
我们可以先把它做加总的动作
然后再去除以它有几笔资料
那这边呢有几笔资料我用n来表示
我们去计算x的长度
然后这边就可以除以n
我们再执行一次看看
这个就是平均的结果是-118点多少多少
那我们再看一下b方向的
一样我们有33笔资料
所以呢他会计算出33个值
这边我们的做法一样
就是把它做加总之后再除以n
再执行
可以看到平均的结果呢就是-27.46
那其实这边如果我们想要计算平均的话
也可以直接这样子写
我们写点mean 他一样是计算平均
这边就不需要在另外去计算x的长度了
可以看到执行的结果是一样的
这边w方向也改一下
好都是一样的
那为了方便
我就把计算斜率或者你可以说计算梯度的这个动作
把它写成一个函式
这边呢我就叫它compute gradient
我们要传入x跟y也就是我们的资料
然后跟wb的值就可以做计算了
我们就把计算的结果把它做回传
w方向以及b方向
那我再开一格来试试看
假设我现在想要知道的是
w等于20然后b等于10的时候
它计算出来的斜率会是多少
这边要先执行再执行它
w方向是537点多少
然后b方向是70点多
计算出w跟b方向的斜率之后
接着我们就可以去更新w还有b的嘛
因为我们的更新方法
就是拿w还有b去减掉它的斜率乘以一个学习率
我们先假设初始的w是0
那初始的b也是0
这边你可以随便乱设我就把它设定成0
然后呢我们就可以去计算当w等于0
b等于0的时候它的斜率是多少
接着我们就可以根据这个斜率
去更新w 还有b的值
要计算斜率就使用刚刚写好的函式
我们把wb带进来
它就会回传给我们w还有b方向的斜率
那我们就可以根据这个斜率去更新w 还有b的值
要更新w的话
我们可以把w去减掉w方向的斜率
然后乘以一个学习率
这边学习率经过我的测试跟实验之后呢
我觉得0.001不错
好那要更新b的话
一样就是把b减掉b方向的斜率
然后乘以这个学习率
我就让w等于更新之后的结果
然后b也等于更新之后的结果
我们把它显示出来看看
执行
可以看到更新之后呢
w从0变成了0.87多
然后b从0变成了0.14多
那接着我们就来看看wb从0,0变成这样子
是不是真的有让cost下降
也就是它是不是真的有往下走
要计算cost的话之前也写好了
就直接复制过来
这个compute cost直接复制过来
那这边呢我们就可以直接拿来做使用
我们就来看看wb本来从0,0
然后呢变成这个新的值之后是不是真的cost有下降
我把它印出来
把它印出来执行
可以看到本来是6,040然后变成5,286
所以真的cost是有在下降的
也就是我们真的有在往下走
好讲到这边我们先暂停一下
我们先看一下刚刚计算梯度的地方是怎么写的
找到compute gradient 在这边
不管是计算w方向还是b方向的梯度
大家应该有发现它都有一个乘以2
那其实这个乘以2是可以省略掉的
这边我们是可以把它省略掉的
好省略完之后我再执行一次
为什么可以省略掉呢
我们再往下看这边
我们是不是拿w
去减掉w方向的斜率乘以一个学习率
然后b去减掉b方向的斜率乘以一个学习率
我们刚刚w跟b方向的斜率都有乘以一个2
就相当于我们有在后面再乘以一个2
那其实这个乘以2是没有必要的
因为呢它会间接的影响到步伐的大小
步伐的大小我们就由learning rate来控制就好了
所以这边乘以2呢其实我们可以不要写
我们直接把两倍写在这边就好了
我们直接让learning rate去乘以2
再计算一次
可以看到其实结果是一样的
所以呢我们上面的这个乘以2
是可以不要写的就把它省略掉
我把这个乘2删掉再执行一次
这次呢就是6040然后变成5656
这个是我们只有更新一次的结果
只更新了一次w跟b的结果
那我们来试试看更新10次会长什么样子呢
我就用一个for回圈
去把这边重复执行10次让他跑10次
然后呢我们顺便记录一下wb跟cost的值
这边cost等于把它记录一下
用一个f string来写
那一开始呢我先写现在是第几次
也就是iteration 第i次更新
然后呢我们记录一下现在的cost是多少
cost的话就是这个值
然后顺便把w跟b的值也把它记录一下
我们执行看看这样会长什么样子呢
第0次的时候cost是这个值然后w跟b
我们来看一下cost 是不是有真的在下降
是真的有在下降哦5656到了3161
这边我让他有个间隔好了
再执行一次
这样舒服了许多
但是呢他小数点有点多所以会看起来有点不整齐
这边如果我们想要让他小数点都只显示两位的话
可以这样子做
我们在后面写上:.2f
这样子写呢就是只会显示小数点后面2位
如果你要3位就是.3f
以此类推
那我把w跟b也只显示2位再执行一次
这样看起来就整齐许多了嘛
cost呢是有在做下降
然后呢就是w一路更新的值b一路更新的值
接着我们来试试看如果给他20次再执行
可以看到cost也是一路在做下降
到20次的时候只剩下1,705
不过呢现在他好像又变得不整齐了嘛
原因是因为这边到第10次的时候他占用了两格
那我们如果想要让他占用的格数都一样的话
这边我们可以在他的后面写上:
然后想要让他占用几格
假设我想要让他占用5格那我就写:5
再执行
这样不管它数字是多少它就是占用5格
这样整齐许多
这边除了计算cost还有w跟b的值以外
我顺便把w 还有b方向的斜率也记录一下
那这边呢他一样会有很多小数点
所以我就让他只显示2位就好了
再执行一次
这样就都记录到了
那我们看到cost的地方
可以看到他还是明显的在下降
所以呢我让他再跑多次一点
看他可以下降到什么程度
跑个100次
往下看还是好像还在下降嘛
但是我们可以看到右边这边
似乎又开始变得不整齐了
这边又开始变得不整齐了
原因是因为我们的数字还是有大小嘛
有可能是两位数三位数
所以他还是会变得不整齐
这边如果我们真的要让他变得很整齐的话
可以用科学符号的显示方式
这边我可以写.2e
把它改成.2e 那它就会显示两位
其他呢以科学符号的方式呈现
什么是科学符号呢
我们执行看看就知道了
可以看到这个就是科学符号
它写5.66e+03
也就是5.66乘以10的3次方的意思
也就是相当于5,660
如果这边你看到的是5.66e-03
那也就是5.66乘以10的-3次方
我们这边用科学符号来表示就整齐了许多
我们看到cost的这个地方
他还是在下降嘛
所以我再让他跑多次一点
这边是让他跑了100次
那我让他跑个1,000次
再执行
我们来看一下
好像还在下降哦
42然后到41还在下降中
那我们就再让他跑多次一点
我让他跑个一万次
那这边1万次都把它印出来就太多了
所以呢我让他1000次才印一次就好了
那这边我就判断如果i
他去除以1,000是整除的话
我才印出这些资讯
好再执行一次
那他就1,000次才会印一次
好那我们可以看到
这边好像还是有点不整齐哦
原因是因为他多了一个负号嘛
那这个问题要解决的话
我们可以在前面加一个空白
加一个空白的话它就是会多让出一位来表示符号
表示这个符号
让这边都多让出一位
再执行一次
这个问题就解决了
我们来看一下cost的地方还在持续下降中
跑了1万次之后呢
好像还在下降哦他从3.51乘以10的一次方到了3.39
那我们再让他跑个跑个2万次来看看
这边我小数点让他显示多位一点好了
这边我让他.4e
好再执行
那这样他就会显示4位
好还是持续在下降
但下降幅度变得很小了
我们就让他跑个2万次就好了
可以看到下降幅度慢慢的越来越小
我们看一下旁边斜率的地方
可以看到w方向的斜率跟b方向的斜率也非常非常的小
快要接近0了
那我就直接把
这个gradient descent的过程
把它写成一个函式
这样可以方便之后做使用
函式的名称我就把它叫做gradient descent
那他要传入的东西呢
就有很多喽
x跟y也就是我们的资料以及初始的w 还有初始的b
然后呢学习率
以及我们要用来判断好坏的cost function
还有要计算斜率的gradient function
最后是你总共要跑几次run iter
跟你多少次要印出资料我叫他p iter
那p iter我让他预设值是1,000
也就是1,000次会印出来一次
所以这边呢就把它改成p iter
这个2万呢就把它改成run iter
然后初始的w是w init
所以我让w 等于w init
初始的b呢是b init
接着计算cost的function呢
要改一下compute cost
把它改成这个function
然后compute gradient也把它改成这个
那这边我顺便把过程中的cost
还有w跟b的值都把它储存起来
cost的话我把它叫做c hist
然后让它是一个列表
那w的话我把它叫做w hist
b也是b hist
这三个列表就是拿来储存
我们跑的这么多次
里面的每一次的cost 还有w跟b的值
这边我就把每一次更新之后的wb还有cost把它储存起来
所以呢w hist
.append 把w储存进来
然后b也是cost也是
把它储存进来
接着最后我就可以做回传的动作
那回传呢我就是把最终的w还有b把它做回传
以及我们过程中的所有w
过程中的所有w还有b 跟cost全部都回传
好我们把它执行
他说有些问题我来看一下
打1,000的这个地方哦我少了一个:
好再执行
没有问题
没有问题之后我们就来使用看看
这边再创建一格
那要使用之前呢我们要设定好初始的w跟b
假设我初始的w跟b呢我都让它等于0
然后learning rate我就让它是0.001
那这里我也可以用科学符号的写法
我写1.0e然后-3
那就是1.0乘以10的-3次方
也就是0.001的意思
那cost function呢
这边我们就要传入compute cost
就是我们计算cost的那一个函式
gradient function我们写好的是compute gradient
这边我们是可以把函式当做参数传入的哦
然后呢是run iter
那run iter呢我让他跑个2万次
最后这个p iter
它预设值是1,000 我就不动它
我可以不动它我就可以不用设定它
好那我们执行看看
它会回传这5个值嘛
所以呢我也把它写一下
这个w呢就是最后的w 我叫它w final
b也是最后的b 我叫它b final
然后是储存的wb还有cost
好我们执行
它怎么只有印出来一次呢
来看一下为什么只有印出来一次
哦这个return的地方
我不小心把它写到for回圈里面了
所以呢应该在外面
再执行一次
这样应该是没问题
1000 好
我们来看一下cost持续在下降中
然后斜率的地方也是在做下降
最终的w 可以看到是9.17多
然后b呢是差不多在27左右
这边我也把它印出来
来看一下最终的w 最终的w跟b值
好我们来看一下
最终的wb是9.14多然后呢27.88多
这里一样我让它不要那么多小数点
我让它显示两位就好
所以我写.2f
最终的wb呢就是9.14以及27.89
那我们就可以拿这个最终的值去做预测啦
大家应该还没忘记
我们想要解决的问题吧
我帮大家复习一下
假设今天你是一个新创公司的老板
你想要聘雇你的第一个员工
但是你不知道应该给他多少薪水
所以你就到市场上去收集了一些
这个职位的相关资料
就是他的年资以及他对应的薪水
那现在呢你是想要用一条直线来表示这些资料
表示完之后你就可以用这条直线来预测
应该给这位员工多少薪水了嘛
那现在呢我们已经找到这条直线了
那我们就可以做预测的动作啦
假设今天来应征的这位员工
他告诉你他有3年半的工作经验
也就是说他的年资有3.5年
那我们就可以帮他做个推算应该给他多少薪水了
这边呢他的年资是3.5
我们就可以用找到的这个w final 去乘以它的3.5
然后呢再加上b的值也就是b final
因为我们是用一条直线来表示这些资料嘛
一条直线就可以写成w乘以x加上b
现在我们的x呢就是3.5
那这个呢单位是k 执行
他就说年资3.5 大概可以给他59.88多少k
这边一样小数点太多了
我就给他个2位就好了呃一位就好了
一位小数点好再执行一次
那就要给他59.9 k
预测出来大概可以给他59.9 k
这里再多个空白
假设又来了一位员工
他告诉你他的年资呢是5.9年
那我们就预测一下
这边我再多打两个字预测
预测薪水好执行
他告诉你他年资5.9的话
那大概预测的薪水也是59.9k 没有
这边我要把它改成5.9 执行
那预测的薪水大概就是81.8k
这样子呢我们的问题就解决了
我们可以这样子来预测薪资
那接着呢我把一些数据也把它画成图来看看
像是这边的cost 我可以把它画成一张图来看看
这边要画图的话我们就可以用画图工具matplotlib
然后呢还会用到numpy
我们就把这2万次更新
cost下降的过程把它画出来看看
我们可以用plt.plot把它画成一条线
那x的值呢这边我们用np.arange
2万次嘛所以就是0~20000
然后y的值呢就是我们的cost的历史资料
它的更新的资料都储存在这里啦
我们就可以把它显示出来看看好执行
可以看到他长这样
那我再帮他加上一些标签跟标题
设定他的title 那title呢这边是总共是2万次更新
然后跟他的cost嘛所以我这边写iteration vs cost
然后再帮他加个x label
x轴的话就是更新的次数嘛就是iteration
然后y轴就是cost 再执行一次
这样子标题还有标签就都上来了
那我们从这张图可以发现
他前面呢下降的非常快
但是后面呢就比较趋缓一点
如果我们想要细部的看前面这一段的话
假设我只想看到100 0~100
那这里我就把它改成0~100
然后呢这里我也就写:100
也就是前100笔资料
好再执行
那这就是他前100次更新的下降过程
如果你想要看其他区间的话也是可以
就自己去设定
这边好像少了一个a iteration
好再执行
最后我们也可以把w跟b 他更新的过程
这2万次更新的过程把它用图画出来
我们先到之前cost function这边
把3D图复制过来3D图在这里
我们把画3D图的这个动作把它复制过来
那这边的话
当时我们是设定w跟b都在-100到100之间嘛
所以呢w跟b
从-100到100之间的这个计算也要复制过来
这里的w跟b从-100到100然后它的cost
这里我就再开一格做计算
我先让他计算
那这边我们会用到中文字体
所以呢还要去做下载字体的动作
一样我到之前的cost function这边
找到下载字体的地方复制过来
再开一格让他做下载
好这边我们就等他一下
让他执行完计算安装跟绘图
OK 画好了
我把它的角度调一下
它本来是0度0度我让它是20度跟-65度
好再执行一次
这个角度不错
红色这点是最低点嘛
接着我们就把w跟b的更新过程
用线的方式把它画上去
那我们要画线的话可以用plot
里面就传入我们储存下来的w hist
b hist以及cost的hist 也就是c hist
这边呢我先执行看看
可以看到他就把线画出来了
只是呢这样子的话我不太知道哪里是初始点
所以我把初始点也把它画出来
要画点的话就用scatter
这里我直接用复制的
那我们要画初始点的话就是他的第0个值
b hist也是第0个值
cost一样是第0个值
这边我让它颜色是绿色
再执行一次
可以看到绿色这点呢是我们初始的位置
然后呢他一路更新更新更新更新到这边
基本上就是到最低点了
ok一路这样更新过来
那我觉得现在这个颜色有点碍眼
这个曲面的颜色有点碍眼
所以我把它的颜色把它取消掉
这个边框我也觉得没有必要
所以呢再执行一次
这样子看起来好一点
我把它的这个不透明度再设定的第一点
我让它是0.3 再执行
这样看起来舒服许多
它是一个这样子的曲面
然后呢我们这个绿色的点是初始点
它一路更新更新更新过来
基本上就是快要到最低点了
因为红色的点是最低点
好那这边我也可以玩玩看
如果我在做gradient descent的时候
设定的是不同的值呢
这边我复制一份到下面
复制到这里
如果这边我的初始点我是设定在-100跟-100的地方
我们试试看
这样子会有什么样子的结果呢
跑完2万次之后呢
一样我们会得到最终的w跟b
还有储存下来的每一次的wb还有cost
我们就再执行一次这边的绘图
看一下会长什么样子
可以看到这次呢他的初始点在这里
然后他就一路往下往下往下走走走....
然后再这样转弯过来
一样是接近快要到最低点的地方
接着我还可以试试看如果这边
我没有让他更新这么多次
我只让他更新个1,000次好执行
我只让他更新1000次我看一下会长什么样子呢
他这次往下走走走
只走到这边就没有继续往前喽
因为我们更新的次数不够多
那你也可以调整其他的
比如说learning rate
我把它调的大一点
我让他是1.0*10的负二次方也就是0.01
那这里我再试一次
我让他这么大的话执行看看
可以看到他还是有到达最低点
那这边你可能会发现
我们设定的初始点不是在-100 -100嘛
那照你说初始点应该在这里
为什么在这里呢
原因是因为其实呢
我们这边里面储存的是第一次更新的结果
所以呢他第一次更新之后就跑到这里了
-100,-100是这里初始的地方
他第一次更新就跑到这了
这里面储存的是从第一次更新到最后一次的结果
那我再试试看
如果把learning rate再调大一点
假设我这里改成5.9 好执行
我们看一下会变成什么样子呢
可以看到他这一次的跨步就非常大喽
他变成这样跨来跨去的
但是好像还是有到最低点嘛
那如果我们再让他更大呢
这边我把它改成1.0*10的-1再执行
好执行
可以看到发生可怕的事情了
我们的那张图那个曲面都不见了
为什么呢
原因是因为他已经超出范围太多了
我们在画那个曲面的时候设定的值是
w跟b都在-100跟100之间
那他现在已经超出太多了
所以才会导致曲面都不见了
当我们的learning rate设的太大的时候
他是有可能每一次的更新
不是离最低点越近哦
反而是离最低点越远
我们这个例子就是每一次的更新他都离最低点越远
所以呢就会导致这样子的状况
整个曲面都不见
刚刚那个例子就像这样
你如果learning rate设的太大的话
他是有可能越走越远的哦
离最低点越走越远
第一步跨到这
第二步跨到这
第三步他就跨到不知道去哪里了
那这边大家就可以自己去玩玩看
设定不同的wb初始值
还有设定不同的learning rate
以及设定不同的更新次数
这个就是我们的gradient descent的实作
做完了简单线性回归之后
我小小的帮大家总结一下
机器学习的过程
以我们这个例子来说
首先第一步就是你要先准备好资料
那根据这个资料分布的样子
我们觉得可以使用一条直线来表示它
所以呢我们用一条直线来表示这些资料
接着我们就是要去找出
最能表示这些资料的那一条直线
也就是最适合这些资料的那一条直线
那什么样子的直线是最适合这些资料呢
我们总要给他一个评判的标准吧
所以呢我们就去设定了
只要这些资料点跟这条直线的距离平方加总
越小的话
那我们就说这条直线越适合这些资料
反之如果越大的话那就是越不适合
好有了评分的方式之后
接着我们总不可能用暴力穷举的方式
去穷举出所有的直线
然后再帮他们全部打个分数
再从中找出最好的那一个吧
样子做太没效率了
我们必须用有效率的方式去找出最适合的直线
那这边呢
我们使用的就是graden descent 梯度下降法
那其实这整个过程呢
大概就是机器学习的流程
你套用到其他例子也是一样的
首先呢你都是要先准备好资料
然后你要根据你的资料去帮他设定一个模型
用这个例子来说
我们设定的模型就是一条直线
设定好模型之后
它里面可能会有一些参数你要去做调整
以这个例子来说就是要调整w跟b
那怎么样调整叫做好
怎么样调整叫做不好
我们总要给他一个评判的标准吧
所以呢我们要设定一个cost function
以这个例子来说我们设定成这个样子
接着我们不太可能去暴力穷举所有的参数组合
然后都去计算他们的cost
再从中找出最好的那一个
这样子做太没效率了
我们必须用有效率的方式去找出最好的参数
要用有效率的方式
也就是我们要去设定一个optimizer
那这个optimizer呢翻成中文是优化器
以这个例子来说
使用的优化器就是gradient descent
这个大概就是简单的机器学习流程
你不管他用到其他的例子
其实呢都是差不多的
一样你都是要先准备好资料
接着呢设定一个模型
然后再设定一个cost function
最后呢要设定一个optimizer OK
第二个要跟大家介绍的模型
叫做多元线性回归
英文是multiple linear regression
它其实跟我们之前介绍的简单线性回归
是差不多的
只是呢它可以有比较多的特征
好我们先来看一下
今天想要解决什么问题
在上一个简单线性回归的例子里面
我们是拿年资去预测薪水嘛
但是大家仔细的想一下
我们只单看年资就想要预测薪水
是不是怪怪的
我们应该考虑更多的因素吧
所以呢现在我们去收集了更齐全的资料
现在除了年资以外
我们还收集了他的学历以及他工作的地方
所以我们现在是想要透过
年资、学历以及工作的地方去预测他的薪水
也就是说我们的特征多了学历还有工作的地方
如果我们一样是想要以一个线性的模型
来表示这些资料的话
那就可以使用到多元线性回归
多元线性回归
用数学的式子写出来长这样
它可以写成y等于W1乘以X1
加上W2乘以X2加上W3乘以X3...
看你有几个特征就可以一路乘下去
最后呢加上一个b
那以我们这个例子来说有三个特征
分别是年资学历以及工作的地方
所以数学式子写出来会长这样
我们想要预测的是月薪
月薪呢就会等于W1去乘以年资
我们的第一个特征加上W2乘以学历第二个特征
再加上W3乘以第三个特征工作的地方
最后加上一个b
那我们的目标呢
就是要找出一组W1、W2跟W3以及b的组合
让他最能表示这些资料
这也就是我们多元线性回归要做的事情
在开始去找最适合的w跟b之前
我想大家应该有发现一个问题
就是以我们这个式子来说
我们拿W2去乘以学历
然后又拿W3去乘以工作的地方
但是呢我们可以看到
学历跟工作的地方这两个特征他们都是文字
要怎么样让文字去成一个数字呢这样不太行嘛
所以呢我们必须先把这两个特征做一些处理
先把他们从文字转换成数字
才有办法做这里的计算嘛
我们先来处理学历这个特征
学历这个特征总共有三种可能的值
分别是高中以下、大学跟硕士以上
从这个特征我们可以看得出来
它其实是有高低关系的
如果有高低关系的话
那我们是不是可以用数字的0、1跟2来表示这三种状况
0就拿来表示最小的高中以下
1呢就表示大学2就是硕士以上
如果一个特征它是存在大小关系
它是存在高低关系的话
我们就可以用这样子的方式来把这些文字取代掉
这样子的取代方式呢它是有一个名称的
它叫做label encoding
我们把刚刚的学历取代掉之后就会变成这样子
回来来看一下
硕士以上我们是用2来表示大学是用1
然后高中的话是高中以下的话是0
所以这边就会变成1 2 0
下面呢以此类推
那我们就先来实作一下这个label encoding
首先一样先把资料读取进来
读取的动作跟之前都是一样的
所以我直接用复制的
不过呢在网址的部分
因为我们这一次的资料它是多了两个特征
所以呢有些改变
我们在salary data这边
因为它是第2版所以我们在后面写上2
一样读取之后我们把它显示出来看看
OK 我们的资料长这样
总共有三个特征分别是年资、学历跟工作的地方
我们现在是想要先处理学历这个特征
想要先把它从文字转换成数字
好那这边我们可以这样子做转换
我们去取得资料的
看一下学历这个特征
它叫做education level
我们去取得这个特征
好先把它显示出来看看
他本来长这样嘛
我们想要让他的大学变成1
然后硕士以上是2 高中以下是0
这边我们可以这样子做
在后面写上点map
然后呢在里面写上字典
我们想要对应的是高中以下让它对应到0
接着呢大学让它对应到1
最后是硕士以上让它对应到2
我们这样子写呢它就会帮我们做转换
把这一个特征
它里面的值呢做这样子的转换
转换完之后我再把这个特征的值把它做改动
这样子改动过来之后呢
我们再把整个data 把它显示出来看看
可以看到他现在就会变成对应的值啦
这边本来第一笔资料是大学嘛
然后第二笔是硕士以上第三笔是高中以下
所以它就会变成1 2 0
然后下面也是做同样的转换
那这样子我们的label encoding就完成了
处理完学历这个特征之后
接着我们来处理工作的地方这个特征
这个特征总共有三种可能的值
分别是城市a、城市b跟城市c
那这边你可能会想
我们是不是可以用同样的方法
我们用label encoding
把城市a、b、c用0 1 2来表示
但是你仔细想一下
你觉得这样子可以嘛
我们并不知道城市abc之间
它有没有存在一个高低的关系
或者存在一个大小的关系
如果我们用0 1 2来表示的话
那谁要是0 谁要是1 谁要是2呢
这种不存在大小关系的特征
如果我们想要把它做转换的话
可以直接把它转换成多个特征
像是这个样子
我们本来是只有一个城市的特征
那我把它改成城市a、城市b跟城市c
变成三个特征
这边的第一笔资料
他本来是在城市a工作嘛
所以呢我们就给他城市a这个属性是1
然后城市b跟城市c这两个属性是0
好再看第二笔资料
第二笔资料呢它原本是在城市c工作
所以我们就给它城市c这个属性是1
然后其他给它0以此类推
这样子的做法呢叫做one hot encoding
只要是我们想要把一个不存在大小关系
不存在高低关系的一个特征
把它从文字转换成数字的话
那我们就可以使用one hot encoding
它就会从一个特征变成多个特征
看这个特征它原本有几个值
有几个可能的值那它就会变成几个特征
以我们这个例子来说
它可能的值就是城市a、b跟c
那就会变成3个特征
城市a、城市b跟城市c
那这样子把它转换完之后
其实我们还可以把这3个特征里面的其中一个把它删掉
为什么呢原因是因为这三个特征里面
其实我们只要知道其中两个特征的值
就可以推导出第三个特征的值了
假设我们现在把城市c这个特征删掉
我们来看一下
有没有办法通过城市A、B 来推导出城市c呢
现在长这个样子
如果城市a是1 然后b是0的话
那城市c肯定就是0嘛
因为呢这三个特征里面只有其中一个会是1
好再看第二笔资料
城市a是0、城市b是0
那城市c就一定是1嘛
因为它不是城市a 不是城市b 肯定就是城市c
以此类推
所以呢我们是有办法透过其中两个特征
就推导出第三个特征的值
那这个时候呢我们就可以把其中一个特征把它删掉
好我们再举一个比较简单一点的例子
假设你现在有一个特征叫做性别
它的值呢只有两种可能
要么是男生要么是女生
那显然这个特征它也不存在高低关系
不存在大小关系嘛
所以我们可以使用one hot encoding
把它变成两个特征分成男生跟女生
但是呢他不是男生就是女生嘛
所以我们可以从其中一个特征
就推导出另外一个特征的值
这样子我们就没有必要把它分成两个特征嘛
因为过多的特征反而会让我们的运算变得更加的复杂
所以呢我们就可以把其中一个特征
把它删除掉
好所以回到原本的例子里面
城市a、b、c这三个特征里面
我们只要知道其中两个的值就可以推导出第三个
那这样子我们就可以把其中一个把它删掉
这边我们是选择把城市c 这个特征删掉
这边提醒一下大家
并不是所有可以被推导出来的特征我们都要把它删掉
因为有些特征即便可以被推导出来
但是它存在着特别的意义
或是它可以加快我们运算的效率
那我们就不会把它删掉
但是呢在one hot encoding的这个例子里面
我们经过转换后是可以把其中一个特征删掉的
好那接着呢
我们就直接来实作one hot encoding
现在我们的资料长这样
我们是想要把city这个特征把它做转换
想要把它从文字转换成数字
那以这个特征来说
我们可以使用one hot encoding把它做转换
这边我们可以使用sklearn
它底下的preprocessing
然后呢我们去使用它里面的one hot encoder
sklearn这个套件呢
它提供了非常多
我们在做机器学习的时候会使用到的东西
像是我们现在引入的这个one hot encoder
它就可以帮我们快速的做转换
这个one hot encoder呢它是一个类别
所以我们先把它做一个创建
我们先创建一个转换器
或者你可以说先创建一个编码器
这边呢我就把它叫做one hot encoder
创建好之后我们可以先让这个编码器
让这个转换器去看过我们的这个特征
城市这个特征
所以呢这边我们可以写点fit
然后去让他看过city这个特征
不过这边要特别注意的是
他只接受传入的是一个二维的矩阵
所以呢我们这样子写是不行的
因为这样子写呢是一个一维的矩阵
想要让他变成二维的我们就再加一对中括号
让他用两对中括号这样子就会是一个二维的矩阵
让他看完这个特征的所有值之后
接着我们就可以把它做转换了
我们可以使用它底下的transform 来做转换
里面一样传入我们要转换的那个特征
那这边一样是要一个二维的矩阵
所以要两对中括号
这里我就把它转换的结果叫做city encoded
接着我们直接把它显示出来看看
执行可以看到转换的结果长这样
为什么会长这样呢
原因是因为这个one hot encoder经过转换之后
预设它会回传给我们的东西是一个稀疏矩阵
OK 是一个稀疏矩阵
如果你不知道什么是稀疏矩阵那也没关系
我们这边想要看到的是
他回传给我们一个完整的矩阵
那完整的矩阵我们可以在后面再写上toarray
那这样子呢他就会回传完整的矩阵给我们
再执行
可以看到这就是我们要的结果啦
它会把一个特征里面总共有3种可能城市a、b、c
把它变成3个特征
OK 变成3个值
那这边我们就可以把转换的结果
把它替代掉原本的这个特征
替代掉原本的这个city这个特征
我们可以这样子做
我们原本的资料是data嘛
我们执行一次
OK 原本的资料长这样
如果我们想要帮他再多加3个特征的话
也就是再多加3列的话
OK是3列我这边再强调一次
在本堂课里面是横行直列横行直列
如果我们想要再帮他多加3列多加3个特征的话
我们可以这样子写
写两对中括号
我想要帮他加一个cityA
然后呢再加一个cityB
最后再加一个cityC
然后我们可以把它的值呢
就指定成我们刚刚转换之后的这一个结果
接着我们再把它显示出来看看
可以看到这样子写呢它就会多加3列
多加3个特征cityA BC
接着我们就可以把city 这个特征删掉啦
因为它已经被转换成这3个特征了
然后呢这三个特征里面
我们又可以删掉其中一个
我把cityC把它删掉
那我们可以这样子做
我们可以写data.drop
然后在第一个参数写上我们想要删掉的特征
想要删掉的特征用一个列表来表示
想要删掉city 还有cityC这两个特征
接着呢第二个参数写上
我们想要删掉的这个东西它的轴线是在哪里axis
我们想要删掉的东西它是列嘛
city跟cityC这两列
想要删掉的东西它是列的话
那axis轴线我们就要指定它是1
如果我们想要删掉的东西是行的话
那这边我们就要指定轴线是0
好所以这边我们写1
接着呢我们就把删掉的结果把它显示出来看看
执行
可以看到现在呢
city跟cityC这两个特征这两列就都不见了
那这样子我们就把工作地点这个特征也处理好了
把文字都做完转换之后
接着通常我们在训练模型的时候
还会把资料分成训练集跟测试集
训练模型就是找出最适合的参数
以我们这个例子来说
就是找出最适合的w跟b
通常我们在训练模型的时候
不会把所有的资料都使用上
我们只会使用到一部分
那另外一部分要做什么呢
另外一部分是要拿来做测试用的
因为你想哦如果我们把所有的资料都拿去做训练
然后呢找出了一组最佳的w跟b
但是我们要怎么样验证这一组w跟b 它的效果是如何呢
我们是不是要测试一下
那要测试的话我们就要把它测试在陌生的资料上
我们是不会拿训练的资料来做测试的
因为训练的资料机器都已经看过了
就相当于是他已经知道答案了
那在他已经知道答案的情况下
我们还拿这个资料来做测试这样就不会准了嘛
所以呢为了有陌生的资料可以拿来做测试
我们通常会把资料分成训练集跟测试集
像是这个样子
假设我们有10笔资料好了
那通常呢训练集会占7成到8成左右
以这个例子我们是占8成
所以有8笔资料会是训练集
然后呢有2成的资料
也就是有2笔资料会是测试集
训练集呢就是拿来找最佳的w跟b
那测试集呢就是我们找出最佳的w跟b之后
拿来做测试看他的效果怎么样
了解了什么是训练集跟测试集之后我们就直接来实作啦
OK 现在我们的资料长这样
首先呢我们先把x跟y把它分出来
大家应该还记得吧
我们想要使用的模型是多元线性回归
多元线性回归写成数学的式子
就是y=W1*X1+W2*X2一路乘下去看你有几个特征
最后呢加上一个b
那以我们现在这个例子有4个特征
分别是年资、学历还有工作的地方
那我们要预测的y呢就会是薪资
所以我们先把x跟y把它分出来
这边x就等于我们去取得它的四个特征
第一个是年资
第二个是学历
然后是cityA跟cityB
然后呢y就会等于我们去取得它的薪水
这里我把x跟y把它显示出来看看
x是这4个特征
然后y呢
就会是薪水没有问题
接着我们就可以把它分成测试集跟训练集啦
这边我们一样可以使用sklearn这个非常好用的工具
使用它底下的model selection
然后我们去引入他底下的train test split
接着就可以使用它来帮我们分成测试集跟训练集啦
在第一个参数里面传入我们的x 也就是特征
然后第二个参数里面传入y
接着我们可以去指定测试集的大小要多少
这边我们可以写test size
那我想要他是占2成就好
这边我可以让他等于0.2
这样子写呢他就会自动把我们资料的2成分出来当做测试集
然后另外的8成分出来当做训练集
如果你想要测试集占3成的话
这边你就可以写0.3 以此类推
那这样子写呢他会回传4个值给我们
分别是拿来训练的x跟拿来测试的x
还有拿来训练的y跟测试的y
所以第一个呢我就叫他x train
然后第二个我叫他x test
接着就是y train 以及y test
他会回传这4个值给我们
那我就把它显示出来看看
我显示出来x train 就是我们拿来训练的x
可以看到它就取出了这几笔资料当做训练集
那我们来看一下它的长度是多少
来看一下它的长度是多少
它的长度是28
那我们看一下原本的x 它的长度是多少
原本的长度是36
我们拿2成当做测试集也就是8成当做训练集
那我们拿36去乘以0.8看一下是多少
是28.8
所以呢他28.8 他就自动把这个点8消掉了
就拿28笔资料当做训练集
那我们顺便看一下测试集他的长度是多少
可以看到总共呢x它是有36笔资料的
然后我们经过分割之后
它有28笔拿来当做训练集然后8笔拿来当做测试集
这边y也是一样的
我们再把x train把它显示出来看一次
这边你会发现一件事情哦
就是我们每次执行的时候
这个x train好像它都会变动哦
我们看一下第一笔资料是5.1 0 然后1 0嘛
我们再执行一次
又变了变成6.9 2 1 0 再执行一次
又变了7.8 2 0 0 为什么会变呢
原因是因为这个分割的过程
它预设会帮我们随机分割
所以呢你每次分割的结果都会不一样
如果你想要让他分割的结果是固定的话
这边我们还可以再设定一个参数
叫做random state
然后你可以给他指定一个数字
每一个数字他都会对应到不同的分割情况
假设我给他的数字是87
好我们再执行一次
可以看到这一次它分割的结果呢长这样
第一笔是4.6 1 1 0
现在在我固定random state等于87的情况下
我再执行
可以看到它是不会变的
但是呢如果我把这个数字把它做改动
我把它改成86
再执行
他就又会变了
那如果我在不改动86的情况下
再继续执行
他就不会变
所以这边如果你想要固定分割的结果
你是可以给他指定一个数字的
这边我就给他指定87
因为我想要它分割的结果是固定的
这样可以方便我后续做演示
好那我把x test也把它显示出来看看
它是长这样总共有8笔资料
那y train呢也把它显示出来
OK 有这些
然后y test
好那这样子呢
我们就成功的把测试集跟训练集把它分好啦
最后呢为了后续方便的计算
我会先把x train 跟x test 把它转换成numpy的格式
现在他们都是pandas的格式
所以执行之后会很漂亮
OK 会有这样的格子
那如果我把它转换成numpy的格式的话它会长这样
我可以在他后面写to numpy
那它就会变成一个矩阵的样子
变成这样子矩阵的样子就会比较丑
不过它会让我后续的计算比较方便
所以这边我先把它做转换
x test 也是一样
我也把它做转换可以让我后续的计算比较方便
把文字都转换成数字
然后也分成训练集跟测试集之后
我们就可以回到模型的地方啦
我们想要用的模型是多元线性回归
那它可以写成这个样子
只不过呢我们的特征已经从3个变成了4个
这个工作的地方呢
已经变成了cityA跟cityB这两个特征
所以我们要改写一下变成这样
那我们现在的目标呢
就是要找出一组W1 2 3 4跟b的组合
让这里预测的月薪可以越接近真实的资料
好那我们就先来实作一下这个部分
首先呢我先来设定w跟b的值
一开始我都先随便设定
w它有1 2 3 4嘛
所以我用一个一维的矩阵来表示它
这个一维的矩阵里面有4个值
所以这里我先引入numpy 把它叫做np
接着呢我就创建w
然后让他是一个矩阵里面有4个值
假设我就让他是1 2 3 4
这个1 2 3 4呢就是表示我们的W1 2 3 4
接着还要设定一个b的值
一样我随便设定我让它是0
设定好w跟b之后
我们是想要让W1去乘以第一个特征
W2乘以第二个W3乘以第三个W4乘以第四个嘛
那现在因为我们是在训练阶段
所以我们要乘的特征是在x train这里
我先把x train把它显示出来
那它长的是这个样子
它总共有4列每一列都代表一个特征
所以我们想要的是
这个1去乘以第一列然后2去乘以第二列
3乘以第三列4乘以第四列
我们想要这样子乘的话
可以直接这样子写
我们直接让x train乘以w
那它就会自动让1去乘以第一列2乘以第二列以此类推
好我们执行
这是乘下来的结果
这边的第一列就是W1乘以X1
第二列就是W2乘以X2 以此类推
那我们想要的是他们做相加嘛
W1乘以X1加上W2乘以X2 然后加上3加上4
也就是我们想要把这里的每一行做相加
我们想要把它每一行做相加的话可以这样子做
先把这边计算的结果把它括号起来
然后再使用点sum
如果这边我只有写这样子的话
他会把这里的每一个值都做加总
不过我们想要的是每一行做加总嘛
我们想要的是横的做加总
那这边我可以再多设定axis等于1
等于1就是横的做加总
如果你想要直的住加总的话你这也可以设定等于0
好那我们来试试看执行
这就是加总的结果
这里的每一个值呢就是刚刚的每一行它的加总
也就是W1乘以X1加上W2乘以X2 加上3加上4的结果
这里都加完了之后
最后我们还要加上一个b嘛
所以呢这边我加上一个b
这边加上b的话他就会让里面的每一个值都加上b
不过我们现在b设定成0 好像看不太出来
所以我把它设定成1好了
我们再执行一次
那这样加呢这里的每一个值都会加1
所以现在这里计算出来的每一个值
就是我们预测的薪水啦
我把它叫做y pred
那接着呢我们就是要找出一组最适合的w跟b
要找出一组最适合的w跟b的组合
那我们首先就要先定义什么叫做最适合
也就是我们要去设定一个评判的标准
那就是我们要去设定一个cost function
这里的cost function
我们可以设定的跟之前简单线性回归的时候一样
因为我们一样是希望预测的月薪
跟真实的资料距离越小越好
所以我就一样把它设定成真实的数据
去减掉预测值然后做平方
这边做平方的原因是因为这边相减有可能会有负数
我们为了计算方便
就直接把它做平方这样就不会有负数了
所以我们现在的目标呢
就是让真实数据去减掉预测值然后做平方
它的值越小越好
也就是这边的cost越小越好
好那我们就直接来实作cost function
我们的cost function是设定成
真实数据去减掉预测值然后做平方嘛
预测值的部分我们上一步已经做好了
这边的y pred就是预测值
我先把它显示出来看看
这边是我们的预测值
真实数据的部分呢
因为我们现在是在训练阶段
所以真实数据就是y train
所以我们是拿y train去减掉y pred
我一样先把y train把它显示出来看看
OK 它总共有这几笔
我们拿y train去减掉y pred
它就是把每一笔做相减
相减完之后我们还会把它做平方
好执行
可以看到这边的每一个值呢
就是我们拿真实的薪水去减掉预测的薪水
然后做平方的结果
那我们是希望这里的值越小越好嘛
想要这里的值越小越好
我们可以计算它的加总或是计算它的平均都可以
这里我就计算它的平均
希望它的平均呢越小越好
计算它的平均可以把它括号起来在后面写上点mean
好执行
可以看到这是平均的结果
那这里我就直接把计算cost的过程把它写成一个函式
这样可以方便我们带入不同的w跟b
我把它叫做compute cost
它一样是传入x跟y 也就是我们的真实数据
然后呢再传入w跟b的值
里面就是先计算y pred的值也就是我们的预测值
只不过这边的x train把它改成x
计算出预测值之后我们就可以计算cost了
计算cost呢就是这里
这边的话一样y train我把它改成y
真实数据去减掉预测值做平方然后再取平均
这个呢就是cost
好那最后就是return cost
直接来试试看
这边我们就直接来使用它compute cost
这里要传入的呢就是x train跟y train
因为我们现在是在训练阶段嘛
然后w跟b呢我一样先传入这两个值
一样先传入这两个值
我们执行看看
可以看到计算的结果跟我们上面是一样的
那如果我把这边的b设定成0呢
然后这边设定成0 2 2 4
好再执行一次
这样子的w、b组合计算出来的cost就比刚刚的还大了
刚刚的是1,772嘛
那这样子呢
我们就把评判的标准也就是cost function把它定义好啦
设定完评判的标准也就是cost function之后
接着我们就是要用有效率的方式
去找出一组w跟b 它可以让Cost越低越好
那这个有效率的方式呢
就是我们要去设定一个optimizer 也就是优化器
在我们这个例子里面
我们一样可以使用gradient descent 梯度下降法
大家应该还记得吧
它就是根据斜率去改变参数
只不过呢我们之前在简单线性回归的时候
参数只有两个w跟b嘛
那我们现在呢参数是变成了5个W1234跟b
我们先看一下之前是怎么样更新参数的
如果我们要更新w的话
就是拿w 去减掉w方向的斜率*学习率
要更新b的话就是b减掉b方向的斜率*学习率
那其实更新参数的方式都是一样的
只是呢我们从两个参数变成了五个参数
现在呢我们有W1234跟b这五个参数
那要更新这五个参数呢
就是个别去减掉他们方向的斜率*学习率
这边各个方向的斜率要怎么样计算呢
其实也是跟之前一样的
我们只要把Cost function去做微分
就可以得到各个方向的斜率了
我们的Cost function
是拿真实数据去减掉预测值然后做平方
写成数学式子就是y减掉y pred然后做平方
其中这个y pred的呢我们又可以把它摊开来
变成W1*X1+W2*X2...
乘到4 然后最后再加上b
如果我们想要知道W1方向的斜率就是把它对W1做微分
或者准确一点说把它对W1做偏微分
如果你想要知道的是W2方向的斜率
那你就是把它对W2做偏微分
以此类推W3 W4跟b都是一样的
这里如果你完全不知道什么是微分的话那也没关系
因为有很多工具都可以帮我们自动的做微分
所以W1方向的斜率经过计算之后长这样
可以看到非常长一串
但是呢其实我们可以发现这边这一串
W1*X1+W2*X2加上3加上4 然后加上b
这一段呢其实就是y pred嘛
所以我把它简化一下就会变成这个样子
它就是2*X1然后去乘以y pred-y的结果
接着用同样的方式去计算出W2方向的斜率它会长这样
我们可以发现其实呢他只是把X1替换成X2而已
其他都是一样的
由此可知W3方向的斜率就是把这边替换成X3
那W4方向的斜率呢就是替换成X4
最后b方向的斜率计算出来会长这样
这边呢就没有再多乘以一个x了
那在这边我们可以看到
不管是w方向还是b方向的斜率
在前面的地方呢都有一个乘以2
不知道大家还记不记得
其实我们有说过这个乘以2是可以省略掉的
因为我们在更新参数的时候
后面都还会再乘以一个学习率嘛
所以这个乘以2呢其实交给学习率来乘就可以了
那这边我们就可以把它全部省略掉
变成这个样子
好知道怎么样计算斜率之后
我们回到原本的地方
现在各个方向的斜率我们都会算了
不过呢他后面还要再乘以一个学习率
这个学习率要怎么设定呢
跟之前一样就是透过测试跟实验
你不能把它设的太大
因为它有可能会直接跨过最低点
又或者是离最低点越来越远
那你也不能把它设的太小
因为它有可能会走到天荒地老都走不到最低点
设定好学习率也会计算斜率之后
我们就只要不断的去更新参数
让它一步步的逼近最低点的位置
就可以找到我们要的最适合的w跟b的组合啦
接着我们就直接来实作gradient descent
首先我们先来计算各个方向的斜率
因为b方向的斜率比较简单所以我先计算它
我把它叫做b gradient
它是y pred去减掉y
那现在是训练阶段所以我们的y就是y train
这个y pred之前都已经计算过了
所以我直接把它复制下来
不过呢我们现在是训练阶段
所以这边的x呢我把它改成x train
我把计算的结果显示出来看看
因为我们的训练集有28笔资料
所以呢这边会有28个值
那我们就把它做个平均
把它括号起来然后使用点mean
这样就可以计算平均了
平均呢是-46.94多
计算完b方向的斜率之后
接着我们来计算w1方向的斜率
我把它叫做w1 gradient
它呢就是y pred去减掉y train
然后前面要再乘以一个x1嘛
那这个x1呢其实就是我们的第一个特征
我们现在是在训练阶段嘛
所以我们的特征是在x train这里
我先把x train把它显示出来
可以看到它总共显示了四列
那这四列呢就是我们的四个特征
这里的x1呢就是第一个特征
也就是这里的第一列
那我们要取得这里的第一列的话可以这样子写
我们写一对中括号然后:, 0
这样子写的意思呢
就是第一个维度里面的所有值我们都要
:就是全部都要的意思
然后逗号0 就表示第二个维度里面的值呢
我们只要最开始的那一个
我们可以看到这个矩阵呢
是一个二维的矩阵
那第一个维度里面的所有值我们都要
也就是这边第一个中括号里面的所有值我们都要
这边的所有值我们都要
然后呢第二个维度我们只要它最开始的那一个值
第二个维度呢就是这边的每一行
我们只要它最开始的那一个值
那就会是这边的第一列
好那我们执行
可以看到它就会把第一列的所有值全部都取出来了
也就是我们的x1
所以这里我就可以把它替换掉
把它替换过来
然后我们把计算的结果显示出来看看
可以看到它总共会计算出28个值
因为我们现在训练集有28笔资料嘛
一样我们就取它的平均
把它括号起来然后取平均
执行
这样W1方向的斜率就计算出来啦
295 -295.8
接着W2W3W4的计算方法都是一样的
所以这里我直接用复制的
这里呢就是改成2 改成3 改成4
然后我们要取得的是第二列嘛
那这里就是1然后2 3
那我们把执行的结果都把它显示出来看看
W1,W2 OK执行
可以看到这个呢就是W1 W234它们方向的斜率
这里我用一个回圈来写会比较方便
所以我重新创建一个w gradient
它里面呢就是存放W1234方向的斜率
这里我就先创建一个里面都是0的矩阵
我让它有4个值
好先把它显示出来看看
里面有4个值我都先让它是0
不过这里直接写4好像不太好
这个4的意思是我们有几个特征
因为我们有几个特征就会有几个w嘛
我们想要知道有几个特征的话
是不是可以直接去取得x train 它总共有几列
因为它有几列就表示我们有几个特征
我们想要知道x train有几列的话这里可以这样子做
我们去取得它的shape 它的形状
它会告诉你它总共有28行4列
也就是第一个维度它有28个值
然后第二个维度呢有4个值
那第二个维度的这个值呢就是我们要的有几个特征
我们想要取得第二个维度的值
这边呢我就中括号1
就可以得到4
所以呢这边我把它改成这样会好一点
接着我就用一个回圈让他去计算这边的斜率
他总共呢会跑四次嘛
所以一样我就把这里直接贴过来
然后w gradient它的第i个斜率呢
就会是这边计算的方法
不过这边我就把它改成i
这样子应该是没问题
我把计算完之后的结果呢也把它显示出来
可以看到四个方向的斜率
W1234呢就是这四个值
好那这样子呢
我们就把w跟b方向的斜率都计算出来啦
这个是w方向这个是b方向
接着一样我把计算斜率的过程把它写成一个函式
这样可以方便之后做使用
我把它叫做compute gradient
那它就是要传入x跟y 也就是我们的真实资料
然后还有w跟b的值
这边我们首先先把y pred把它计算出来
那y pred这边已经计算过了我直接把它贴过来
y pred的计算完之后呢我创建一个空白的矩阵
创建一个里面都是0的矩阵
然后呢这边要改成x
然后呢用一个for回圈去计算每一个w它的斜率
这里也改成x 这里都改成x
那这边计算完之后
我们还要计算b方向的斜率嘛
b方向的斜率呢我直接也是贴过来
这里一样改成y
好那计算完我们把它的结果做回传
w gradient 以及b
OK 执行
那我们就直接来使用看看
这边呢要传入的x
因为现在是训练阶段所以x跟y都是x train y train
w跟b呢我一样传入这边的这个值
好我们执行看看
可看到结果呢跟上面是一模一样的
w跟b都是一样的
我们做个改动假设我把b变成1
然后这边变成1 2 2 4
再执行一次
那这样子计算出来的斜率就会不一样喽
好会计算斜率之后
接着我们就试着来更新参数啦
要更新w的话就是让w去减掉w方向的斜率
然后呢乘以一个学习率
更新b的话就是一样
只是把这边改成b
那这边学习率的话
我先随便设定假设我让他是0.001
w跟b的初始值呢我一样让它是这样子
w跟b方向的斜率我们就直接呼叫这个函式来做计算
它就会把斜率回传给我们了
w跟b方向的
这里我就把w跟b更新的结果把它显示出来看看
看它有什么不一样
可以看到本来是1 2 2 4嘛
然后变成了1.2多2.0多2.0多4.0多
然后b也有改动
接着我们来看一下它的cost
经过这样子的更新之后是不是真的有变小
也就是它是不是真的有往低处去走呢
这边我就直接使用这里的函式来计算cost
在还没有更新之前先计算一次
然后我把它的结果把它印出来
在更新完之后呢我再把它显示出来一次
看一下会不会真的有变小
可以看到真的变小了
本来是1,800多然后变成1,675
这边确定他有变小之后
接着我们就是要不断重复这边的动作
让他一直去不断的更新w跟b的值
那这边呢我们就把它写成一个函式
叫做gradient descent
其实这个函式我们在之前简单线性回归的时候就已经做过了
这个写法呢基本上是一模一样的
所以我直接把它复制过来
好那我们直接执行
执行完之后呢我们就可以直接呼叫它啦
那这边我们之前也有呼叫过了
所以我也直接把它复制过来
不过这边有几个地方要改
这边w跟b的初始值呢我把它改成这样子
learning rate呢我是设定成0.001嘛
所以这边也可以写成这个样子
我先让他跑个1万次就好
好那这边呢
因为我们现在已经分成测试集跟训练集了
所以这边我们现在是训练阶段我写x train跟y train
后面的地方基本都是一样的我们不需要改动它
这边compute gradient跟compute cost
我们的名字都是命名的一样
好那我就执行它
可以看到它发现的错误
会发生错误的原因是因为这边的w跟w gradient
我们使用到的是numpy矩阵格式
在这里
在这边w跟w gradient
我们使用到的是numpy的矩阵格式
那我们使用numpy的矩阵格式的话
他就没有办法直接写: .2e 来把这里的格式做转换
所以这里我先把它都删掉看看
我们再执行一次
这样应该就不会有问题了
可以看到果然就没有问题了
可以看到cost是有在做下降的
然后呢w的值跟b的值呢在这边都有在做更新
不过我们没有把它做这样子的格式化之后
看起来就会丑丑的嘛
就会不整齐
这边是w方向斜率跟b方向斜率
因为w有W1234 所以这边有4个值
这边也是有W1234 所以有4个值
不过现在执行起来很丑嘛
如果我们想要让它漂亮一点的话
可以直接去设定numpy矩阵它印出来的格式是长什么样子
这边我们可以这样设定np.set_printoptions
设定它的formatter 它要是一个字典
然后我希望浮点数它的格式呢长得是这个样子
冒号空白.2e的这个格式
最后在后面写上点format
那这样子设定呢就相当于我们这样子写
就相当于这边这样子写
他就会把这个矩阵里面的每一个值
都用这个格式把它印出来
好那我们再重新执行一次
这里再执行
可以看到这边就变得漂亮多了
那我们看一下这个cost的地方
是有一直在下降没有问题
这边跑完1万次之后我们可以发现他好像还在下降
cost好像还在下降
这边我测试看看如果我让他的学习率大一点
好 看来还是有在下降哦
而且下降的明显比刚刚快
所以这个学习率应该是没有问题的
慢慢的好像下降的速度越来越慢了
这边我就先设定这样然后让他跑个1万次就好
那这边大家可以自己去玩玩看
设定不同的初始w 设定不同的初始b
不同的learning rate 还有跑不同的次数
会有什么样子的结果
这里我就把它最后找出来的w跟b
把它显示出来看看
可以看到它最终找到的w跟b呢是这5个值
这里我想要验证这5个值到底是好还是不好
我们就可以把它使用在测试集上面啦
我们拿最终找到的w去乘以x test 也就是测试集
这样子乘呢就是W1*X1 W2*X2然后3跟4
这边乘完之后我们要把它做相加嘛
所以我把它括号起来把它做相加
我想要它做相加的方向是axis等于1
最后呢还要再加上一个b
加上我们最后找到的这个b
那这边计算出来的结果就是我们在测试集上面的预测
我把它叫做y pred
我们就可以对比一下
在测试集上面的预测跟真实的值究竟差了多少
这边我把它显示成Pandas的dataframe格式会比较好看一点
它会有格子
我让他有两列
第一列是我们在测试集上的预测结果y pred
然后呢第二列就是测试集上的真实资料y test
我们来看一下究竟有差多少执行
这边出现错误多打了一个u
再执行
还是有错
data 好再执行
可以看到左边的这一列呢
是我们在测试集上面预测的结果
然后右边这一列是测试集上的真实资料
我们预测是4.0多然后真实是43.8
好像没有差很多嘛
67.7 72.7好像差的还可以
61.6 60 OK 差别感觉还可以
好那我们就
成功的把gradient descent把它实作出来了
也找到了最终的w跟b
我们把最终的这组w跟b 把它使用在测试集上面
结果是这个样子
最后如果我们想要精准一点知道
这样子的预测到底是好还是不好
除了直接去看他们的误差以外
我们也可以计算他的cost
因为cost的值就是我们评判好坏的标准嘛
所以呢这边我们可以计算他的cost
那我们直接使用compute cost
现在我们是测试集
所以x呢是x test y是y test
然后w跟b 就是我们最终找到的w final跟b final
我们计算看看
它的cost是18.1多
那我们去看一下
对比一下之前在训练的时候cost是多少
我们在做训练的时候
最终cost降到2.52*10的一次方就是25.2多
这样看起来是没有问题的
因为我们在测试集上面的cost
反而比训练集上面还小
那就表示说
他的表现好像比我们在训练集上面还好
所以经过cost的计算以及上面的交叉比对之后
如果这个误差是你可以接受的
我们就可以把这个模型使用在真实的情况上啦
假设今天真的有人来面试了
这个人他告诉你他的年资是5.3年
然后学历是硕士以上工作的地方在城市A
经过面试之后我觉得我要录取这个人
但是呢我不知道应该要给他多少薪水
这个时候我们就可以使用训练好的这个模型
来预测一下大概可以给他多少薪水
那首先我们要先把资料做一些处理
因为这边有文字嘛我们要先把它转换成数字
在测试集上面怎么样把资料做转换的
在真实的情况就怎么样做转换
这边我就直接转换了
年资5.3 没有问题直接使用它
那硕士以上我们是用label encoding把它转换成2
然后工作的地方
我们是用one hot encoding 把它变成3个特征
接着又会删掉其中一个所以会变成2个特征
所以这边城市A
第三个特征就是1 然后第四个特征就是0
这边我用一个矩阵来表示它
我就叫它x real
它是等于np.array
如果这边你是有做特征缩放的话
一样在真实的情况下我们也要做特征缩放
那特征缩放呢我来往上看
我们特征缩放做的地方在这里
我们的测试集是怎么样做缩放的
那我们在真实的情况就怎么样做缩放
OK 我直接复制过来
我们的x test是这样做缩放的嘛
所以呢x real也比照办理
那我们把缩放的结果把它显示出来看看
他说有出一点问题
这边他说只接受传入的是二维的阵列
不接受传入一维的
没有错我忘记了
transform 他只接受传入的是二维的矩阵
不接受传入一维的
所以这边我再加一对中括号
他就会变成二维的了
好再执行
可以看到这就是经过缩放之后的结果
那接着我们就可以把它套用到模型里面了
我们的模型是这样子做计算的嘛
我直接复制过来
那这边我们要套用进来的呢
是x real 所以这边把它改掉
那我们把最后这个叫做y real
一样把它显示出来看看
可以看到最后模型的预测呢
是跟我们说可以给这个人6.55*10的一次方这样子的薪水
也就是65.5k
那如果今天又有第二个人来面试了
他告诉你他的工作经验是7.2年
然后他是高中以下的学历
那工作的地方呢在城市B好了
一样我们如果想要预测一下可以给这个人多少薪水
我就把这一笔资料也把它加进来
直接在这边再多写一笔
它是7.2 然后高中以下对我们来说就是0 转换之后是0
城市b呢转换之后就是0, 1
OK 这是第二个人
我们一样做同样的预测执行
可以看到模型给出的预测
就是说可以给这个人23.4k的薪水
那这个就是怎么样把模型套用到真实的情况上
在上一步我们已经做完了gradient descent
其实呢在我们这个例子
我们是可以加速gradient descent的
只要利用一个小小的技巧
叫做特征缩放英文是feature scaling
它就可以让我们达到加速的效果
好我们先看一下
以现在这个例子有四个特征嘛
分别是年资、学历还有工作的地方cityA跟cityB
然后我们是以多元线性回归去预测他的月薪
所以写起来会长这样
W1*X1+W2*X2加上3加上4 最后加上b
这边的X1234呢就是我们的这四个特征
那我们从这四个特征的值可以发现
它们的分布是不一样的
以第一个特征来说它的分布范围呢大概是1到10之间
然后第二个特征呢是0到2
第三跟第四个特征呢不是0就是1
所以他们分布的范围是这样子
我们可以很明显的看出来
x1这个特征它的分布范围是大于其他这三个特征的
所以我们把它带回原本的这个式子里面
就会长这样
我们w1是乘以x1
所以呢它是乘以一个相对比较大的值
然后W234呢都是乘以相对比较小的值
只要这边的大小它的差距越大的话
就让我们的gradient descent越慢
也就是让我们的梯度下降越慢
为什么呢
因为你看这边W1 他是乘以一个比较大的值
然后W234都乘比较小的值
也就是说这个W1他只要稍微有一点点的变动
就会很大的影响这边计算出来的结果
因为他是乘以一个比较大的值嘛
那它很大的影响这边计算出来的结果
也就间接的影响计算出来的cost
也就是说w1它只要稍微有一点点变动
计算出来的cost也会变动很大
所以这边如果我们拿W1跟W2来比较他们相对应的cost的话
大概会长这样
这里我用一个等高线图来做比较
中心点的地方是cost最低的地方越往外圈cost越高
然后x轴是W1 y轴是W2
我们可以看到这个等高线图它是一个狭长型的
为什么呢
因为这边W1 它是乘以一个相对较大的值
所以W1它只要有一点点的变动
就会很大的影响这边cost的值
我们说了最低点呢是这个红点的地方
然后越往外圈是cost越大
这边可以看得到W1只要有一点点变动
这个cost的变动就会很大
相反的W2的变动就不怎么样影响cost的值
那我们来看一下
在这种情况下做gradient descent会发生什么事情呢
假设我们的初始点是在这里
初始的w1 2是在这里
我们做gradient descent参数的更新
就很有可能发生这样子的状况
可以发现它在这里来回震荡
为什么呢
因为我们说了
w1它只要稍微有一点变动就会很大的影响cost
那我们这边在做gradient descent更新W1的时候
就很有可能一不小心就更新过头了
所以呢这边不小心更新过头了就到这里
又不小心更新过头了
就会导致这样来回的震荡
那这样子呢就会让我们到最低点的速度变得很慢
也就是我们的gradient descent会变得很慢
那我们要怎么样解决这个问题呢
非常的简单
会造成这个问题的原因就是特征的大小范围不一样嘛
我们这边第一个特征的范围比较大然后其他比较小
所以才会造成这个问题嘛
想要要解决的话
我们就把特征的范围都变成同样的就可以了
我就把这边的大也变成小
我们来看一下四个特征都在同一个范围之后
我们的等高线图就会变成这个样子
那我们现在在做gradient descent的话
就会非常的顺利
直接呢走到最低点的地方
好所以呢
我们只要把每一个特征它的大小缩放到同一个范围内
就可以加速我们的gradient descent
要做特征缩放有很多种方式
这边我就介绍一个很经典很常用到的
叫做标准化英文是standardization
他的做法呢是把我们的特征
去减掉这个特征的平均再除以这个特征的标准差
以我们的年资特征来说的话
就是把年资的每一笔资料都扣掉年资的平均
再除以年资的标准差
这边如果你不知道什么是标准差也没关系
因为有很多工具都可以帮我们自动去做计算
所以如果我们把每一个特征
都经过标准化之后就会变成这个样子
可以看到他们的大小范围呢就会都非常的接近
这边你可能会有疑问说
我们后面这3个特征不是本来就很小了嘛
为什么还要做特征缩放呢
没有错他们本来就很小了
所以如果你要做跟不做都是可以的
这边我就全部都把它做缩放了
接着呢我们就直接来实作特征缩放啦
要做特征缩放的话
我们是在分完测试集跟训练集之后才做特征缩放
我们分测试集跟训练集是在这里嘛
所以呢在他分完之后我们才做特征缩放
这边我们要做特征缩放的方法是标准化嘛
要用标准化的话我们可以直接引入sklearn
它底下的prepossessing
然后呢再去引入standard scaler
那我们可以这样使用它
因为它是一个类别所以我先把它做创建
把它叫做scaler
创建完之后呢我们再让他去看过训练集的特征资料
注意哦这边只能让他看训练集的特征资料
不能让他看测试集的特征资料
因为测试集的资料我们只有在做测试的时候才能使用到
这边我们可以写点fit
然后把x train把它传进来
这样传进来之后
它就会计算这里面特征的平均、标准差等等的
好那它计算完之后
我们就可以把它做转换啦
要做转换我们可以写点transform
然后一样把x train把它传进来
这样它就会做转换了
我们把转换的结果直接替代掉原本的
好那我们把它显示出来看看
这就是转换之后的结果
那这里我顺便把x test也把它做个转换
这里我们只是先做转换没有要使用它
这样之后再做测试的时候会比较方便
那一样这边我们就是把转换之后的结果直接替代掉
这边特别注意一下
我们不会再另外根据测试集的资料
去计算他的标准差啊计算他的平均
然后再做转换
我们会直接使用训练集拟合出来的结果
也就是这边训练集所计算出来的标准差跟平均
就会直接使用到测试集上面来做转换
那一样我直接把它显示出来看看
这个呢就是测试集转换出来的结果
接着我们直接来比较一下
经过特征缩放之后我们再去做gradient descent
跟没有做特征缩放的gradient descent
它差别在哪
我们之前做的gradient descent它在这边
这个是结果
我直接复制一份
在这里再重新执行一次
这里所有的参数都是一样的
唯一不同的呢是我们的x train经过了特征缩放
那我在全部都相同的情况下再执行一次
来看一下是不是真的有比较快
可以看到大概在1,000次的更新的时候
它的cost呢就到2.5*10的一次方了
然后下面2,000 3,000次的更新
基本上cost都没有动了
所以呢我们可以猜测
它差不多是已经到达了最低点的地方
我们对比一下之前的结果
之前一直更新更新更新到了差不多4000次左右
他才到2.5*10的一次方
所以呢我们很明显的可以看得出来
经过特征缩放之后
确实我们在做gradient descent 他下降的速度有比较快
接下来跟大家介绍
我们在做分类问题的时候非常好用的一个模型
叫做逻辑回归英文是logistic regression
先来了解一下今天我们想要解决的问题
假设我们知道一个人有没有得糖尿病
可能跟他的年纪、体重、血糖还有性别有关系
所以呢我们就去收集了一些资料
这边的每一笔资料就代表一个人
他的年纪、体重、血糖还有性别以及他有没有得糖尿病
1的话就表示他有得糖尿病0的话就是没有
所以呢我们就是想要根据这4个特征
去预测这个人他有没有得糖尿病
那有没有得糖尿病输出的值只有两种可能嘛
要么是1 要么是0
也就是有得糖尿病跟没有得糖尿病
这样就跟我们前两个例子差很多了嘛
我们前两个例子
在做简单线性回归跟多元线性回归的时候
预测的是月薪
那月薪它输出的可能就有无限多种
不像这边输出的可能只有两种
要么有得糖尿病要么没有得
这种输出的可能性是有限的
我们就会说它是一个分类问题英文是classification
这边稍微打个预防针
这些资料都是我随机产生的
所以如果你有医学背景的人不用太认真
然后你可能也会说
不是血糖超过多少就有得糖尿病吗
一样我们先当作这些我们都不知道
好接着用图的方式来看一下
这是之前线性回归的例子
我们想要用年资去预测薪水
那其实特征的地方呢可以不只有年资
还可以有工作的地方、学历等等的
这边是为了图方便呈现所以我只显示年资
那我们说可以用一条线来表示这些资料嘛
那回到我们今天的这个例子
我们想要用一个人的血糖去预测他有没有糖尿病
这边的特征一样可以有很多个
可以有刚刚说的体重、年纪、性别等等的
一样这里我为了方便图的呈现
所以我只画一个血糖的特征
我们可以看到这边资料的分布就跟左边差很多了嘛
因为这边它的输出值只有两种可能
要么是1 要么是0
也就是有糖尿病跟没有糖尿病
所以呢看起来就会长这样
那这个时候你还觉得我们要用一条线来表示这些资料嘛
好像不太对吧
那怎么办呢
其实我们也不用做太大的调整
只要把这条线稍微弯曲一下变成这个样子
是不是就好像可以表示这些资料了嘛
这条弯曲的线它的值只可能在0到1之间
那就跟我们的资料非常的吻合
因为我们的资料它不是1就是0
那现在的问题就会变成我们要怎么样把它做弯曲呢
非常的简单
我们只要透过一个函数叫做sigmoid function
中文的话可以把它叫做s型函数
就可以达到弯曲的效果了
以我们之前线性回归的例子来说
我们数学式子可以写成这样y=w*x+b
或者你有很多特征的话
我们可以写成y=W1*X1+W2*X2
一路加上去看你有几个特征
如果我们想要把这样子线性的模型做弯曲的话
只要把它带入sigmoid function就可以了
那这个sigmoid function长这样
它是1/1+e的一个次方
念起来有点绕口令的感觉哦
那我们只要把这个线性的模型呢
并且加上负号它带到次方这边就可以做弯曲了并
这边你可能会有一个疑问
就是这个英文字母的e是什么意思呢
这个e它只是一个常数代表的是2.7182818....
跟我们的数学圆周率π一样它只是一个常数
圆周率π就是3.1415926.... 嘛
所以我们只要把这边这一串
把它带到次方的这个位置并且加上负号
就可以达到弯曲的效果了
那在带入之前呢
我先把这边的y把它做个改变我把它改成z
OK改成z
那带入进去之后呢
我们新的预测值y 就会变成这个样子
把这一串带到里面来看你有几个特征这边就是乘几个
这个呢就是我们逻辑回归的模型
大家也不要看他长这个样子就觉得很可怕
其实有很多工具都可以帮我们自动的做计算
回到我们想要解决的问题
今天我们是想要用年纪、体重、血糖还有性别
来预测有没有糖尿病
所以呢我们的特征就有这4个
也就是说我们想要找出一组最佳的W1234以及b的组合
让它带入这边的Sigmoid function做了弯曲之后
可以最能表示我们的资料
那接着我们就直接来实作啦
首先我们一样先把资料读取进来
读取的动作跟之前都是一样的所以我直接用复制的
不过这边资料的网址是不一样的所以我把它改一下
那这个网址呢一样在课程档案里面你可以找得到
好那我们执行它
可以看到这就是我们的资料
总共有0-399 所以有400笔资料
读取进来之后我们先把资料做个处理
这边有文字嘛文字的部分我们要先把它转换成数字
这里我就把男生转换成0 女生转换成1
所以呢我们去取得它的gender 也就是性别这个特征
然后呢我去把它做个转换
我们可以用map把它做转换
是男生对应到1 女生对应到0
那我们把它转换完之后再把它显示出来看看
可以看到这样就转换完成了
接着我们就来把资料分成训练集跟测试集
那分法跟之前都是一样的所以我就直接用复制的
OK 在这边
直接复制过来
不过这边的x跟y 呢要改一下
我们的特征是age 然后是体重...
y的部分是有没有糖尿病
那这样分完之后呢我把它显示出来看看
把x train跟x test显示出来看看
OK 这个就是分完的结果
那我们也把y的部分也显示出来看看
y train跟y test
OK 没有问题
这边我们一样是测试集用0.2 也就是2成
那我们总共有400笔资料嘛
所以2成就会是80笔测试集320笔是训练集
接着因为我们的特征有4个嘛
那他们分布的范围又都不一样
如果我们想要让他在往后的gradient descent
跑得比较快的话
那我们需要做个特征缩放
特征缩放的部分跟之前都是一样的
所以一样我直接用复制的
OK 特征缩放在这里
直接复制过来
那这边呢我们一样把缩放的结果显示一下
可以看到这个就是缩放之后的结果
我把x test也显示一下
OK 没有问题
资料处理的部分都完成了之后
我们就可以把它带入到模型里面啦
首先我先随便设定w跟b的值
那这边呢我先把numpy把它引入进来
w的话我就让它是里面有4个值的阵列
因为我们有4个特征嘛
OK 有4个特征
W1234我就让它是1234
接着还要设定一个b
b的话我就让它是1
那我们的模型呢是这样
先让w去乘以x
我们现在训练阶段所以我乘以x train
好把它的结果显示出来
这是乘完之后的结果
乘完之后我们要把它做相加嘛
这跟之前都是一样的
所以我们用sum 然后让它是轴线1的部分做相加
再执行
好这是相加之后的结果
加完之后我们要让它加上b
那这样子呢这一串就会是我们之前
多元线性回归的时候预测的y
那我们现在是要用逻辑回归
所以呢这个我把它叫做z
接着我们就是要把这个z 把它带到sigmoid function里面
我就先来做sigmoid function
我把它叫做就叫做sigmoid 然后它传入一个z
计算的方式就是1去除以1加上
一个英文字母e的某个次方嘛
所以呢英文字母的e这边可以写np.exp
然后他要几次方呢
就是写在这个小括号里面
那我们想要的是-z次方
好就把它回传
这边呢分母的地方要括号起来
那我把这个numpy的引入把它写到这里
OK 执行
接着我们就直接来使用它
我们就把这个z把它带进去看一下
经过转换之后可以看到
经过这个simoid function之后呢
里面的每个值它都会在0到1之间
所以呢现在我们已经成功的把这个线性的模型
这边本来是多元线性回归嘛
我们已经把这个线性的模型做了弯曲
接着呢一样
我们就是要找出一组最佳的w跟b的组合
让它最能表示我们的资料