在过去几年中,神经网络领域的发展很是迅猛,也是如今图像识别和自动翻译领域中最强者。TensorFlow 是谷歌发布的数值计算和神经网络的新框架。本文中,咱们将演示如何使用TensorFlow和Spark一块儿训练和应用深度学习模型。html
你可能会困惑:在最高性能深度学习实现仍是单节点的当下, Spark 的用处在哪里?为了回答这个问题,咱们将会演示两个例子并解释如何使用 Spark 和机器集群搭配 TensorFlow 来提升深度学习的管道数。java
超参数调整: 使用 Spark 来找到最优的神经网络训练参数集,减小十倍训练时间并下降34%的失误率。python
部署模型规模: 使用 Spark 在大量数据上应用训练完毕的神经网络模型。web
超参数调整
深度机器学习(ML)技术的一个典型应用是人工神经网络。它们采起一个复杂的输入,如图像或音频记录,而后对这些信号应用复杂的数学变换。此变换的输出是更易于由其余ML算法处理的数字向量。人工神经网络经过模仿人类大脑的视觉皮层的神经元(以至关简化的形式)执行该转换。算法
就像人类学会解读他们所看到的,人工神经网络须要经过训练来识别那些“有趣”的具体模式。能够是简单的模式,好比边缘,圆形,但也能够是更复杂的模式。在这里,咱们将用NIST提供的经典数据集来训练神经网络以识别这些数字:微信
TensorFlow 库将会自动建立各类形状和大小的神经网络训练算法。创建一个神经网络的实际过程,比单纯在数据集上跑一些算法要复杂得多。一般会有一些很是重要的超参数(通俗地说,参数配置)须要设置,这将影响该模型是如何训练的。选择正确的参数可让性能优越,而坏的参数将会致使长时间的训练和糟糕的表现。在实践中,机器学习从业者会屡次使用不一样的超参数重复运行相同的模型,以期找到最佳的集合。这是一个被称为超参数调整的经典技术。markdown
创建一个神经网络时,有许多须要精心挑选的重要超参数。 例如:网络
每层的神经元数目:太少的神经元会下降网络的表达能力,但太多会大大增长运行时间,并返回模糊噪音。session
学习速度:若是太高,神经网络将只专一于看到过去的几个样例,并忽略以前积累的经验。若是过低,则须要很长时间才能达到一个很好的状态。app
这里有趣的是,即便 TensorFlow 自己不予分发,超参数调整过程是“易并行”(embarrassingly parallel),而且可使用 Spark 来分配的。在这种状况下,咱们可使用 Spark 广播通用的元素,例如数据和模型描述,而后以容许错误的方式安排机器集群中的个体进行独立的重复性计算。
如何使用 Spark 提升精度?用默认的超参数设置精度为99.2%。咱们在测试集上的最好结果是99.47%的精确度,这减小了34%的测试偏差。分布式计算时间与添加到集群的节点数量成线性关系:使用有13个节点的集群,咱们可以并行培养13个模型,这相比于在同一台机器一个接着一个训练速度提高了7倍。这里是相对于该集群上机器的数量的计算时间(以秒计)的曲线图:
最重要的是,咱们分析了大量训练过程当中的超参数的灵敏度。例如,咱们相对于不一样数目的神经元所得学习率绘制了最终测试性能图:
这显示了一个典型的神经网络权衡曲线:
学习速度是很是关键的:若是它过低,神经网络没有学到任何东西(高测试偏差)。若是它过高,训练过程可能发生随机振荡甚至在某些配置下出现发散。
神经元的数目对于得到良好的性能来讲没有那么重要,而且有更多神经元的网络的学习率更加敏感。这是奥卡姆剃刀原则:对大多数目标来讲,简单的模型每每已经“足够好”。除非你在训练中投入大量的时间和资源,并找到合适的超参数来除去这缺乏的1%测试偏差,这才会有所不一样。
经过使用参数稀疏样本,咱们能够在最优的参数集下取得零失误率。
我该如何使用它?
尽管 TensorFlow 可使用每个 worker 上的全部核心,但每一个工人同一时间只能运行一个任务,咱们能够将它们打包以限制竞争。TensorFlow 库能够按照[instructions on the TensorFlow website](https://www.tensorflow.org/get_started/os_setup.html)上的指示在 Spark 集群上做为一个普通的Python库进行安装。下面的笔记展现了用户如何安装 TensorFlow 库并重复该文章的实验:
大规模部署
TensorFlow 模型能够直接在管道内嵌入对数据集执行的复杂识别任务。做为一个例子,咱们将展现咱们如何可以使用一个已经训练完成的股票神经网络模型标注一组图片
首先使用 Spark 内置的广播机制将该模型分发到集群中的worker上:
with gfile.FastGFile( 'classify_image_graph_def.pb', 'rb') as f:
model_data = f.read()
model_data_bc = sc.broadcast(model_data)
以后,这个模型被加载到每一个节点上,而且应用于图片。这是每一个节点运行的代码框架:
def apply_batch(image_url):
# Creates a new TensorFlow graph of computation and imports the model
with tf.Graph().as_default() as g:
graph_def = tf.GraphDef()
graph_def.ParseFromString(model_data_bc.value)
tf.import_graph_def(graph_def, name='')
# Loads the image data from the URL:
image_data = urllib.request.urlopen(img_url, timeout=1.0).read()
# Runs a tensor flow session that loads the
with tf.Session() as sess:
softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data}) return predictions
经过将图片打包在一块儿,这份代码能够运行地更快。
下面是图片的一个样例:
这是神经网络对于这张图片的解释,至关精确:
('coral reef', 0.88503921),
('scuba diver', 0.025853464),
('brain coral', 0.0090828091),
('snorkel', 0.0036010914),
('promontory, headland, head, foreland', 0.0022605944)])
期待
咱们已经展现了如何将 Spark 和 TensorFlow结合起来训练和部署手写数字识别和图片分类的神经网络。尽管咱们使用的神经网络框架自身只能在单节点运行,但咱们能够用 Spark 分发超参数调节过程和模型部署。这不只缩短了训练时间,并且还提升了精度,使咱们更好地理解各类超参数的灵敏度。
尽管这支持是只适用于Python的,咱们仍期待着能够提供 TensorFlow 和 Spark其它框架之间更深度的集成。
本文分享自微信公众号 - 云服务圈(heidcloud)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。