本日的农人面临着一个巨大的寻衅 —— 用更少的地皮养活日益增长的环球人口。估量到2050年,天下人口将增长到近100亿,使环球粮食需求增加50%。
随着粮食需求的增长,地皮、水和其他资源将面临更大的压力。农业中固有的可变性,如景象条件的变革,以及杂草和害虫等威胁,也会对农人生产粮食的能力产生影响。在利用更少资源的同时生产更多粮食的唯一方法是通过智能机器,该机器可以帮助事情困难的农人,供应更高的同等性,准确性和效率。
农业机器人
在蓝河科技,我们正在制造下一代智能机器。农人利用我们的工具来掌握杂草和降落本钱,以促进农业可持续发展。
我们的除草机器人集成了摄像头、打算机视觉、机器学习和机器人技能,制造了一款智能喷雾器,可以在田间行驶(利用AutoTrac将驾驶员的负载降至最低),并快速锁定目标并喷洒杂草,使作物无缺无损。
这台机器须要实时决定什么是庄稼什么是杂草。当机器在野生手驶时,高分辨率相机以高帧速率采集图像。
我们开拓了一个卷积神经网络(CNN),利用Pytorch剖析每一帧,并天生一张像素精确的农作物和杂草所在的舆图。一旦所有的植物都被识别出来,每个杂草和作物都被映射到田间位置,机器人只喷洒杂草。
全体过程在几毫秒内完成,由于效率很高,农人就可以覆盖尽可能多的地皮。
这是一个很棒的See&Spray视频,详细先容了该过程。
https://youtu.be/XH-EFtTa6IU为了支持机器学习(ML)和机器人技能,我们基于NVIDIA Jetson AGX Xavier Edge AI平台构建了一个令人印象深刻的打算单元。
由于我们所有的推断都是实时进行的,上传到云端须要的韶光太长,以是我们将做事器场带到现场。
专门用于视觉推理和喷雾机器人的机器人的总打算能力与IBM的超级打算机Blue Gene(2007)相称。这使它成为环球移动机械中具有最高打算能力的机器!
我的研究职员和工程师团队卖力演习识别作物和杂草的神经网络模型。这是一个具有寻衅性的问题,由于许多杂草看起来就像庄稼。专业的农学家和杂草科学家演习我们的标签事情职员精确地标记图像——你能创造下面哪些是杂草吗?
不才图中,棉花植物为绿色,杂草为赤色。
机器学习栈
在机器学习方面,我们有一个繁芜的堆栈。我们用Pytorch演习我们所有的模特。我们在Pytorch上建立了一组内部库,许可我们进行可重复的机器学习实验。我的团队职责分为三类:
建立生产模型以支配到机器人上以不断提高模型性能为目标,进行机器学习实验和研究与机器学习、A/B测试、流程改进、软件工程干系的数据剖析/数据科学我们选择Pytorch是由于它非常灵巧且易于调试。新的团队成员可以很快跟上进度,而且文档非常详尽。
在利用PyTorch之前,我们的团队广泛利用Caffe和Tensorflow。2019年,我们决定改用Pytorch,过渡顺利。同时也为事情流的研究供应了支持。
例如,我们利用Torchvision库进行图像变换和张量变换。它包含了一些基本的功能,并且与像imgauge这样的繁芜的增强包进行了很好的集成。torchvision 中的变换工具与imgauge的集造诣是小菜一碟。
下面是一个利用Fashion MNIST数据集(https://github.com/zalandoresearch/fashion-mnist) 的代码示例。
名为CustomAugmentor的类将初始化布局函数中的iaa.Sequential工具,然后在call方法中调用invoke_image()。然后,在ToTensor()之前,将CustomAugmentor()添加到对transforms.Compose()的调用中。
现在,当加载批次进行演习和验证时,train和val数据加载器将运用CustomAugmentor()中定义的增强。
from imgaug import augmenters as iaaimport numpy as npimport osimport torchfrom torch.utils.data import DataLoader, random_splitfrom torchvision.datasets import FashionMNISTfrom torchvision import datasets, transformsDATA_DIR = './fashionMNIST/'class CustomAugmentor: def __init__(self): self.aug = iaa.Sequential([iaa.flip.Fliplr(p=0.5), iaa.GaussianBlur(sigma=(0.0, 0.1)), iaa.Multiply((0.9, 1.1)), iaa.Dropout((0, 0.05)), iaa.AdditiveGaussianNoise(scale=(0, 0.05255)) ]) def __call__(self, img): img = np.array(img) # 在此处返回一个副本以办理缺点:ValueError:至少一个步幅 #在给定的numpy数组中为负,张量为负跨度 #当前不支持。 return self.aug.augment_image(img).copy()# 转换图像transform=transforms.Compose([CustomAugmentor(), transforms.ToTensor()])fmnist_train = FashionMNIST(DATA_DIR, train=True, download=True, transform=transform)fmnist_test = FashionMNIST(DATA_DIR, train=False, download=True, transform=transforms.ToTensor())fmnist_train, fmnist_val = random_split(fmnist_train, [55000, 5000])train_dl = DataLoader(fmnist_train, batch_size=64)val_dl = DataLoader(fmnist_val, batch_size=64)test_dl = DataLoader(fmnist_test, batch_size=64)
此外,PyTorch已成为打算机视觉生态系统中最喜好的工具(请参阅https://paperswithcode.com/,PyTorch是常见的提交)。这样一来,我们就可以轻松地考试测验诸如Debiased Contrastive Learning之类的新技能进行半监督式演习。
在模型演习方面,我们有两个正常的事情流程:生产和研究。
对付研究运用程序,我们的团队在内部本地打算群集上运行PyTorch。在本地群集上实行的作业由Slurm管理,Slurm是基于HPC批处理作业的调度程序。它是免费的,易于设置和掩护的,并且供应了我们小组运行数千个机器学习作业所需的所有功能。
对付基于生产的事情流程,我们在AWS托管的Kubernetes(K8s)集群之上利用Argo事情流程。我们的PyTorch演习代码是利用Docker支配到云中的。
在农业机器人上支配模型
对付生产支配,我们的紧张任务之一是在边缘打算设备上进行高速推理。如果机器人须要开得慢一点来等待推断,它在田间的效率就不可能那么高了。
为此,我们利用TensorRT将网络转换为NVIDIA Jetson AGX Xavier优化模型。TensorRT不接管JIT模型作为输入,因此我们利用ONNX从JIT转换为ONNX格式,然后利用TensorRT转换为直接支配到设备上的TensorRT引擎文件。
随着工具栈的发展,我们期望这个过程也会得到改进。我们的模型利用Jenkins构建过程支配到Artifactory,并通过从Artifactory中提取将它们支配到现场的远程机器上。
为了监控和评估我们的机器学习运行,我们创造 http://wandb.com/ 平台是最好的办理方案。他们的API使得将W&B日志集成到现有的代码库中变得更快。我们利用W&B监控正在进行的演习,包括演习的实时曲线和验证丢失。
SGD vs Adam Project作为利用Pytorch和W&B的一个例子,我将运行一个实验,并比较在Pytorch中利用不同求解器的结果。Pytorch中有许多不同的求解器——很明显的问题是你该当选择哪一种?
Adam 是一个很受欢迎的办理方案。它常日在不须要设置任何参数的情形下给出良好的结果,并且是我们常日会选择的模型。该求解器位于 https://pytorch.org/docs/stable/optim.html#torch.optim.Adam 下
对付机器学习研究职员来说,另一个盛行的求解器选择是随机梯度低落(SGD)。此求解器在Pytorch中可用 https://pytorch.org/docs/stable/optim.html#torch.optim.SGD 得到
如果你是不知道两者之间的差异,或者如果你须要复习,我建议你把这两个的差异写下来。动量是机器学习中的一个主要观点,它可以避免陷入优化空间中的局部最小值,从而找到更好的办理方案。利用SGD和动量的问题是:我能找到击败Adam的SGD的动量设置吗?
实验装置如下。我对每次运行利用相同的演习数据,并在同一个测试集中评估结果。我要比较一下F1 score在不同的运行中的得分。我用SGD作为求解器设置了许多次运行,并从0–0.99扫描动量值(当利用动量时,大于1.0的任何值都会导致求解器发散)。
我设置了运行10次,动量值从0到0.9,增量为0.1。接下来,我又运行了10次,这次动量值在0.90到0.99之间,增量为0.01。在看了这些结果之后,我还进行了一组动量值为0.999和0.9999的实验。每次运行都利用不同的随机种子,并在W&B中被授予“SGD扫描”标签。结果如图1所示。
从图1非常清楚,动量值越大,f1分数越高。最佳值0.9447在动量值0.999时涌现,在动量值0.9999时低落到0.9394。数值如下表所示。
表1:每次运行在上表中显示为一行。末了一栏是运行的动量设置。显示了第2类(庄稼)的F1得分,准确性和召回率。
这些结果与Adam比较如何?为了测试这一点,我仅用默认参数来利用 torch.optim.Adam 。我用W&B中的“Adam runs”标签来标识这些运行记录。我还标记了每一组SGD运行以进行比较。
由于每次运行利用不同的随机种子,求解器每次初始化都会不同,并在末了一个epoch利用不同的权重。这会在每次运行的测试集中给出轻微不同的结果。为了比较它们,我须要丈量Adam和SGD运行值的分布。利用W&B中按标签分组的箱形图可以轻松做到这一点。
结果在图2中以图脸色势显示,在表2中以表格形式显示。完全的报告也可以在线得到。
https://app.wandb.ai/blueriver/blog-post/reports/AI-For-AG-Production-ML-for-Agriculture--VmlldzoxNTA1MDg?accessToken=icdp45djyu5zxey5h0sa41bdvoncfqp1buga0h2fnj6cgf6cs8xsg23hiar8qr14你可以看到,仅通过SGD调度动量值就无法击败Adam。动量设置为0.999可以得到非常相似的结果,但Adam运行的方差更小,均匀值也更高。因此,Adam彷佛是办理我们的植物分割问题的一个好选择!
Pytorch可视化
通过集成Pytorch,W&B可以在每一层获取梯度,让我们在演习期间检讨网络。
W&B实验跟踪还可以使Pytorch模型在演习期间更随意马虎可视化,因此你可以在中心仪表板上实时查看丢失曲线。我们在团队会议中利用这些可视化效果来谈论最新结果并共享更新。
当图像通过Pytorch模型时,我们将预测记录到 Weights & Biases 中,以可视化模型演习的结果。在这里我们可以看到预测、精确标注和标签。这样可以轻松地确定模型性能未达到我们期望的情形。
在这里,我们可以快速浏览精确标注,预测以及两者之间的差异。我们将农作物标记为绿色,将杂草标记为赤色。如你所见,该模型在识别图像中的农作物和杂草方面做得相称合理。
以下是如何在W&B中利用数据帧的简短代码示例:
# Per-sample dataframe with images.data = []# Loop through the mini-batches. Each batch is a dictionary.For batch in batches: image = batch[“image”].astype(np.uint8) label = batch[“label”] pred = batch[“prediction”] zeros = np.zeros_like(image) diff = np.zeros_like(pred) diff[np.where(pred != label)] = 255.0 datapoint = {} datapoint['image'] = wandb.Image(image) # colorize_segmentation is a method which alpha-blends the class colors into an image. datapoint['pred'] = wandb.Image(colorize_segmentation(zeros, pred, alpha=1.0)) datapoint['label'] = wandb.Image(colorize_segmentation(zeros, label, alpha=1.0)) datapoint['diff'] = wandb.Image(diff) data.append(datapoint)# Convert the list of datapoints to a pandas dataframe and log it to W&B.log_df = pd.DataFrame(data)wandb.run.summary['my_awesome_dataframe’'] = log_df
可复制模型
再现性和可追溯性是任何ML系统的关键特性,而且很难得到精确的结果。当比较不同的网络体系构造和超参数时,输入数据必须相同才能使运行具有可比性。
常日ML团队中的个体实践者都会保存YAML或JSON配置文件——要找到团队成员的运行记录并仔细查看他们的配置文件以找出利用了什么演习集和超参数,这是一件非常痛楚的事情。我们都做过,我们都讨厌。
W&B刚刚发布的一个新特性办理了这个问题。工件(Artifact)许可我们跟踪演习和评估运行的输入和输出。这对我们的可重复性和可追溯性有很大帮助。我可以知道利用了哪些数据集来演习模型,天生了哪些模型(来自多次运行)以及模型评估的结果。
范例的用例如下。数据暂存过程将下载最新和最大的数据,并将其暂存到磁盘上进行演习和测试(每个数据集都是单独的)。这些数据集被指定为工件(Artifact)。
演习运行将演习集工件(Artifact)作为输入,并将经由演习的模型输出为输出工件(Artifact)。评估过程将测试集工件(Artifact)与演习的模型工件(Artifact)一起作为输入,并输出可能包含一组度量或图像的评估。
有向无环图(DAG)是在W&B中形成和可视化的。这是很有帮助的,由于跟踪将机器学习模型发布莅临盆中所涉及的工件(Artifact)非常主要。这样的DAG很随意马虎形成:
Artifacts特性的一大优点是可以选择上载所有工件(Artifact)(数据集、模型、评估),也可以选择只上载对工件(Artifact)的引用。这是一个很好的特性,由于移动大量数据既耗时又慢。对付数据集工件(Artifact),我们只需在W&B中存储对这些工件(Artifact)的引用,这就许可我们保持对数据的掌握(并避免永劫光的传输),并且在机器学习中仍旧可以得到可追溯性和再现性。
# 初始化 wandb.wandb_run = wandb.init(job_type="train", reinit=True, project=”blog-post”, tags=[“SGD Sweep”], tensorboard=False) # 指定用于演习运行的工件(Artifact)。在这里我们指定一个演习数据集和测试数据集。artifact_list = [{“name”: “blueriver/blog-post/train-dataset:latest”, “type”: “dataset”}, {“name”: “blueriver/blog-post/test-dataset:latest”, “type”: “dataset”}]# 遍历列表,并见告wandb利用工件(Artifact)。for elem in artifact_list: artifact = wandb_run.use_artifact(elem[“name”], elem[“type”])
领导ML团队
回顾我领导机器学习工程师团队的这些年,我看到了一些常见的寻衅:
效率:当我们开拓新模型时,我们须要快速试验并分享结果。Pytorch使我们很随意马虎快速添加新特性,W&B为我们供应了调试和改进模型所需的可见性。
灵巧性:与我们的客户互助,每天都会带来新的寻衅。我们的团队须要能够知足我们不断变革的需求的工具,这便是为什么我们选择Pytorch作为其发达发展的生态系统,选择W&B作为轻量级的模块化集成。
性能:归根结底,我们须要为我们的农业机器人建立最精确和最快的模型。Pytorch使我们能够快速迭代,然后将模型产品化并支配到现场。我们在W&B的开拓过程中具有完备的可视性和透明度,使我们很随意马虎确定性能最好的模型。