从零开始学人工智能(7)--Python · 神经网络(六)· 拓展

浏览: 1455

作者:射命丸咲    Python 与 机器学习 爱好者

知乎专栏:https://zhuanlan.zhihu.com/carefree0910-pyml 

个人网站:http://www.carefree0910.com 

往期阅读:

从零开始学人工智能(5)--Python · 神经网络(四)· 网络

从零开始学人工智能(6)--Python · 神经网络(五)· Cost & Optimizer

最终成品的 GitHub 地址:

https://github.com/carefree0910/MachineLearning/tree/master/NN

本章用到的 GitHub 地址:

https://github.com/carefree0910/MachineLearning/blob/master/Zhihu/NN/two/Network.py

这一章主要是将上一章提到的一些拓展实现出来。由于这些和神经网络的算法本身没有太大关系而更多只是编程能力的考验,所以我不会说得太详细而只会说一个大概思路

  • 分 batch 训练

    • 把训练数据集分成 batch 来训练的原因有许多,我在这里只说其中两个比较直观的原因:
      极端的栗子就是把所有数据集扔进网络里面训练(这也是我们目前实现的方法)。这样的话一个 epoch 里面就只能更新一次、而且数据集大了之后内存就会爆炸(……)

      • 同一个 epoch 中的更新次数降低,收敛变慢

      • 内存扛不住

    • 实现的方法很简单,这里就只放代码了。分两步走:

      • 训练前判断是否有必要分 batch (如果数据集比 batch_size 还小就没必要),同时算出一个 epoch 里面要训练多少个 batch

        train_len = len(x_train)batch_size = min(batch_size, train_len)do_random_batch = train_len >= batch_sizetrain_repeat = int(train_len / batch_size) + 1
      • 训练时依 batch 训练

        for _i in range(train_repeat):
           if do_random_batch:
               batch = np.random.choice(train_len, batch_size)
               x_batch, y_batch = x_train[batch], y_train[batch]
           else:
               x_batch, y_batch = x_train, y_train
           self._train_step.run(
               feed_dict={self._tfx: x_batch, self._tfy: y_batch})
  • 预测时分批预测

    • 还是因为内存问题。实现的方法有两种:一种是比较常见的按个数分组,一种是我采取的按数据大小分组。换句话说:
      常见做法有一个显而易见的缺点:如果单个数据很庞大的话、这样做可能还是会爆内存

      • 常见的做法是每批预测 k 个数据

      • 我的做法是每批预测 m 个数据,这 m 个数据一共包含一百万左右个数字

    • 实现稍微有些繁复、主要是要考虑 tensorflow 的 session 的生存周期(不知道能不能这样说……)、但其实思路是平凡的。下面姑且贴一下核心代码,但建议跳过(喂)

      def _get_prediction(self, x, batch_size=1e6, out_of_sess=False):
         single_batch = int(batch_size / np.prod(x.shape[1:]))
         if not single_batch:
             single_batch = 1
         if single_batch >= len(x):
             if not out_of_sess:
                 return self._y_pred.eval(feed_dict={self._tfx: x})
             with self._sess.as_default():
                 x = x.astype(np.float32)
                 return self.get_rs(x).eval(feed_dict={self._tfx: x})
         if not out_of_sess:
             rs = [self._y_pred.eval(
                       feed_dict={self._tfx: x[:single_batch]})]
         else:
             rs = [self.get_rs(x[:single_batch])]
         count = single_batch
         while count < len(x):
             count += single_batch
             if count >= len(x):
                 if not out_of_sess:
                     rs.append(self._y_pred.eval(feed_dict={
                         self._tfx: x[count - single_batch:]}))
                 else:
                     rs.append(self.get_rs(x[count - single_batch:]))
             else:
                 if not out_of_sess:
                     rs.append(self._y_pred.eval(feed_dict={
                         self._tfx: x[count - single_batch:count]}))
                 else:
                     rs.append(self.get_rs(x[count - single_batch:count]))
         if out_of_sess:
             with self._sess.as_default():
                 rs = [_rs.eval() for _rs in rs]
         return np.vstack(rs)
  • 交叉验证

    • 交叉验证大概有三种:K 折交叉验证、留一验证、和 Holdout 验证。我们要采用的就是最后这一种、因为它最简单(喂

    • 实现起来也很直观:只需要在一开始把数据随机打乱然后按比例分割即可

      if train_rate is not None:
         train_rate = float(train_rate)
         train_len = int(len(x) * train_rate)
         shuffle_suffix = np.random.permutation(int(len(x)))
         x, y = x[shuffle_suffix], y[shuffle_suffix]
         x_train, y_train = x[:train_len], y[:train_len]
         x_test, y_test = x[train_len:], y[train_len:]else:
         x_train = x_test = x
         y_train = y_test = y

      用到了一点 Numpy 的技巧、不过(应该)不是唯一的做法

  • 实时记录结果

    • 这一块的东西挺多的、可能只能大概看看思路:

      • 定义一个属性 self._logs 以存储我们的记录

      • 这个属性是一个字典,key 为 train 的 value 对应着训练数据集的记录,key 为 test 的 value 则对应测试数据集的

      • 记录的东西通常是对模型的某种评估,常用的评估有三种:损失(loss)、准确率(acc)和 F1-score。最后这个评估是针对二类问题的,具体数学含义可以看这里(https://en.wikipedia.org/wiki/F1_score

      • 定义三个函数,一个拿来记录这些评估,一个拿来 print 出最新的评估,一个拿来可视化评估

    • 实现的话不难但繁,需要定义好几个东西。这里就不贴代码了否则总有灌水的感觉(……),感兴趣的观众老爷们可以直接看源代码(https://github.com/carefree0910/MachineLearning/blob/master/Zhihu/NN/two/Network.py) ( σ'ω')σ

以上大概把上一章留下来的坑填了一遍。至此一个还算能用的神经网络模型就已经做好了,它诚然还有相当大可优化的空间、不过作为基础来说业已足够

从下一章开始就是比较重头戏的 CNN 了;本来从 NN 到 CNN 的拓展其实并不太平凡,可是 tensorflow 这个外挂愣是把这件事情变得相当容易……想起当初用纯 Numpy 好不容易才把 CNN 整合进这个框架结果看到 tensorflow 之后直接傻眼……唉不说了挺心疼自己的(叹

最后贴一个比较普适的、不限于 NN 的二维数据可视化函数作为结束吧:

def visualize_2d(self, x, y, plot_scale=2, plot_precision=0.01):
   plot_num = int(1 / plot_precision)
   xf = np.linspace(
       np.min(x) * plot_scale, np.max(x) * plot_scale, plot_num)
   yf = np.linspace(
       np.min(x) * plot_scale, np.max(x) * plot_scale, plot_num)
   input_x, input_y = np.meshgrid(xf, yf)
   input_xs = np.c_[input_x.ravel(), input_y.ravel()]
   output_ys_2d = np.argmax(self.predict(input_xs), axis=1).reshape(
       len(xf), len(yf))
   plt.contourf(input_x, input_y, output_ys_2d, cmap=plt.cm.Spectral)
   plt.scatter(x[:, 0], x[:, 1],
       c=np.argmax(y, axis=1), s=40, cmap=plt.cm.Spectral)
   plt.axis("off")
   plt.show()

把 predict 函数换成任一个有预测功能的函数都行。在我们这个 NN 里,它的效果大概如下:

希望观众老爷们能够喜欢~

公众号后台回复关键词学习

回复 人工智能          揭开人工智能的神秘面纱

回复 贝叶斯算法      贝叶斯算法与新闻分类

回复 机器学习          R&Python机器学习

回复 阿里数据          阿里数据系列课程

回复 Python             Python机器学习案例实战

回复 Spark               征服Spark第一季

回复 kaggle             机器学习kaggle案例

回复 大数据             大数据系列视频

回复 数据分析          数据分析人员的转型

回复 数据挖掘          数据挖掘与人工智能

回复 机器学习          R&Python机器学习

回复 阿里数据          阿里数据系列课程

回复 R                      R&Python机器学习入门

推荐 0
本文由 人工智能爱好者社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册