Jekyll2023-11-16T06:54:21+00:00https://blog.caiyongji.com/feed.xmlCAIYONGJI’S BLOGLet's make progress!caiyongjii@caiyongji.comGPT最佳实践:五分钟打造你自己的GPT2023-11-10T00:00:00+00:002023-11-10T00:00:00+00:00https://blog.caiyongji.com/2023/11/10/GPTs-generate-your-own-gpt-in-5-mins<p>前几天OpenAI的My GPTs栏目还是灰色的,就在今天已经开放使用了。有幸第一时间体验了一把生成自己的GPT,效果着实惊艳!!!我打造的GPT模型我会放到文章末尾,大家感兴趣也可以自己体验一下。
<img src="/assets/images/20231110/image.png" alt="Alt text" /></p>
<h1 id="打造自己的gpt模型">打造自己的GPT模型</h1>
<p>点击Create a GPT,可以进入到下面这个界面,左侧是一个GPT Builder的对话框,右边是你随时更改GPT配置后的预览。
<img src="/assets/images/20231110/image-1.png" alt="Alt text" /></p>
<p>点进去Configure配置,可以看到具体的头像、名称、描述、说明、对话引导、知识库、可选择的模型能力(是否打开联网、Dall·E图像生成、代码解释器)以及Actions这个是模型调用API的能力。
<img src="/assets/images/20231110/img5.png" alt="Alt text" /></p>
<p>我上传了我所有的mardown文章内容,然后告诉模型,我要一个博客写作GPT帮我写技术文章。</p>
<h1 id="gpt-builder">GPT builder</h1>
<p>然后,我让GPT Builder给我一些建议,他给我罗列了一些,他告诉我可以针对我的需求加入合适的用户交互,要突出技术专长,要经常更新(做不到),可以加入我自己的头像,最重要的是,他说他可以fine-tuning模型。这点我非常惊讶,因为fine-tuning是真正的让GPT背后的模型适配你的数据,也就是我创造的GPT需求,它需要根据数据反向传播影响模型参数的,而fine-tuning的成本也是不便宜的。<br />
我试了试,它真的根据我的需求调整了模型。
<img src="/assets/images/20231110/image-2.png" alt="Alt text" /></p>
<h1 id="发布">发布</h1>
<p>发布时可以选择公开发布,它提示你公开的GPT模型可能会出现在未来GPT商店里,足以看出openAI对整个模型生态的野心。</p>
<p><img src="/assets/images/20231110/image-3.png" alt="Alt text" /></p>
<h1 id="实践">实践</h1>
<p>我让他根据我以往的写作风格写一篇技术文章,它选择了<a href="https://blog.caiyongji.com/2023/11/10/gpt-sample.html">《深入理解Python异步编程:从原理到实践》</a>我已经放到了我的个人博客上,大家可以自己看看写的怎么样。<br />
甚至,我让他把文章改成markdown格式,并提供一个下载链接,它也做!到!了!
<img src="/assets/images/20231110/image-4.png" alt="Alt text" /></p>
<h1 id="caibloggpt">CaiBlogGPT</h1>
<p>总的来说,这意味着老板们想要啥可以自己打造了,哪有什么技术壁垒。我的理解是,谁有数据,谁就有模型能力,技术层面,已经是傻瓜式了。 机器学习已经毫无意义,打造自己的knowledge base(知识库)吧。那么谁有整合这些数据的能力呢?这个赢家通吃,强者恒强的世界呀!<br />
这就是我生成自己的GPT的体验。大家可以试试我用5分钟打造的gpt: <a href="https://chat.openai.com/g/g-ARKi8yoKs-caibloggpt">https://chat.openai.com/g/g-ARKi8yoKs-caibloggpt</a>。</p>
<p>我从来只原创,也不水文章(咳咳),所以几年没更新。我早已财务自由(并没有),下次再见。</p>caiyongjii@caiyongji.com前几天OpenAI的My GPTs栏目还是灰色的,就在今天已经开放使用了。有幸第一时间体验了一把生成自己的GPT,效果着实惊艳!!!我打造的GPT模型我会放到文章末尾,大家感兴趣也可以自己体验一下。 打造自己的GPT模型 点击Create a GPT,可以进入到下面这个界面,左侧是一个GPT Builder的对话框,右边是你随时更改GPT配置后的预览。 点进去Configure配置,可以看到具体的头像、名称、描述、说明、对话引导、知识库、可选择的模型能力(是否打开联网、Dall·E图像生成、代码解释器)以及Actions这个是模型调用API的能力。 我上传了我所有的mardown文章内容,然后告诉模型,我要一个博客写作GPT帮我写技术文章。 GPT builder 然后,我让GPT Builder给我一些建议,他给我罗列了一些,他告诉我可以针对我的需求加入合适的用户交互,要突出技术专长,要经常更新(做不到),可以加入我自己的头像,最重要的是,他说他可以fine-tuning模型。这点我非常惊讶,因为fine-tuning是真正的让GPT背后的模型适配你的数据,也就是我创造的GPT需求,它需要根据数据反向传播影响模型参数的,而fine-tuning的成本也是不便宜的。 我试了试,它真的根据我的需求调整了模型。 发布 发布时可以选择公开发布,它提示你公开的GPT模型可能会出现在未来GPT商店里,足以看出openAI对整个模型生态的野心。 实践 我让他根据我以往的写作风格写一篇技术文章,它选择了《深入理解Python异步编程:从原理到实践》我已经放到了我的个人博客上,大家可以自己看看写的怎么样。 甚至,我让他把文章改成markdown格式,并提供一个下载链接,它也做!到!了! CaiBlogGPT 总的来说,这意味着老板们想要啥可以自己打造了,哪有什么技术壁垒。我的理解是,谁有数据,谁就有模型能力,技术层面,已经是傻瓜式了。 机器学习已经毫无意义,打造自己的knowledge base(知识库)吧。那么谁有整合这些数据的能力呢?这个赢家通吃,强者恒强的世界呀! 这就是我生成自己的GPT的体验。大家可以试试我用5分钟打造的gpt: https://chat.openai.com/g/g-ARKi8yoKs-caibloggpt。 我从来只原创,也不水文章(咳咳),所以几年没更新。我早已财务自由(并没有),下次再见。(Sample)深入理解Python异步编程:从原理到实践2023-11-10T00:00:00+00:002023-11-10T00:00:00+00:00https://blog.caiyongji.com/2023/11/10/gpt-sample<h1 id="深入理解python异步编程从原理到实践">深入理解Python异步编程:从原理到实践</h1>
<p>在当今快速发展的技术世界里,Python异步编程已经成为了一个热门话题。随着应用程序和服务越来越依赖于网络通信和I/O操作,有效地管理这些操作变得尤为重要。本文将深入探索Python中的异步编程,从基本原理到实际应用,让你全面了解这一强大工具。</p>
<h2 id="一异步编程的基本原理">一、异步编程的基本原理</h2>
<p>异步编程是一种编程范式,它允许程序在等待一个长时间运行的任务(如I/O操作)完成时继续执行其他任务。这与传统的同步编程形成对比,后者在执行长时间运行的任务时会阻塞程序的其余部分。</p>
<p>在Python中,异步编程主要依赖于<code class="language-plaintext highlighter-rouge">asyncio</code>库。<code class="language-plaintext highlighter-rouge">asyncio</code>是Python用于编写并发代码的库,它使用<code class="language-plaintext highlighter-rouge">async</code>和<code class="language-plaintext highlighter-rouge">await</code>语法进行异步编程。使用<code class="language-plaintext highlighter-rouge">asyncio</code>,你可以编写单线程并发代码来执行多个任务,这些任务可以在等待I/O操作或长时间运行的任务完成时被挂起。</p>
<h2 id="二异步编程的优势">二、异步编程的优势</h2>
<p>异步编程的主要优势在于其高效的资源利用。在传统的同步应用中,程序在执行例如网络请求或磁盘读写操作时会被阻塞,从而导致CPU时间的浪费。而在异步应用中,当一个任务被阻塞时,程序可以切换到其他任务,从而使CPU始终保持忙碌状态,提高了程序的整体效率。</p>
<h2 id="三python中的异步编程实践">三、Python中的异步编程实践</h2>
<p>要开始使用Python进行异步编程,首先需要理解<code class="language-plaintext highlighter-rouge">async</code>和<code class="language-plaintext highlighter-rouge">await</code>关键字的用法。<code class="language-plaintext highlighter-rouge">async</code>定义了一个异步函数,而<code class="language-plaintext highlighter-rouge">await</code>用于挂起异步函数的执行,直到相关的操作完成。</p>
<h3 id="示例异步http请求">示例:异步HTTP请求</h3>
<p>以下是一个使用<code class="language-plaintext highlighter-rouge">asyncio</code>和<code class="language-plaintext highlighter-rouge">aiohttp</code>库进行异步HTTP请求的简单示例:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="kn">import</span> <span class="nn">aiohttp</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">fetch</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">session</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="k">return</span> <span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">text</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">aiohttp</span><span class="p">.</span><span class="n">ClientSession</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
<span class="n">html</span> <span class="o">=</span> <span class="k">await</span> <span class="n">fetch</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="s">'http://python.org'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">html</span><span class="p">)</span>
<span class="n">asyncio</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</code></pre></div></div>
<p>在这个示例中,<code class="language-plaintext highlighter-rouge">fetch</code>函数是一个异步函数,它获取一个网页的内容并返回。<code class="language-plaintext highlighter-rouge">main</code>函数则创建一个<code class="language-plaintext highlighter-rouge">aiohttp</code>会话,并调用<code class="language-plaintext highlighter-rouge">fetch</code>函数。注意<code class="language-plaintext highlighter-rouge">fetch</code>和<code class="language-plaintext highlighter-rouge">main</code>函数前的<code class="language-plaintext highlighter-rouge">async</code>关键字,以及它们内部<code class="language-plaintext highlighter-rouge">await</code>语句的使用。</p>
<h2 id="四结论">四、结论</h2>
<p>异步编程是Python中一个强大而有用的工具,特别是在处理大量的I/O密集型任务时。通过有效利用程序等待时间,异步编程能显著提高应用程序的性能和响应能力。虽然它可能在一开始看起来有些复杂,但一旦掌握了异步编程的基本原理和实践,你就能写出更高效、更优化的Python代码。</p>caiyongjii@caiyongji.com深入理解Python异步编程:从原理到实践 在当今快速发展的技术世界里,Python异步编程已经成为了一个热门话题。随着应用程序和服务越来越依赖于网络通信和I/O操作,有效地管理这些操作变得尤为重要。本文将深入探索Python中的异步编程,从基本原理到实际应用,让你全面了解这一强大工具。 一、异步编程的基本原理 异步编程是一种编程范式,它允许程序在等待一个长时间运行的任务(如I/O操作)完成时继续执行其他任务。这与传统的同步编程形成对比,后者在执行长时间运行的任务时会阻塞程序的其余部分。 在Python中,异步编程主要依赖于asyncio库。asyncio是Python用于编写并发代码的库,它使用async和await语法进行异步编程。使用asyncio,你可以编写单线程并发代码来执行多个任务,这些任务可以在等待I/O操作或长时间运行的任务完成时被挂起。 二、异步编程的优势 异步编程的主要优势在于其高效的资源利用。在传统的同步应用中,程序在执行例如网络请求或磁盘读写操作时会被阻塞,从而导致CPU时间的浪费。而在异步应用中,当一个任务被阻塞时,程序可以切换到其他任务,从而使CPU始终保持忙碌状态,提高了程序的整体效率。 三、Python中的异步编程实践 要开始使用Python进行异步编程,首先需要理解async和await关键字的用法。async定义了一个异步函数,而await用于挂起异步函数的执行,直到相关的操作完成。 示例:异步HTTP请求 以下是一个使用asyncio和aiohttp库进行异步HTTP请求的简单示例: import asyncio import aiohttp async def fetch(session, url): async with session.get(url) as response: return await response.text() async def main(): async with aiohttp.ClientSession() as session: html = await fetch(session, 'http://python.org') print(html) asyncio.run(main()) 在这个示例中,fetch函数是一个异步函数,它获取一个网页的内容并返回。main函数则创建一个aiohttp会话,并调用fetch函数。注意fetch和main函数前的async关键字,以及它们内部await语句的使用。 四、结论 异步编程是Python中一个强大而有用的工具,特别是在处理大量的I/O密集型任务时。通过有效利用程序等待时间,异步编程能显著提高应用程序的性能和响应能力。虽然它可能在一开始看起来有些复杂,但一旦掌握了异步编程的基本原理和实践,你就能写出更高效、更优化的Python代码。如何对抗信息茧房?2021-07-29T00:00:00+00:002021-07-29T00:00:00+00:00https://blog.caiyongji.com/2021/07/29/how-to-confront-info-cocoon<p><em>首先声明:本文表达观点,提供一种思考问题的角度,并非严谨的论述论证。为了直击问题本质,高效陈述观点,行文过程中出现的不严谨之处皆是作者表述方式问题,与观点本身无关。无论作者表述多么拙劣,都希望读者可以考虑观点的合理行,对其进行深度的思考。所有“另当别论的个例”皆另当别论,不在本文简洁表述的范围内。</em></p>
<p>人们对信息的需求并非全方位的,大家只注意自己选择的东西和使自己愉悦的领域,久而久之,会将自身桎梏于蚕茧一般的“茧房”中,这就是信息茧房(Information Cocoons)。</p>
<h2 id="一算法驯化">一、算法驯化</h2>
<p>你看到什么你就是什么?<br />
不!<br />
资本想玩皇帝的新装这套,又是道德绑架,又是洞穿人性的。<br />
根据熵增定律,任何系统的混乱程度都在不断增大。这里的熵就是指混乱度,就是说,啥事都是学坏容易,学好难。如果不加约束,互联网上的每个人都是往低俗、劣质发展的。<br />
我从来都不会高估人性,当然我对人性也有相当的自信。简单与性感,质朴与高调,逻辑与搞笑,节俭与时髦,枯燥与新奇,等待和现在就要…… 当人们需要在两者之间做出选择时,大部分人会选择后者。与其投入、等待,在许久之后获得回报和立刻获得愉悦之间,人们更愿意选择容易而非困难,这是人性。<br />
当人们沉浸在推荐算法提供的短期的高度满意的环境中,人们很难感知到自身的信息受限。这时,如果只给你提供有限的选择(比如上滑下滑),那么茧房就形成了。这就是为什么你搭上了某类信息的边,并稍微表现出一点兴趣,你就会陷入到某类信息的漩涡中,直到你成为某个消费品类的客户。</p>
<h2 id="二利益驱动">二、利益驱动</h2>
<p>信息茧房里的人最终会沉迷于那些有趣的、低成本的、使人满足的低俗的娱乐内容中。人们就像是含着奶嘴的巨婴一样,又有生产力,又遵纪守法,又节约资源,又有消费能力,除了费一点电以外,人们消耗的资源降低了。<br />
可是对个人而言,它没有好处。看似什么都直到,只是“没用的知识增加了”。看似见识过人间百态,可又不那么真实,像是表演。看似每天都有收获,可总感觉很空虚。看似了解了世界的大,却连卧室都没走出半步……</p>
<h2 id="三拓展渠道">三、拓展渠道</h2>
<p>摆脱信息茧房的重要手段是,增加自主性。不要推荐,自己主动搜索。你要知道,现在互联网环境的信噪比是越来越低的,有效信息夹杂在大量的垃圾信息中。随着众多论坛、社区向下沉市场扩大,形成了劣币驱逐良币的趋势。懂得人不说话,不懂的人声音大。<br />
因此,我们获取信息的渠道不能只靠网络。<br />
大家可以通过书籍、现实朋友、展会、论坛、峰会等渠道获取信息。没事买一些杂书看一看,自身有能力学一门新的语言又会打开一个不同的新世界。同一个世界,不同的文化竟然讲述着不同的故事。</p>
<h2 id="四总结">四、总结</h2>
<p>对抗信息茧房的手段:<br />
1. 拓展信息获取渠道,避免让互联网成为你唯一获取信息的渠道。
2. 增加获取信息的随机性,比如多买些杂书看。</p>caiyongjii@caiyongji.com首先声明:本文表达观点,提供一种思考问题的角度,并非严谨的论述论证。为了直击问题本质,高效陈述观点,行文过程中出现的不严谨之处皆是作者表述方式问题,与观点本身无关。无论作者表述多么拙劣,都希望读者可以考虑观点的合理行,对其进行深度的思考。所有“另当别论的个例”皆另当别论,不在本文简洁表述的范围内。 人们对信息的需求并非全方位的,大家只注意自己选择的东西和使自己愉悦的领域,久而久之,会将自身桎梏于蚕茧一般的“茧房”中,这就是信息茧房(Information Cocoons)。 一、算法驯化 你看到什么你就是什么? 不! 资本想玩皇帝的新装这套,又是道德绑架,又是洞穿人性的。 根据熵增定律,任何系统的混乱程度都在不断增大。这里的熵就是指混乱度,就是说,啥事都是学坏容易,学好难。如果不加约束,互联网上的每个人都是往低俗、劣质发展的。 我从来都不会高估人性,当然我对人性也有相当的自信。简单与性感,质朴与高调,逻辑与搞笑,节俭与时髦,枯燥与新奇,等待和现在就要…… 当人们需要在两者之间做出选择时,大部分人会选择后者。与其投入、等待,在许久之后获得回报和立刻获得愉悦之间,人们更愿意选择容易而非困难,这是人性。 当人们沉浸在推荐算法提供的短期的高度满意的环境中,人们很难感知到自身的信息受限。这时,如果只给你提供有限的选择(比如上滑下滑),那么茧房就形成了。这就是为什么你搭上了某类信息的边,并稍微表现出一点兴趣,你就会陷入到某类信息的漩涡中,直到你成为某个消费品类的客户。 二、利益驱动 信息茧房里的人最终会沉迷于那些有趣的、低成本的、使人满足的低俗的娱乐内容中。人们就像是含着奶嘴的巨婴一样,又有生产力,又遵纪守法,又节约资源,又有消费能力,除了费一点电以外,人们消耗的资源降低了。 可是对个人而言,它没有好处。看似什么都直到,只是“没用的知识增加了”。看似见识过人间百态,可又不那么真实,像是表演。看似每天都有收获,可总感觉很空虚。看似了解了世界的大,却连卧室都没走出半步…… 三、拓展渠道 摆脱信息茧房的重要手段是,增加自主性。不要推荐,自己主动搜索。你要知道,现在互联网环境的信噪比是越来越低的,有效信息夹杂在大量的垃圾信息中。随着众多论坛、社区向下沉市场扩大,形成了劣币驱逐良币的趋势。懂得人不说话,不懂的人声音大。 因此,我们获取信息的渠道不能只靠网络。 大家可以通过书籍、现实朋友、展会、论坛、峰会等渠道获取信息。没事买一些杂书看一看,自身有能力学一门新的语言又会打开一个不同的新世界。同一个世界,不同的文化竟然讲述着不同的故事。 四、总结 对抗信息茧房的手段: 1. 拓展信息获取渠道,避免让互联网成为你唯一获取信息的渠道。 2. 增加获取信息的随机性,比如多买些杂书看。机器学习(六):通俗易懂无监督学习K-Means聚类算法及代码实践2021-03-20T00:00:00+00:002021-03-20T00:00:00+00:00https://blog.caiyongji.com/2021/03/20/machine-learning-6<blockquote>
<p>K-Means是一种无监督学习方法,用于将无标签的数据集进行聚类。其中K指集群的数量,Means表示寻找集群中心点的手段。</p>
</blockquote>
<h1 id="一-无监督学习-k-means">一、 无监督学习 K-Means</h1>
<p>贴标签是需要花钱的。<br />
所以人们研究处理无标签数据集的方法。(笔者狭隘了)<br />
面对无标签的数据集,我们期望从数据中找出一定的规律。一种最简单也最快速的聚类算法应运而生—K-Means。<br />
它的核心思想很简单:物以类聚。</p>
<p><strong>用直白的话简单解释它的算法执行过程如下:</strong></p>
<ol>
<li>随便选择K个中心点(大哥)。</li>
<li>把距离它足够近的数据(小弟)吸纳为成员,聚成K个集群(组织)。</li>
<li>各集群(组织)内部重新选择中心点(大哥),选择标准是按照距离取<strong>均值</strong>作为中心点(大哥)。</li>
<li>重复2、3步骤直到收敛(组织成员相对稳定)。</li>
</ol>
<p>这就是<del>黑涩会形成</del>聚类的过程。</p>
<h1 id="二-k-means代码实践">二、 K-Means代码实践</h1>
<h2 id="21-鸢尾花数据集">2.1 鸢尾花数据集</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="n">pd</span>
<span class="kn">import</span> <span class="nn">seaborn</span> <span class="k">as</span> <span class="n">sns</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="c1"># 大家不用在意这个域名
</span><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">'https://blog.caiyongji.com/assets/iris.csv'</span><span class="p">)</span>
<span class="n">sns</span><span class="p">.</span><span class="n">scatterplot</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="s">'petal_length'</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="s">'petal_width'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">df</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s">'species'</span><span class="p">)</span>
</code></pre></div></div>
<p>我们得到带标签的数据如下:</p>
<p><img src="/assets/images/20210320/1.png" alt="image" /></p>
<h2 id="22-k-means训练数据">2.2 K-Means训练数据</h2>
<p>我们移除数据标签,仅使用花瓣长、宽作为数据输入,并使用无监督学习方法K-Means进行训练。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">X</span> <span class="o">=</span> <span class="n">df</span><span class="p">[[</span><span class="s">'petal_length'</span><span class="p">,</span><span class="s">'petal_width'</span><span class="p">]].</span><span class="n">to_numpy</span><span class="p">()</span>
<span class="kn">from</span> <span class="nn">sklearn.cluster</span> <span class="kn">import</span> <span class="n">KMeans</span>
<span class="n">k</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">kmeans</span> <span class="o">=</span> <span class="n">KMeans</span><span class="p">(</span><span class="n">n_clusters</span><span class="o">=</span><span class="n">k</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
<span class="n">y_pred</span> <span class="o">=</span> <span class="n">kmeans</span><span class="p">.</span><span class="n">fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="n">X</span><span class="p">[</span><span class="n">y_pred</span><span class="o">==</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">X</span><span class="p">[</span><span class="n">y_pred</span><span class="o">==</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="s">"ro"</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">"group 1"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="n">X</span><span class="p">[</span><span class="n">y_pred</span><span class="o">==</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">X</span><span class="p">[</span><span class="n">y_pred</span><span class="o">==</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="s">"bo"</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">"group 0"</span><span class="p">)</span>
<span class="c1"># plt.legend(loc=2)
</span><span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>
<p>得到分类数据如下,我们并不知道下方数据类别分别代表什么意义。</p>
<p><img src="/assets/images/20210320/2.png" alt="image" /></p>
<p>我们将K分别取1-6的值,可得到如下图所示分类结果:</p>
<p><img src="/assets/images/20210320/3.png" alt="image" /></p>
<p>那么K值的选择有什么意义呢?我们如何选择?</p>
<h1 id="三k的选择">三、K的选择</h1>
<h2 id="31-惯性指标inertia">3.1 惯性指标(inertia)</h2>
<p>K-Means的惯性计算方式是,<strong>每个样本与最接近的集群中心点的均方距离的总和</strong>。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">kmeans_per_k</span> <span class="o">=</span> <span class="p">[</span><span class="n">KMeans</span><span class="p">(</span><span class="n">n_clusters</span><span class="o">=</span><span class="n">k</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">).</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span>
<span class="n">inertias</span> <span class="o">=</span> <span class="p">[</span><span class="n">model</span><span class="p">.</span><span class="n">inertia_</span> <span class="k">for</span> <span class="n">model</span> <span class="ow">in</span> <span class="n">kmeans_per_k</span><span class="p">]</span>
<span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mf">3.5</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">inertias</span><span class="p">,</span> <span class="s">"bo-"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s">"$k$"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">"Inertia"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">annotate</span><span class="p">(</span><span class="s">'Elbow'</span><span class="p">,</span>
<span class="n">xy</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">inertias</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span>
<span class="n">xytext</span><span class="o">=</span><span class="p">(</span><span class="mf">0.55</span><span class="p">,</span> <span class="mf">0.55</span><span class="p">),</span>
<span class="n">textcoords</span><span class="o">=</span><span class="s">'figure fraction'</span><span class="p">,</span>
<span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">,</span>
<span class="n">arrowprops</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">facecolor</span><span class="o">=</span><span class="s">'black'</span><span class="p">,</span> <span class="n">shrink</span><span class="o">=</span><span class="mf">0.1</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">axis</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mf">8.5</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1300</span><span class="p">])</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>
<p><img src="/assets/images/20210320/4.png" alt="image" /></p>
<p>以上代码中<code class="language-plaintext highlighter-rouge">model.inertia_</code>即K-Means方法中的惯性指标。<br />
一般地,惯性越小模型越好,但伴随K值的增大,惯性下降的速度变的很慢,因此我们选择“肘部”的K值,作为最优的K值选择。</p>
<h2 id="32-轮廓系数指标silhouette">3.2 轮廓系数指标(silhouette)</h2>
<p>K-Means的轮廓系数计算方式是,<strong>与集群内其他样本的平均距离记为a,与外部集群样本的平均距离记为b,轮廓系数(b-a)/max(a,b)</strong>。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sklearn.metrics</span> <span class="kn">import</span> <span class="n">silhouette_score</span>
<span class="n">silhouette_scores</span> <span class="o">=</span> <span class="p">[</span><span class="n">silhouette_score</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">model</span><span class="p">.</span><span class="n">labels_</span><span class="p">)</span>
<span class="k">for</span> <span class="n">model</span> <span class="ow">in</span> <span class="n">kmeans_per_k</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span>
<span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">silhouette_scores</span><span class="p">,</span> <span class="s">"bo-"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s">"$k$"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">"Silhouette score"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">axis</span><span class="p">([</span><span class="mf">1.8</span><span class="p">,</span> <span class="mf">8.5</span><span class="p">,</span> <span class="mf">0.55</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">])</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>
<p><img src="/assets/images/20210320/5.png" alt="image" /></p>
<p>以上代码中<code class="language-plaintext highlighter-rouge">silhouette_score</code>方法可取得K-Means的轮廓系数值。<br />
一般地,轮廓系数指标越大越好,我们可以看到当K为2、3时均可取得不错的聚类效果。</p>
<h1 id="四自动选择k值拓展">四、自动选择K值(拓展)</h1>
<h2 id="41-简单理解贝叶斯定理">4.1 简单理解贝叶斯定理</h2>
<p>白话解释贝叶斯:<strong>当有新的证据出现时,不确定的事情更加确信了。</strong> 这里的“确信”是指对不确定的事情的信心程度。</p>
<p>公式(可忽略):</p>
\[P(A|B) = \frac{P(A)P(B|A)}{P(B)}\]
<table>
<tbody>
<tr>
<td>其中,P(A) 表示事件A发生的概率,P(A</td>
<td>B)表示事件B发生时事件A发生的概率。上面的公式中B就是所谓的证据。这里要注意的是,P(B)的出现让P(A</td>
<td>B)变的更确定了,并不是说概率变高了或者变低了。概率的高或者低都是一种确定。它是一种信心程度的体现。</td>
</tr>
</tbody>
</table>
<h2 id="42-贝叶斯高斯混合模型">4.2 贝叶斯高斯混合模型</h2>
<p>我们使用<code class="language-plaintext highlighter-rouge">BayesianGaussianMixture</code>方法,而无需指定明确的K值。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sklearn.mixture</span> <span class="kn">import</span> <span class="n">BayesianGaussianMixture</span>
<span class="n">bgm</span> <span class="o">=</span> <span class="n">BayesianGaussianMixture</span><span class="p">(</span><span class="n">n_components</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">n_init</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
<span class="n">y_pred</span> <span class="o">=</span> <span class="n">bgm</span><span class="p">.</span><span class="n">fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="n">np</span><span class="p">.</span><span class="nb">round</span><span class="p">(</span><span class="n">bgm</span><span class="p">.</span><span class="n">weights_</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</code></pre></div></div>
<p>输出: <code class="language-plaintext highlighter-rouge">array([0.4 , 0.33, 0.27, 0. , 0. , 0. , 0. , 0. , 0. , 0. ])</code></p>
<p>以上代码的执行逻辑是,初始化10个集群,不断调整有关集群数贝叶斯先验知识,来将不必要的集群权重设为0(或接近0),来确定最终K值。</p>
<h1 id="五总结系列完结">五、总结(系列完结)</h1>
<h2 id="51-机器学习系列完结">5.1 机器学习系列完结</h2>
<p><strong>我相信</strong>,截至到目前,大家对机器学习已经有了一个基本的认识。最重要的是,大家亲手实践了机器学习的代码。无论你对机器学习有多么模糊的认识,都能近距离的接触到机器学习,<strong>这一点很重要</strong>。</p>
<p>当初,我发现市面上大部分的教程都对数学有<strong>强依赖</strong>,让很多人敬而远之。我觉得,无论顶尖的科学研究还是普罗大众的教育科普都有其不可替代的巨大价值。流于表面的广泛未必没有其意义,因此我选择了<strong>舍弃严谨,贴近通俗</strong>。</p>
<p>当然,想要深耕于AI领域,数学是充分且必要的条件。如果付得起时间和机会成本,请认真且努力,绝不会辜负你。</p>
<h2 id="52-深度学习系列开始">5.2 深度学习系列开始</h2>
<p>深度学习是一台结构复杂的机器,但它的操作却相对简单。<strong>甚至</strong>,会给你比传统机器学习算法更简单的感受。<br />
我们拭目以待!感谢大家!</p>
<p>往期文章:</p>
<ul>
<li><a href="https://mp.weixin.qq.com/s/rW59lwwTPdqCPTMDoBbjIQ">机器学习(五):通俗易懂决策树与随机森林及代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/QqXNgfyZVwZ-Aze6XTbvng">机器学习(四):通俗理解支持向量机SVM及代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/cEbGM0_Lrt8elfubxSF9jg">机器学习(三):理解逻辑回归及二分类、多分类代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/_bHi-XH5ZXI4jDUzwH3xpQ">机器学习(二):理解线性回归与梯度下降并做简单预测</a></li>
<li><a href="https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q">机器学习(一):5分钟理解机器学习并上手实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/5brLPnUP6sYvc-_JO7IzkA">前置机器学习(五):30分钟掌握常用Matplotlib用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/LlLkkBfI-4s3qdVaiv7EdQ">前置机器学习(四):一文掌握Pandas用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/U8dV8ENzzSx_VwBDdJdr_w">前置机器学习(三):30分钟掌握常用NumPy用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/PCGThwI-YD7_hHxO35V8xw">前置机器学习(二):30分钟掌握常用Jupyter Notebook用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/BLxyqK3CGV9yd92yGEs4XQ">前置机器学习(一):数学符号及希腊字母</a></li>
</ul>caiyongjii@caiyongji.comK-Means是一种无监督学习方法,用于将无标签的数据集进行聚类。其中K指集群的数量,Means表示寻找集群中心点的手段。 一、 无监督学习 K-Means 贴标签是需要花钱的。 所以人们研究处理无标签数据集的方法。(笔者狭隘了) 面对无标签的数据集,我们期望从数据中找出一定的规律。一种最简单也最快速的聚类算法应运而生—K-Means。 它的核心思想很简单:物以类聚。 用直白的话简单解释它的算法执行过程如下: 随便选择K个中心点(大哥)。 把距离它足够近的数据(小弟)吸纳为成员,聚成K个集群(组织)。 各集群(组织)内部重新选择中心点(大哥),选择标准是按照距离取均值作为中心点(大哥)。 重复2、3步骤直到收敛(组织成员相对稳定)。 这就是黑涩会形成聚类的过程。 二、 K-Means代码实践 2.1 鸢尾花数据集 import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 大家不用在意这个域名 df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv') sns.scatterplot(x='petal_length',y='petal_width',data=df,hue='species') 我们得到带标签的数据如下: 2.2 K-Means训练数据 我们移除数据标签,仅使用花瓣长、宽作为数据输入,并使用无监督学习方法K-Means进行训练。 X = df[['petal_length','petal_width']].to_numpy() from sklearn.cluster import KMeans k = 2 kmeans = KMeans(n_clusters=k, random_state=42) y_pred = kmeans.fit_predict(X) plt.plot(X[y_pred==1, 0], X[y_pred==1, 1], "ro", label="group 1") plt.plot(X[y_pred==0, 0], X[y_pred==0, 1], "bo", label="group 0") # plt.legend(loc=2) plt.show() 得到分类数据如下,我们并不知道下方数据类别分别代表什么意义。 我们将K分别取1-6的值,可得到如下图所示分类结果: 那么K值的选择有什么意义呢?我们如何选择? 三、K的选择 3.1 惯性指标(inertia) K-Means的惯性计算方式是,每个样本与最接近的集群中心点的均方距离的总和。 kmeans_per_k = [KMeans(n_clusters=k, random_state=42).fit(X) for k in range(1, 10)] inertias = [model.inertia_ for model in kmeans_per_k] plt.figure(figsize=(8, 3.5)) plt.plot(range(1, 10), inertias, "bo-") plt.xlabel("$k$", fontsize=14) plt.ylabel("Inertia", fontsize=14) plt.annotate('Elbow', xy=(2, inertias[2]), xytext=(0.55, 0.55), textcoords='figure fraction', fontsize=16, arrowprops=dict(facecolor='black', shrink=0.1) ) plt.axis([1, 8.5, 0, 1300]) plt.show() 以上代码中model.inertia_即K-Means方法中的惯性指标。 一般地,惯性越小模型越好,但伴随K值的增大,惯性下降的速度变的很慢,因此我们选择“肘部”的K值,作为最优的K值选择。 3.2 轮廓系数指标(silhouette) K-Means的轮廓系数计算方式是,与集群内其他样本的平均距离记为a,与外部集群样本的平均距离记为b,轮廓系数(b-a)/max(a,b)。 from sklearn.metrics import silhouette_score silhouette_scores = [silhouette_score(X, model.labels_) for model in kmeans_per_k[1:]] plt.figure(figsize=(8, 3)) plt.plot(range(2, 10), silhouette_scores, "bo-") plt.xlabel("$k$", fontsize=14) plt.ylabel("Silhouette score", fontsize=14) plt.axis([1.8, 8.5, 0.55, 0.8]) plt.show() 以上代码中silhouette_score方法可取得K-Means的轮廓系数值。 一般地,轮廓系数指标越大越好,我们可以看到当K为2、3时均可取得不错的聚类效果。 四、自动选择K值(拓展) 4.1 简单理解贝叶斯定理 白话解释贝叶斯:当有新的证据出现时,不确定的事情更加确信了。 这里的“确信”是指对不确定的事情的信心程度。 公式(可忽略): \[P(A|B) = \frac{P(A)P(B|A)}{P(B)}\] 其中,P(A) 表示事件A发生的概率,P(A B)表示事件B发生时事件A发生的概率。上面的公式中B就是所谓的证据。这里要注意的是,P(B)的出现让P(A B)变的更确定了,并不是说概率变高了或者变低了。概率的高或者低都是一种确定。它是一种信心程度的体现。 4.2 贝叶斯高斯混合模型 我们使用BayesianGaussianMixture方法,而无需指定明确的K值。 from sklearn.mixture import BayesianGaussianMixture bgm = BayesianGaussianMixture(n_components=10, n_init=10, random_state=42) y_pred = bgm.fit_predict(X) np.round(bgm.weights_, 2) 输出: array([0.4 , 0.33, 0.27, 0. , 0. , 0. , 0. , 0. , 0. , 0. ]) 以上代码的执行逻辑是,初始化10个集群,不断调整有关集群数贝叶斯先验知识,来将不必要的集群权重设为0(或接近0),来确定最终K值。 五、总结(系列完结) 5.1 机器学习系列完结 我相信,截至到目前,大家对机器学习已经有了一个基本的认识。最重要的是,大家亲手实践了机器学习的代码。无论你对机器学习有多么模糊的认识,都能近距离的接触到机器学习,这一点很重要。 当初,我发现市面上大部分的教程都对数学有强依赖,让很多人敬而远之。我觉得,无论顶尖的科学研究还是普罗大众的教育科普都有其不可替代的巨大价值。流于表面的广泛未必没有其意义,因此我选择了舍弃严谨,贴近通俗。 当然,想要深耕于AI领域,数学是充分且必要的条件。如果付得起时间和机会成本,请认真且努力,绝不会辜负你。 5.2 深度学习系列开始 深度学习是一台结构复杂的机器,但它的操作却相对简单。甚至,会给你比传统机器学习算法更简单的感受。 我们拭目以待!感谢大家! 往期文章: 机器学习(五):通俗易懂决策树与随机森林及代码实践 机器学习(四):通俗理解支持向量机SVM及代码实践 机器学习(三):理解逻辑回归及二分类、多分类代码实践 机器学习(二):理解线性回归与梯度下降并做简单预测 机器学习(一):5分钟理解机器学习并上手实践 前置机器学习(五):30分钟掌握常用Matplotlib用法 前置机器学习(四):一文掌握Pandas用法 前置机器学习(三):30分钟掌握常用NumPy用法 前置机器学习(二):30分钟掌握常用Jupyter Notebook用法 前置机器学习(一):数学符号及希腊字母机器学习(五):通俗易懂决策树与随机森林及代码实践2021-02-25T00:00:00+00:002021-02-25T00:00:00+00:00https://blog.caiyongji.com/2021/02/25/machine-learning-5<p>与SVM一样,决策树是通用的机器学习算法。随机森林,顾名思义,将决策树分类器集成到一起就形成了更强大的机器学习算法。它们都是很基础但很强大的机器学习工具,虽然我们现在有更先进的算法工具来训练模型,但决策树与随机森林因其简单灵活依然广受喜爱,建议大家学习。</p>
<h1 id="一决策树">一、决策树</h1>
<h2 id="11-什么是决策树">1.1 什么是决策树</h2>
<p>我们可以把决策树想象成IF/ELSE判别式深度嵌套的二叉树形结构。以我们在<a href="https://mp.weixin.qq.com/s/cEbGM0_Lrt8elfubxSF9jg">《机器学习(三):理解逻辑回归及二分类、多分类代码实践》</a>所举的鸢尾花数据集为例。</p>
<p>我们曾用<code class="language-plaintext highlighter-rouge">seaborn</code>绘制花瓣长度和宽度特征对应鸢尾花种类的散点图,如下:</p>
<p><img src="/assets/images/20210225/1.png" alt="image" /></p>
<p>当花瓣长度小于2.45则为山鸢尾(setosa),剩下的我们判断花瓣宽度小于1.75则为变色鸢尾(versicolor)剩下的为维吉尼亚鸢尾(virginica)。那么我用导图画一下这种判别式的树形结构如下:</p>
<p><img src="/assets/images/20210225/2.png" alt="image" /></p>
<p>因此,当我们面对任意鸢尾花的样本,我们只需要<strong>从根节点到叶子节点遍历决策树</strong>,就可以得到鸢尾花的分类结论。</p>
<p>这就是决策树。</p>
<h2 id="12-决策树代码实践">1.2 决策树代码实践</h2>
<p>我们导入数据集(大家不用在意这个域名),并训练模型:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="n">pd</span>
<span class="kn">from</span> <span class="nn">sklearn.tree</span> <span class="kn">import</span> <span class="n">DecisionTreeClassifier</span>
<span class="c1">#引入数据集
</span><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">'https://blog.caiyongji.com/assets/iris.csv'</span><span class="p">)</span>
<span class="c1">#决策树模型
</span><span class="n">X</span> <span class="o">=</span> <span class="n">df</span><span class="p">[[</span><span class="s">'petal_length'</span><span class="p">,</span><span class="s">'petal_width'</span><span class="p">]].</span><span class="n">to_numpy</span><span class="p">()</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s">'species'</span><span class="p">]</span>
<span class="n">tree_clf</span> <span class="o">=</span> <span class="n">DecisionTreeClassifier</span><span class="p">(</span><span class="n">max_depth</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
<span class="n">tree_clf</span><span class="p">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
</code></pre></div></div>
<p>我们来可视化决策树:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">from</span> <span class="nn">sklearn.tree</span> <span class="kn">import</span> <span class="n">plot_tree</span>
<span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span><span class="mi">8</span><span class="p">))</span>
<span class="n">plot_tree</span><span class="p">(</span><span class="n">tree_clf</span><span class="p">,</span><span class="n">filled</span><span class="o">=</span><span class="bp">True</span><span class="p">);</span>
</code></pre></div></div>
<p><img src="/assets/images/20210225/3.png" alt="image" /></p>
<p>如上图,我们可以看到根节点总实例数为150时,由<code class="language-plaintext highlighter-rouge">value = [50, 50, 50]</code>可知,实际样本分类为50个山鸢尾花实例、50个变色鸢尾花实例、50个维吉尼亚鸢尾花实例。我们再看最末尾右侧的叶子节点(紫色),由<code class="language-plaintext highlighter-rouge">value = [0, 1, 45]</code>可知,实际样本分类为0个山鸢尾花实例、1个变色鸢尾花实例、45个维吉尼亚鸢尾花实例。</p>
<p>那么gini = 0.043是什么意思呢?</p>
<h2 id="13-基尼不纯度">1.3 基尼不纯度</h2>
<p>显然我们进行分类时,每一个类别实际混入其他类的数量越少分类就越<strong>纯粹</strong>,这种纯度我们通过如下公式表示:</p>
\[G_i = 1 - \sum_{k=1}^{n}{p^2_{i,k}}\]
<p>我们计算维吉尼亚鸢尾花节点(紫色)的gini系数<code class="language-plaintext highlighter-rouge">1-((0/46)**2 + (1/46)**2 + (45/46)**2) = 0.04253308128544431 ≈0.043</code> 。</p>
<p>我们使用基尼(gini)不纯度来衡量决策树的好坏。那么我们通过最小化基尼不纯度min(gini)来求解X[0],X[1](即,花瓣长度宽度特征)边界的过程就决策树模型的训练过程。</p>
<h1 id="二随机森林">二、随机森林</h1>
<h2 id="21-大数定理与随机森林">2.1 大数定理与随机森林</h2>
<p>其实随机森林很简单,我们把决策树随机组合在一起就是随机森林,它比单个的决策树更有效。</p>
<p>凭什么?</p>
<p>假设我们有一枚不均匀的硬币,投掷它有51%的概率为正面,49%的概率为背面,那么当投掷1000次时,“大多数为正面”这件事的概率为75%。投掷10000次时,“大多数为正面”这件事的概率为97%。这就是大数定理,它体现的是群体智慧。<em>质量不够,数量来凑</em>。由此可知,当前寻找最佳模型的方法不止是技巧的比拼,也同样是算力的比拼。</p>
<h2 id="22-随机森林代码实践">2.2 随机森林代码实践</h2>
<h3 id="221-引入新的数据集">2.2.1. 引入新的数据集</h3>
<p>添加引用:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="n">pd</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">import</span> <span class="nn">seaborn</span> <span class="k">as</span> <span class="n">sns</span>
</code></pre></div></div>
<p>导入数据集(大家不用在意这个域名):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">"https://blog.caiyongji.com/assets/penguins_size.csv"</span><span class="p">)</span>
<span class="n">df</span> <span class="o">=</span> <span class="n">df</span><span class="p">.</span><span class="n">dropna</span><span class="p">()</span>
<span class="n">df</span><span class="p">.</span><span class="n">head</span><span class="p">()</span>
</code></pre></div></div>
<table>
<thead>
<tr>
<th style="text-align: left">species</th>
<th style="text-align: left">island</th>
<th style="text-align: right">culmen_length_mm</th>
<th style="text-align: right">culmen_depth_mm</th>
<th style="text-align: right">flipper_length_mm</th>
<th style="text-align: right">body_mass_g</th>
<th style="text-align: left">sex</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">Adelie</td>
<td style="text-align: left">Torgersen</td>
<td style="text-align: right">39.1</td>
<td style="text-align: right">18.7</td>
<td style="text-align: right">181</td>
<td style="text-align: right">3750</td>
<td style="text-align: left">MALE</td>
</tr>
<tr>
<td style="text-align: left">Adelie</td>
<td style="text-align: left">Torgersen</td>
<td style="text-align: right">39.5</td>
<td style="text-align: right">17.4</td>
<td style="text-align: right">186</td>
<td style="text-align: right">3800</td>
<td style="text-align: left">FEMALE</td>
</tr>
<tr>
<td style="text-align: left">Adelie</td>
<td style="text-align: left">Torgersen</td>
<td style="text-align: right">40.3</td>
<td style="text-align: right">18</td>
<td style="text-align: right">195</td>
<td style="text-align: right">3250</td>
<td style="text-align: left">FEMALE</td>
</tr>
<tr>
<td style="text-align: left">Adelie</td>
<td style="text-align: left">Torgersen</td>
<td style="text-align: right">36.7</td>
<td style="text-align: right">19.3</td>
<td style="text-align: right">193</td>
<td style="text-align: right">3450</td>
<td style="text-align: left">FEMALE</td>
</tr>
<tr>
<td style="text-align: left">Adelie</td>
<td style="text-align: left">Torgersen</td>
<td style="text-align: right">39.3</td>
<td style="text-align: right">20.6</td>
<td style="text-align: right">190</td>
<td style="text-align: right">3650</td>
<td style="text-align: left">MALE</td>
</tr>
</tbody>
</table>
<p>企鹅数据集包含特征和标签如下:</p>
<ul>
<li><strong>特征</strong>:所在岛屿island、鸟喙长度culmen_length_mm、鸟喙深度culmen_depth_mm、脚蹼长度flipper_length_mm、体重(g)、性别</li>
<li><strong>标签</strong>:物种species:Chinstrap, Adélie, or Gentoo</li>
</ul>
<h3 id="222-观察数据">2.2.2 观察数据</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sns</span><span class="p">.</span><span class="n">pairplot</span><span class="p">(</span><span class="n">df</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s">'species'</span><span class="p">)</span>
</code></pre></div></div>
<p>我们通过pairplot方法绘制特征两两之间的对应关系。</p>
<p><img src="/assets/images/20210225/4.png" alt="image" /></p>
<h3 id="223-预处理">2.2.3 预处理</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">X</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">get_dummies</span><span class="p">(</span><span class="n">df</span><span class="p">.</span><span class="n">drop</span><span class="p">(</span><span class="s">'species'</span><span class="p">,</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">),</span><span class="n">drop_first</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s">'species'</span><span class="p">]</span>
<span class="n">X</span><span class="p">.</span><span class="n">head</span><span class="p">()</span>
</code></pre></div></div>
<p>注意,<code class="language-plaintext highlighter-rouge">get_dummies</code>方法将字符串属性的列转换成了数字属性的多个列。如,岛屿island和性别sex分别转换成了island_Dream、island_Torgersen和sex_FEMALE、sex_MALE。这是一种独热编码的关系,比如sex_FEMALE与sex_MALE属性独立,在空间内没有向量关系。</p>
<table>
<thead>
<tr>
<th style="text-align: right">culmen_length_mm</th>
<th style="text-align: right">culmen_depth_mm</th>
<th style="text-align: right">flipper_length_mm</th>
<th style="text-align: right">body_mass_g</th>
<th style="text-align: right">island_Dream</th>
<th style="text-align: right">island_Torgersen</th>
<th style="text-align: right">sex_FEMALE</th>
<th style="text-align: right">sex_MALE</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">39.1</td>
<td style="text-align: right">18.7</td>
<td style="text-align: right">181</td>
<td style="text-align: right">3750</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">39.5</td>
<td style="text-align: right">17.4</td>
<td style="text-align: right">186</td>
<td style="text-align: right">3800</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
<td style="text-align: right">1</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">40.3</td>
<td style="text-align: right">18</td>
<td style="text-align: right">195</td>
<td style="text-align: right">3250</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
<td style="text-align: right">1</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">36.7</td>
<td style="text-align: right">19.3</td>
<td style="text-align: right">193</td>
<td style="text-align: right">3450</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
<td style="text-align: right">1</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">39.3</td>
<td style="text-align: right">20.6</td>
<td style="text-align: right">190</td>
<td style="text-align: right">3650</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
<td style="text-align: right">0</td>
<td style="text-align: right">1</td>
</tr>
</tbody>
</table>
<h3 id="224-训练数据">2.2.4 训练数据</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#训练
</span><span class="kn">from</span> <span class="nn">sklearn.model_selection</span> <span class="kn">import</span> <span class="n">train_test_split</span>
<span class="kn">from</span> <span class="nn">sklearn.ensemble</span> <span class="kn">import</span> <span class="n">RandomForestClassifier</span>
<span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">test_size</span><span class="o">=</span><span class="mf">0.3</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">101</span><span class="p">)</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">RandomForestClassifier</span><span class="p">(</span><span class="n">n_estimators</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="n">max_features</span><span class="o">=</span><span class="s">'auto'</span><span class="p">,</span><span class="n">random_state</span><span class="o">=</span><span class="mi">101</span><span class="p">)</span>
<span class="n">model</span><span class="p">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span><span class="n">y_train</span><span class="p">)</span>
<span class="c1">#预测
</span><span class="kn">from</span> <span class="nn">sklearn.metrics</span> <span class="kn">import</span> <span class="n">accuracy_score</span>
<span class="n">preds</span> <span class="o">=</span> <span class="n">model</span><span class="p">.</span><span class="n">predict</span><span class="p">(</span><span class="n">X_test</span><span class="p">)</span>
<span class="n">accuracy_score</span><span class="p">(</span><span class="n">y_test</span><span class="p">,</span><span class="n">preds</span><span class="p">)</span>
</code></pre></div></div>
<p>使用随机森林分类器<code class="language-plaintext highlighter-rouge">RandomForestClassifier</code>训练,得到模型精度为97%。</p>
<h3 id="225-网格搜索与adaboost提升法拓展">2.2.5 网格搜索与AdaBoost提升法(拓展)</h3>
<p>我们使用<code class="language-plaintext highlighter-rouge">AdaBoostClassifier</code>分类器集成数个决策树分类器<code class="language-plaintext highlighter-rouge">DecisionTreeClassifier</code>进行分类。并使用网格搜索方法<code class="language-plaintext highlighter-rouge">GridSearchCV</code>来寻找最优参数。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sklearn.model_selection</span> <span class="kn">import</span> <span class="n">GridSearchCV</span>
<span class="kn">from</span> <span class="nn">sklearn.ensemble</span> <span class="kn">import</span> <span class="n">AdaBoostClassifier</span>
<span class="n">ada_clf</span> <span class="o">=</span> <span class="n">AdaBoostClassifier</span><span class="p">(</span><span class="n">DecisionTreeClassifier</span><span class="p">(</span><span class="n">max_depth</span><span class="o">=</span><span class="mi">1</span><span class="p">),</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">101</span><span class="p">)</span>
<span class="n">ada_clf</span><span class="p">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span> <span class="n">y_train</span><span class="p">)</span>
<span class="n">param_grid</span> <span class="o">=</span> <span class="p">{</span><span class="s">'n_estimators'</span><span class="p">:[</span><span class="mi">10</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">40</span><span class="p">],</span> <span class="s">'learning_rate'</span><span class="p">:[</span><span class="mf">0.01</span><span class="p">,</span><span class="mf">0.1</span><span class="p">,</span><span class="mf">0.5</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="s">'algorithm'</span><span class="p">:[</span><span class="s">'SAMME'</span><span class="p">,</span> <span class="s">'SAMME.R'</span><span class="p">]}</span>
<span class="n">grid</span> <span class="o">=</span> <span class="n">GridSearchCV</span><span class="p">(</span><span class="n">ada_clf</span><span class="p">,</span><span class="n">param_grid</span><span class="p">)</span>
<span class="n">grid</span><span class="p">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span><span class="n">y_train</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"grid.best_params_ = "</span><span class="p">,</span><span class="n">grid</span><span class="p">.</span><span class="n">best_params_</span><span class="p">,</span><span class="s">", grid.best_score_ ="</span> <span class="p">,</span><span class="n">grid</span><span class="p">.</span><span class="n">best_score_</span><span class="p">)</span>
</code></pre></div></div>
<p>这是一种集成学习技术,输出如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>grid.best_params_ = {'algorithm': 'SAMME', 'learning_rate': 1, 'n_estimators': 20} , grid.best_score_ = 0.9914893617021276
</code></pre></div></div>
<h1 id="总结">总结</h1>
<p>二叉树是决策树的核心逻辑,随机森林是大数定理的应用实现。这种基本思想即使不用数学公式也可以很容易的解释清楚,这也是我做这个系列课程(文章)的主要风格特点。我认为,数学是对现实世界的解释,但现实世界并不能被数学<strong>完全解释</strong>。像谷歌AI主管Laurence Moroney所说:</p>
<blockquote>
<p>很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。</p>
</blockquote>
<p>希望那一天可以早点到来吧……</p>
<p>往期文章:</p>
<ul>
<li><a href="https://mp.weixin.qq.com/s/QqXNgfyZVwZ-Aze6XTbvng">机器学习(四):通俗理解支持向量机SVM及代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/cEbGM0_Lrt8elfubxSF9jg">机器学习(三):理解逻辑回归及二分类、多分类代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/_bHi-XH5ZXI4jDUzwH3xpQ">机器学习(二):理解线性回归与梯度下降并做简单预测</a></li>
<li><a href="https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q">机器学习(一):5分钟理解机器学习并上手实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/5brLPnUP6sYvc-_JO7IzkA">前置机器学习(五):30分钟掌握常用Matplotlib用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/LlLkkBfI-4s3qdVaiv7EdQ">前置机器学习(四):一文掌握Pandas用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/U8dV8ENzzSx_VwBDdJdr_w">前置机器学习(三):30分钟掌握常用NumPy用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/PCGThwI-YD7_hHxO35V8xw">前置机器学习(二):30分钟掌握常用Jupyter Notebook用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/BLxyqK3CGV9yd92yGEs4XQ">前置机器学习(一):数学符号及希腊字母</a></li>
</ul>caiyongjii@caiyongji.com与SVM一样,决策树是通用的机器学习算法。随机森林,顾名思义,将决策树分类器集成到一起就形成了更强大的机器学习算法。它们都是很基础但很强大的机器学习工具,虽然我们现在有更先进的算法工具来训练模型,但决策树与随机森林因其简单灵活依然广受喜爱,建议大家学习。 一、决策树 1.1 什么是决策树 我们可以把决策树想象成IF/ELSE判别式深度嵌套的二叉树形结构。以我们在《机器学习(三):理解逻辑回归及二分类、多分类代码实践》所举的鸢尾花数据集为例。 我们曾用seaborn绘制花瓣长度和宽度特征对应鸢尾花种类的散点图,如下: 当花瓣长度小于2.45则为山鸢尾(setosa),剩下的我们判断花瓣宽度小于1.75则为变色鸢尾(versicolor)剩下的为维吉尼亚鸢尾(virginica)。那么我用导图画一下这种判别式的树形结构如下: 因此,当我们面对任意鸢尾花的样本,我们只需要从根节点到叶子节点遍历决策树,就可以得到鸢尾花的分类结论。 这就是决策树。 1.2 决策树代码实践 我们导入数据集(大家不用在意这个域名),并训练模型: import numpy as np import pandas as pd from sklearn.tree import DecisionTreeClassifier #引入数据集 df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv') #决策树模型 X = df[['petal_length','petal_width']].to_numpy() y = df['species'] tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42) tree_clf.fit(X, y) 我们来可视化决策树: import matplotlib.pyplot as plt from sklearn.tree import plot_tree plt.figure(figsize=(12,8)) plot_tree(tree_clf,filled=True); 如上图,我们可以看到根节点总实例数为150时,由value = [50, 50, 50]可知,实际样本分类为50个山鸢尾花实例、50个变色鸢尾花实例、50个维吉尼亚鸢尾花实例。我们再看最末尾右侧的叶子节点(紫色),由value = [0, 1, 45]可知,实际样本分类为0个山鸢尾花实例、1个变色鸢尾花实例、45个维吉尼亚鸢尾花实例。 那么gini = 0.043是什么意思呢? 1.3 基尼不纯度 显然我们进行分类时,每一个类别实际混入其他类的数量越少分类就越纯粹,这种纯度我们通过如下公式表示: \[G_i = 1 - \sum_{k=1}^{n}{p^2_{i,k}}\] 我们计算维吉尼亚鸢尾花节点(紫色)的gini系数1-((0/46)**2 + (1/46)**2 + (45/46)**2) = 0.04253308128544431 ≈0.043 。 我们使用基尼(gini)不纯度来衡量决策树的好坏。那么我们通过最小化基尼不纯度min(gini)来求解X[0],X[1](即,花瓣长度宽度特征)边界的过程就决策树模型的训练过程。 二、随机森林 2.1 大数定理与随机森林 其实随机森林很简单,我们把决策树随机组合在一起就是随机森林,它比单个的决策树更有效。 凭什么? 假设我们有一枚不均匀的硬币,投掷它有51%的概率为正面,49%的概率为背面,那么当投掷1000次时,“大多数为正面”这件事的概率为75%。投掷10000次时,“大多数为正面”这件事的概率为97%。这就是大数定理,它体现的是群体智慧。质量不够,数量来凑。由此可知,当前寻找最佳模型的方法不止是技巧的比拼,也同样是算力的比拼。 2.2 随机森林代码实践 2.2.1. 引入新的数据集 添加引用: import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns 导入数据集(大家不用在意这个域名): df = pd.read_csv("https://blog.caiyongji.com/assets/penguins_size.csv") df = df.dropna() df.head() species island culmen_length_mm culmen_depth_mm flipper_length_mm body_mass_g sex Adelie Torgersen 39.1 18.7 181 3750 MALE Adelie Torgersen 39.5 17.4 186 3800 FEMALE Adelie Torgersen 40.3 18 195 3250 FEMALE Adelie Torgersen 36.7 19.3 193 3450 FEMALE Adelie Torgersen 39.3 20.6 190 3650 MALE 企鹅数据集包含特征和标签如下: 特征:所在岛屿island、鸟喙长度culmen_length_mm、鸟喙深度culmen_depth_mm、脚蹼长度flipper_length_mm、体重(g)、性别 标签:物种species:Chinstrap, Adélie, or Gentoo 2.2.2 观察数据 sns.pairplot(df,hue='species') 我们通过pairplot方法绘制特征两两之间的对应关系。 2.2.3 预处理 X = pd.get_dummies(df.drop('species',axis=1),drop_first=True) y = df['species'] X.head() 注意,get_dummies方法将字符串属性的列转换成了数字属性的多个列。如,岛屿island和性别sex分别转换成了island_Dream、island_Torgersen和sex_FEMALE、sex_MALE。这是一种独热编码的关系,比如sex_FEMALE与sex_MALE属性独立,在空间内没有向量关系。 culmen_length_mm culmen_depth_mm flipper_length_mm body_mass_g island_Dream island_Torgersen sex_FEMALE sex_MALE 39.1 18.7 181 3750 0 1 0 1 39.5 17.4 186 3800 0 1 1 0 40.3 18 195 3250 0 1 1 0 36.7 19.3 193 3450 0 1 1 0 39.3 20.6 190 3650 0 1 0 1 2.2.4 训练数据 #训练 from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101) model = RandomForestClassifier(n_estimators=10,max_features='auto',random_state=101) model.fit(X_train,y_train) #预测 from sklearn.metrics import accuracy_score preds = model.predict(X_test) accuracy_score(y_test,preds) 使用随机森林分类器RandomForestClassifier训练,得到模型精度为97%。 2.2.5 网格搜索与AdaBoost提升法(拓展) 我们使用AdaBoostClassifier分类器集成数个决策树分类器DecisionTreeClassifier进行分类。并使用网格搜索方法GridSearchCV来寻找最优参数。 from sklearn.model_selection import GridSearchCV from sklearn.ensemble import AdaBoostClassifier ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), random_state=101) ada_clf.fit(X_train, y_train) param_grid = {'n_estimators':[10,15,20,25,30,35,40], 'learning_rate':[0.01,0.1,0.5,1], 'algorithm':['SAMME', 'SAMME.R']} grid = GridSearchCV(ada_clf,param_grid) grid.fit(X_train,y_train) print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_) 这是一种集成学习技术,输出如下: grid.best_params_ = {'algorithm': 'SAMME', 'learning_rate': 1, 'n_estimators': 20} , grid.best_score_ = 0.9914893617021276 总结 二叉树是决策树的核心逻辑,随机森林是大数定理的应用实现。这种基本思想即使不用数学公式也可以很容易的解释清楚,这也是我做这个系列课程(文章)的主要风格特点。我认为,数学是对现实世界的解释,但现实世界并不能被数学完全解释。像谷歌AI主管Laurence Moroney所说: 很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。 希望那一天可以早点到来吧…… 往期文章: 机器学习(四):通俗理解支持向量机SVM及代码实践 机器学习(三):理解逻辑回归及二分类、多分类代码实践 机器学习(二):理解线性回归与梯度下降并做简单预测 机器学习(一):5分钟理解机器学习并上手实践 前置机器学习(五):30分钟掌握常用Matplotlib用法 前置机器学习(四):一文掌握Pandas用法 前置机器学习(三):30分钟掌握常用NumPy用法 前置机器学习(二):30分钟掌握常用Jupyter Notebook用法 前置机器学习(一):数学符号及希腊字母机器学习(四):通俗理解支持向量机SVM及代码实践2021-02-15T00:00:00+00:002021-02-15T00:00:00+00:00https://blog.caiyongji.com/2021/02/15/machine-learning-4<p><a href="https://mp.weixin.qq.com/s/cEbGM0_Lrt8elfubxSF9jg">上一篇文章</a>我们介绍了使用逻辑回归来处理分类问题,本文我们讲一个更强大的分类模型。本文依旧侧重代码实践,你会发现我们解决问题的手段越来越丰富,问题处理起来越来越简单。</p>
<p>支持向量机(Support Vector Machine, SVM)是最受欢迎的机器学习模型之一。它特别适合处理中小型复杂数据集的分类任务。</p>
<h1 id="一什么是支持向量机">一、什么是支持向量机</h1>
<p>SMV在众多实例中寻找一个最优的决策边界,这个边界上的实例叫做支持向量,它们“支持”(支撑)分离开超平面,所以它叫支持向量机。</p>
<p>那么我们如何保证我们得到的决策边界是<strong>最优</strong>的呢?</p>
<p><img src="/assets/images/20210215/1.png" alt="image" /></p>
<p>如上图,三条黑色直线都可以完美分割数据集。由此可知,我们仅用单一直线可以得到无数个解。那么,其中怎样的直线是最优的呢?</p>
<p><img src="/assets/images/20210215/2.png" alt="image" /></p>
<p>如上图,我们计算直线到分割实例的距离,使得我们的直线与数据集的<strong>距离尽可能的远</strong>,那么我们就可以得到唯一的解。最大化上图虚线之间的距离就是我们的目标。而上图中重点圈出的实例就叫做支持向量。</p>
<p>这就是支持向量机。</p>
<h1 id="二从代码中映射理论">二、从代码中映射理论</h1>
<h2 id="21-导入数据集">2.1 导入数据集</h2>
<p>添加引用:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
</code></pre></div></div>
<p>导入数据集(大家不用在意这个域名):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df = pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv')
df.head()
</code></pre></div></div>
<table>
<thead>
<tr>
<th style="text-align: right"> </th>
<th style="text-align: right">Med_1_mL</th>
<th style="text-align: right">Med_2_mL</th>
<th style="text-align: right">Virus Present</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">0</td>
<td style="text-align: right">6.50823</td>
<td style="text-align: right">8.58253</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: right">4.12612</td>
<td style="text-align: right">3.07346</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: right">6.42787</td>
<td style="text-align: right">6.36976</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: right">3.67295</td>
<td style="text-align: right">4.90522</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">4</td>
<td style="text-align: right">1.58032</td>
<td style="text-align: right">2.44056</td>
<td style="text-align: right">1</td>
</tr>
</tbody>
</table>
<p>该数据集模拟了一项医学研究,对感染病毒的小白鼠使用不同剂量的两种药物,观察两周后小白鼠是否感染病毒。</p>
<ul>
<li><strong>特征</strong>: 1. 药物Med_1_mL 药物Med_2_mL</li>
<li><strong>标签</strong>:是否感染病毒(1感染/0不感染)</li>
</ul>
<h2 id="22-观察数据">2.2 观察数据</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus Present',data=df)
</code></pre></div></div>
<p>我们用seaborn绘制两种药物在不同剂量特征对应感染结果的散点图。</p>
<p><img src="/assets/images/20210215/3.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.pairplot(df,hue='Virus Present')
</code></pre></div></div>
<p>我们通过pairplot方法绘制特征两两之间的对应关系。</p>
<p><img src="/assets/images/20210215/4.png" alt="image" /></p>
<p>我们可以做出大概的判断,当加大药物剂量可使小白鼠避免被感染。</p>
<h2 id="23-使用svm训练数据集">2.3 使用SVM训练数据集</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#SVC: Supprt Vector Classifier支持向量分类器
from sklearn.svm import SVC
#准备数据
y = df['Virus Present']
X = df.drop('Virus Present',axis=1)
#定义模型
model = SVC(kernel='linear', C=1000)
#训练模型
model.fit(X, y)
# 绘制图像
# 定义绘制SVM边界方法
def plot_svm_boundary(model,X,y):
X = X.values
y = y.values
# Scatter Plot
plt.scatter(X[:, 0], X[:, 1], c=y, s=30,cmap='coolwarm')
# plot the decision function
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# create grid to evaluate model
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = model.decision_function(xy).reshape(XX.shape)
# plot decision boundary and margins
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
# plot support vectors
ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100,
linewidth=1, facecolors='none', edgecolors='k')
plt.show()
plot_svm_boundary(model,X,y)
</code></pre></div></div>
<p><img src="/assets/images/20210215/5.png" alt="image" /></p>
<p>我们导入<code class="language-plaintext highlighter-rouge">sklearn</code>下的<code class="language-plaintext highlighter-rouge">SVC</code>(Supprt Vector Classifier)分类器,它是SVM的一种实现。</p>
<h2 id="24-svc参数c">2.4 SVC参数C</h2>
<p>SVC方法参数<code class="language-plaintext highlighter-rouge">C</code>代表L2正则化参数,正则化的强度与<code class="language-plaintext highlighter-rouge">C</code>的值城<strong>反比</strong>,即C值越大正则化强度越弱,其必须严格为正。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>model = SVC(kernel='linear', C=0.05)
model.fit(X, y)
plot_svm_boundary(model,X,y)
</code></pre></div></div>
<p>我们减少C的值,可以看到模型拟合数据的程度减弱。</p>
<p><img src="/assets/images/20210215/6.png" alt="image" /></p>
<h2 id="25-核技巧">2.5 核技巧</h2>
<p>SVC方法的<code class="language-plaintext highlighter-rouge">kernel</code>参数可取值<code class="language-plaintext highlighter-rouge">{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}</code>。像前文中所使用的那样,我们可以使<code class="language-plaintext highlighter-rouge">kernel='linear'</code>进行线性分类。那么如果我们像进行非线性分类呢?</p>
<h3 id="251-多项式内核">2.5.1 多项式内核</h3>
<p><strong>多项式内核</strong><code class="language-plaintext highlighter-rouge">kernel='poly'</code>的原理简单来说就是,<strong>用单一特征生成多特征来拟合曲线</strong>。比如我们拓展X到y的对应关系如下:</p>
<table>
<thead>
<tr>
<th style="text-align: right"> </th>
<th style="text-align: right">X</th>
<th style="text-align: right">X^2</th>
<th style="text-align: right">X^3</th>
<th style="text-align: right">y</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">0</td>
<td style="text-align: right">6.50823</td>
<td style="text-align: right">6.50823**2</td>
<td style="text-align: right">6.50823**3</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: right">4.12612</td>
<td style="text-align: right">4.12612**2</td>
<td style="text-align: right">4.12612**3</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: right">6.42787</td>
<td style="text-align: right">6.42787**2</td>
<td style="text-align: right">6.42787**3</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: right">3.67295</td>
<td style="text-align: right">3.67295**2</td>
<td style="text-align: right">3.67295**3</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">4</td>
<td style="text-align: right">1.58032</td>
<td style="text-align: right">1.58032**2</td>
<td style="text-align: right">1.58032**3</td>
<td style="text-align: right">1</td>
</tr>
</tbody>
</table>
<p>这样我们就可以用曲线来拟合数据集。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>model = SVC(kernel='poly', C=0.05,degree=5)
model.fit(X, y)
plot_svm_boundary(model,X,y)
</code></pre></div></div>
<p>我们使用多项式内核,并通过<code class="language-plaintext highlighter-rouge">degree=5</code>设置多项式的<strong>最高次数</strong>为5。我们可以看出分割出现了一定的弧度。</p>
<p><img src="/assets/images/20210215/7.png" alt="image" /></p>
<h3 id="252-高斯rbf内核">2.5.2 高斯RBF内核</h3>
<p>SVC方法默认内核为高斯<code class="language-plaintext highlighter-rouge">RBF</code>,即Radial Basis Function(径向基函数)。这时我们需要引入<code class="language-plaintext highlighter-rouge">gamma</code>参数来控制钟形函数的形状。增加gamma值会使钟形曲线变得更窄,因此每个实例影响的范围变小,决策边界更不规则。减小gamma值会使钟形曲线变得更宽,因此每个实例的影响范围变大,决策边界更平坦。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>model = SVC(kernel='rbf', C=1,gamma=0.01)
model.fit(X, y)
plot_svm_boundary(model,X,y)
</code></pre></div></div>
<p><img src="/assets/images/20210215/8.png" alt="image" /></p>
<h2 id="26-调参技巧网格搜索">2.6 调参技巧:网格搜索</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from sklearn.model_selection import GridSearchCV
svm = SVC()
param_grid = {'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]}
grid = GridSearchCV(svm,param_grid)
grid.fit(X,y)
print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_)
</code></pre></div></div>
<p>我们可以通过<code class="language-plaintext highlighter-rouge">GridSearchCV</code>方法来遍历超参数的各种可能性来寻求最优超参数。这是通过算力碾压的方式暴力调参的手段。当然,在分析问题阶段,我们必须限定了各参数的可选范围才能应用此方法。</p>
<p>因为数据集太简单,我们在遍历第一种可能性时就已经得到100%的准确率了,输出如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>grid.best_params_ = {'C': 0.01, 'gamma': 0.01, 'kernel': 'rbf'} , grid.best_score_ = 1.0
</code></pre></div></div>
<h1 id="总结">总结</h1>
<p>当我们处理线性可分的数据集时,可以使用<code class="language-plaintext highlighter-rouge">SVC(kernel='linear')</code>方法来训练数据,当然我们也可以使用更快的方法<code class="language-plaintext highlighter-rouge">LinearSVC</code>来训练数据,特别是当训练集特别大或特征非常多的时候。<br />
当我们处理非线性SVM分类时,可以使用高斯RBF内核,多项式内核,sigmoid内核来进行非线性模型的的拟合。当然我们也可以通过GridSearchCV寻找最优参数。</p>
<p>往期文章:</p>
<ul>
<li><a href="https://mp.weixin.qq.com/s/cEbGM0_Lrt8elfubxSF9jg">机器学习(三):理解逻辑回归及二分类、多分类代码实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/_bHi-XH5ZXI4jDUzwH3xpQ">机器学习(二):理解线性回归与梯度下降并做简单预测</a></li>
<li><a href="https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q">机器学习(一):5分钟理解机器学习并上手实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/5brLPnUP6sYvc-_JO7IzkA">前置机器学习(五):30分钟掌握常用Matplotlib用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/LlLkkBfI-4s3qdVaiv7EdQ">前置机器学习(四):一文掌握Pandas用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/U8dV8ENzzSx_VwBDdJdr_w">前置机器学习(三):30分钟掌握常用NumPy用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/PCGThwI-YD7_hHxO35V8xw">前置机器学习(二):30分钟掌握常用Jupyter Notebook用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/BLxyqK3CGV9yd92yGEs4XQ">前置机器学习(一):数学符号及希腊字母</a></li>
</ul>caiyongjii@caiyongji.com上一篇文章我们介绍了使用逻辑回归来处理分类问题,本文我们讲一个更强大的分类模型。本文依旧侧重代码实践,你会发现我们解决问题的手段越来越丰富,问题处理起来越来越简单。 支持向量机(Support Vector Machine, SVM)是最受欢迎的机器学习模型之一。它特别适合处理中小型复杂数据集的分类任务。 一、什么是支持向量机 SMV在众多实例中寻找一个最优的决策边界,这个边界上的实例叫做支持向量,它们“支持”(支撑)分离开超平面,所以它叫支持向量机。 那么我们如何保证我们得到的决策边界是最优的呢? 如上图,三条黑色直线都可以完美分割数据集。由此可知,我们仅用单一直线可以得到无数个解。那么,其中怎样的直线是最优的呢? 如上图,我们计算直线到分割实例的距离,使得我们的直线与数据集的距离尽可能的远,那么我们就可以得到唯一的解。最大化上图虚线之间的距离就是我们的目标。而上图中重点圈出的实例就叫做支持向量。 这就是支持向量机。 二、从代码中映射理论 2.1 导入数据集 添加引用: import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt 导入数据集(大家不用在意这个域名): df = pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv') df.head() Med_1_mL Med_2_mL Virus Present 0 6.50823 8.58253 0 1 4.12612 3.07346 1 2 6.42787 6.36976 0 3 3.67295 4.90522 1 4 1.58032 2.44056 1 该数据集模拟了一项医学研究,对感染病毒的小白鼠使用不同剂量的两种药物,观察两周后小白鼠是否感染病毒。 特征: 1. 药物Med_1_mL 药物Med_2_mL 标签:是否感染病毒(1感染/0不感染) 2.2 观察数据 sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus Present',data=df) 我们用seaborn绘制两种药物在不同剂量特征对应感染结果的散点图。 sns.pairplot(df,hue='Virus Present') 我们通过pairplot方法绘制特征两两之间的对应关系。 我们可以做出大概的判断,当加大药物剂量可使小白鼠避免被感染。 2.3 使用SVM训练数据集 #SVC: Supprt Vector Classifier支持向量分类器 from sklearn.svm import SVC #准备数据 y = df['Virus Present'] X = df.drop('Virus Present',axis=1) #定义模型 model = SVC(kernel='linear', C=1000) #训练模型 model.fit(X, y) # 绘制图像 # 定义绘制SVM边界方法 def plot_svm_boundary(model,X,y): X = X.values y = y.values # Scatter Plot plt.scatter(X[:, 0], X[:, 1], c=y, s=30,cmap='coolwarm') # plot the decision function ax = plt.gca() xlim = ax.get_xlim() ylim = ax.get_ylim() # create grid to evaluate model xx = np.linspace(xlim[0], xlim[1], 30) yy = np.linspace(ylim[0], ylim[1], 30) YY, XX = np.meshgrid(yy, xx) xy = np.vstack([XX.ravel(), YY.ravel()]).T Z = model.decision_function(xy).reshape(XX.shape) # plot decision boundary and margins ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--']) # plot support vectors ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100, linewidth=1, facecolors='none', edgecolors='k') plt.show() plot_svm_boundary(model,X,y) 我们导入sklearn下的SVC(Supprt Vector Classifier)分类器,它是SVM的一种实现。 2.4 SVC参数C SVC方法参数C代表L2正则化参数,正则化的强度与C的值城反比,即C值越大正则化强度越弱,其必须严格为正。 model = SVC(kernel='linear', C=0.05) model.fit(X, y) plot_svm_boundary(model,X,y) 我们减少C的值,可以看到模型拟合数据的程度减弱。 2.5 核技巧 SVC方法的kernel参数可取值{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}。像前文中所使用的那样,我们可以使kernel='linear'进行线性分类。那么如果我们像进行非线性分类呢? 2.5.1 多项式内核 多项式内核kernel='poly'的原理简单来说就是,用单一特征生成多特征来拟合曲线。比如我们拓展X到y的对应关系如下: X X^2 X^3 y 0 6.50823 6.50823**2 6.50823**3 0 1 4.12612 4.12612**2 4.12612**3 1 2 6.42787 6.42787**2 6.42787**3 0 3 3.67295 3.67295**2 3.67295**3 1 4 1.58032 1.58032**2 1.58032**3 1 这样我们就可以用曲线来拟合数据集。 model = SVC(kernel='poly', C=0.05,degree=5) model.fit(X, y) plot_svm_boundary(model,X,y) 我们使用多项式内核,并通过degree=5设置多项式的最高次数为5。我们可以看出分割出现了一定的弧度。 2.5.2 高斯RBF内核 SVC方法默认内核为高斯RBF,即Radial Basis Function(径向基函数)。这时我们需要引入gamma参数来控制钟形函数的形状。增加gamma值会使钟形曲线变得更窄,因此每个实例影响的范围变小,决策边界更不规则。减小gamma值会使钟形曲线变得更宽,因此每个实例的影响范围变大,决策边界更平坦。 model = SVC(kernel='rbf', C=1,gamma=0.01) model.fit(X, y) plot_svm_boundary(model,X,y) 2.6 调参技巧:网格搜索 from sklearn.model_selection import GridSearchCV svm = SVC() param_grid = {'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]} grid = GridSearchCV(svm,param_grid) grid.fit(X,y) print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_) 我们可以通过GridSearchCV方法来遍历超参数的各种可能性来寻求最优超参数。这是通过算力碾压的方式暴力调参的手段。当然,在分析问题阶段,我们必须限定了各参数的可选范围才能应用此方法。 因为数据集太简单,我们在遍历第一种可能性时就已经得到100%的准确率了,输出如下: grid.best_params_ = {'C': 0.01, 'gamma': 0.01, 'kernel': 'rbf'} , grid.best_score_ = 1.0 总结 当我们处理线性可分的数据集时,可以使用SVC(kernel='linear')方法来训练数据,当然我们也可以使用更快的方法LinearSVC来训练数据,特别是当训练集特别大或特征非常多的时候。 当我们处理非线性SVM分类时,可以使用高斯RBF内核,多项式内核,sigmoid内核来进行非线性模型的的拟合。当然我们也可以通过GridSearchCV寻找最优参数。 往期文章: 机器学习(三):理解逻辑回归及二分类、多分类代码实践 机器学习(二):理解线性回归与梯度下降并做简单预测 机器学习(一):5分钟理解机器学习并上手实践 前置机器学习(五):30分钟掌握常用Matplotlib用法 前置机器学习(四):一文掌握Pandas用法 前置机器学习(三):30分钟掌握常用NumPy用法 前置机器学习(二):30分钟掌握常用Jupyter Notebook用法 前置机器学习(一):数学符号及希腊字母机器学习(三):理解逻辑回归及二分类、多分类代码实践2021-02-01T00:00:00+00:002021-02-01T00:00:00+00:00https://blog.caiyongji.com/2021/02/01/machine-learning-3<p>本文是<a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxMjU4NjI4MQ==&action=getalbum&album_id=1696710764742393857&scene=173&from_msgid=2247484303&from_itemidx=1&count=3#wechat_redirect">机器学习系列</a>的第三篇,算上<a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzUxMjU4NjI4MQ==&action=getalbum&album_id=1627166768236412929&scene=173&from_msgid=2247484161&from_itemidx=1&count=3#wechat_redirect">前置机器学习系列</a>是第八篇。本文的概念相对简单,主要侧重于代码实践。<br />
<a href="https://mp.weixin.qq.com/s?__biz=MzUxMjU4NjI4MQ==&mid=2247484303&idx=1&sn=3880ff2318ee5f005fbe07e308d1c714&chksm=f96364c9ce14eddf2bb66703d249e6b62797a29e6fcbd69756ee3260352fe668860282830503&scene=178&cur_album_id=1696710764742393857#rd">上一篇文章</a>说到,我们可以用线性回归做预测,但显然现实生活中不止有预测的问题还有分类的问题。我们可以从预测值的类型上简单区分:<strong>连续变量的预测为回归,离散变量的预测为分类。</strong></p>
<h1 id="一逻辑回归二分类">一、逻辑回归:二分类</h1>
<h2 id="11-理解逻辑回归">1.1 理解逻辑回归</h2>
<p>我们把连续的预测值进行人工定义,边界的一边定义为1,另一边定义为0。这样我们就把回归问题转换成了分类问题。</p>
<p><img src="/assets/images/20210201/1.png" alt="image" /></p>
<p>如上图,我们把连续的变量分布<strong>压制</strong>在0-1的范围内,并以0.5作为我们分类决策的<strong>边界</strong>,大于0.5的概率则判别为1,小于0.5的概率则判别为0。</p>
<p><img src="/assets/images/20210201/2.png" alt="image" /></p>
<p>我们无法使用无穷大和负无穷大进行算术运算,我们通过逻辑回归函数(Sigmoid函数/S型函数/Logistic函数)可以讲数值计算限定在0-1之间。</p>
\[\sigma(x) = \frac{1}{1+e^{-x}}\]
<p>以上就是逻辑回归的简单解释。下面我们应用真实的数据案例来进行二分类代码实践。</p>
<h2 id="12-代码实践---导入数据集">1.2 代码实践 - 导入数据集</h2>
<p>添加引用:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
</code></pre></div></div>
<p>导入数据集(大家不用在意这个域名):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df = pd.read_csv('https://blog.caiyongji.com/assets/hearing_test.csv')
df.head()
</code></pre></div></div>
<table>
<thead>
<tr>
<th style="text-align: right">age</th>
<th style="text-align: right">physical_score</th>
<th style="text-align: right">test_result</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">33</td>
<td style="text-align: right">40.7</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">50</td>
<td style="text-align: right">37.2</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td style="text-align: right">52</td>
<td style="text-align: right">24.7</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">56</td>
<td style="text-align: right">31</td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td style="text-align: right">35</td>
<td style="text-align: right">42.9</td>
<td style="text-align: right">1</td>
</tr>
</tbody>
</table>
<p>该数据集,对5000名参与者进行了一项实验,以研究年龄和身体健康对听力损失的影响,尤其是听高音的能力。此数据显示了研究结果对参与者进行了身体能力的评估和评分,然后必须进行音频测试(通过/不通过),以评估他们听到高频的能力。</p>
<ul>
<li><strong>特征</strong>:1. 年龄 2. 健康得分</li>
<li><strong>标签</strong>:(1通过/0不通过)</li>
</ul>
<h2 id="13-观察数据">1.3 观察数据</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.scatterplot(x='age',y='physical_score',data=df,hue='test_result')
</code></pre></div></div>
<p>我们用<code class="language-plaintext highlighter-rouge">seaborn</code>绘制年龄和健康得分特征对应测试结果的散点图。</p>
<p><img src="/assets/images/20210201/3.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.pairplot(df,hue='test_result')
</code></pre></div></div>
<p>我们通过<code class="language-plaintext highlighter-rouge">pairplot</code>方法绘制特征两两之间的对应关系。</p>
<p><img src="/assets/images/20210201/4.png" alt="image" /></p>
<p>我们可以大致做出判断,当年龄超过60很难通过测试,通过测试者普遍健康得分超过30。</p>
<h2 id="14-训练模型">1.4 训练模型</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score,classification_report,plot_confusion_matrix
#准备数据
X = df.drop('test_result',axis=1)
y = df['test_result']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=50)
scaler = StandardScaler()
scaled_X_train = scaler.fit_transform(X_train)
scaled_X_test = scaler.transform(X_test)
#定义模型
log_model = LogisticRegression()
#训练模型
log_model.fit(scaled_X_train,y_train)
#预测数据
y_pred = log_model.predict(scaled_X_test)
accuracy_score(y_test,y_pred)
</code></pre></div></div>
<p>我们经过准备数据,定义模型为<code class="language-plaintext highlighter-rouge">LogisticRegression</code>逻辑回归模型,通过<code class="language-plaintext highlighter-rouge">fit</code>方法拟合训练数据,最后通过<code class="language-plaintext highlighter-rouge">predict</code>方法进行预测。<br />
最终我们调用<code class="language-plaintext highlighter-rouge">accuracy_score</code>方法得到模型的准确率为92.2%。</p>
<h1 id="二模型性能评估准确率精确度召回率">二、模型性能评估:准确率、精确度、召回率</h1>
<p>我们是如何得到准确率是92.2%的呢?我们调用<code class="language-plaintext highlighter-rouge">plot_confusion_matrix</code>方法绘制混淆矩阵。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>plot_confusion_matrix(log_model,scaled_X_test,y_test)
</code></pre></div></div>
<p>我们观察500个测试实例,得到矩阵如下:</p>
<p><img src="/assets/images/20210201/5.png" alt="image" /></p>
<p>我们对以上矩阵进行定义如下:</p>
<ul>
<li><strong>真正类TP(True Positive)</strong> :预测为正,实际结果为正。如,上图右下角285。</li>
<li><strong>真负类TN(True Negative)</strong> :预测为负,实际结果为负。如,上图左上角176。</li>
<li><strong>假正类FP(False Positive)</strong> :预测为正,实际结果为负。如,上图左下角19。</li>
<li><strong>假负类FN(False Negative)</strong> :预测为负,实际结果为正。如,上图右上角20。</li>
</ul>
<p><strong>准确率(Accuracy)</strong> 公式如下:</p>
\[Accuracy = \frac{TP+TN}{TP+TN+FP+FN}\]
<p>带入本例得:</p>
\[Accuracy = \frac{285+176}{285+176+20+19} = 0.922\]
<p><strong>精确度(Precision)</strong> 公式如下:</p>
\[Precision = \frac{TP}{TP+FP}\]
<p>带入本例得:<br />
\(Precision = \frac{285}{285+19} = 0.9375\)</p>
<p><strong>召回率(Recall)</strong> 公式如下:</p>
\[Recall = \frac{TP}{TP+FN}\]
<p>带入本例得:</p>
\[Recall = \frac{285}{285+20} = 0.934\]
<p>我们调用<code class="language-plaintext highlighter-rouge">classification_report</code>方法可验证结果。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>print(classification_report(y_test,y_pred))
</code></pre></div></div>
<p><img src="/assets/images/20210201/6.png" alt="image" /></p>
<h1 id="三softmax多分类">三、Softmax:多分类</h1>
<h2 id="31-理解softmax多元逻辑回归">3.1 理解softmax多元逻辑回归</h2>
<p>Logistic回归和Softmax回归都是基于线性回归的分类模型,两者无本质区别,都是从伯努利分结合最大对数似然估计。</p>
<p><strong>最大似然估计</strong>:简单来说,最大似然估计就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值。</p>
<p><em>术语“概率”(probability)和“似然”(likelihood)在英语中经常互换使用,但是它们在统计学中的含义却大不相同。给定具有一些参数θ的统计模型,用“概率”一词描述未来的结果x的合理性(知道参数值θ),而用“似然”一词表示描述在知道结果x之后,一组特定的参数值θ的合理性。</em></p>
<p>Softmax回归模型首先计算出每个类的分数,然后对这些分数应用softmax函数,估计每个类的概率。我们预测具有最高估计概率的类,简单来说就是找得分最高的类。</p>
<h2 id="32-代码实践---导入数据集">3.2 代码实践 - 导入数据集</h2>
<p>导入数据集(大家不用在意这个域名):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv')
df.head()
</code></pre></div></div>
<table>
<thead>
<tr>
<th style="text-align: right">sepal_length</th>
<th style="text-align: right">sepal_width</th>
<th style="text-align: right">petal_length</th>
<th style="text-align: right">petal_width</th>
<th style="text-align: left">species</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">5.1</td>
<td style="text-align: right">3.5</td>
<td style="text-align: right">1.4</td>
<td style="text-align: right">0.2</td>
<td style="text-align: left">setosa</td>
</tr>
<tr>
<td style="text-align: right">4.9</td>
<td style="text-align: right">3</td>
<td style="text-align: right">1.4</td>
<td style="text-align: right">0.2</td>
<td style="text-align: left">setosa</td>
</tr>
<tr>
<td style="text-align: right">4.7</td>
<td style="text-align: right">3.2</td>
<td style="text-align: right">1.3</td>
<td style="text-align: right">0.2</td>
<td style="text-align: left">setosa</td>
</tr>
<tr>
<td style="text-align: right">4.6</td>
<td style="text-align: right">3.1</td>
<td style="text-align: right">1.5</td>
<td style="text-align: right">0.2</td>
<td style="text-align: left">setosa</td>
</tr>
<tr>
<td style="text-align: right">5</td>
<td style="text-align: right">3.6</td>
<td style="text-align: right">1.4</td>
<td style="text-align: right">0.2</td>
<td style="text-align: left">setosa</td>
</tr>
</tbody>
</table>
<p>该数据集,包含150个鸢尾花样本数据,数据特征包含花瓣的长度和宽度和萼片的长度和宽度,包含三个属种的鸢尾花,分别是山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica)。</p>
<ul>
<li><strong>特征</strong>:1. 花萼长度 2. 花萼宽度 3. 花瓣长度 4 花萼宽度</li>
<li><strong>标签</strong>:种类:山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica)</li>
</ul>
<h2 id="33-观察数据">3.3 观察数据</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.scatterplot(x='sepal_length',y='sepal_width',data=df,hue='species')
</code></pre></div></div>
<p>我们用<code class="language-plaintext highlighter-rouge">seaborn</code>绘制<strong>花萼</strong>长度和宽度特征对应鸢尾花种类的散点图。</p>
<p><img src="/assets/images/20210201/7.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.scatterplot(x='petal_length',y='petal_width',data=df,hue='species')
</code></pre></div></div>
<p>我们用<code class="language-plaintext highlighter-rouge">seaborn</code>绘制<strong>花瓣</strong>长度和宽度特征对应鸢尾花种类的散点图。</p>
<p><img src="/assets/images/20210201/8.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sns.pairplot(df,hue='species')
</code></pre></div></div>
<p>我们通过<code class="language-plaintext highlighter-rouge">pairplot</code>方法绘制特征两两之间的对应关系。</p>
<p><img src="/assets/images/20210201/9.png" alt="image" /></p>
<p>我们可以大致做出判断,综合考虑花瓣和花萼尺寸最小的为山鸢尾花,中等尺寸的为变色鸢尾花,尺寸最大的为维吉尼亚鸢尾花。</p>
<h2 id="34-训练模型">3.4 训练模型</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#准备数据
X = df.drop('species',axis=1)
y = df['species']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=50)
scaler = StandardScaler()
scaled_X_train = scaler.fit_transform(X_train)
scaled_X_test = scaler.transform(X_test)
#定义模型
softmax_model = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50)
#训练模型
softmax_model.fit(scaled_X_train,y_train)
#预测数据
y_pred = softmax_model.predict(scaled_X_test)
accuracy_score(y_test,y_pred)
</code></pre></div></div>
<p>我们经过准备数据,定义模型<code class="language-plaintext highlighter-rouge">LogisticRegression</code>的<code class="language-plaintext highlighter-rouge">multi_class="multinomial"</code>多元逻辑回归模型,设置求解器为<code class="language-plaintext highlighter-rouge">lbfgs</code>,通过<code class="language-plaintext highlighter-rouge">fit</code>方法拟合训练数据,最后通过<code class="language-plaintext highlighter-rouge">predict</code>方法进行预测。<br />
最终我们调用<code class="language-plaintext highlighter-rouge">accuracy_score</code>方法得到模型的准确率为92.1%。</p>
<p>我们调用<code class="language-plaintext highlighter-rouge">classification_report</code>方法查看准确率、精确度、召回率。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>print(classification_report(y_test,y_pred))
</code></pre></div></div>
<p><img src="/assets/images/20210201/10.png" alt="image" /></p>
<h2 id="35-拓展绘制花瓣分类">3.5 拓展:绘制花瓣分类</h2>
<p>我们仅提取花瓣长度和花瓣宽度的特征来绘制鸢尾花的分类图像。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#提取特征
X = df[['petal_length','petal_width']].to_numpy()
y = df["species"].factorize(['setosa', 'versicolor','virginica'])[0]
#定义模型
softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50)
#训练模型
softmax_reg.fit(X, y)
#随机测试数据
x0, x1 = np.meshgrid(
np.linspace(0, 8, 500).reshape(-1, 1),
np.linspace(0, 3.5, 200).reshape(-1, 1),
)
X_new = np.c_[x0.ravel(), x1.ravel()]
#预测
y_proba = softmax_reg.predict_proba(X_new)
y_predict = softmax_reg.predict(X_new)
#绘制图像
zz1 = y_proba[:, 1].reshape(x0.shape)
zz = y_predict.reshape(x0.shape)
plt.figure(figsize=(10, 4))
plt.plot(X[y==2, 0], X[y==2, 1], "g^", label="Iris virginica")
plt.plot(X[y==1, 0], X[y==1, 1], "bs", label="Iris versicolor")
plt.plot(X[y==0, 0], X[y==0, 1], "yo", label="Iris setosa")
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0'])
plt.contourf(x0, x1, zz, cmap=custom_cmap)
contour = plt.contour(x0, x1, zz1, cmap=plt.cm.brg)
plt.clabel(contour, inline=1, fontsize=12)
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
plt.legend(loc="center left", fontsize=14)
plt.axis([0, 7, 0, 3.5])
plt.show()
</code></pre></div></div>
<p>得到鸢尾花根据花瓣分类的图像如下:</p>
<p><img src="/assets/images/20210201/11.png" alt="image" /></p>
<h1 id="四小结">四、小结</h1>
<p>相比于概念的理解,本文更侧重上手实践,通过动手编程你应该有“手热”的感觉了。截至到本文,你应该对机器学习的概念有了一定的掌握,我们简单梳理一下:</p>
<ol>
<li>机器学习的分类</li>
<li>机器学习的工业化流程</li>
<li>特征、标签、实例、模型的概念</li>
<li>过拟合、欠拟合</li>
<li>损失函数、最小二乘法</li>
<li>梯度下降、学习率
7.线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术</li>
<li>Sigmoid函数、Softmax函数、最大似然估计</li>
</ol>
<p>如果你还有不清楚的地方请参考:</p>
<ul>
<li><a href="https://mp.weixin.qq.com/s/_bHi-XH5ZXI4jDUzwH3xpQ">机器学习(二):理解线性回归与梯度下降并做简单预测</a></li>
<li><a href="https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q">机器学习(一):5分钟理解机器学习并上手实践</a></li>
<li><a href="https://mp.weixin.qq.com/s/5brLPnUP6sYvc-_JO7IzkA">前置机器学习(五):30分钟掌握常用Matplotlib用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/LlLkkBfI-4s3qdVaiv7EdQ">前置机器学习(四):一文掌握Pandas用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/U8dV8ENzzSx_VwBDdJdr_w">前置机器学习(三):30分钟掌握常用NumPy用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/PCGThwI-YD7_hHxO35V8xw">前置机器学习(二):30分钟掌握常用Jupyter Notebook用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/BLxyqK3CGV9yd92yGEs4XQ">前置机器学习(一):数学符号及希腊字母</a></li>
</ul>caiyongjii@caiyongji.com本文是机器学习系列的第三篇,算上前置机器学习系列是第八篇。本文的概念相对简单,主要侧重于代码实践。 上一篇文章说到,我们可以用线性回归做预测,但显然现实生活中不止有预测的问题还有分类的问题。我们可以从预测值的类型上简单区分:连续变量的预测为回归,离散变量的预测为分类。 一、逻辑回归:二分类 1.1 理解逻辑回归 我们把连续的预测值进行人工定义,边界的一边定义为1,另一边定义为0。这样我们就把回归问题转换成了分类问题。 如上图,我们把连续的变量分布压制在0-1的范围内,并以0.5作为我们分类决策的边界,大于0.5的概率则判别为1,小于0.5的概率则判别为0。 我们无法使用无穷大和负无穷大进行算术运算,我们通过逻辑回归函数(Sigmoid函数/S型函数/Logistic函数)可以讲数值计算限定在0-1之间。 \[\sigma(x) = \frac{1}{1+e^{-x}}\] 以上就是逻辑回归的简单解释。下面我们应用真实的数据案例来进行二分类代码实践。 1.2 代码实践 - 导入数据集 添加引用: import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt 导入数据集(大家不用在意这个域名): df = pd.read_csv('https://blog.caiyongji.com/assets/hearing_test.csv') df.head() age physical_score test_result 33 40.7 1 50 37.2 1 52 24.7 0 56 31 0 35 42.9 1 该数据集,对5000名参与者进行了一项实验,以研究年龄和身体健康对听力损失的影响,尤其是听高音的能力。此数据显示了研究结果对参与者进行了身体能力的评估和评分,然后必须进行音频测试(通过/不通过),以评估他们听到高频的能力。 特征:1. 年龄 2. 健康得分 标签:(1通过/0不通过) 1.3 观察数据 sns.scatterplot(x='age',y='physical_score',data=df,hue='test_result') 我们用seaborn绘制年龄和健康得分特征对应测试结果的散点图。 sns.pairplot(df,hue='test_result') 我们通过pairplot方法绘制特征两两之间的对应关系。 我们可以大致做出判断,当年龄超过60很难通过测试,通过测试者普遍健康得分超过30。 1.4 训练模型 from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score,classification_report,plot_confusion_matrix #准备数据 X = df.drop('test_result',axis=1) y = df['test_result'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=50) scaler = StandardScaler() scaled_X_train = scaler.fit_transform(X_train) scaled_X_test = scaler.transform(X_test) #定义模型 log_model = LogisticRegression() #训练模型 log_model.fit(scaled_X_train,y_train) #预测数据 y_pred = log_model.predict(scaled_X_test) accuracy_score(y_test,y_pred) 我们经过准备数据,定义模型为LogisticRegression逻辑回归模型,通过fit方法拟合训练数据,最后通过predict方法进行预测。 最终我们调用accuracy_score方法得到模型的准确率为92.2%。 二、模型性能评估:准确率、精确度、召回率 我们是如何得到准确率是92.2%的呢?我们调用plot_confusion_matrix方法绘制混淆矩阵。 plot_confusion_matrix(log_model,scaled_X_test,y_test) 我们观察500个测试实例,得到矩阵如下: 我们对以上矩阵进行定义如下: 真正类TP(True Positive) :预测为正,实际结果为正。如,上图右下角285。 真负类TN(True Negative) :预测为负,实际结果为负。如,上图左上角176。 假正类FP(False Positive) :预测为正,实际结果为负。如,上图左下角19。 假负类FN(False Negative) :预测为负,实际结果为正。如,上图右上角20。 准确率(Accuracy) 公式如下: \[Accuracy = \frac{TP+TN}{TP+TN+FP+FN}\] 带入本例得: \[Accuracy = \frac{285+176}{285+176+20+19} = 0.922\] 精确度(Precision) 公式如下: \[Precision = \frac{TP}{TP+FP}\] 带入本例得: \(Precision = \frac{285}{285+19} = 0.9375\) 召回率(Recall) 公式如下: \[Recall = \frac{TP}{TP+FN}\] 带入本例得: \[Recall = \frac{285}{285+20} = 0.934\] 我们调用classification_report方法可验证结果。 print(classification_report(y_test,y_pred)) 三、Softmax:多分类 3.1 理解softmax多元逻辑回归 Logistic回归和Softmax回归都是基于线性回归的分类模型,两者无本质区别,都是从伯努利分结合最大对数似然估计。 最大似然估计:简单来说,最大似然估计就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值。 术语“概率”(probability)和“似然”(likelihood)在英语中经常互换使用,但是它们在统计学中的含义却大不相同。给定具有一些参数θ的统计模型,用“概率”一词描述未来的结果x的合理性(知道参数值θ),而用“似然”一词表示描述在知道结果x之后,一组特定的参数值θ的合理性。 Softmax回归模型首先计算出每个类的分数,然后对这些分数应用softmax函数,估计每个类的概率。我们预测具有最高估计概率的类,简单来说就是找得分最高的类。 3.2 代码实践 - 导入数据集 导入数据集(大家不用在意这个域名): df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv') df.head() sepal_length sepal_width petal_length petal_width species 5.1 3.5 1.4 0.2 setosa 4.9 3 1.4 0.2 setosa 4.7 3.2 1.3 0.2 setosa 4.6 3.1 1.5 0.2 setosa 5 3.6 1.4 0.2 setosa 该数据集,包含150个鸢尾花样本数据,数据特征包含花瓣的长度和宽度和萼片的长度和宽度,包含三个属种的鸢尾花,分别是山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica)。 特征:1. 花萼长度 2. 花萼宽度 3. 花瓣长度 4 花萼宽度 标签:种类:山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica) 3.3 观察数据 sns.scatterplot(x='sepal_length',y='sepal_width',data=df,hue='species') 我们用seaborn绘制花萼长度和宽度特征对应鸢尾花种类的散点图。 sns.scatterplot(x='petal_length',y='petal_width',data=df,hue='species') 我们用seaborn绘制花瓣长度和宽度特征对应鸢尾花种类的散点图。 sns.pairplot(df,hue='species') 我们通过pairplot方法绘制特征两两之间的对应关系。 我们可以大致做出判断,综合考虑花瓣和花萼尺寸最小的为山鸢尾花,中等尺寸的为变色鸢尾花,尺寸最大的为维吉尼亚鸢尾花。 3.4 训练模型 #准备数据 X = df.drop('species',axis=1) y = df['species'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=50) scaler = StandardScaler() scaled_X_train = scaler.fit_transform(X_train) scaled_X_test = scaler.transform(X_test) #定义模型 softmax_model = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50) #训练模型 softmax_model.fit(scaled_X_train,y_train) #预测数据 y_pred = softmax_model.predict(scaled_X_test) accuracy_score(y_test,y_pred) 我们经过准备数据,定义模型LogisticRegression的multi_class="multinomial"多元逻辑回归模型,设置求解器为lbfgs,通过fit方法拟合训练数据,最后通过predict方法进行预测。 最终我们调用accuracy_score方法得到模型的准确率为92.1%。 我们调用classification_report方法查看准确率、精确度、召回率。 print(classification_report(y_test,y_pred)) 3.5 拓展:绘制花瓣分类 我们仅提取花瓣长度和花瓣宽度的特征来绘制鸢尾花的分类图像。 #提取特征 X = df[['petal_length','petal_width']].to_numpy() y = df["species"].factorize(['setosa', 'versicolor','virginica'])[0] #定义模型 softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50) #训练模型 softmax_reg.fit(X, y) #随机测试数据 x0, x1 = np.meshgrid( np.linspace(0, 8, 500).reshape(-1, 1), np.linspace(0, 3.5, 200).reshape(-1, 1), ) X_new = np.c_[x0.ravel(), x1.ravel()] #预测 y_proba = softmax_reg.predict_proba(X_new) y_predict = softmax_reg.predict(X_new) #绘制图像 zz1 = y_proba[:, 1].reshape(x0.shape) zz = y_predict.reshape(x0.shape) plt.figure(figsize=(10, 4)) plt.plot(X[y==2, 0], X[y==2, 1], "g^", label="Iris virginica") plt.plot(X[y==1, 0], X[y==1, 1], "bs", label="Iris versicolor") plt.plot(X[y==0, 0], X[y==0, 1], "yo", label="Iris setosa") from matplotlib.colors import ListedColormap custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0']) plt.contourf(x0, x1, zz, cmap=custom_cmap) contour = plt.contour(x0, x1, zz1, cmap=plt.cm.brg) plt.clabel(contour, inline=1, fontsize=12) plt.xlabel("Petal length", fontsize=14) plt.ylabel("Petal width", fontsize=14) plt.legend(loc="center left", fontsize=14) plt.axis([0, 7, 0, 3.5]) plt.show() 得到鸢尾花根据花瓣分类的图像如下: 四、小结 相比于概念的理解,本文更侧重上手实践,通过动手编程你应该有“手热”的感觉了。截至到本文,你应该对机器学习的概念有了一定的掌握,我们简单梳理一下: 机器学习的分类 机器学习的工业化流程 特征、标签、实例、模型的概念 过拟合、欠拟合 损失函数、最小二乘法 梯度下降、学习率 7.线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术 Sigmoid函数、Softmax函数、最大似然估计 如果你还有不清楚的地方请参考: 机器学习(二):理解线性回归与梯度下降并做简单预测 机器学习(一):5分钟理解机器学习并上手实践 前置机器学习(五):30分钟掌握常用Matplotlib用法 前置机器学习(四):一文掌握Pandas用法 前置机器学习(三):30分钟掌握常用NumPy用法 前置机器学习(二):30分钟掌握常用Jupyter Notebook用法 前置机器学习(一):数学符号及希腊字母机器学习(二):理解线性回归与梯度下降并做简单预测2021-01-19T00:00:00+00:002021-01-19T00:00:00+00:00https://blog.caiyongji.com/2021/01/19/machine-learning-2<h1 id="预测从瞎猜开始">预测从瞎猜开始</h1>
<p>按<a href="https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q">上一篇文章</a>所说,机器学习是应用数学方法在数据中发现规律的过程。既然数学是对现实世界的解释,那么我们回归现实世界,做一些对照的想象。</p>
<p>想象我们面前有一块塑料泡沫做的白板,白板上分布排列着数枚蓝色的图钉,隐约地它们似乎存在着某种规律,我们试着找出规律。</p>
<p><img src="/assets/images/20210119/1.png" alt="image" /></p>
<p>白板上的图钉(<strong>数据</strong>)如上图所示,我们有没有一种方法(<strong>数学算法</strong>)来寻找规律(<strong>模型解释</strong>)呢? 既然不知道怎么做,那我们瞎猜吧!</p>
<p>我拿起两根木棒在白板前比划,试着用木棒表示数据的规律。我随便放了放,如下图所示:</p>
<p><img src="/assets/images/20210119/2.png" alt="image" /></p>
<p>它们似乎都在一定程度上能表示蓝色图钉的规律,那么问题来了,绿色(虚线)和红色(实线)哪一个表示更好呢?</p>
<h1 id="损失函数成本函数">损失函数(成本函数)</h1>
<p>好与坏是很主观的表达,主观的感受是不可靠的,我们必须找到一种客观的度量方式。我们想当然的认为误差最小的表示,是最好的。那么,我们引出一种量化误差的方法—最小二乘法。</p>
<p><strong>最小二乘法</strong>:使误差的平方和最小的办法,是一种误差统计方法,二乘就是平方的意思。<br />
$ SE = \sum{(y_{pred} -y_{true})^2} $</p>
<p>最小二乘法的解释是这样的,我们用<code class="language-plaintext highlighter-rouge">预测值-实际值</code>表示单点的误差,再把它们的<code class="language-plaintext highlighter-rouge">平方和</code>加到一起来表示整体误差。(<em>平方的好处可以处理掉负数值,用绝对值的和也不是不可以。</em>)我们用这个最终值来表示损失(成本),而可以表示损失(成本)的函数就叫做损失函数(成本函数)。</p>
<p><img src="/assets/images/20210119/3.png" alt="image" /></p>
<p>如上图我们可以看到,蓝色点到实线的距离就是我们要带入公式的误差。虽然它们看上去相近,但经过计算的结果是红色实线(<code class="language-plaintext highlighter-rouge">y=3x+2</code>)的损失为27.03,而绿色实线(<code class="language-plaintext highlighter-rouge">y=4x+4</code>)的损失为29.54,显然红色模型优于绿色模型。</p>
<p>那么,还有没有比红色实线更好的模型来表示数据呢?有没有一种方式来找到它呢?</p>
<h1 id="梯度下降">梯度下降</h1>
<p>我们把木棒(实线、模型)的表示数学化,我们既然可以用3、4做为x的系数,那我们当然可以尝试别的数字。我们用如下公式表示这种关系:</p>
<p>$ y = wx + b $</p>
<p>其中,x和y是已知的,我们不断调整<code class="language-plaintext highlighter-rouge">w</code>(<strong>权重</strong>)和<code class="language-plaintext highlighter-rouge">b</code>(<strong>偏差</strong>),然后再带入损失函数以求得最小值的过程,就是<strong>梯度下降</strong>。</p>
<p>我们从-50开始到50结束设置<code class="language-plaintext highlighter-rouge">w</code>的值,我们通过随机数来设置偏置<code class="language-plaintext highlighter-rouge">b</code>,然后再带入损失函数计算我们的预测和实际值的误差损失,得到如下曲线:</p>
<p><img src="/assets/images/20210119/4.png" alt="image" /></p>
<p><strong>需要注意的是,我们绘制的图像是根据权重和损失绘制的曲线。而我们的模型表示是一条直线。</strong><br />
我们可以看到,在上图中我们是可以找到极小值的,大概在5左右,此处是我们损失最小的位置,这时我们的模型最能表示数据的规律。</p>
<p>梯度可以<strong>完全</strong>理解为导数,梯度下降的过程就是我们不断求导的过程。</p>
<h1 id="学习率步长">学习率(步长)</h1>
<p>不断调整权重和偏差来来寻找损失函数最小值的过程就是我们使用梯度下降方法拟合数据寻找最佳模型的过程。那么既然我们有了解决方案,是不是该考虑如何提升效率了,我们如何快速地找到最低点?</p>
<p>想象一下,当你迷失在山上的浓雾之中,你能感觉到的只有你脚下路面的坡度。快速到达山脚的一个策略就是沿着最陡的方向下坡。梯度下降中的一个重要的参数就是每一步的<strong>步长</strong>(<strong>学习率</strong>),如果步长太小,算法需要经过大量迭代才会收敛,如果步长太大,你可能会直接越过山谷,导致算法发散,值越来越大。</p>
<p>设置步长为过小:</p>
<p><img src="/assets/images/20210119/5.gif" alt="image" /></p>
<p>设置步长过大:</p>
<p><img src="/assets/images/20210119/6.gif" alt="image" /></p>
<p>设置步长适当:</p>
<p><img src="/assets/images/20210119/7.gif" alt="image" /></p>
<p>步长是算法自己学习不出来的,它必须由外界指定。<br />
这种算法不能学习,需要人为设定的参数,就叫做<strong>超参数</strong>。</p>
<h1 id="线性回归">线性回归</h1>
<p>最终我们找到了<strong>线性</strong>模型来解释自变量x与因变量y之间的关系,这就是<strong>线性回归</strong>。回归的解释是,事物总是倾向于朝着某种“平均”发展,这种<strong>趋势</strong>叫做回归,所以回归多用于预测。</p>
<p><img src="/assets/images/20210119/8.png" alt="image" /></p>
<p>上图,红线是我们拟合出的最佳模型,在此模型上我们可以寻找到2.2,2.6,2.8的预测值,分别对应图中的三个红点。</p>
<p>这也是线性回归的基本意义。</p>
<h1 id="代码实践">代码实践</h1>
<p>准备数据:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
X = 2 * np.random.rand(10)
y = 4 + 3 * X + np.random.randn(10)
plt.plot(X, y, "bo")
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 2, 0, 15])
plt.show()
</code></pre></div></div>
<p>绘制<code class="language-plaintext highlighter-rouge">y=3x+2</code>和<code class="language-plaintext highlighter-rouge">y=4x+4</code>两条直线:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>plt.plot(X, y, "bo")
plt.plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2")
plt.plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4")
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 2, 0, 15])
plt.legend(loc="upper left")
plt.show()
</code></pre></div></div>
<p>计算损失,并比较<code class="language-plaintext highlighter-rouge">y=3x+2</code>和<code class="language-plaintext highlighter-rouge">y=4x+4</code>两条直线:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fig, ax_list = plt.subplots(nrows=1, ncols=2,figsize=(20,10))
ax_list[0].plot(X, y, "bo")
ax_list[0].plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2")
loss = 0
for i in range(10):
ax_list[0].plot([X[i],X[i]], [y[i],3*X[i]+2], color='grey')
loss= loss + np.square(3*X[i]+2-y[i])
pass
ax_list[0].axis([0, 2, 0, 15])
ax_list[0].legend(loc="upper left")
ax_list[0].title.set_text('loss=%s'%loss)
ax_list[1].plot(X, y, "bo")
ax_list[1].plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4")
loss = 0
for i in range(10):
ax_list[1].plot([X[i],X[i]], [y[i],4*X[i]+4], color='grey')
loss= loss + np.square(4*X[i]+4-y[i])
pass
ax_list[1].axis([0, 2, 0, 15])
ax_list[1].legend(loc="upper left")
ax_list[1].title.set_text('loss=%s'%loss)
fig.subplots_adjust(wspace=0.1,hspace=0.5)
fig.suptitle("Calculate loss",fontsize=16)
</code></pre></div></div>
<p>训练模型,并预测:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X.reshape(-1,1),y.reshape(-1,1))
X_test = [[2.2],[2.6],[2.8]]
y_test = lr.predict(X_test)
X_pred = 3 * np.random.rand(100, 1)
y_pred = lr.predict(X_pred)
plt.scatter(X,y, c='b', label='real')
plt.plot(X_test,y_test, 'r', label='predicted point' ,marker=".", ms=20)
plt.plot(X_pred,y_pred, 'r-', label='predicted')
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 3, 0, 15])
plt.legend(loc="upper left")
loss = 0
for i in range(10):
loss = loss + np.square(y[i]-lr.predict([[X[i]]]))
plt.title("loss=%s"%loss)
plt.show()
</code></pre></div></div>
<h1 id="其他回归">其他回归</h1>
<p>要怎么真正理解回归(regression)呢?通过大量的数据统计,个体小的豆子往往倾向于产生比其更大的后代,而个体大的豆子往往倾向于产生比其更小的后代,新产生的个体有向着豆子的平均值的一种趋势,这种趋势就是回归。我们本篇文章讲的线性回归就是应用于<strong>预测</strong>的一种技术。这时,回归往往与分类相对。</p>
<p>线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术。我先对这些技术做一个简单整理,让大家把脉络理清,等大家实际需要再深入探索。<strong>试图去穷尽知识只会把自己拖向疲累</strong>。</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>解释</th>
<th>公式</th>
</tr>
</thead>
<tbody>
<tr>
<td>线性回归(Linear Regression)</td>
<td>一种以线性模型来建模自变量与因变量关系的方法</td>
<td>$ y = wx+b $</td>
</tr>
<tr>
<td>逻辑回归(Logistic Regression)</td>
<td>对特定类别进行建模,用于二分类</td>
<td>$ y=\frac{1}{1+e^{-x}} $</td>
</tr>
<tr>
<td>多项式回归(Polynomial Regression)</td>
<td>自变量 x 和因变量 y 之间的关系被建模为关于 x 的 n 次多项式</td>
<td>$ y=\beta_0 + \beta_1x + \beta_2x^2 + … + \beta_mx^m + \varepsilon $ (cαiyongji水印)</td>
</tr>
<tr>
<td>逐步回归(Stepwise Regression)</td>
<td>将多个变量一个一个地引入到模型,找到其对模型影响大的变量</td>
<td> </td>
</tr>
<tr>
<td>套索回归(Lasso Regression)</td>
<td>稀疏矩阵,消除不重要的特征,MSE+L1范数</td>
<td>$ J(\theta)=MSE(\theta) + \alpha\sum\mid\theta\mid $ ,其中,α越大模型权重越小</td>
</tr>
<tr>
<td>岭回归(Ridge Regression)</td>
<td>正则化线性回归,增加模型自由度,防止过拟合,MSE+L2范数</td>
<td>$ J(\theta)=MSE(\theta) + \alpha\frac{1}{2}\sum\theta^2 $ ,其中,α越大模型权重越小</td>
</tr>
<tr>
<td>弹性网络(ElasticNet)</td>
<td>介于岭回归和Lasso回归之间</td>
<td>$ J(\theta)=MSE(\theta) + \gamma\alpha\sum\mid\theta\mid + \alpha\frac{1-\gamma}{2}\sum\theta^2 $ ,其中,γ介于0和1之间,接近0则更倾向于岭回归,接近1则更倾向于Lasso回归</td>
</tr>
</tbody>
</table>caiyongjii@caiyongji.com预测从瞎猜开始 按上一篇文章所说,机器学习是应用数学方法在数据中发现规律的过程。既然数学是对现实世界的解释,那么我们回归现实世界,做一些对照的想象。 想象我们面前有一块塑料泡沫做的白板,白板上分布排列着数枚蓝色的图钉,隐约地它们似乎存在着某种规律,我们试着找出规律。 白板上的图钉(数据)如上图所示,我们有没有一种方法(数学算法)来寻找规律(模型解释)呢? 既然不知道怎么做,那我们瞎猜吧! 我拿起两根木棒在白板前比划,试着用木棒表示数据的规律。我随便放了放,如下图所示: 它们似乎都在一定程度上能表示蓝色图钉的规律,那么问题来了,绿色(虚线)和红色(实线)哪一个表示更好呢? 损失函数(成本函数) 好与坏是很主观的表达,主观的感受是不可靠的,我们必须找到一种客观的度量方式。我们想当然的认为误差最小的表示,是最好的。那么,我们引出一种量化误差的方法—最小二乘法。 最小二乘法:使误差的平方和最小的办法,是一种误差统计方法,二乘就是平方的意思。 $ SE = \sum{(y_{pred} -y_{true})^2} $ 最小二乘法的解释是这样的,我们用预测值-实际值表示单点的误差,再把它们的平方和加到一起来表示整体误差。(平方的好处可以处理掉负数值,用绝对值的和也不是不可以。)我们用这个最终值来表示损失(成本),而可以表示损失(成本)的函数就叫做损失函数(成本函数)。 如上图我们可以看到,蓝色点到实线的距离就是我们要带入公式的误差。虽然它们看上去相近,但经过计算的结果是红色实线(y=3x+2)的损失为27.03,而绿色实线(y=4x+4)的损失为29.54,显然红色模型优于绿色模型。 那么,还有没有比红色实线更好的模型来表示数据呢?有没有一种方式来找到它呢? 梯度下降 我们把木棒(实线、模型)的表示数学化,我们既然可以用3、4做为x的系数,那我们当然可以尝试别的数字。我们用如下公式表示这种关系: $ y = wx + b $ 其中,x和y是已知的,我们不断调整w(权重)和b(偏差),然后再带入损失函数以求得最小值的过程,就是梯度下降。 我们从-50开始到50结束设置w的值,我们通过随机数来设置偏置b,然后再带入损失函数计算我们的预测和实际值的误差损失,得到如下曲线: 需要注意的是,我们绘制的图像是根据权重和损失绘制的曲线。而我们的模型表示是一条直线。 我们可以看到,在上图中我们是可以找到极小值的,大概在5左右,此处是我们损失最小的位置,这时我们的模型最能表示数据的规律。 梯度可以完全理解为导数,梯度下降的过程就是我们不断求导的过程。 学习率(步长) 不断调整权重和偏差来来寻找损失函数最小值的过程就是我们使用梯度下降方法拟合数据寻找最佳模型的过程。那么既然我们有了解决方案,是不是该考虑如何提升效率了,我们如何快速地找到最低点? 想象一下,当你迷失在山上的浓雾之中,你能感觉到的只有你脚下路面的坡度。快速到达山脚的一个策略就是沿着最陡的方向下坡。梯度下降中的一个重要的参数就是每一步的步长(学习率),如果步长太小,算法需要经过大量迭代才会收敛,如果步长太大,你可能会直接越过山谷,导致算法发散,值越来越大。 设置步长为过小: 设置步长过大: 设置步长适当: 步长是算法自己学习不出来的,它必须由外界指定。 这种算法不能学习,需要人为设定的参数,就叫做超参数。 线性回归 最终我们找到了线性模型来解释自变量x与因变量y之间的关系,这就是线性回归。回归的解释是,事物总是倾向于朝着某种“平均”发展,这种趋势叫做回归,所以回归多用于预测。 上图,红线是我们拟合出的最佳模型,在此模型上我们可以寻找到2.2,2.6,2.8的预测值,分别对应图中的三个红点。 这也是线性回归的基本意义。 代码实践 准备数据: import numpy as np import matplotlib.pyplot as plt np.random.seed(42) X = 2 * np.random.rand(10) y = 4 + 3 * X + np.random.randn(10) plt.plot(X, y, "bo") plt.xlabel("$X$", fontsize=18) plt.ylabel("$y$", rotation=0, fontsize=18) plt.axis([0, 2, 0, 15]) plt.show() 绘制y=3x+2和y=4x+4两条直线: plt.plot(X, y, "bo") plt.plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2") plt.plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4") plt.xlabel("$X$", fontsize=18) plt.ylabel("$y$", rotation=0, fontsize=18) plt.axis([0, 2, 0, 15]) plt.legend(loc="upper left") plt.show() 计算损失,并比较y=3x+2和y=4x+4两条直线: fig, ax_list = plt.subplots(nrows=1, ncols=2,figsize=(20,10)) ax_list[0].plot(X, y, "bo") ax_list[0].plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2") loss = 0 for i in range(10): ax_list[0].plot([X[i],X[i]], [y[i],3*X[i]+2], color='grey') loss= loss + np.square(3*X[i]+2-y[i]) pass ax_list[0].axis([0, 2, 0, 15]) ax_list[0].legend(loc="upper left") ax_list[0].title.set_text('loss=%s'%loss) ax_list[1].plot(X, y, "bo") ax_list[1].plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4") loss = 0 for i in range(10): ax_list[1].plot([X[i],X[i]], [y[i],4*X[i]+4], color='grey') loss= loss + np.square(4*X[i]+4-y[i]) pass ax_list[1].axis([0, 2, 0, 15]) ax_list[1].legend(loc="upper left") ax_list[1].title.set_text('loss=%s'%loss) fig.subplots_adjust(wspace=0.1,hspace=0.5) fig.suptitle("Calculate loss",fontsize=16) 训练模型,并预测: from sklearn.linear_model import LinearRegression lr = LinearRegression() lr.fit(X.reshape(-1,1),y.reshape(-1,1)) X_test = [[2.2],[2.6],[2.8]] y_test = lr.predict(X_test) X_pred = 3 * np.random.rand(100, 1) y_pred = lr.predict(X_pred) plt.scatter(X,y, c='b', label='real') plt.plot(X_test,y_test, 'r', label='predicted point' ,marker=".", ms=20) plt.plot(X_pred,y_pred, 'r-', label='predicted') plt.xlabel("$X$", fontsize=18) plt.ylabel("$y$", rotation=0, fontsize=18) plt.axis([0, 3, 0, 15]) plt.legend(loc="upper left") loss = 0 for i in range(10): loss = loss + np.square(y[i]-lr.predict([[X[i]]])) plt.title("loss=%s"%loss) plt.show() 其他回归 要怎么真正理解回归(regression)呢?通过大量的数据统计,个体小的豆子往往倾向于产生比其更大的后代,而个体大的豆子往往倾向于产生比其更小的后代,新产生的个体有向着豆子的平均值的一种趋势,这种趋势就是回归。我们本篇文章讲的线性回归就是应用于预测的一种技术。这时,回归往往与分类相对。 线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术。我先对这些技术做一个简单整理,让大家把脉络理清,等大家实际需要再深入探索。试图去穷尽知识只会把自己拖向疲累。 名称 解释 公式 线性回归(Linear Regression) 一种以线性模型来建模自变量与因变量关系的方法 $ y = wx+b $ 逻辑回归(Logistic Regression) 对特定类别进行建模,用于二分类 $ y=\frac{1}{1+e^{-x}} $ 多项式回归(Polynomial Regression) 自变量 x 和因变量 y 之间的关系被建模为关于 x 的 n 次多项式 $ y=\beta_0 + \beta_1x + \beta_2x^2 + … + \beta_mx^m + \varepsilon $ (cαiyongji水印) 逐步回归(Stepwise Regression) 将多个变量一个一个地引入到模型,找到其对模型影响大的变量 套索回归(Lasso Regression) 稀疏矩阵,消除不重要的特征,MSE+L1范数 $ J(\theta)=MSE(\theta) + \alpha\sum\mid\theta\mid $ ,其中,α越大模型权重越小 岭回归(Ridge Regression) 正则化线性回归,增加模型自由度,防止过拟合,MSE+L2范数 $ J(\theta)=MSE(\theta) + \alpha\frac{1}{2}\sum\theta^2 $ ,其中,α越大模型权重越小 弹性网络(ElasticNet) 介于岭回归和Lasso回归之间 $ J(\theta)=MSE(\theta) + \gamma\alpha\sum\mid\theta\mid + \alpha\frac{1-\gamma}{2}\sum\theta^2 $ ,其中,γ介于0和1之间,接近0则更倾向于岭回归,接近1则更倾向于Lasso回归机器学习(一):5分钟理解机器学习并上手实践2021-01-15T00:00:00+00:002021-01-15T00:00:00+00:00https://blog.caiyongji.com/2021/01/15/machine-learning-1<h1 id="引言">引言</h1>
<p>现在市面上的机器学习教程大多先学习数学基础,然后学机器学习的数学算法,再建立机器学习的数学模型,再学习深度学习,再学习工程化,再考虑落地。这其中每个环节都在快速发展,唯独落地特别困难。我们花费大量时间成本去学习以上内容,成本无疑是特别昂贵的。所以我们不如先“盲人摸象”、“不求甚解”地探索下机器学习,浅尝辄止。如果想到自己的应用场景,再学以致用,深入探索。这无疑是使沉没成本最低的决策。<br />
本教程适合兴趣广泛的人士增加自己知识的广度,从应用的角度谨“使用”机器学习这款工具,是典型的黑盒思维。这非常契合笔者的思维方式,当然也是我个人的格局局限。<br />
本教程会浅显易懂,让你走的很快。但如果你想走的更远还请学习数学。当然我们也只是暂时放下数学,先构建自己的知识体系。</p>
<p><strong>先抬头看路,找准适合自己的方向,再埋头赶路,或深耕下去……</strong></p>
<h1 id="把视角拉高">把视角拉高</h1>
<p>从手工到工业化再到人工智能,这是把人类从生产活动中逐渐解放的过程。用机器来帮助人们工作,一直是人类的美好愿望。让机器智能化,以此来代替人力做更智能问题,这可以作为人工智能的简单解释。 <br />
很多教程或者书籍把人工智能、机器学习、深度学习的关系解释为从属关系,人工智能 > 机器学习 > 深度学习。这种解释不错,但却无法表示他们之间的更深层次的关系。 <br />
<strong>机器学习是通过数学方法在数据中寻找解释,以此来实现人工智能的一种手段。而深度学习是参照神经系统在机器学习基础上发展出的一种高级技巧。</strong> 它们之间是存在一定的依托关系、进化趋势的。<br />
狭义地讲,传统的机器学习是通过数学模型不断求导来找出数据规律的过程。这其中数学模型的选择尤为重要。随着GPU、TPU等算力的发展,算法技术的进步,甚至出现了自动选模型、自动调参的技术。我们可以构建复杂的神经网络结构,只要有足够的算力支持,足够的时间我们可以用深度学习处理非常复杂的任务。所以在代码操作上,深度学习甚至比传统的机器学习对程序员更友好、更易理解。我们先学习传统机器学习而非直接学习深度学习的好处是,我们可以通过对“黑盒”的拆箱来理解机器学习过程,掌握机器学习的概念,我会对其中应用的数学模型进行解释。</p>
<p>我们先来看一下人工智能产业链的结构,如下图:</p>
<p><img src="/assets/images/20210115/1.png" alt="image" /></p>
<p>我们可以看到,机器学习的三大基石—算力、算法与数据。机器学习的发展离不开算法数学的进步,同样离不开算力的发展。<br />
在技术层面,机器学习在计算机视觉(CV, Computer Vision)和自然语言处理(NLP, Nature Language Processing)取得了关键的发展和应用。<br />
算法分类上,机器学习分为监督学习、非监督学习、半监督学习、强化学习等。</p>
<ul>
<li><strong>监督学习</strong>:数据样本有标签。</li>
<li><strong>非监督学习</strong>:数据样本无标签。</li>
<li><strong>半监督学习</strong>:数据样本有部分(少量)标签。</li>
<li><strong>强化学习</strong>:趋向结果则奖励,偏离结果则惩罚。</li>
</ul>
<p>所谓Garbage in, Garbage out(垃圾进,垃圾出)。数据是机器学习的重中之重。我们需要花费大量的时间来处理数据,甚至占到整个机器学习任务的90%以上。<br />
比如数据处理过程中的数据采集,如果我们采样的方式欠妥,就可能导致非代表性的数据集,这就导致了采样偏差。<br />
我们的数据可能会有很多无效的数据,我们需要剔除无效的数据,就叫做数据清洗。<br />
我们通过挖掘大量数据来发现不太明显的规律,就称作数据挖掘。</p>
<h1 id="机器学习工业化流程">机器学习工业化流程</h1>
<p>我们以一款工业化流水线工具TFX为例,看一下机器学习的技术流程。</p>
<p><img src="/assets/images/20210115/2.png" alt="image" /></p>
<p>流程分为数据输入、数据验证、特征工程、训练模型、验证模型、应用良好模型和提供模型六个部分:</p>
<ol>
<li>输入数据,并根据需要拆分数据集。</li>
<li>生成训练数据和服务数据的特征统计信息。通过从训练数据中推断出类型、类别和范围来创建架构。识别训练数据和服务数据中的异常值。</li>
<li>对数据集执行特征工程。</li>
<li>训练模型,调整模型的超参数。</li>
<li>对训练结果进行深入分析,并帮助验证导出的模型。检查模型是否确实可以从基础架构提供服务,并防止推送不良模型。</li>
<li>将模型部署到服务基础架构。</li>
</ol>
<p>我想通过以上解释,大家应该可以对机器学习的实践方法有了一定宏观的了解。</p>
<h1 id="机器是如何学习的">机器是如何学习的</h1>
<p>我们从宏观角度看了机器学习的产业结构、工业化流程,你应该对你自己在机器学习的这些环节中有哪些发挥有了一定的把握。现在我们把视角拉回到微观层面,看看机器是如何学习的。</p>
<p>我们以摄氏度转换华氏度为例。<br />
传统编程中,我们要求得摄氏度和华氏度的关系,我们必须找出公式:
\(Fahrenheit = Celsius * 1.8 + 32\)</p>
<p>而在对机器学习来说,我们有大量的数据,却需要找出关系。机器学习的过程就是不断求导,以此来找出数学模型,来解释规律的过程。</p>
<p><img src="/assets/images/20210115/3.png" alt="image" /></p>
<p>如图所示,我们有摄氏度数据0, 8, 15, 22, 38以及华氏度数据32, 46.4, 59, 71.6, 100.4,机器学习的过程就是找出公式的过程。
其中,摄氏度就是我们的<strong>特征</strong>,华氏度就是我们的<strong>标签</strong>,摄氏度与华氏度的关系就是<strong>实例</strong>。</p>
<ul>
<li><strong>特征</strong>:我们模型的输入。 在这种情况下,只有一个值-摄氏度。</li>
<li><strong>标签</strong>:我们的模型预测的输出。 在这种情况下,只有一个值-华氏度。</li>
<li><strong>实例</strong>:训练期间使用的一对输入/输出。 在我们的例子中,是摄氏度/华氏度一对数据,例如,(0, 32), (8, 46.4)。</li>
</ul>
<p>蓝色的部分表示我们设置好数学函数,然后通过不断的调整权重与偏差不断地<strong>拟合</strong>数据,最终得到可以表示规律的<strong>模型</strong>的过程。</p>
<ul>
<li><strong>拟合</strong>:通过训练数据,使模型来概括表示数据的过程。</li>
<li><strong>模型</strong>:图结构,包含了训练过程中的权重与偏差的数据。其中的图为由各函数组成的计算结构。</li>
</ul>
<h1 id="简单上手机器学习代码">简单上手机器学习代码</h1>
<p>在上手代码之前我默认你已经配置好了环境,掌握了Jupyter, Numpy, Pandas, Matplotlib的用法。如果你没有掌握以上技能,请参考我写的配套教程<a href="https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUxMjU4NjI4MQ==&scene=1&album_id=1627166768236412929&count=3#wechat_redirect">前置机器学习系列</a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import numpy as np
import matplotlib.pyplot as plt
celsius = [[-40], [-10], [ 0], [ 8], [15], [22], [ 38]]
fahrenheit = [[-40], [ 14], [32], [46.4], [59], [71.6], [100.4]]
plt.scatter(celsius,fahrenheit, c='red', label='real')
plt.xlabel('celsius')
plt.ylabel('fahrenheit')
plt.legend()
plt.grid(True)
plt.title('real data')
plt.show()
</code></pre></div></div>
<p>如上代码所示,我们准备摄氏度与华氏度的数据,然后通过matplotlib库绘制图像。</p>
<p><img src="/assets/images/20210115/4.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(celsius,fahrenheit)
</code></pre></div></div>
<p>我们通过上方仅仅3行代码就训练了数据。<code class="language-plaintext highlighter-rouge">LinearRegression</code>是scikit-learn包下的线性回归方法,是普通的最小二乘线性回归。而<code class="language-plaintext highlighter-rouge">fit</code>就是拟合的意思,以此来训练模型。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>celsius_test = [[-50],[-30],[10],[20],[50],[70]]
fahrenheit_test = lr.predict(celsius_test)
plt.scatter(celsius,fahrenheit, c='red', label='real')
plt.scatter(celsius_test,fahrenheit_test, c='orange', label='predicted')
plt.xlabel('celsius')
plt.ylabel('fahrenheit')
plt.legend()
plt.grid(True)
plt.title('estimated vs real data')
plt.show()
</code></pre></div></div>
<p>接下来我们调用<code class="language-plaintext highlighter-rouge">lr.predict(celsius_test)</code>方法来进行预测,以此来检验我们的模型准确度。我们通过下方图像中黄色的点可以看出,我们的模型非常准确。</p>
<p><img src="/assets/images/20210115/5.png" alt="image" /></p>
<p><strong>你就说这玩意简单不简单!</strong> 咳咳,别嚣张,我们好好玩。</p>
<h1 id="顺带一提的深度学习代码">顺带一提的深度学习代码</h1>
<p>既然都上手了,我们也试一试深度学习代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import tensorflow as tf
import numpy as np
# prepare data
celsius_q = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float)
fahrenheit_a = np.array([-40, 14, 32, 46.4, 59, 71.6, 100.4], dtype=float)
# fit model
model = tf.keras.Sequential([tf.keras.layers.Dense(units=1, input_shape=[1])])
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1))
history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
print("Finished training the model")
# print loss
import matplotlib.pyplot as plt
plt.xlabel('Epoch Number')
plt.ylabel("Loss Magnitude")
plt.plot(history.history['loss'])
</code></pre></div></div>
<p>我们使用TensorFlow内置的Keras方法创建了1层的神经网络,选择了MSE损失函数以及Adam优化器,训练了500代。</p>
<p>如下图可以看到,随着代(epoch)数量的增加,损失函数的结果逐渐降低。</p>
<p><img src="/assets/images/20210115/6.png" alt="image" /></p>
<p>那么什么是损失函数呢?我们在接下来的文章中一探究竟。感谢您的关注与支持!</p>
<h1 id="前置学习系列">前置学习系列</h1>
<ul>
<li><a href="https://mp.weixin.qq.com/s/5brLPnUP6sYvc-_JO7IzkA">前置机器学习(五):30分钟掌握常用Matplotlib用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/LlLkkBfI-4s3qdVaiv7EdQ">前置机器学习(四):一文掌握Pandas用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/U8dV8ENzzSx_VwBDdJdr_w">前置机器学习(三):30分钟掌握常用NumPy用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/PCGThwI-YD7_hHxO35V8xw">前置机器学习(二):30分钟掌握常用Jupyter Notebook用法</a></li>
<li><a href="https://mp.weixin.qq.com/s/BLxyqK3CGV9yd92yGEs4XQ">前置机器学习(一):数学符号及希腊字母</a></li>
</ul>caiyongjii@caiyongji.com引言 现在市面上的机器学习教程大多先学习数学基础,然后学机器学习的数学算法,再建立机器学习的数学模型,再学习深度学习,再学习工程化,再考虑落地。这其中每个环节都在快速发展,唯独落地特别困难。我们花费大量时间成本去学习以上内容,成本无疑是特别昂贵的。所以我们不如先“盲人摸象”、“不求甚解”地探索下机器学习,浅尝辄止。如果想到自己的应用场景,再学以致用,深入探索。这无疑是使沉没成本最低的决策。 本教程适合兴趣广泛的人士增加自己知识的广度,从应用的角度谨“使用”机器学习这款工具,是典型的黑盒思维。这非常契合笔者的思维方式,当然也是我个人的格局局限。 本教程会浅显易懂,让你走的很快。但如果你想走的更远还请学习数学。当然我们也只是暂时放下数学,先构建自己的知识体系。 先抬头看路,找准适合自己的方向,再埋头赶路,或深耕下去…… 把视角拉高 从手工到工业化再到人工智能,这是把人类从生产活动中逐渐解放的过程。用机器来帮助人们工作,一直是人类的美好愿望。让机器智能化,以此来代替人力做更智能问题,这可以作为人工智能的简单解释。 很多教程或者书籍把人工智能、机器学习、深度学习的关系解释为从属关系,人工智能 > 机器学习 > 深度学习。这种解释不错,但却无法表示他们之间的更深层次的关系。 机器学习是通过数学方法在数据中寻找解释,以此来实现人工智能的一种手段。而深度学习是参照神经系统在机器学习基础上发展出的一种高级技巧。 它们之间是存在一定的依托关系、进化趋势的。 狭义地讲,传统的机器学习是通过数学模型不断求导来找出数据规律的过程。这其中数学模型的选择尤为重要。随着GPU、TPU等算力的发展,算法技术的进步,甚至出现了自动选模型、自动调参的技术。我们可以构建复杂的神经网络结构,只要有足够的算力支持,足够的时间我们可以用深度学习处理非常复杂的任务。所以在代码操作上,深度学习甚至比传统的机器学习对程序员更友好、更易理解。我们先学习传统机器学习而非直接学习深度学习的好处是,我们可以通过对“黑盒”的拆箱来理解机器学习过程,掌握机器学习的概念,我会对其中应用的数学模型进行解释。 我们先来看一下人工智能产业链的结构,如下图: 我们可以看到,机器学习的三大基石—算力、算法与数据。机器学习的发展离不开算法数学的进步,同样离不开算力的发展。 在技术层面,机器学习在计算机视觉(CV, Computer Vision)和自然语言处理(NLP, Nature Language Processing)取得了关键的发展和应用。 算法分类上,机器学习分为监督学习、非监督学习、半监督学习、强化学习等。 监督学习:数据样本有标签。 非监督学习:数据样本无标签。 半监督学习:数据样本有部分(少量)标签。 强化学习:趋向结果则奖励,偏离结果则惩罚。 所谓Garbage in, Garbage out(垃圾进,垃圾出)。数据是机器学习的重中之重。我们需要花费大量的时间来处理数据,甚至占到整个机器学习任务的90%以上。 比如数据处理过程中的数据采集,如果我们采样的方式欠妥,就可能导致非代表性的数据集,这就导致了采样偏差。 我们的数据可能会有很多无效的数据,我们需要剔除无效的数据,就叫做数据清洗。 我们通过挖掘大量数据来发现不太明显的规律,就称作数据挖掘。 机器学习工业化流程 我们以一款工业化流水线工具TFX为例,看一下机器学习的技术流程。 流程分为数据输入、数据验证、特征工程、训练模型、验证模型、应用良好模型和提供模型六个部分: 输入数据,并根据需要拆分数据集。 生成训练数据和服务数据的特征统计信息。通过从训练数据中推断出类型、类别和范围来创建架构。识别训练数据和服务数据中的异常值。 对数据集执行特征工程。 训练模型,调整模型的超参数。 对训练结果进行深入分析,并帮助验证导出的模型。检查模型是否确实可以从基础架构提供服务,并防止推送不良模型。 将模型部署到服务基础架构。 我想通过以上解释,大家应该可以对机器学习的实践方法有了一定宏观的了解。 机器是如何学习的 我们从宏观角度看了机器学习的产业结构、工业化流程,你应该对你自己在机器学习的这些环节中有哪些发挥有了一定的把握。现在我们把视角拉回到微观层面,看看机器是如何学习的。 我们以摄氏度转换华氏度为例。 传统编程中,我们要求得摄氏度和华氏度的关系,我们必须找出公式: \(Fahrenheit = Celsius * 1.8 + 32\) 而在对机器学习来说,我们有大量的数据,却需要找出关系。机器学习的过程就是不断求导,以此来找出数学模型,来解释规律的过程。 如图所示,我们有摄氏度数据0, 8, 15, 22, 38以及华氏度数据32, 46.4, 59, 71.6, 100.4,机器学习的过程就是找出公式的过程。 其中,摄氏度就是我们的特征,华氏度就是我们的标签,摄氏度与华氏度的关系就是实例。 特征:我们模型的输入。 在这种情况下,只有一个值-摄氏度。 标签:我们的模型预测的输出。 在这种情况下,只有一个值-华氏度。 实例:训练期间使用的一对输入/输出。 在我们的例子中,是摄氏度/华氏度一对数据,例如,(0, 32), (8, 46.4)。 蓝色的部分表示我们设置好数学函数,然后通过不断的调整权重与偏差不断地拟合数据,最终得到可以表示规律的模型的过程。 拟合:通过训练数据,使模型来概括表示数据的过程。 模型:图结构,包含了训练过程中的权重与偏差的数据。其中的图为由各函数组成的计算结构。 简单上手机器学习代码 在上手代码之前我默认你已经配置好了环境,掌握了Jupyter, Numpy, Pandas, Matplotlib的用法。如果你没有掌握以上技能,请参考我写的配套教程前置机器学习系列 import numpy as np import matplotlib.pyplot as plt celsius = [[-40], [-10], [ 0], [ 8], [15], [22], [ 38]] fahrenheit = [[-40], [ 14], [32], [46.4], [59], [71.6], [100.4]] plt.scatter(celsius,fahrenheit, c='red', label='real') plt.xlabel('celsius') plt.ylabel('fahrenheit') plt.legend() plt.grid(True) plt.title('real data') plt.show() 如上代码所示,我们准备摄氏度与华氏度的数据,然后通过matplotlib库绘制图像。 from sklearn.linear_model import LinearRegression lr = LinearRegression() lr.fit(celsius,fahrenheit) 我们通过上方仅仅3行代码就训练了数据。LinearRegression是scikit-learn包下的线性回归方法,是普通的最小二乘线性回归。而fit就是拟合的意思,以此来训练模型。 celsius_test = [[-50],[-30],[10],[20],[50],[70]] fahrenheit_test = lr.predict(celsius_test) plt.scatter(celsius,fahrenheit, c='red', label='real') plt.scatter(celsius_test,fahrenheit_test, c='orange', label='predicted') plt.xlabel('celsius') plt.ylabel('fahrenheit') plt.legend() plt.grid(True) plt.title('estimated vs real data') plt.show() 接下来我们调用lr.predict(celsius_test)方法来进行预测,以此来检验我们的模型准确度。我们通过下方图像中黄色的点可以看出,我们的模型非常准确。 你就说这玩意简单不简单! 咳咳,别嚣张,我们好好玩。 顺带一提的深度学习代码 既然都上手了,我们也试一试深度学习代码: import tensorflow as tf import numpy as np # prepare data celsius_q = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float) fahrenheit_a = np.array([-40, 14, 32, 46.4, 59, 71.6, 100.4], dtype=float) # fit model model = tf.keras.Sequential([tf.keras.layers.Dense(units=1, input_shape=[1])]) model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1)) history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False) print("Finished training the model") # print loss import matplotlib.pyplot as plt plt.xlabel('Epoch Number') plt.ylabel("Loss Magnitude") plt.plot(history.history['loss']) 我们使用TensorFlow内置的Keras方法创建了1层的神经网络,选择了MSE损失函数以及Adam优化器,训练了500代。 如下图可以看到,随着代(epoch)数量的增加,损失函数的结果逐渐降低。 那么什么是损失函数呢?我们在接下来的文章中一探究竟。感谢您的关注与支持! 前置学习系列 前置机器学习(五):30分钟掌握常用Matplotlib用法 前置机器学习(四):一文掌握Pandas用法 前置机器学习(三):30分钟掌握常用NumPy用法 前置机器学习(二):30分钟掌握常用Jupyter Notebook用法 前置机器学习(一):数学符号及希腊字母2021,新世界!2020-12-31T00:00:00+00:002020-12-31T00:00:00+00:00https://blog.caiyongji.com/2020/12/31/2021-new-world<blockquote>
<p>如果我们不能击败它,就必须与之共存。</p>
</blockquote>
<p><strong>随便聊聊。文末有红包🧧现金💰书籍📖赠送。</strong></p>
<p>新冠病毒正在彻底改变世界,人类与之斗争,没有人敢断言结果。我们做职业规划、人生规划时,要重新考虑风险。</p>
<h1 id="中国崛起">中国崛起</h1>
<p><strong>IMF预计,中国是2020年全球唯一一个经济正增长的主要经济体。</strong></p>
<p>中国在悠悠的历史长河中,一直不是以民主为核心的。我们受孔孟思想的影响深远,我们尊师重道,信仰真理,追随权威。当面对灾难时,这尤其有效,我们让最有能力的人做决定,听从他的一切指挥,脱离困境。这是人民出让权力,政府执行软强制主义的典型方式。它显然比所谓的“可操控的民主”更高级,更何况随着社会的进步,中国在一点点将人民的权力归还给人民。这种信任让中国人比任何国家都团结,我们认准的方向,都是无人能挡的,无论对错。</p>
<p>这让中国的拳头是最硬的。</p>
<p>当然中国有中国的问题,但无疑我们不该忽略中国巨大的优势。疫情前很多有钱的朋友在讲海外资产配置,现在在考虑把热钱留在中国。我想很大的原因就是因为中国更安全。我听说某个F家的朋友一直远程办公,2020年初去三亚度假,然后全年在三亚工作(度假)。</p>
<h1 id="行业变化">行业变化</h1>
<p>谈生活之前不得不谈行业。</p>
<p>虽然很多传统行业不得不需要线下人员参与,但我相信我的读者大多偏向于互联网、IT、软件产业。我们有脱离线下转到线上的机会,这是我们的优势,我们可以坦然的承认这一点。</p>
<p>传统行业,比如农行、制造业重要吗?相当重要。但我们过了只追求吃饱穿暖的阶段了,我们有了更高的追求,我们扬帆起航追求的是星辰大海……</p>
<p>有人说,没人种田你们所有人都会饿死。其实不是的,这只是固守在传统行业上的人的嫉妒罢了。如果真的没人种田了,国家会有统一的、机械的、标准化的农耕方式来代替人力。这时多余的人力还是要转移到新兴的行业上去。这只是时间早晚的问题。历史的车轮没有任何人可以阻止,我们顺应着时代才能让自己过的更好。</p>
<p>这个世界不惩罚墨守成规的人,它会只奖励那些拥抱变化的人,渐渐地那些站在原地的人就被多数人落下了。举个简单的例子,我们不惩罚单身的人,但会给有孩子的人减免个税。</p>
<p><strong>快递、外卖、远程会议,网课、网红、直播带货。</strong> 这些是2020年新钱的主要流向的典型例子。直播经济、网红经济、娱乐经济,很多人对此是嗤之以鼻的,我只是想说我们别着急否定他们,有时候困住你的恰恰是你自己的旧思想,那些条条框框。如果我说有些人一年赚到的钱是别人300年赚到的钱呢?或许他们的收入不稳定,但你能活到300岁吗?</p>
<p>虽然个例不代表整个行业,但它能代表行业趋势。有时候我们承认别人优秀,才能自己和自己真正地和解。</p>
<h1 id="生活变化">生活变化</h1>
<p>再具体到生活谈变化。</p>
<p>还记得2010年的主流手机是什么?没错,10年前诺基亚还是大哥,流量1M一块钱。10年后的今天,流量1G一块钱,人们实时语音,视频通话。很多没等官方通报,视频已经在群里传飞起来了。<br />
今年(2020年)我在的园区场地着火,先是日本的朋友发给我的消息,我才抬头看到窗外的浓烟。不查领导酒驾的交警,不戴口罩防疫的干部,不让群众使用卫生间的机关,10年前没人想到贪腐是靠互联网整治的。信息的超快速传输已经彻底改变了我们的生活。中国山区田园生活的景象可以传到纽约,我们可以看卖翡翠的演员忍痛割爱,甚至远隔万里的情侣也可以有别样的情趣……咳咳。</p>
<p>沟通的方式变了,购物的方式变了。我们的世界变好了也变坏了,但绝对和以前不一样了。也许有些技术并不稀奇,几年甚至几十年前就有了,但以前成本高昂,现在普及量产还可以再送你两桶都有,让普通百姓用得起了,这就很了不起。我看到一个短视频里,有学生被叫到黑板前做题,下面的同学用蓝牙耳机偷偷告诉他答案了。</p>
<p>我终于可以说那句话了,<strong>你的孩子生活在你永远无法想象的未来,你甚至连做梦都梦不到。</strong></p>
<blockquote>
<p>Your children are not your children.<br />
They are the sons and daughters of Life’s longing for itself.<br />
They come through you but not from you,<br />
And though they are with you, yet they belong not to you.<br />
You may give them your love but not your thoughts,<br />
For they have their own thoughts.<br />
You may house their bodies but not their souls,<br />
For their souls dwell in the house of tomorrow,<br />
which you cannot visit, not even in your dreams.</p>
</blockquote>
<p>—Kahlil Gibran</p>
<h1 id="拥抱变化">拥抱变化</h1>
<p>我表达一下我自己浅薄的看法,为了让意见有更多参考的价值,我不会说一些模棱两可却正确的话。我的表述可能不严谨、很狭隘,但应该会很直接、很有用。如果你发现我语言或逻辑上的漏洞请参考互联网上的其他知识自行判断,兼听则明。每个道理都有其有限的作用范围,也跟每个人的认知偏差有关,不能一概而论,也无需争论对错。</p>
<p><strong>世界看中国,中国看北京。</strong></p>
<p>随着“内循环”政策的提出,北京的地位变得更加重要,超过了长三角、珠三角经济区的地位。无疑是老大中的老大。以后北京无疑是中国天花板最高的城市。</p>
<p>选择城市就像爬山,在爬之前你并不知道你能爬多高,但如果你足够优秀,你在一个小山头很容易爬到山顶,当你想换一座山的时候,成本无疑是非常高的。一线城市有更多、更好的机会,它们永远有足够大的舞台让你发挥。如果不是舞台不够大,是你不够强,或者你不想去争名逐利,二三线甚至十八线城市也可以让人活得很舒服。</p>
<p>抛下北京不谈,我认为新的城市优先级会从南到北排序,深圳、环深圳、上海、环上海、海南。</p>
<p><strong>线下转线上。</strong></p>
<p>如果你有机会一定要让自己尽量的靠近线上。跟着新钱走,有机会。远离实体接触,更安全。脱离坐班,更自由。</p>
<p>而时间自由是实现财务自由的第一步。</p>
<p>线上的机会太多了,大家尽量选择门槛高的,能发挥自己优势的领域。一是避免过分竞争,杀入一片红海,生存还是很难的。二是用自己的特长、高门槛来构建壁垒,让自己有竞争力,可以持续发展,而不是一锤子买卖。</p>
<p><strong>你自己独一无二的灵感。</strong></p>
<p>试试呗?加油。</p>
<h1 id="ai未来">AI未来</h1>
<p>目前,<strong>人工智能非常适合简单的、重复性的工作。</strong></p>
<p>AI在医学领域有大量的应用,但它无法代替医生,很长一段时间内都不可能。AI在自动驾驶领域有高速的发展,但它无法代替司机,小范围的有限条件下后续可以,但无法普及。AI还没有强大到代替专业的人,但它可以做为辅助手段帮助专家,节省专家的精力。</p>
<p>在可以预见的未来,AI会取代那些低技术含量、做重复工作的劳动力。理由很简单,AI不用保险、AI不会抱怨、AI不用休息,无需年假、奖金。AI稳定且高效,它不会因为与老婆吵架而工作不在状态,也不会因为连续工作24小时而效率下降,甚至AI可以在毫秒级内做出人类无法做出的连续反应。</p>
<p>比如公务员、银行职员。目前很多大银行推出的无人银行的概念已经足够说明了,这点我就不具体说了。说说公务员,我指的是公务员中那些技术含量低的工作,也就是那些所谓的钱多事少的工作。越是容易的、简单的工作越容易被取代,以后追求稳定可以,太清闲就别想了,提升自己的一技之长才是正道。我为什么这么说呢,因为我已经见到有AI公司和政府部门洽谈合作了。</p>
<p><em>(注意:每种职业都有不可替代的努力的、勤奋的人,我尊重每一个职业。上文单单指价值产出少,可替代性强的工作内容。)</em></p>
<p><strong>打工人还是打工人,工具人终被工具替代。</strong></p>
<h1 id="拥抱ai">拥抱AI</h1>
<p>其实你问问中国最优秀的那批人,世界将会怎样?他们也不知道。唯一可以确定的是,没人可以阻挡世界的发展,除了顺从你别无选择。AI正在取代一些人的工作,虽然残酷,但这是事实。</p>
<p>有人觉得AI是博士、研究生从事的行业,至少要有计算机,数学的背景。一提数学就头大。其实大可不必。2020年5月,韩国TFUG邀请谷歌的AI主管Laurence Moroney进行了一次采访,我有幸听到他对AI的看法,我这里简单翻译下他的意思,并不是他的原话。</p>
<blockquote>
<p>很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。</p>
</blockquote>
<p><em>参考Youtube 4分06秒:<a href="https://www.youtube.com/watch?v=8kMaqQNubNA">https://www.youtube.com/watch?v=8kMaqQNubNA</a></em></p>
<p>其实,对于先避开数学接触机器学习,再试着深入了解原理,这种方式我是非常认可的。我们不见得要跑到所有人的最前面,我们勇敢的往这个方向走就可以了。先当“调包侠”如果有机会再当“调参侠”也是不错的选择。</p>
<p>我正在写这方面的教程,我的方式就是先避开数学,先看看机器学习究竟长什么样,再去深入它的理论。<strong>大家可以关注我,公众号【caiyongji】</strong>,2021年我会不断的更新AI方向的原创文章,包括人工智能科普、机器学习教程。</p>
<h1 id="说回新冠">说回新冠</h1>
<p>早在2月份的时候我看了朋友给我发的关于新冠病毒的论文,它和艾滋病有着某种程度的相似,我想了想最近几十年来医学界在艾滋病领域的发展,说实话,我是悲观的。随着欧洲病毒的变异,我想我们真的需要认真对待,做好与之长期相处的准备。世界正在改变,2021年的新世界,我们要顺应新的规则。<strong>先保护好自己,再来爱这个世界。</strong></p>
<h1 id="爱惜自己">爱惜自己</h1>
<p>大家可以选择996,但一定要记得爱惜自己。我们不知道明天和死亡哪个先来。</p>
<p>我们要学会使用工具,而不是把自己变成工具。在工作中,大家要学聪明一点,不要做那些低价值的重复性的工作,也就是说,少做打杂的工作让自己沦为工具人。要想着在工作中,哪些技能是你能带走的,<strong>自己能带走的本事才是真的本事</strong>。历练自己,就是要挑着那些能带走的技能历练,不要挑那些谁都能干的任务,不要把自己当作一颗螺丝钉。</p>
<p>有人可能会说,这样会不会太自私了?兄弟,我巴不得你们自私一点,你可以为了自己拼命,可以为了家人拼命,唯独不要为资本拼命。某种程度上来说,为资本拼命害人害己。</p>
<p>中国每天都在有造富的神话,让人们都心浮气躁了。其实你看的新闻全都是小概率事件。新闻之所以是新闻,正是因为它不常见所以人们才爱看。你身边整天充斥的消息,并不是这个世界的真相。</p>
<p>有些人不信命,总想带着天涯海角的辽阔期待着一个奇迹。我劝大家不要相信奇迹,相信什么自己是天选之人。<strong>我说的命不是指命运,而是指你能力的上限。</strong> 我们要做那些大概率成功的事情,而不是去搏一个小概率。中国教育真正牛的地方在于,它能把那些资质平庸的人培养成可用的人才,让那些没有天赋的人也有机会展示自己。</p>
<p>我不是叫你不去努力,努力可以,但要留有退路。不要跟自己较劲,更不要透支自己的一切去赌明天。稳步向前,别急。</p>
<p>珍惜眼前,跟自己和解。</p>
<h1 id="祝福">祝福</h1>
<p>我祝你2021年一切顺利!新年快乐!</p>
<p>本文同步于公众号【caiyongji】,<a href="https://mp.weixin.qq.com/s/x0SpRfGTfGfQ_UPcNaGr5w">原文文末</a>有红包🧧现金💰书籍📖赠送。</p>caiyongjii@caiyongji.com如果我们不能击败它,就必须与之共存。 随便聊聊。文末有红包🧧现金💰书籍📖赠送。 新冠病毒正在彻底改变世界,人类与之斗争,没有人敢断言结果。我们做职业规划、人生规划时,要重新考虑风险。 中国崛起 IMF预计,中国是2020年全球唯一一个经济正增长的主要经济体。 中国在悠悠的历史长河中,一直不是以民主为核心的。我们受孔孟思想的影响深远,我们尊师重道,信仰真理,追随权威。当面对灾难时,这尤其有效,我们让最有能力的人做决定,听从他的一切指挥,脱离困境。这是人民出让权力,政府执行软强制主义的典型方式。它显然比所谓的“可操控的民主”更高级,更何况随着社会的进步,中国在一点点将人民的权力归还给人民。这种信任让中国人比任何国家都团结,我们认准的方向,都是无人能挡的,无论对错。 这让中国的拳头是最硬的。 当然中国有中国的问题,但无疑我们不该忽略中国巨大的优势。疫情前很多有钱的朋友在讲海外资产配置,现在在考虑把热钱留在中国。我想很大的原因就是因为中国更安全。我听说某个F家的朋友一直远程办公,2020年初去三亚度假,然后全年在三亚工作(度假)。 行业变化 谈生活之前不得不谈行业。 虽然很多传统行业不得不需要线下人员参与,但我相信我的读者大多偏向于互联网、IT、软件产业。我们有脱离线下转到线上的机会,这是我们的优势,我们可以坦然的承认这一点。 传统行业,比如农行、制造业重要吗?相当重要。但我们过了只追求吃饱穿暖的阶段了,我们有了更高的追求,我们扬帆起航追求的是星辰大海…… 有人说,没人种田你们所有人都会饿死。其实不是的,这只是固守在传统行业上的人的嫉妒罢了。如果真的没人种田了,国家会有统一的、机械的、标准化的农耕方式来代替人力。这时多余的人力还是要转移到新兴的行业上去。这只是时间早晚的问题。历史的车轮没有任何人可以阻止,我们顺应着时代才能让自己过的更好。 这个世界不惩罚墨守成规的人,它会只奖励那些拥抱变化的人,渐渐地那些站在原地的人就被多数人落下了。举个简单的例子,我们不惩罚单身的人,但会给有孩子的人减免个税。 快递、外卖、远程会议,网课、网红、直播带货。 这些是2020年新钱的主要流向的典型例子。直播经济、网红经济、娱乐经济,很多人对此是嗤之以鼻的,我只是想说我们别着急否定他们,有时候困住你的恰恰是你自己的旧思想,那些条条框框。如果我说有些人一年赚到的钱是别人300年赚到的钱呢?或许他们的收入不稳定,但你能活到300岁吗? 虽然个例不代表整个行业,但它能代表行业趋势。有时候我们承认别人优秀,才能自己和自己真正地和解。 生活变化 再具体到生活谈变化。 还记得2010年的主流手机是什么?没错,10年前诺基亚还是大哥,流量1M一块钱。10年后的今天,流量1G一块钱,人们实时语音,视频通话。很多没等官方通报,视频已经在群里传飞起来了。 今年(2020年)我在的园区场地着火,先是日本的朋友发给我的消息,我才抬头看到窗外的浓烟。不查领导酒驾的交警,不戴口罩防疫的干部,不让群众使用卫生间的机关,10年前没人想到贪腐是靠互联网整治的。信息的超快速传输已经彻底改变了我们的生活。中国山区田园生活的景象可以传到纽约,我们可以看卖翡翠的演员忍痛割爱,甚至远隔万里的情侣也可以有别样的情趣……咳咳。 沟通的方式变了,购物的方式变了。我们的世界变好了也变坏了,但绝对和以前不一样了。也许有些技术并不稀奇,几年甚至几十年前就有了,但以前成本高昂,现在普及量产还可以再送你两桶都有,让普通百姓用得起了,这就很了不起。我看到一个短视频里,有学生被叫到黑板前做题,下面的同学用蓝牙耳机偷偷告诉他答案了。 我终于可以说那句话了,你的孩子生活在你永远无法想象的未来,你甚至连做梦都梦不到。 Your children are not your children. They are the sons and daughters of Life’s longing for itself. They come through you but not from you, And though they are with you, yet they belong not to you. You may give them your love but not your thoughts, For they have their own thoughts. You may house their bodies but not their souls, For their souls dwell in the house of tomorrow, which you cannot visit, not even in your dreams. —Kahlil Gibran 拥抱变化 我表达一下我自己浅薄的看法,为了让意见有更多参考的价值,我不会说一些模棱两可却正确的话。我的表述可能不严谨、很狭隘,但应该会很直接、很有用。如果你发现我语言或逻辑上的漏洞请参考互联网上的其他知识自行判断,兼听则明。每个道理都有其有限的作用范围,也跟每个人的认知偏差有关,不能一概而论,也无需争论对错。 世界看中国,中国看北京。 随着“内循环”政策的提出,北京的地位变得更加重要,超过了长三角、珠三角经济区的地位。无疑是老大中的老大。以后北京无疑是中国天花板最高的城市。 选择城市就像爬山,在爬之前你并不知道你能爬多高,但如果你足够优秀,你在一个小山头很容易爬到山顶,当你想换一座山的时候,成本无疑是非常高的。一线城市有更多、更好的机会,它们永远有足够大的舞台让你发挥。如果不是舞台不够大,是你不够强,或者你不想去争名逐利,二三线甚至十八线城市也可以让人活得很舒服。 抛下北京不谈,我认为新的城市优先级会从南到北排序,深圳、环深圳、上海、环上海、海南。 线下转线上。 如果你有机会一定要让自己尽量的靠近线上。跟着新钱走,有机会。远离实体接触,更安全。脱离坐班,更自由。 而时间自由是实现财务自由的第一步。 线上的机会太多了,大家尽量选择门槛高的,能发挥自己优势的领域。一是避免过分竞争,杀入一片红海,生存还是很难的。二是用自己的特长、高门槛来构建壁垒,让自己有竞争力,可以持续发展,而不是一锤子买卖。 你自己独一无二的灵感。 试试呗?加油。 AI未来 目前,人工智能非常适合简单的、重复性的工作。 AI在医学领域有大量的应用,但它无法代替医生,很长一段时间内都不可能。AI在自动驾驶领域有高速的发展,但它无法代替司机,小范围的有限条件下后续可以,但无法普及。AI还没有强大到代替专业的人,但它可以做为辅助手段帮助专家,节省专家的精力。 在可以预见的未来,AI会取代那些低技术含量、做重复工作的劳动力。理由很简单,AI不用保险、AI不会抱怨、AI不用休息,无需年假、奖金。AI稳定且高效,它不会因为与老婆吵架而工作不在状态,也不会因为连续工作24小时而效率下降,甚至AI可以在毫秒级内做出人类无法做出的连续反应。 比如公务员、银行职员。目前很多大银行推出的无人银行的概念已经足够说明了,这点我就不具体说了。说说公务员,我指的是公务员中那些技术含量低的工作,也就是那些所谓的钱多事少的工作。越是容易的、简单的工作越容易被取代,以后追求稳定可以,太清闲就别想了,提升自己的一技之长才是正道。我为什么这么说呢,因为我已经见到有AI公司和政府部门洽谈合作了。 (注意:每种职业都有不可替代的努力的、勤奋的人,我尊重每一个职业。上文单单指价值产出少,可替代性强的工作内容。) 打工人还是打工人,工具人终被工具替代。 拥抱AI 其实你问问中国最优秀的那批人,世界将会怎样?他们也不知道。唯一可以确定的是,没人可以阻挡世界的发展,除了顺从你别无选择。AI正在取代一些人的工作,虽然残酷,但这是事实。 有人觉得AI是博士、研究生从事的行业,至少要有计算机,数学的背景。一提数学就头大。其实大可不必。2020年5月,韩国TFUG邀请谷歌的AI主管Laurence Moroney进行了一次采访,我有幸听到他对AI的看法,我这里简单翻译下他的意思,并不是他的原话。 很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。 参考Youtube 4分06秒:https://www.youtube.com/watch?v=8kMaqQNubNA 其实,对于先避开数学接触机器学习,再试着深入了解原理,这种方式我是非常认可的。我们不见得要跑到所有人的最前面,我们勇敢的往这个方向走就可以了。先当“调包侠”如果有机会再当“调参侠”也是不错的选择。 我正在写这方面的教程,我的方式就是先避开数学,先看看机器学习究竟长什么样,再去深入它的理论。大家可以关注我,公众号【caiyongji】,2021年我会不断的更新AI方向的原创文章,包括人工智能科普、机器学习教程。 说回新冠 早在2月份的时候我看了朋友给我发的关于新冠病毒的论文,它和艾滋病有着某种程度的相似,我想了想最近几十年来医学界在艾滋病领域的发展,说实话,我是悲观的。随着欧洲病毒的变异,我想我们真的需要认真对待,做好与之长期相处的准备。世界正在改变,2021年的新世界,我们要顺应新的规则。先保护好自己,再来爱这个世界。 爱惜自己 大家可以选择996,但一定要记得爱惜自己。我们不知道明天和死亡哪个先来。 我们要学会使用工具,而不是把自己变成工具。在工作中,大家要学聪明一点,不要做那些低价值的重复性的工作,也就是说,少做打杂的工作让自己沦为工具人。要想着在工作中,哪些技能是你能带走的,自己能带走的本事才是真的本事。历练自己,就是要挑着那些能带走的技能历练,不要挑那些谁都能干的任务,不要把自己当作一颗螺丝钉。 有人可能会说,这样会不会太自私了?兄弟,我巴不得你们自私一点,你可以为了自己拼命,可以为了家人拼命,唯独不要为资本拼命。某种程度上来说,为资本拼命害人害己。 中国每天都在有造富的神话,让人们都心浮气躁了。其实你看的新闻全都是小概率事件。新闻之所以是新闻,正是因为它不常见所以人们才爱看。你身边整天充斥的消息,并不是这个世界的真相。 有些人不信命,总想带着天涯海角的辽阔期待着一个奇迹。我劝大家不要相信奇迹,相信什么自己是天选之人。我说的命不是指命运,而是指你能力的上限。 我们要做那些大概率成功的事情,而不是去搏一个小概率。中国教育真正牛的地方在于,它能把那些资质平庸的人培养成可用的人才,让那些没有天赋的人也有机会展示自己。 我不是叫你不去努力,努力可以,但要留有退路。不要跟自己较劲,更不要透支自己的一切去赌明天。稳步向前,别急。 珍惜眼前,跟自己和解。 祝福 我祝你2021年一切顺利!新年快乐! 本文同步于公众号【caiyongji】,原文文末有红包🧧现金💰书籍📖赠送。