<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>happybai (天亮Byron)</title>
    <link>https://ruby-china.org/happybai</link>
    <description>I'm a genius.</description>
    <language>en-us</language>
    <item>
      <title>[踩坑 / 分享] Ruby 机器学习尝试 — 训练 Atari (雅达利) 打弹球游戏 AI</title>
      <description>&lt;p&gt;众所周知 Ruby 的机器学习一直是相对弱势的区域，那么它的表现究竟如何呢？本文通过尝试实现一个相对复杂的机器学习算法（DQN）来踩一遍在 Ruby 环境下使用机器学习遇到的坑。由于各式各样的坑，最终 Ruby 版本只完成了模型的 80% 且部分核心依旧借助了 Python。而且因为效率问题，最后也无法真正训练出效果，不过即便如此还是分享出来让大家了解一下吧。&lt;/p&gt;

&lt;p&gt;Python 版源码：&lt;a href="https://github.com/happybai/atari-agents" rel="nofollow" target="_blank"&gt;https://github.com/happybai/atari-agents&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ruby 实验源码：&lt;a href="https://github.com/happybai/atari-agents-rb" rel="nofollow" target="_blank"&gt;https://github.com/happybai/atari-agents-rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Atari 游戏环境 Ruby 接口：&lt;a href="https://github.com/happybai/ale_ruby_interface" rel="nofollow" target="_blank"&gt;https://github.com/happybai/ale_ruby_interface&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;（下图为 Python 版本算法用 CPU 训练 1 个小时的结果）&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2018/6be5a751-93d1-487d-a02c-b9ead58232b3.gif!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="一、Atari（雅达利） 训练环境准备"&gt;一、Atari（雅达利）训练环境准备&lt;/h2&gt;
&lt;p&gt;坑一：缺乏相应环境或相应环境的 Ruby 实现。&lt;/p&gt;

&lt;p&gt;很多机器学习的用例都会提供一个学习环境来方便大家来做研究比如，atari 的环境 &lt;a href="https://github.com/mgbellemare/Arcade-Learning-Environment" rel="nofollow" target="_blank" title=""&gt;Arcade-Learning-Environment&lt;/a&gt;，增强学习算法的环境 &lt;a href="https://github.com/openai/gym" rel="nofollow" target="_blank" title=""&gt;gym&lt;/a&gt;, 星际争霸 2 的学习环境 &lt;a href="https://github.com/deepmind/pysc2" rel="nofollow" target="_blank" title=""&gt;pysc2&lt;/a&gt;。这些环境基本都是 C++ 加上 Python 的接口，或者只有 Python 的版本。好在很多真正有效率的机器学习的库其实都是 C++ 为核心加上 Python 做为接口。本例子中也是以 Arcade-Learning-Environment 为核心，制作了 Ruby 的调用接口 &lt;a href="https://github.com/happybai/ale_ruby_interface" rel="nofollow" target="_blank" title=""&gt;ale_ruby_interface&lt;/a&gt;，来实现了训练的环境。是的，这样就可以用 Ruby 玩 Atari 游戏了！&lt;/p&gt;
&lt;h2 id="二、相关 Ruby 机器学习库的准备"&gt;二、相关 Ruby 机器学习库的准备&lt;/h2&gt;
&lt;p&gt;坑二：主流 Ruby 机器学习库活跃低，更新缓慢，文档不全，不研究一下连装都装不上。&lt;/p&gt;

&lt;p&gt;这个例子里用到了两个机器学习的库 &lt;a href="https://github.com/SciRuby/nmatrix" rel="nofollow" target="_blank" title=""&gt;NMatrix&lt;/a&gt; 和  Tensorflow 的 Ruby 实现 &lt;a href="https://github.com/somaticio/tensorflow.rb" rel="nofollow" target="_blank" title=""&gt;tensorflow.rb&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;其中 NMatrix 的安装就遇到了问题 &lt;a href="https://github.com/SciRuby/nmatrix/issues/591" rel="nofollow" target="_blank"&gt;https://github.com/SciRuby/nmatrix/issues/591&lt;/a&gt; 且不支持高版本的 gcc 编译。&lt;/p&gt;

&lt;p&gt;tensorflow.rb 的原理也仅仅是 Ruby 调用 Tensorflow 的 C++ 文件。需要 &lt;a href="https://docs.bazel.build/versions/master/install.html" rel="nofollow" target="_blank" title=""&gt;Bazel&lt;/a&gt; 来编译，通过 &lt;a href="http://www.swig.org/download.html" rel="nofollow" target="_blank" title=""&gt;swig&lt;/a&gt; 来调用，安装起来也相对复杂。&lt;/p&gt;
&lt;h2 id="三、构建 Tensorflow 算法图"&gt;三、构建 Tensorflow 算法图&lt;/h2&gt;
&lt;p&gt;Tensorflow 的基本思想是构建一个算法图，然后加载到 Session 里运行。那么图的构建是 Tensorflow 中非常重要的一步，tensorflow.rb 自然也提供了这部分功能。但是（坑三：tensorflow.rb 提供 api 太少，且文档和错误提示不足）仅仅实现了最核心的部分，所有操作仅通过一个方法 AddOperation 来进行的。具体使用方法，只能去看 Tensorflow 的文档和源码来猜。最关键的是 — &lt;strong&gt;没有错误提示！&lt;/strong&gt;。参数错了只会报内存溢出。最终我还是放弃了在 Ruby 里进行图的构建，不过好在 tensorflow.rb 里提供了加载已经构建完毕图的方法（实际上 tensorflow.rb 自己的例子也是加载现成的图文件）。所以最终我还是选择从 Python 版本把算法图导出成文件（&lt;a href="https://github.com/google/protobuf" rel="nofollow" target="_blank" title=""&gt;protobuf&lt;/a&gt; 格式），再通过 Ruby 导入，来完成运算图的构建。&lt;/p&gt;
&lt;h2 id="四、数据预处理"&gt;四、数据预处理&lt;/h2&gt;
&lt;p&gt;除了核心图的构建，很多数据的预处理也是构成算法的重要的组成部分，比如本例子中的 History、Memory 类、图片的转换，各种矩阵的 reshape，将训练的结果录成视频。这方面 Ruby 差距就不是很明显了，相反比之 Python 还更顺手一些，只是（坑四：NMatrix 的效率应该不是很好）NMatrix 处理大矩阵效率好像有些差。最终运行的时候效率还不到 Python 版本的 1%，不过关于效率的问题，也有部分原因是有些库我没找到对应的 Ruby 版本就自己随便实现了下，忽略这部分的差距，初步估计应该至少能达到 python 的 10%。&lt;/p&gt;
&lt;h2 id="五、开始训练"&gt;五、开始训练&lt;/h2&gt;
&lt;p&gt;除了上面的效率问题，我刚开始训练模型的时候，跑了 10 分钟后突然就内存溢出了（坑五：由于 Ruby 会经常和 C++ 的库进行交互，不成熟的库动不动就内存溢出，且原因很难查找）。最后原因也许是 tensorflow.rb 的一个 &lt;a href="https://github.com/somaticio/tensorflow.rb/issues/106" rel="nofollow" target="_blank" title=""&gt;bug&lt;/a&gt; 。总之修改了 tensorflow.rb 中的一行源码，重新编译安装后。就解决了这个问题。但这种错误真心及其难调试。最终这个模型终于可以稳定训练了，不过由于效率问题以及其他因素，所以并不会有效果。即便如此，也算是跑了一个相对完整的算法了。&lt;/p&gt;
&lt;h2 id="六、使用训练后的成熟模型"&gt;六、使用训练后的成熟模型&lt;/h2&gt;
&lt;p&gt;虽然上面的模型最终没有训练成功，不过假如我们只是使用训练后的程序模型来玩一下，那 Ruby 应该还是可以的。也就是说，如果不考虑做科学研究，仅仅在应用层面上，也许 Ruby 并没有太多的短板。&lt;/p&gt;
&lt;h2 id="七、总结"&gt;七、总结&lt;/h2&gt;
&lt;p&gt;客观的说，Ruby 的科学计算还是远远落后于 Python，如果我们真想要涉足这个领域，学习一下 Python 的代价可能还不如看两遍线性代数来得大。不过如果在未来，很多算法会变得更加成熟，仅考虑在应用层面，相信 Ruby 也未尝不是一种优秀的选择。&lt;/p&gt;

&lt;p&gt;DQN 算法相关：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.intel.com/demystifying-deep-reinforcement-learning/" rel="nofollow" target="_blank"&gt;https://ai.intel.com/demystifying-deep-reinforcement-learning/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@awjuliani/simple-reinforcement-learning-with-tensorflow-part-4-deep-q-networks-and-beyond-8438a3e2b8df" rel="nofollow" target="_blank"&gt;https://medium.com/@awjuliani/simple-reinforcement-learning-with-tensorflow-part-4-deep-q-networks-and-beyond-8438a3e2b8df&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://mnemstudio.org/path-finding-q-learning-tutorial.htm" rel="nofollow" target="_blank"&gt;http://mnemstudio.org/path-finding-q-learning-tutorial.htm&lt;/a&gt;&lt;/p&gt;</description>
      <author>happybai</author>
      <pubDate>Wed, 18 Apr 2018 14:59:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/35478</link>
      <guid>https://ruby-china.org/topics/35478</guid>
    </item>
    <item>
      <title>请教一下，在 API 中，保存前端 Canvas 生成的预览图的解决方案</title>
      <description>&lt;p&gt;项目结构：后端 rails-api，前端 react、webpack.
后端统计出一批数据、前端可以根据这些数据生成效果图，现在需要将这批效果图保存到数据库 (carrierwave) 中。
数据不由人工录入，也就是说没有 UI，所以没办法直接传图片信息到后端。
是先产生原数据--&amp;gt;React 前端通过异步 API 生成图片--&amp;gt;要将图片信息保存到数据库 (上传到 s3 等一系列操作)
我现在想到了四种方案&lt;/p&gt;

&lt;p&gt;方案一：在 rails 端重新写一遍生成算法，并绘制图片存起来
生成算法可能很复杂，比较麻烦。&lt;/p&gt;

&lt;p&gt;方案二：rails 端使用 execjs 之类的，执行 js 并把图片存起来
可能需要将 react 组件抽象成独立可用的。并且因为前端有 react、webpack，不确定 execjs 能否顺利执行。&lt;/p&gt;

&lt;p&gt;方案三：react 端进行部分服务端渲染，将这些图片变成可抓取的 HTML，然后 Rails 把数据抓过来
这有点本末倒置的感觉。&lt;/p&gt;

&lt;p&gt;方案四：类似 Selenium 之类的，在服务器上模拟浏览器操作，然后把图片保存出来。
需要在服务器上装很多奇奇怪怪的包。&lt;/p&gt;
&lt;h2 id="哪种比较合理，或者还有没有更好的方案？感谢各位~"&gt;哪种比较合理，或者还有没有更好的方案？感谢各位~&lt;/h2&gt;
&lt;p&gt;最后解决方案采用了在服务端使用 phantomjs 跑，不过需要改写一下 react 组件。
另外服务端渲染也是可行的&lt;/p&gt;</description>
      <author>happybai</author>
      <pubDate>Tue, 28 Jun 2016 16:43:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/30390</link>
      <guid>https://ruby-china.org/topics/30390</guid>
    </item>
    <item>
      <title>.NET Core 1.0 正式发布了</title>
      <description>&lt;p&gt;&lt;a href="https://www.microsoft.com/net/core#macos" rel="nofollow" target="_blank"&gt;https://www.microsoft.com/net/core#macos&lt;/a&gt;
&lt;a href="https://github.com/dotnet/core" rel="nofollow" target="_blank"&gt;https://github.com/dotnet/core&lt;/a&gt;&lt;/p&gt;</description>
      <author>happybai</author>
      <pubDate>Tue, 28 Jun 2016 12:06:29 +0800</pubDate>
      <link>https://ruby-china.org/topics/30384</link>
      <guid>https://ruby-china.org/topics/30384</guid>
    </item>
  </channel>
</rss>
