如何让团队开始使用ML,以及如何最好地将ML与我们运行的现有系统集成? 实际上没有用Java构建的ML框架(有DL4J,但我真的不知道有人在使用它,MXNet有一个ScalaAPI而不是Java,而且它不是用Java编写的,Tensorflow有一个不完整的JavaAPI),但Java在企业中有着巨大的用途,在过去20年中,全球有数万亿美元投资于金融服务、贸易、电子商务和电信公司——这个名单是无穷无尽的。对于机器学习,“第一公民”编程语言不是Java,而是Python。就个人而言,我喜欢用Python和Java编写代码,但FrankGreco提出了一个有趣的问题,让我开始思考: Java还需要什么才能在ML中与Python竞争?如果Java认真对待实际支持机器学习会怎样? 很重要吗? 自1998年以来,Java一直是多项企业转型的领导者——Web、移动、浏览器和原生、消息传递、i18n和l10n全球化支持、扩展和支持各种企业信息存储。值得一提的是,从关系数据库到Elasticsearch。 机器学习行业并非如此。如果Java团队进入ML,他们只有两个选择:在Python中重新训练/共同训练。使用供应商API将机器学习功能添加到您的企业系统。 这两种选择都不是很好。第一个需要大量的前期时间和投资以及持续的维护成本,而第二个风险是供应商锁定、供应商不支持、引入第三方组件(具有网络价格),这可能是一个性能关键系统,并且需要您可以在组织边界之外共享数据——这对某些人来说是不合适的。在我看来,最具破坏性的是文化损耗的可能性?-团队无法更改他们不理解或维护的代码,而Java团队有可能在下一波企业计算、机器学习中落后。 因此,Java编程语言和平台拥有一流的机器学习支持非常重要,否则,Java将面临在未来5到5年内被支持ML的语言慢慢取代的风险10年。 为什么Python在ML中独领风骚? 首先,让我们考虑一下为什么Python是机器学习和深度学习的主要语言。我怀疑这一切都始于一个功能——对列表的切片支持。这种支持是可扩展的:任何实现__getitem__和__setitem__方法的Python类都可以使用这种语法进行切片。下面的代码片段展示了这个Python特性的强大和自然。 a=[1,2,3,4,5,6,7,8]print(a[1:4])#returns[2,3,4]--选择中间元素的切片打印(a[1:-1])#returns[2,3,4,5,6,7]-跳过第0个和最后一个元素print(a[4:])#returns[5,6,7,8]-默认终点print(a[:4])#returns[1,2,3,4]-默认起点 当然还有更多。Python代码比旧的Java代码更干净、更简洁。通过对未经检查的异常的支持,开发人员可以轻松编写一次性Python脚本来尝试和polyfill,而不会陷入“一切都是类”的Java思维模式。使用Python很容易。 但现在我认为主要因素-虽然Python社区在保持2.7和3之间的凝聚力方面做了一顿狗餐,但他们在构建一个设计良好、快速的数值计算库(NumPy)方面做得更好。Numpy是围绕ndarrays构建的——N维对象数组。直接来自文档:“NumPy的主要对象是同构多维数组。它是一个元素表(通常是数字),所有元素类型相同,由正整数元组索引”。 NumPy就是将数据放入ndarray,然后对其执行操作。NumPy支持多种类型的索引、广播、矢量化以提高速度,并且通常允许开发人员轻松创建和操作大型数字数组。 下一个片段显示正在进行的ndarray索引和广播,这是ML/DL中的核心操作。 importnumpyasnp#Simplebroadcastexamplea=np.array([1.0,2.0,3.0])b=2.0c=a*bprint(c)#returns[2.4.6.]-标量b自动提升/广播并应用于向量a以创建c#return[2.4.6.]-标量b被自动提升/广播并应用于向量a以在NumPy中创建c#2-d(秩为2的矩阵)索引-这扩展到张量-即rank>2y=np.arange(35).reshape(5,7)print(y)#array([[0,1,2,3,4,5,6],#[7,8,9,10,11,12,13],#[14,15,16,17,18,19,20],#[21,22,23,24,25,26,27],#[28,29,30,31,32,33,34]])print(y[0,0])#单个单元格访问-符号是行优先的,返回0print(y[4,])#返回所有第4行:array([28,29,30,31,32,33,34])print(y[:,2])#returnsallthecolumn2:array([2,9,16,23,30]) 处理大型多维数字数组是核心机器学习编码,尤其是深度学习。深度神经网络是节点格和边格的数值模型。训练网络或对其执行推理时的运行时操作需要快速矩阵乘法。 NumPy启用并启用了更多-?scipy、pandas和许多其他依赖NumPy的库。领先的深度学习库(谷歌的Tensorflow、Facebook的PyTorch)在Python上投入了大量资金。Tensorflow有其他用于Go、Java和JavaScript的API,但它们不完整并且被认为是不稳定的。PyTorch最初是用Lua编写的,在2017年从一种相当小的语言转移到主要的PythonML生态系统后,人气大幅上升。 Python的缺点 Python不是一种完美的语言——尤其是最流行的Python运行时-CPython-具有全局解释器锁(GIL),因此性能扩展并不简单。此外,PyTorch和Tensorflow等PythonDL框架仍然将核心方法卸载到不透明的实现中。 例如,NVidia的cuDNN库对PyTorch中[url=https://pytorch.org/docs/stable/nn.html#rnn]RNN/LSTM实现[/url]的范围产生了深远的影响。RNN和LSTM是非常重要的DL技术,特别是对于商业应用,因为它们专门用于分类和预测连续的、可变长度的序列——例如网络点击流、文本片段、用户事件等。 公平对待Python,这种不透明/限制适用于几乎所有不是用C或C++编写的ML/DL框架。为什么?因为为了从核心获得最大性能,矩阵乘法等高频运算,开发人员试图尽可能“接近底层冶金”。 Java需要做什么来竞争? 我建议对Java平台进行三个主要的添加,如果它们存在,将在Java中萌芽一个健康和繁荣的机器学习生态系统: 1。在核心语言中添加本机索引/切片支持,以与Python的易用性和表现力相媲美,可能以现有的List 接口为中心,用于有序集合。此支持还需要识别重载以支持点#2。 2。构建一个Tensor实现-可能在java.math包中,但也桥接到CollectionsAPI。这组类和接口将相当于ndarray,具有额外的索引支持——特别是三种类型的NumPy索引:字段访问、基本切片和编码ML所需的高级索引。 3。支持广播-任意(但兼容)维度的标量和张量。 如果这三个东西存在于核心Java语言和运行时中,它将打开构建“NumJava”(相当于NumPy)的道路。ProjectPanama还可用于提供对在CPU、GPU、TPU等上运行的快速张量操作的矢量化低级访问,以帮助JavaML成为最快的。 我并不是说这些添加是微不足道的——远非如此,但Java平台的潜在优势是巨大的。 下面的代码片段显示了我们的NumPy广播和索引示例如何使用NumJava中的Tensor类,核心语言支持切片语法并遵守当前对运算符重载的限制。 //由Java广播的张量//在Java10中使用var语法为简洁起见//Java不支持运算符重载,因此我们不能执行“a*b”//我们应该将其添加到列表中要求?vara=newTensor([1.0,2.0,3.0]);varb=2.0;varc=a.mult(b);/***还有一个片段展示了JavaTensor类的外观。*显示JavaTensor班级外观片段。*/importstaticjava.math.Numeric.arange;//arange返回张量实例,reshape定义在tensorvary=arange(35).reshape(5,7);System.out.println(y);//张量([[0,1,2,3,4,5,6],//[7,8,9,10,11,12,13],//[14,15,16,17,18,19,20],//[21,22,23,24,25,26,27],//[28,29,30,31,32,33,34]])System.out.println(y[0,0]);//单个单元格访问-符号是行优先的,返回0System.out.println(y[4,]);//返回所有第4行(从0idx开始的第5行):tensor([28,29,30,31,32,33,34])System.out.println(y[:,2]);//返回第2列的所有内容(第3列从0idx开始):tensor([2,9,16,23,30]) 总结 从本文概述的实际出发点出发,我们可以拥有尽可能多的用Java编写并在JRE上运行的机器/深度学习框架有Web、持久性或XML解析器-想象一下!我们可以设想支持用于尖端计算机视觉的卷积神经网络(CNN)的Java框架,用于顺序数据集(对业务至关重要)的LSTM等RNN实现,以及具有自动微分等尖端ML功能的Java框架。然后,这些框架将为下一代企业级系统提供动力和动力——所有这些系统都使用相同的工具——IDE、测试框架和持续集成。
